diff --git a/Analysis/CrossSectionAnalysis.cc b/Analysis/CrossSectionAnalysis.cc --- a/Analysis/CrossSectionAnalysis.cc +++ b/Analysis/CrossSectionAnalysis.cc @@ -1,101 +1,99 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the CrossSectionAnalysis class. // #include "CrossSectionAnalysis.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "Herwig/Sampling/GeneralSampler.h" #include "Herwig/Utilities/XML/ElementIO.h" using namespace Herwig; CrossSectionAnalysis::CrossSectionAnalysis() {} -CrossSectionAnalysis::~CrossSectionAnalysis() {} - #ifndef LWH_AIAnalysisFactory_H #ifndef LWH #define LWH ThePEGLWH #endif #include "ThePEG/Analysis/LWH/AnalysisFactory.h" #endif void CrossSectionAnalysis::dofinish() { AnalysisHandler::dofinish(); Ptr::tptr seh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); Ptr::tptr sampler = dynamic_ptr_cast::tptr>(seh->sampler()); unsigned long attemptedPoints = sampler->attempts(); double sumOfWeights = sampler->sumWeights(); double sumOfSquaredWeights = sampler->sumWeights2(); CrossSection maxXSection = sampler->maxXSec(); XML::Element elem(XML::ElementTypes::Element,"Run"); elem.appendAttribute("name",generator()->runName()); elem.appendAttribute("attemptedPoints",attemptedPoints); elem.appendAttribute("sumOfWeights",sumOfWeights*maxXSection/picobarn); elem.appendAttribute("sumOfSquaredWeights",sumOfSquaredWeights*sqr(maxXSection/picobarn)); XML::Element xhistos(XML::ElementTypes::Element,"Histograms"); elem.append(xhistos); string fname = generator()->filename() + string("-") + name() + string(".xml"); ofstream runXML(fname.c_str()); runXML << setprecision(16); XML::ElementIO::put(elem,runXML); } IBPtr CrossSectionAnalysis::clone() const { return new_ptr(*this); } IBPtr CrossSectionAnalysis::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void CrossSectionAnalysis::persistentOutput(PersistentOStream &) const {} void CrossSectionAnalysis::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigCrossSectionAnalysis("Herwig::CrossSectionAnalysis", "HwJetsAnalysis.so"); void CrossSectionAnalysis::Init() { static ClassDocumentation documentation ("There is no documentation for the CrossSectionAnalysis class"); } diff --git a/Analysis/CrossSectionAnalysis.h b/Analysis/CrossSectionAnalysis.h --- a/Analysis/CrossSectionAnalysis.h +++ b/Analysis/CrossSectionAnalysis.h @@ -1,105 +1,97 @@ // -*- C++ -*- #ifndef Herwig_CrossSectionAnalysis_H #define Herwig_CrossSectionAnalysis_H // // This is the declaration of the CrossSectionAnalysis class. // #include "ThePEG/Handlers/AnalysisHandler.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the CrossSectionAnalysis class. * * @see \ref CrossSectionAnalysisInterfaces "The interfaces" * defined for CrossSectionAnalysis. */ class CrossSectionAnalysis: public AnalysisHandler { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ CrossSectionAnalysis(); - /** - * The destructor. - */ - virtual ~CrossSectionAnalysis(); - //@} - 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). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ CrossSectionAnalysis & operator=(const CrossSectionAnalysis &) = delete; }; } #endif /* Herwig_CrossSectionAnalysis_H */ diff --git a/Analysis/HJetsAnalysis.cc b/Analysis/HJetsAnalysis.cc --- a/Analysis/HJetsAnalysis.cc +++ b/Analysis/HJetsAnalysis.cc @@ -1,127 +1,125 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the HJetsAnalysis class. // #include "HJetsAnalysis.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; HJetsAnalysis::HJetsAnalysis() {} -HJetsAnalysis::~HJetsAnalysis() {} - IBPtr HJetsAnalysis::clone() const { return new_ptr(*this); } IBPtr HJetsAnalysis::fullclone() const { return new_ptr(*this); } void HJetsAnalysis::reconstructHardObjects(ParticleVector& parts) { ParticleVector::iterator higgs = parts.begin(); for ( ; higgs != parts.end(); ++higgs ) { if ( (**higgs).id() == ParticleID::h0 ) break; } if ( higgs == parts.end() ) throw Exception() << "No Higgs found in HJetsAnalysis" << Exception::abortnow; hardObjectMomentum("h") = (**higgs).momentum(); parts.erase(higgs); } void HJetsAnalysis::analyzeSpecial(long id, double weight) { if ( nJets() < 2 ) return; higgsYStar().count(Statistics::EventContribution(yStar(jetMomentum(1),jetMomentum(2),hardObjectMomentum("h")),weight,0.1),id); if ( nJets() > 2 ) thirdJetYStar().count(Statistics::EventContribution(yStar(jetMomentum(1),jetMomentum(2),jetMomentum(3)),weight,0.1),id); if ( nJets() > 3 ) fourthJetYStar().count(Statistics::EventContribution(yStar(jetMomentum(1),jetMomentum(2),jetMomentum(4)),weight,0.1),id); if ( nJets() > 1 ) { LorentzMomentum p12 = jetMomentum(1) + jetMomentum(2); double dphi = JetsPlusAnalysis::PairProperties::dPhi(p12,hardObjectMomentum("h")); jet12HiggsDeltaPhi().count(Statistics::EventContribution(dphi,weight,0.1),id); // Jeppe delta phi double minRap = jetMomentum(1).rapidity(); double maxRap = minRap; for ( unsigned int k = 2; k <= nJets(); ++k ) { double yjet = jetMomentum(k).rapidity(); minRap = min(minRap,yjet); maxRap = max(maxRap,yjet); } double hrap = hardObjectMomentum("h").rapidity(); if ( minRap < hrap && hrap < maxRap ) { LorentzMomentum pLeft, pRight; for ( unsigned int k = 1; k <= nJets(); ++k ) { const LorentzMomentum& pjet = jetMomentum(k); if ( pjet.rapidity() < hrap ) pLeft += pjet; else pRight += pjet; } double jeppedphi = JetsPlusAnalysis::PairProperties::dPhi(pLeft,pRight); jeppeDeltaPhi().count(Statistics::EventContribution(jeppedphi,weight,0.1),id); } } } void HJetsAnalysis::finalize(XML::Element& xhistos) { if ( !theHiggsYStar.bins().empty() ) { theHiggsYStar.finalize(); xhistos.append(theHiggsYStar.toXML()); } if ( !theThirdJetYStar.bins().empty() ) { theThirdJetYStar.finalize(); xhistos.append(theThirdJetYStar.toXML()); } if ( !theFourthJetYStar.bins().empty() ) { theFourthJetYStar.finalize(); xhistos.append(theFourthJetYStar.toXML()); } if ( !theJet12HiggsDeltaPhi.bins().empty() ) { theJet12HiggsDeltaPhi.finalize(); xhistos.append(theJet12HiggsDeltaPhi.toXML()); } if ( !theJeppeDeltaPhi.bins().empty() ) { theJeppeDeltaPhi.finalize(); xhistos.append(theJeppeDeltaPhi.toXML()); } } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void HJetsAnalysis::persistentOutput(PersistentOStream &) const {} void HJetsAnalysis::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigHJetsAnalysis("Herwig::HJetsAnalysis", "JetCuts.so HwJetsAnalysis.so"); void HJetsAnalysis::Init() { static ClassDocumentation documentation ("There is no documentation for the HJetsAnalysis class"); } diff --git a/Analysis/HJetsAnalysis.h b/Analysis/HJetsAnalysis.h --- a/Analysis/HJetsAnalysis.h +++ b/Analysis/HJetsAnalysis.h @@ -1,212 +1,204 @@ // -*- C++ -*- #ifndef Herwig_HJetsAnalysis_H #define Herwig_HJetsAnalysis_H // // This is the declaration of the HJetsAnalysis class. // #include "Herwig/Analysis/JetsPlusAnalysis.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the HJetsAnalysis class. * * @see \ref HJetsAnalysisInterfaces "The interfaces" * defined for HJetsAnalysis. */ class HJetsAnalysis: public Herwig::JetsPlusAnalysis { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ HJetsAnalysis(); - /** - * The destructor. - */ - virtual ~HJetsAnalysis(); - //@} - public: /** * Reconstruct the desired electroweak objects and fill the * respective momenta. Remove the reconstructed particles from the * list. */ virtual void reconstructHardObjects(ParticleVector&); protected: /** * Perform any additional analysis required */ virtual void analyzeSpecial(long id, double weight); /** * Append any additional histograms to the given histogram element */ virtual void finalize(XML::Element&); 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: /** * Relative rapidity of the Higgs between the first two jets */ Statistics::Histogram theHiggsYStar; /** * Relative rapidity of the third jet between the first two jets */ Statistics::Histogram theThirdJetYStar; /** * Relative rapidity of the fourth jet between the first two jets */ Statistics::Histogram theFourthJetYStar; /** * Delta phi between the Higgs and the two-jet system */ Statistics::Histogram theJet12HiggsDeltaPhi; /** * Jeppe's delta phi */ Statistics::Histogram theJeppeDeltaPhi; protected: /** * Calculate ystar given two jets and object of interest */ double yStar(const LorentzMomentum& jet1, const LorentzMomentum& jet2, const LorentzMomentum& obj) const { double y1 = jet1.rapidity(); double y2 = jet2.rapidity(); double res = obj.rapidity() - 0.5*(y1+y2); return res/(y1-y2); } /** * Relative rapidity of the Higgs between the first two jets */ Statistics::Histogram& higgsYStar() { if ( !theHiggsYStar.bins().empty() ) return theHiggsYStar; return theHiggsYStar = Statistics::Histogram("HiggsYStar",Statistics::Histogram::regularBinEdges(-6,6,120),false,false); } /** * Relative rapidity of the third jet between the first two jets */ Statistics::Histogram& thirdJetYStar() { if ( !theThirdJetYStar.bins().empty() ) return theThirdJetYStar; return theThirdJetYStar = Statistics::Histogram("Jet3YStar",Statistics::Histogram::regularBinEdges(-6,6,120),false,false); } /** * Relative rapidity of the fourth jet between the first two jets */ Statistics::Histogram& fourthJetYStar() { if ( !theFourthJetYStar.bins().empty() ) return theFourthJetYStar; return theFourthJetYStar = Statistics::Histogram("Jet4YStar",Statistics::Histogram::regularBinEdges(-6,6,120),false,false); } /** * Delta phi between the Higgs and the two-jet system */ Statistics::Histogram& jet12HiggsDeltaPhi() { if ( !theJet12HiggsDeltaPhi.bins().empty() ) return theJet12HiggsDeltaPhi; return theJet12HiggsDeltaPhi = Statistics::Histogram("Jet12hDeltaPhi", Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,32), make_pair(-Constants::pi,Constants::pi)); } /** * Delta phi between the Higgs and the two-jet system */ Statistics::Histogram& jeppeDeltaPhi() { if ( !theJeppeDeltaPhi.bins().empty() ) return theJeppeDeltaPhi; return theJeppeDeltaPhi = Statistics::Histogram("JeppeDeltaPhi", Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,32), make_pair(-Constants::pi,Constants::pi)); } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HJetsAnalysis & operator=(const HJetsAnalysis &) = delete; }; } #endif /* Herwig_HJetsAnalysis_H */ diff --git a/Analysis/JetsPlusAnalysis.cc b/Analysis/JetsPlusAnalysis.cc --- a/Analysis/JetsPlusAnalysis.cc +++ b/Analysis/JetsPlusAnalysis.cc @@ -1,363 +1,359 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the JetsPlusAnalysis class. // #include "JetsPlusAnalysis.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/EventRecord/SubProcessGroup.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "Herwig/Sampling/GeneralSampler.h" #include "Herwig/Utilities/XML/ElementIO.h" using namespace Herwig; JetsPlusAnalysis::JetsPlusAnalysis() : theIsShowered(false) {} -JetsPlusAnalysis::~JetsPlusAnalysis() {} - - - #ifndef LWH_AIAnalysisFactory_H #ifndef LWH #define LWH ThePEGLWH #endif #include "ThePEG/Analysis/LWH/AnalysisFactory.h" #endif struct SortPt { inline bool operator()(const LorentzMomentum& a, const LorentzMomentum& b) const { return a.perp() > b.perp(); } }; void JetsPlusAnalysis::reconstructJets(const ParticleVector& parts) { tcPDVector outType; vector outMomenta; for ( ParticleVector::const_iterator p = parts.begin(); p != parts.end(); ++p ) { outType.push_back((**p).dataPtr()); outMomenta.push_back((**p).momentum()); } jetFinder()->cluster(outType, outMomenta, tcCutsPtr(), tcPDPtr(),tcPDPtr()); sort(outMomenta.begin(),outMomenta.end(),SortPt()); for ( vector::ptr>::iterator j = theJetRegions.begin(); j != theJetRegions.end(); ++j ) (**j).reset(); for ( size_t k = 0; k < outMomenta.size(); ++k ) { for ( vector::ptr>::const_iterator r = jetRegions().begin(); r != jetRegions().end(); ++r ) { if ( (**r).matches(tCutsPtr(),k+1,outMomenta[k])) { jetMomentum(k+1) = outMomenta[k]; break; } } } } void JetsPlusAnalysis::analyze(ParticleVector& parts, long id, double weight) { clear(); reconstructHardObjects(parts); reconstructJets(parts); for ( map::const_iterator h = theHardObjects.begin(); h != theHardObjects.end(); ++h ) { hardObjectProperties(h->first).count(h->second,weight,id); map::const_iterator g = h; ++g; for ( ; g != theHardObjects.end(); ++g ) { hardPairProperties(h->first,g->first).count(h->second,g->second,weight,id); } } unsigned int njets = 0; Energy jetSummedPerp = ZERO; double jetSummedRapidity = 0.0; double jetSummedPhi = 0.0; Energy jetSummedM = ZERO; nJetsInclusive().count(Statistics::EventContribution(njets,weight,0.0),id); if ( njets == theJets.size() ) nJetsExclusive().count(Statistics::EventContribution(njets,weight,0.0),id); for ( map::const_iterator h = theJets.begin(); h != theJets.end(); ++h ) { njets += 1; jetProperties(h->first).count(h->second,weight,id); jetInclusiveProperties().count(h->second,weight,id); nJetsInclusive().count(Statistics::EventContribution(njets,weight,0.0),id); if ( njets == theJets.size() ) { exclusiveJetProperties(h->first).count(h->second,weight,id); nJetsExclusive().count(Statistics::EventContribution(njets,weight,0.0),id); } jetSummedPerp += h->second.perp(); jetSummedRapidity += h->second.rapidity(); jetSummedPhi += h->second.phi(); jetSummedM += h->second.m(); map::const_iterator g = h; ++g; for ( ; g != theJets.end(); ++g ) { jetPairProperties(h->first,g->first).count(h->second,g->second,weight,id); map::const_iterator g1 = g; ++g1; for ( ; g1 != theJets.end(); ++g1 ) { LorentzMomentum p123 = h->second + g->second + g1->second; threeJetProperties(h->first,g->first,g1->first).count(p123,weight,id); map::const_iterator g2 = g1; ++g2; for ( ; g2 != theJets.end(); ++g2 ) { LorentzMomentum p1234 = h->second + g->second + g1->second + g2->second; fourJetProperties(h->first,g->first,g1->first,g2->first).count(p1234,weight,id); } } } } if ( njets > 0 ) jetSummedProperties().count(jetSummedPerp,jetSummedRapidity, jetSummedPhi,jetSummedM, weight,id); if ( njets > 0 ) jetAverageProperties().count(jetSummedPerp/njets,jetSummedRapidity/njets, jetSummedPhi/njets,jetSummedM/njets, weight,id); for ( map::const_iterator h = theHardObjects.begin(); h != theHardObjects.end(); ++h ) { for ( map::const_iterator g = theJets.begin(); g != theJets.end(); ++g ) { jetHardPairProperties(g->first,h->first).count(g->second,h->second,weight,id); } } analyzeSpecial(id,weight); } void JetsPlusAnalysis::analyze(tEventPtr event, long ieve, int, int) { // doing nothing // AnalysisHandler::analyze(event, ieve, loop, state); Ptr::tptr seh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); Ptr::tptr sampler = dynamic_ptr_cast::tptr>(seh->sampler()); double norm = sampler->maxXSec()/picobarn; if ( !theIsShowered ) { tSubProPtr sub = event->primarySubProcess(); Ptr::tptr grp = dynamic_ptr_cast::tptr>(sub); ParticleVector hfs = sub->outgoing(); analyze(hfs,ieve,norm*event->weight()*sub->groupWeight()); if ( grp ) { for ( SubProcessVector::const_iterator s = grp->dependent().begin(); s != grp->dependent().end(); ++s ) { ParticleVector fs = (**s).outgoing(); analyze(fs,ieve,norm*event->weight()*(**s).groupWeight()); } } } else { ParticleVector fs; event->getFinalState(fs); analyze(fs,ieve,norm*event->weight()); } } void JetsPlusAnalysis::dofinish() { AnalysisHandler::dofinish(); Ptr::tptr seh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); Ptr::tptr sampler = dynamic_ptr_cast::tptr>(seh->sampler()); unsigned long attemptedPoints = sampler->attempts(); double sumOfWeights = sampler->sumWeights(); double sumOfSquaredWeights = sampler->sumWeights2(); CrossSection maxXSection = sampler->maxXSec(); XML::Element elem(XML::ElementTypes::Element,"Run"); elem.appendAttribute("name",generator()->runName()); elem.appendAttribute("attemptedPoints",attemptedPoints); elem.appendAttribute("sumOfWeights",sumOfWeights*maxXSection/picobarn); elem.appendAttribute("sumOfSquaredWeights",sumOfSquaredWeights*sqr(maxXSection/picobarn)); XML::Element xhistos(XML::ElementTypes::Element,"Histograms"); for ( map::iterator h = theHardObjectProperties.begin(); h != theHardObjectProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map::iterator h = theJetProperties.begin(); h != theJetProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map::iterator h = theExclusiveJetProperties.begin(); h != theExclusiveJetProperties.end(); ++h ) { h->second.finalize(xhistos); } if ( !theJetInclusiveProperties.pt.bins().empty() ) { theJetInclusiveProperties.finalize(xhistos); } if ( !theJetSummedProperties.pt.bins().empty() ) { theJetSummedProperties.finalize(xhistos); } if ( !theJetAverageProperties.pt.bins().empty() ) { theJetAverageProperties.finalize(xhistos); } if ( !theNJetsInclusive.bins().empty() ) { theNJetsInclusive.finalize(); xhistos.append(theNJetsInclusive.toXML()); } if ( !theNJetsExclusive.bins().empty() ) { theNJetsExclusive.finalize(); xhistos.append(theNJetsExclusive.toXML()); } for ( map,PairProperties>::iterator h = theHardPairProperties.begin(); h != theHardPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theJetPairProperties.begin(); h != theJetPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theJetHardPairProperties.begin(); h != theJetHardPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,ObjectProperties>::iterator h = theThreeJetProperties.begin(); h != theThreeJetProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,ObjectProperties>::iterator h = theFourJetProperties.begin(); h != theFourJetProperties.end(); ++h ) { h->second.finalize(xhistos); } finalize(xhistos); elem.append(xhistos); string fname = generator()->filename() + string("-") + name() + string(".xml"); ofstream runXML(fname.c_str()); runXML << setprecision(16); XML::ElementIO::put(elem,runXML); } IBPtr JetsPlusAnalysis::clone() const { return new_ptr(*this); } IBPtr JetsPlusAnalysis::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void JetsPlusAnalysis::persistentOutput(PersistentOStream & os) const { os << theIsShowered << theJetFinder << theJetRegions; } void JetsPlusAnalysis::persistentInput(PersistentIStream & is, int) { is >> theIsShowered >> theJetFinder >> theJetRegions; } // *** 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 describeHerwigJetsPlusAnalysis("Herwig::JetsPlusAnalysis", "JetCuts.so HwJetsAnalysis.so"); void JetsPlusAnalysis::Init() { static ClassDocumentation documentation ("There is no documentation for the JetsPlusAnalysis class"); static Reference interfaceJetFinder ("JetFinder", "", &JetsPlusAnalysis::theJetFinder, false, false, true, false, false); static RefVector interfaceJetRegions ("JetRegions", "", &JetsPlusAnalysis::theJetRegions, -1, false, false, true, false, false); static Switch interfaceIsShowered ("IsShowered", "", &JetsPlusAnalysis::theIsShowered, false, false, false); static SwitchOption interfaceIsShoweredYes (interfaceIsShowered, "Yes", "", true); static SwitchOption interfaceIsShoweredNo (interfaceIsShowered, "No", "", false); } diff --git a/Analysis/JetsPlusAnalysis.h b/Analysis/JetsPlusAnalysis.h --- a/Analysis/JetsPlusAnalysis.h +++ b/Analysis/JetsPlusAnalysis.h @@ -1,659 +1,651 @@ // -*- C++ -*- #ifndef Herwig_JetsPlusAnalysis_H #define Herwig_JetsPlusAnalysis_H // // This is the declaration of the JetsPlusAnalysis 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" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the JetsPlusAnalysis class. * * @see \ref JetsPlusAnalysisInterfaces "The interfaces" * defined for JetsPlusAnalysis. */ class JetsPlusAnalysis: public AnalysisHandler { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ JetsPlusAnalysis(); - /** - * The destructor. - */ - virtual ~JetsPlusAnalysis(); - //@} - 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 hard objects and jets for the next event */ void clear() { theHardObjects.clear(); theJets.clear(); } /** * Reconstruct the desired electroweak objects and fill the * respective momenta. Remove the reconstructed particles from the * list. */ virtual void reconstructHardObjects(ParticleVector&) {} /** * Set the momentum of the indicated electroweak object. */ LorentzMomentum& hardObjectMomentum(const string& id) { return theHardObjects[id]; } /** * Reconstruct the jets and fill the respective momenta. */ virtual void reconstructJets(const ParticleVector&); /** * The jet finder to use */ Ptr::tptr jetFinder() const { return theJetFinder; } /** * The jet regions to match. */ const vector::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]; } 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 pt_logx; /** * Rapidity */ Statistics::Histogram y; /** * Azimuth */ Statistics::Histogram phi; /** * Mass */ Statistics::Histogram mass; /** * Default constructor */ ObjectProperties() {} /** * Construct given Ecm */ ObjectProperties(const string& name, Energy) : pt(name + "Pt",Statistics::Histogram::regularBinEdges(0,1000,1000),true,false), pt_logx(name + "PtLogX",Statistics::Histogram::logBinEdges(0.1,1000,1000),true,false), y(name + "Y",Statistics::Histogram::regularBinEdges(-6,6,120),false,false), phi(name + "Phi",Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,32), make_pair(-Constants::pi,Constants::pi)), mass(name + "Mass",Statistics::Histogram::regularBinEdges(0,1000,1000),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,1.),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,1.),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,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,1.),id); } /** * Convert to XML */ void finalize(XML::Element& elem) { pt.finalize(); elem.append(pt.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()); } }; /** * 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()); } }; private: /** * Switch between fixed order and showered */ bool theIsShowered; /** * The jet finder to use */ Ptr::ptr theJetFinder; /** * The jet regions to match. */ vector::ptr> theJetRegions; /** * The reconstructed hard objects. */ map theHardObjects; /** * The reconstructed jets */ map theJets; /** * Hard object properties */ map theHardObjectProperties; /** * Jet properties */ map theJetProperties; /** * Exclusive jet properties */ map 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; /** * Hard object pair properties */ map,PairProperties> theHardPairProperties; /** * Jet pair properties */ map,PairProperties> theJetPairProperties; /** * Jet/hard pair properties */ map,PairProperties> theJetHardPairProperties; /** * Trijet properties */ map,ObjectProperties> theThreeJetProperties; /** * Fourjet properties */ map,ObjectProperties> theFourJetProperties; protected: /** * Hard object properties */ ObjectProperties& hardObjectProperties(const string& id) { map::iterator h = theHardObjectProperties.find(id); if ( h != theHardObjectProperties.end() ) return h->second; return theHardObjectProperties[id] = ObjectProperties(id,generator()->maximumCMEnergy()); } /** * Jet properties */ ObjectProperties& jetProperties(const unsigned int id) { map::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::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); } /** * Hard object pair properties */ PairProperties& hardPairProperties(const string& id, const string& jd) { map,PairProperties>::iterator h = theHardPairProperties.find(make_pair(id,jd)); if ( h != theHardPairProperties.end() ) return h->second; return theHardPairProperties[make_pair(id,jd)] = PairProperties(id+jd,generator()->maximumCMEnergy()); } /** * Jet pair properties */ PairProperties& jetPairProperties(const unsigned int id, const unsigned int jd) { map,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/hard pair properties */ PairProperties& jetHardPairProperties(const unsigned int id, const string& jd) { map,PairProperties>::iterator h = theJetHardPairProperties.find(make_pair(id,jd)); if ( h != theJetHardPairProperties.end() ) return h->second; ostringstream ids; ids << "Jet" << id << jd; return theJetHardPairProperties[make_pair(id,jd)] = PairProperties(ids.str(),generator()->maximumCMEnergy()); } /** * Trijet properties */ ObjectProperties& threeJetProperties(const unsigned int id1, const unsigned int id2, const unsigned int id3) { map,ObjectProperties>::iterator it = theThreeJetProperties.find(std::tuple(id1,id2,id3)); if ( it != theThreeJetProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << id3; return theThreeJetProperties[std::tuple(id1,id2,id3)] = ObjectProperties(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,ObjectProperties>::iterator it = theFourJetProperties.find(std::tuple(id1,id2,id3,id4)); if ( it != theFourJetProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << id3 << id4; return theFourJetProperties[std::tuple(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. */ JetsPlusAnalysis & operator=(const JetsPlusAnalysis &) = delete; }; } #endif /* Herwig_JetsPlusAnalysis_H */ diff --git a/Analysis/LeptonsJetsAnalysis.cc b/Analysis/LeptonsJetsAnalysis.cc --- a/Analysis/LeptonsJetsAnalysis.cc +++ b/Analysis/LeptonsJetsAnalysis.cc @@ -1,611 +1,609 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the LeptonsJetsAnalysis class. // #include "LeptonsJetsAnalysis.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/EventRecord/SubProcessGroup.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "Herwig/Sampling/GeneralSampler.h" #include "Herwig/Utilities/XML/ElementIO.h" using namespace Herwig; LeptonsJetsAnalysis::LeptonsJetsAnalysis() : theIsShowered(false), theApplyCuts(false) {} -LeptonsJetsAnalysis::~LeptonsJetsAnalysis() {} - #ifndef LWH_AIAnalysisFactory_H #ifndef LWH #define LWH ThePEGLWH #endif #include "ThePEG/Analysis/LWH/AnalysisFactory.h" #endif struct SortPt { inline bool operator()(const LorentzMomentum& a, const LorentzMomentum& b) const { return a.perp() > b.perp(); } }; struct SortId { inline bool operator()(const pair& a, const pair& b) const { // sort by abs(pid); if equal, first particle, then antiparticle // this puts pairs forming bosons next to each other long p1 = a.first; long p2 = b.first; if (abs(p1)==abs(p2)) { return p1 > p2; } else { return abs(p1) < abs(p2); } } }; void LeptonsJetsAnalysis::reconstructJets(const ParticleVector& parts) { tcPDVector outType; vector outMomenta; for ( ParticleVector::const_iterator p = parts.begin(); p != parts.end(); ++p ) { outType.push_back((**p).dataPtr()); outMomenta.push_back((**p).momentum()); } jetFinder()->cluster(outType, outMomenta, tcCutsPtr(), tcPDPtr(),tcPDPtr()); sort(outMomenta.begin(),outMomenta.end(),SortPt()); for ( vector::ptr>::iterator j = theJetRegions.begin(); j != theJetRegions.end(); ++j ) (**j).reset(); for ( size_t k = 0; k < outMomenta.size(); ++k ) { for ( vector::ptr>::const_iterator r = jetRegions().begin(); r != jetRegions().end(); ++r ) { if ( (**r).matches(tCutsPtr(),k+1,outMomenta[k])) { jetMomentum(k+1) = outMomenta[k]; break; } } } } void LeptonsJetsAnalysis::reconstructEWParticles(ParticleVector& parts) { vector< pair > partall; vector partl, partnu, parth; LorentzMomentum ptmiss = LorentzMomentum(ZERO,ZERO,ZERO,ZERO); ParticleVector::iterator p = parts.begin(); while (p != parts.end()) { PID pid = (**p).id(); if ( ( static_cast(pid) == ParticleID::eminus ) || ( static_cast(pid) == ParticleID::eplus ) || ( static_cast(pid) == ParticleID::muminus ) || ( static_cast(pid) == ParticleID::muplus ) || ( static_cast(pid) == ParticleID::tauminus ) || ( static_cast(pid) == ParticleID::tauplus ) ) { partall.push_back(pair(pid,(**p).momentum())); partl.push_back((**p).momentum()); p = parts.erase(p); } else if ( ( static_cast(pid) == ParticleID::nu_e ) || ( static_cast(pid) == ParticleID::nu_ebar ) || ( static_cast(pid) == ParticleID::nu_mu ) || ( static_cast(pid) == ParticleID::nu_mubar ) || ( static_cast(pid) == ParticleID::nu_tau ) || ( static_cast(pid) == ParticleID::nu_taubar ) ) { partall.push_back(pair(pid,(**p).momentum())); partnu.push_back((**p).momentum()); ptmiss += (**p).momentum(); p = parts.erase(p); } else if ( static_cast(pid) == ParticleID::h0 ) { partall.push_back(pair(pid,(**p).momentum())); parth.push_back((**p).momentum()); p = parts.erase(p); } else p++; } sort(partall.begin(),partall.end(),SortId()); sort(partl.begin(),partl.end(),SortPt()); sort(partnu.begin(),partnu.end(),SortPt()); sort(parth.begin(),parth.end(),SortPt()); // make missing transverse momentum transverse and also add as last entry in EWID ptmiss.setE(ptmiss.perp()); ptmiss.setZ(0*GeV); partall.push_back(pair(ParticleID::nu_e,ptmiss)); for ( size_t k = 0; k < partall.size(); ++k ) eWIDMomentum(k+1) = partall[k].second; for ( size_t k = 0; k < partl.size(); ++k ) chargedLeptonMomentum(k+1) = partl[k]; for ( size_t k = 0; k < partnu.size(); ++k ) neutrinoMomentum(k+1) = partnu[k]; for ( size_t k = 0; k < parth.size(); ++k ) higgsMomentum(k+1) = parth[k]; pTmissMomentum() = ptmiss; } void LeptonsJetsAnalysis::analyze(ParticleVector& parts, long id, double weight) { clear(); reconstructEWParticles(parts); reconstructJets(parts); if ( theApplyCuts ) { // VBF cuts if ( nJets()<2 ) return; if ( (jetMomentum(1)+jetMomentum(2)).m() < 600*GeV ) return; if ( abs(jetMomentum(1).rapidity()-jetMomentum(2).rapidity()) < 3.6 ) return; // if ( jetMomentum(1).rapidity()*jetMomentum(2).rapidity() > 0 ) return; for ( map::const_iterator h = theChargedLeptons.begin(); h != theChargedLeptons.end(); ++h ) { if ( h->second.perp() < 20*GeV ) return; if ( abs(h->second.rapidity()) > 2.5 ) return; } } unsigned int njets = 0; Energy jetSummedPerp = ZERO; double jetSummedRapidity = 0.0; double jetSummedPhi = 0.0; Energy jetSummedM = ZERO; nJetsInclusive().count(Statistics::EventContribution(njets,weight,0.0),id); if ( njets == theJets.size() ) nJetsExclusive().count(Statistics::EventContribution(njets,weight,0.0),id); for ( map::const_iterator h = theJets.begin(); h != theJets.end(); ++h ) { njets += 1; jetProperties(h->first).count(h->second,weight,id); jetInclusiveProperties().count(h->second,weight,id); nJetsInclusive().count(Statistics::EventContribution(njets,weight,0.0),id); if ( njets == theJets.size() ) { exclusiveJetProperties(h->first).count(h->second,weight,id); nJetsExclusive().count(Statistics::EventContribution(njets,weight,0.0),id); } jetSummedPerp += h->second.perp(); jetSummedRapidity += h->second.rapidity(); jetSummedPhi += h->second.phi(); jetSummedM += h->second.m(); map::const_iterator g = h; ++g; for ( ; g != theJets.end(); ++g ) { jetPairProperties(h->first,g->first).count(h->second,g->second,weight,id); map::const_iterator g1 = g; ++g1; for ( ; g1 != theJets.end(); ++g1 ) { threeJetProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id); map::const_iterator g2 = g1; ++g2; for ( ; g2 != theJets.end(); ++g2 ) { LorentzMomentum p1234 = h->second + g->second + g1->second + g2->second; fourJetProperties(h->first,g->first,g1->first,g2->first).count(p1234,weight,id); } } for ( map::const_iterator g1 = theEWIDs.begin(); g1 != theEWIDs.end(); ++g1 ) jetPairEWIDTripleProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id); for ( map::const_iterator g1 = theChargedLeptons.begin(); g1 != theChargedLeptons.end(); ++g1 ) jetPairChargedLeptonTripleProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id); for ( map::const_iterator g1 = theNeutrinos.begin(); g1 != theNeutrinos.end(); ++g1 ) jetPairNeutrinoTripleProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id); jetPairPTmissTripleProperties(h->first,g->first).count(h->second,g->second,pTmissMomentum(),weight,id); for ( map::const_iterator g1 = theHiggs.begin(); g1 != theHiggs.end(); ++g1 ) jetPairHiggsTripleProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id); } for ( map::const_iterator g = theEWIDs.begin(); g != theEWIDs.end(); ++g ) jetEWIDPairProperties(h->first,g->first).count(h->second,g->second,weight,id); for ( map::const_iterator g = theChargedLeptons.begin(); g != theChargedLeptons.end(); ++g ) jetChargedLeptonPairProperties(h->first,g->first).count(h->second,g->second,weight,id); for ( map::const_iterator g = theNeutrinos.begin(); g != theNeutrinos.end(); ++g ) jetNeutrinoPairProperties(h->first,g->first).count(h->second,g->second,weight,id); jetPTmissPairProperties(h->first).count(h->second,pTmissMomentum(),weight,id); for ( map::const_iterator g = theHiggs.begin(); g != theHiggs.end(); ++g ) jetHiggsPairProperties(h->first,g->first).count(h->second,g->second,weight,id); } if ( njets > 0 ) jetSummedProperties().count(jetSummedPerp,jetSummedRapidity, jetSummedPhi,jetSummedM, weight,id); if ( njets > 0 ) jetAverageProperties().count(jetSummedPerp/njets,jetSummedRapidity/njets, jetSummedPhi/njets,jetSummedM/njets, weight,id); for ( map::const_iterator h = theEWIDs.begin(); h != theEWIDs.end(); ++h ) { eWIDProperties(h->first).count(h->second,weight,id); map::const_iterator g = h; ++g; for ( ; g != theEWIDs.end(); ++g ) { eWIDPairProperties(h->first,g->first).count(h->second,g->second,weight,id); map::const_iterator g1 = g; ++g1; for ( ; g1 != theEWIDs.end(); ++g1 ) { threeEWIDProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id); map::const_iterator g2 = g1; ++g2; for ( ; g2 != theEWIDs.end(); ++g2 ) { LorentzMomentum p1234 = h->second + g->second + g1->second + g2->second; fourEWIDProperties(h->first,g->first,g1->first,g2->first).count(p1234,weight,id); } } } } for ( map::const_iterator h = theChargedLeptons.begin(); h != theChargedLeptons.end(); ++h ) { chargedLeptonProperties(h->first).count(h->second,weight,id); map::const_iterator g = h; ++g; for ( ; g != theChargedLeptons.end(); ++g ) { chargedLeptonPairProperties(h->first,g->first).count(h->second,g->second,weight,id); map::const_iterator g1 = g; ++g1; for ( ; g1 != theChargedLeptons.end(); ++g1 ) { threeChargedLeptonProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id); map::const_iterator g2 = g1; ++g2; for ( ; g2 != theChargedLeptons.end(); ++g2 ) { LorentzMomentum p1234 = h->second + g->second + g1->second + g2->second; fourChargedLeptonProperties(h->first,g->first,g1->first,g2->first).count(p1234,weight,id); } } } } for ( map::const_iterator h = theNeutrinos.begin(); h != theNeutrinos.end(); ++h ) { neutrinoProperties(h->first).count(h->second,weight,id); } pTmissProperties().count(pTmissMomentum(),weight,id); for ( map::const_iterator h = theHiggs.begin(); h != theHiggs.end(); ++h ) { higgsProperties(h->first).count(h->second,weight,id); } analyzeSpecial(id,weight); } void LeptonsJetsAnalysis::analyze(tEventPtr event, long ieve, int loop, int state) { AnalysisHandler::analyze(event, ieve, loop, state); Ptr::tptr seh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); Ptr::tptr sampler = dynamic_ptr_cast::tptr>(seh->sampler()); double norm = sampler->maxXSec()/picobarn; if ( !theIsShowered ) { tSubProPtr sub = event->primarySubProcess(); Ptr::tptr grp = dynamic_ptr_cast::tptr>(sub); ParticleVector hfs = sub->outgoing(); analyze(hfs,ieve,norm*event->weight()*sub->groupWeight()); if ( grp ) { for ( SubProcessVector::const_iterator s = grp->dependent().begin(); s != grp->dependent().end(); ++s ) { ParticleVector fs = (**s).outgoing(); analyze(fs,ieve,norm*event->weight()*(**s).groupWeight()); } } } else { ParticleVector fs; event->getFinalState(fs); analyze(fs,ieve,norm*event->weight()); } } void LeptonsJetsAnalysis::dofinish() { AnalysisHandler::dofinish(); Ptr::tptr seh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); Ptr::tptr sampler = dynamic_ptr_cast::tptr>(seh->sampler()); unsigned long attemptedPoints = sampler->attempts(); double sumOfWeights = sampler->sumWeights(); double sumOfSquaredWeights = sampler->sumWeights2(); CrossSection maxXSection = sampler->maxXSec(); XML::Element elem(XML::ElementTypes::Element,"Run"); elem.appendAttribute("name",generator()->runName()); elem.appendAttribute("attemptedPoints",attemptedPoints); elem.appendAttribute("sumOfWeights",sumOfWeights*maxXSection/picobarn); elem.appendAttribute("sumOfSquaredWeights",sumOfSquaredWeights*sqr(maxXSection/picobarn)); XML::Element xhistos(XML::ElementTypes::Element,"Histograms"); for ( map::iterator h = theJetProperties.begin(); h != theJetProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map::iterator h = theExclusiveJetProperties.begin(); h != theExclusiveJetProperties.end(); ++h ) { h->second.finalize(xhistos); } if ( !theJetInclusiveProperties.pt.bins().empty() ) { theJetInclusiveProperties.finalize(xhistos); } if ( !theJetSummedProperties.pt.bins().empty() ) { theJetSummedProperties.finalize(xhistos); } if ( !theJetAverageProperties.pt.bins().empty() ) { theJetAverageProperties.finalize(xhistos); } if ( !theNJetsInclusive.bins().empty() ) { theNJetsInclusive.finalize(); xhistos.append(theNJetsInclusive.toXML()); } if ( !theNJetsExclusive.bins().empty() ) { theNJetsExclusive.finalize(); xhistos.append(theNJetsExclusive.toXML()); } for ( map::iterator h = theEWIDProperties.begin(); h != theEWIDProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map::iterator h = theChargedLeptonProperties.begin(); h != theChargedLeptonProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map::iterator h = theNeutrinoProperties.begin(); h != theNeutrinoProperties.end(); ++h ) { h->second.finalize(xhistos); } thePTmissProperties.finalize(xhistos); for ( map::iterator h = theHiggsProperties.begin(); h != theHiggsProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theJetPairProperties.begin(); h != theJetPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theJetEWIDPairProperties.begin(); h != theJetEWIDPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theJetChargedLeptonPairProperties.begin(); h != theJetChargedLeptonPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theJetNeutrinoPairProperties.begin(); h != theJetNeutrinoPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map::iterator h = theJetPTmissPairProperties.begin(); h != theJetPTmissPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theJetHiggsPairProperties.begin(); h != theJetHiggsPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theEWIDPairProperties.begin(); h != theEWIDPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,PairProperties>::iterator h = theChargedLeptonPairProperties.begin(); h != theChargedLeptonPairProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,TripleProperties>::iterator h = theThreeJetProperties.begin(); h != theThreeJetProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,TripleProperties>::iterator h = theJetPairEWIDTripleProperties.begin(); h != theJetPairEWIDTripleProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,TripleProperties>::iterator h = theJetPairChargedLeptonTripleProperties.begin(); h != theJetPairChargedLeptonTripleProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,TripleProperties>::iterator h = theJetPairNeutrinoTripleProperties.begin(); h != theJetPairNeutrinoTripleProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,TripleProperties>::iterator h = theJetPairPTmissTripleProperties.begin(); h != theJetPairPTmissTripleProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,TripleProperties>::iterator h = theJetPairHiggsTripleProperties.begin(); h != theJetPairHiggsTripleProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,TripleProperties>::iterator h = theThreeEWIDProperties.begin(); h != theThreeEWIDProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,TripleProperties>::iterator h = theThreeChargedLeptonProperties.begin(); h != theThreeChargedLeptonProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,ObjectProperties>::iterator h = theFourJetProperties.begin(); h != theFourJetProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,ObjectProperties>::iterator h = theFourEWIDProperties.begin(); h != theFourEWIDProperties.end(); ++h ) { h->second.finalize(xhistos); } for ( map,ObjectProperties>::iterator h = theFourChargedLeptonProperties.begin(); h != theFourChargedLeptonProperties.end(); ++h ) { h->second.finalize(xhistos); } finalize(xhistos); elem.append(xhistos); string fname = generator()->filename() + string("-") + name() + string(".xml"); ofstream runXML(fname.c_str()); runXML << setprecision(16); XML::ElementIO::put(elem,runXML); } IBPtr LeptonsJetsAnalysis::clone() const { return new_ptr(*this); } IBPtr LeptonsJetsAnalysis::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void LeptonsJetsAnalysis::persistentOutput(PersistentOStream & os) const { os << theIsShowered << theApplyCuts << theJetFinder << theJetRegions; } void LeptonsJetsAnalysis::persistentInput(PersistentIStream & is, int) { is >> theIsShowered >> theApplyCuts >> theJetFinder >> theJetRegions; } // *** 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 describeHerwigLeptonsJetsAnalysis("Herwig::LeptonsJetsAnalysis", "JetCuts.so HwJetsAnalysis.so"); void LeptonsJetsAnalysis::Init() { static ClassDocumentation documentation ("General-purpose analysis for processes with jets and leptons"); static Reference interfaceJetFinder ("JetFinder", "", &LeptonsJetsAnalysis::theJetFinder, false, false, true, false, false); static RefVector interfaceJetRegions ("JetRegions", "", &LeptonsJetsAnalysis::theJetRegions, -1, false, false, true, false, false); static Switch interfaceIsShowered ("IsShowered", "", &LeptonsJetsAnalysis::theIsShowered, false, false, false); static SwitchOption interfaceIsShoweredYes (interfaceIsShowered, "Yes", "", true); static SwitchOption interfaceIsShoweredNo (interfaceIsShowered, "No", "", false); static Switch interfaceApplyCuts ("ApplyCuts", "", &LeptonsJetsAnalysis::theApplyCuts, false, false, false); static SwitchOption interfaceApplyCutsYes (interfaceApplyCuts, "Yes", "", true); static SwitchOption interfaceApplyCutsNo (interfaceApplyCuts, "No", "", false); } diff --git a/Analysis/LeptonsJetsAnalysis.h b/Analysis/LeptonsJetsAnalysis.h --- a/Analysis/LeptonsJetsAnalysis.h +++ b/Analysis/LeptonsJetsAnalysis.h @@ -1,1137 +1,1129 @@ // -*- 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" 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::tptr jetFinder() const { return theJetFinder; } /** * The jet regions to match. */ const vector::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), 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::ptr theJetFinder; /** * The jet regions to match. */ vector::ptr> theJetRegions; /** * The reconstructed jets */ map theJets; /** * The reconstructed electroweak particles */ map theEWIDs; /** * The reconstructed charged leptons */ map theChargedLeptons; /** * The reconstructed neutrinos */ map theNeutrinos; /** * The reconstructed missing pT */ LorentzMomentum thePTmiss; /** * The reconstructed Higgs */ map theHiggs; /** * Jet properties */ map theJetProperties; /** * Exclusive jet properties */ map 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 theEWIDProperties; /** * Charged lepton properties */ map theChargedLeptonProperties; /** * Neutrino properties */ map theNeutrinoProperties; /** * missing pT properties */ ObjectProperties thePTmissProperties; /** * Higgs properties */ map theHiggsProperties; /** * Jet pair properties */ map,PairProperties> theJetPairProperties; /** * Jet/electroweak pair properties */ map,PairProperties> theJetEWIDPairProperties; /** * Jet/charged lepton pair properties */ map,PairProperties> theJetChargedLeptonPairProperties; /** * Jet/neutrino pair properties */ map,PairProperties> theJetNeutrinoPairProperties; /** * Jet/missing pT pair properties */ map theJetPTmissPairProperties; /** * Jet/Higgs pair properties */ map,PairProperties> theJetHiggsPairProperties; /** * Electroweak pair properties */ map,PairProperties> theEWIDPairProperties; /** * Charged lepton pair properties */ map,PairProperties> theChargedLeptonPairProperties; /** * Trijet properties */ map,TripleProperties> theThreeJetProperties; /** * Jet-pair/electroweak triple properties */ map,TripleProperties> theJetPairEWIDTripleProperties; /** * Jet-pair/charged lepton triple properties */ map,TripleProperties> theJetPairChargedLeptonTripleProperties; /** * Jet-pair/neutrino triple properties */ map,TripleProperties> theJetPairNeutrinoTripleProperties; /** * Jet-pair/missing pT triple properties */ map,TripleProperties> theJetPairPTmissTripleProperties; /** * Jet-pair/Higgs triple properties */ map,TripleProperties> theJetPairHiggsTripleProperties; /** * Triple electroweak properties */ map,TripleProperties> theThreeEWIDProperties; /** * Triple charged lepton properties */ map,TripleProperties> theThreeChargedLeptonProperties; /** * Fourjet properties */ map,ObjectProperties> theFourJetProperties; /** * Four electroweak properties */ map,ObjectProperties> theFourEWIDProperties; /** * Four charged lepton properties */ map,ObjectProperties> theFourChargedLeptonProperties; protected: /** * Jet properties */ ObjectProperties& jetProperties(const unsigned int id) { map::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::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::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::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::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::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,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,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,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,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::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,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,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,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,TripleProperties>::iterator it = theThreeJetProperties.find(std::tuple(id1,id2,id3)); if ( it != theThreeJetProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << id3; return theThreeJetProperties[std::tuple(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,TripleProperties>::iterator it = theJetPairEWIDTripleProperties.find(std::tuple(id1,id2,id3)); if ( it != theJetPairEWIDTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "EWID" << id3; return theJetPairEWIDTripleProperties[std::tuple(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,TripleProperties>::iterator it = theJetPairChargedLeptonTripleProperties.find(std::tuple(id1,id2,id3)); if ( it != theJetPairChargedLeptonTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "ChargedLepton" << id3; return theJetPairChargedLeptonTripleProperties[std::tuple(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,TripleProperties>::iterator it = theJetPairNeutrinoTripleProperties.find(std::tuple(id1,id2,id3)); if ( it != theJetPairNeutrinoTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "Neutrino" << id3; return theJetPairNeutrinoTripleProperties[std::tuple(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,TripleProperties>::iterator it = theJetPairPTmissTripleProperties.find(pair(id1,id2)); if ( it != theJetPairPTmissTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "PTmiss"; return theJetPairPTmissTripleProperties[pair(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,TripleProperties>::iterator it = theJetPairHiggsTripleProperties.find(std::tuple(id1,id2,id3)); if ( it != theJetPairHiggsTripleProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << "Higgs" << id3; return theJetPairHiggsTripleProperties[std::tuple(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,TripleProperties>::iterator it = theThreeEWIDProperties.find(std::tuple(id1,id2,id3)); if ( it != theThreeEWIDProperties.end() ) return it->second; ostringstream ids; ids << "EWID" << id1 << id2 << id3; return theThreeEWIDProperties[std::tuple(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,TripleProperties>::iterator it = theThreeChargedLeptonProperties.find(std::tuple(id1,id2,id3)); if ( it != theThreeChargedLeptonProperties.end() ) return it->second; ostringstream ids; ids << "ChargedLepton" << id1 << id2 << id3; return theThreeChargedLeptonProperties[std::tuple(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,ObjectProperties>::iterator it = theFourJetProperties.find(std::tuple(id1,id2,id3,id4)); if ( it != theFourJetProperties.end() ) return it->second; ostringstream ids; ids << "Jet" << id1 << id2 << id3 << id4; return theFourJetProperties[std::tuple(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,ObjectProperties>::iterator it = theFourEWIDProperties.find(std::tuple(id1,id2,id3,id4)); if ( it != theFourEWIDProperties.end() ) return it->second; ostringstream ids; ids << "EWID" << id1 << id2 << id3 << id4; return theFourEWIDProperties[std::tuple(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,ObjectProperties>::iterator it = theFourChargedLeptonProperties.find(std::tuple(id1,id2,id3,id4)); if ( it != theFourChargedLeptonProperties.end() ) return it->second; ostringstream ids; ids << "ChargedLepton" << id1 << id2 << id3 << id4; return theFourChargedLeptonProperties[std::tuple(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 &) = delete; }; } #endif /* Herwig_LeptonsJetsAnalysis_H */ diff --git a/Analysis/TTJetsAnalysis.cc b/Analysis/TTJetsAnalysis.cc --- a/Analysis/TTJetsAnalysis.cc +++ b/Analysis/TTJetsAnalysis.cc @@ -1,78 +1,76 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the TTJetsAnalysis class. // #include "TTJetsAnalysis.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; TTJetsAnalysis::TTJetsAnalysis() {} -TTJetsAnalysis::~TTJetsAnalysis() {} - IBPtr TTJetsAnalysis::clone() const { return new_ptr(*this); } IBPtr TTJetsAnalysis::fullclone() const { return new_ptr(*this); } void TTJetsAnalysis::reconstructHardObjects(ParticleVector& parts) { ParticleVector::iterator t = parts.begin(); for ( ; t != parts.end(); ++t ) { if ( (**t).id() == ParticleID::t ) break; } if ( t == parts.end() ) throw Exception() << "No ttbar pair found in TTJetsAnalysis" << Exception::abortnow; hardObjectMomentum("T") = (**t).momentum(); parts.erase(t); ParticleVector::iterator tbar = parts.begin(); for ( ; tbar != parts.end(); ++tbar ) { if ( (**tbar).id() == ParticleID::tbar ) break; } if ( tbar == parts.end() ) throw Exception() << "No ttbar pair found in TTJetsAnalysis" << Exception::abortnow; hardObjectMomentum("Tbar") = (**tbar).momentum(); parts.erase(tbar); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void TTJetsAnalysis::persistentOutput(PersistentOStream &) const {} void TTJetsAnalysis::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigTTJetsAnalysis("Herwig::TTJetsAnalysis", "JetCuts.so HwJetsAnalysis.so"); void TTJetsAnalysis::Init() { static ClassDocumentation documentation ("There is no documentation for the TTJetsAnalysis class"); } diff --git a/Analysis/TTJetsAnalysis.h b/Analysis/TTJetsAnalysis.h --- a/Analysis/TTJetsAnalysis.h +++ b/Analysis/TTJetsAnalysis.h @@ -1,106 +1,98 @@ // -*- C++ -*- #ifndef Herwig_TTJetsAnalysis_H #define Herwig_TTJetsAnalysis_H // // This is the declaration of the TTJetsAnalysis class. // #include "Herwig/Analysis/JetsPlusAnalysis.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the TTJetsAnalysis class. * * @see \ref TTJetsAnalysisInterfaces "The interfaces" * defined for TTJetsAnalysis. */ class TTJetsAnalysis: public Herwig::JetsPlusAnalysis { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ TTJetsAnalysis(); - /** - * The destructor. - */ - virtual ~TTJetsAnalysis(); - //@} - public: /** * Reconstruct the desired electroweak objects and fill the * respective momenta. Remove the reconstructed particles from the * list. */ virtual void reconstructHardObjects(ParticleVector&); 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TTJetsAnalysis & operator=(const TTJetsAnalysis &) = delete; }; } #endif /* Herwig_TTJetsAnalysis_H */ diff --git a/Analysis/ZJetsAnalysis.cc b/Analysis/ZJetsAnalysis.cc --- a/Analysis/ZJetsAnalysis.cc +++ b/Analysis/ZJetsAnalysis.cc @@ -1,79 +1,77 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the ZJetsAnalysis class. // #include "ZJetsAnalysis.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; ZJetsAnalysis::ZJetsAnalysis() {} -ZJetsAnalysis::~ZJetsAnalysis() {} - IBPtr ZJetsAnalysis::clone() const { return new_ptr(*this); } IBPtr ZJetsAnalysis::fullclone() const { return new_ptr(*this); } void ZJetsAnalysis::reconstructHardObjects(ParticleVector& parts) { ParticleVector::iterator eplus = parts.begin(); for ( ; eplus != parts.end(); ++eplus ) { if ( (**eplus).id() == ParticleID::eplus ) break; } if ( eplus == parts.end() ) throw Exception() << "No e+e- pair found in ZJetsAnalysis" << Exception::abortnow; LorentzMomentum peplus = (**eplus).momentum(); parts.erase(eplus); ParticleVector::iterator eminus = parts.begin(); for ( ; eminus != parts.end(); ++eminus ) { if ( (**eminus).id() == ParticleID::eminus ) break; } if ( eminus == parts.end() ) throw Exception() << "No e+e- pair found in ZJetsAnalysis" << Exception::abortnow; LorentzMomentum peminus = (**eminus).momentum(); parts.erase(eminus); hardObjectMomentum("Z") = peplus + peminus; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ZJetsAnalysis::persistentOutput(PersistentOStream &) const {} void ZJetsAnalysis::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigZJetsAnalysis("Herwig::ZJetsAnalysis", "JetCuts.so HwJetsAnalysis.so"); void ZJetsAnalysis::Init() { static ClassDocumentation documentation ("There is no documentation for the ZJetsAnalysis class"); } diff --git a/Analysis/ZJetsAnalysis.h b/Analysis/ZJetsAnalysis.h --- a/Analysis/ZJetsAnalysis.h +++ b/Analysis/ZJetsAnalysis.h @@ -1,106 +1,98 @@ // -*- C++ -*- #ifndef Herwig_ZJetsAnalysis_H #define Herwig_ZJetsAnalysis_H // // This is the declaration of the ZJetsAnalysis class. // #include "Herwig/Analysis/JetsPlusAnalysis.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the ZJetsAnalysis class. * * @see \ref ZJetsAnalysisInterfaces "The interfaces" * defined for ZJetsAnalysis. */ class ZJetsAnalysis: public Herwig::JetsPlusAnalysis { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ ZJetsAnalysis(); - /** - * The destructor. - */ - virtual ~ZJetsAnalysis(); - //@} - public: /** * Reconstruct the desired electroweak objects and fill the * respective momenta. Remove the reconstructed particles from the * list. */ virtual void reconstructHardObjects(ParticleVector&); 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ZJetsAnalysis & operator=(const ZJetsAnalysis &) = delete; }; } #endif /* Herwig_ZJetsAnalysis_H */ diff --git a/Decay/BranchingRatioReweighter.cc b/Decay/BranchingRatioReweighter.cc --- a/Decay/BranchingRatioReweighter.cc +++ b/Decay/BranchingRatioReweighter.cc @@ -1,81 +1,79 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the BranchingRatioReweighter class. // #include "BranchingRatioReweighter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/EventRecord/StandardSelectors.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "Herwig/Utilities/EnumParticles.h" using namespace Herwig; BranchingRatioReweighter::BranchingRatioReweighter() {} -BranchingRatioReweighter::~BranchingRatioReweighter() {} - void BranchingRatioReweighter:: handle(EventHandler & eh,const tPVector & ,const Hint & ) { tEventPtr event = eh.currentEvent(); // weight double weight = 1.; // get all the particles set particles; event->select(inserter(particles),ThePEG::AllSelector()); for(set::const_iterator it=particles.begin();it!=particles.end();++it) { // skip stable if((**it).dataPtr()->stable()) continue; // skip remnant and clusters if((**it).id()==ParticleID::Remnant || (**it).id()==ParticleID::Cluster) continue; // if spacelike skip if((**it).mass()incoming().first || *it == event->incoming().second ) continue; // find unique particles bool unique = true; for(unsigned int ix=0;ix<(**it).children().size();++ix) { if((**it).children()[ix]->id()==(**it).id()) { unique = false; break; } } if(!unique) continue; weight *= (**it).dataPtr()->decaySelector().sum(); } // do the reweighting if ( dynamic_cast(&eh) ) { StandardEventHandler& seh = dynamic_cast(eh); seh.reweight(weight); } } IBPtr BranchingRatioReweighter::clone() const { return new_ptr(*this); } IBPtr BranchingRatioReweighter::fullclone() const { return new_ptr(*this); } // The following static variable is needed for the type description system in ThePEG. DescribeNoPIOClass describeHerwigBranchingRatioReweighter("Herwig::BranchingRatioReweighter", "Herwig.so"); void BranchingRatioReweighter::Init() { static ClassDocumentation documentation ("The BranchingRatioReweighter class reweights events if some" " decay modes are switched off"); } diff --git a/Decay/BranchingRatioReweighter.h b/Decay/BranchingRatioReweighter.h --- a/Decay/BranchingRatioReweighter.h +++ b/Decay/BranchingRatioReweighter.h @@ -1,102 +1,94 @@ // -*- C++ -*- #ifndef Herwig_BranchingRatioReweighter_H #define Herwig_BranchingRatioReweighter_H // // This is the declaration of the BranchingRatioReweighter class. // #include "ThePEG/Handlers/StepHandler.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Decay * The BranchingRatioReweighter class is designed to reweight events * where some decay modes of a particle, or many particles, have been * switched off in order to improve the statistics. * * @see \ref BranchingRatioReweighterInterfaces "The interfaces" * defined for BranchingRatioReweighter. */ class BranchingRatioReweighter: public StepHandler { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ BranchingRatioReweighter(); - /** - * The destructor. - */ - virtual ~BranchingRatioReweighter(); - //@} - public: /** @name Virtual functions required by the StepHandler class. */ //@{ /** * The main function called by the EventHandler class to * perform a step. Given the current state of an Event, this function * performs the event generation step and includes the result in a new * Step object int the Event record. * @param eh the EventHandler in charge of the Event generation. * @param tagged if not empty these are the only particles which should * be considered by the StepHandler. * @param hint a Hint object with possible information from previously * performed steps. * @throws Veto if the StepHandler requires the current step to be discarded. * @throws Stop if the generation of the current Event should be stopped * after this call. * @throws Exception if something goes wrong. */ virtual void handle(EventHandler & eh, const tPVector & tagged, const Hint & hint); //@} public: /** * 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; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ BranchingRatioReweighter & operator=(const BranchingRatioReweighter &) = delete; }; } #endif /* Herwig_BranchingRatioReweighter_H */ diff --git a/Decay/Dalitz/DalitzResonance.h b/Decay/Dalitz/DalitzResonance.h --- a/Decay/Dalitz/DalitzResonance.h +++ b/Decay/Dalitz/DalitzResonance.h @@ -1,156 +1,158 @@ // -*- C++ -*- #ifndef Herwig_DalitzResonance_H #define Herwig_DalitzResonance_H // // This is the declaration of the DalitzResonance class. // #include "ThePEG/Config/ThePEG.h" #include "DalitzResonance.fh" #include namespace Herwig { using namespace ThePEG; namespace ResonanceType { /** * Enum for the type of resonace */ enum Type {NonResonant=0, Spin0=1,Spin1=3,Spin2=5, Spin0E691=11,Spin1E691=13,Spin2E691=15, BABARf0=21, Spin0Gauss=31, Flattef0=41, Spin0Complex=51, Flattea0=61, FlatteKstar0=71, Sigma=81, Spin1GS=23, Spin0NonResonant=101, Spin1NonResonant=103, Spin2NonResonant=105, Spin0MIPWA=-1, PiPiI2=-11, KMatrix=-21, LASS=-31}; } /** * The DalitzResonance class provides a container class for * information on resonances in multi-body dalitz decays. */ class DalitzResonance: public Base { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ - DalitzResonance() {} + DalitzResonance() : id(0), type(ResonanceType::NonResonant),mass(ZERO),width(ZERO), + daughter1(0),daughter2(0),spectator(0),amp(0.),R(ZERO) + {} /** * Constructor specifiying the parameters */ DalitzResonance(long pid, ResonanceType::Type rtype, Energy m, Energy w, unsigned int d1, unsigned int d2, unsigned int s, double mag, double phi, InvEnergy rr) : id(pid), type(rtype), mass(m),width(w), daughter1(d1),daughter2(d2),spectator(s), amp(mag*exp(Complex(0,phi))), R(rr) {} //@} public: /** * Return the Breit-Wigner times the form factor */ virtual Complex BreitWigner(const Energy & mAB, const Energy & mA, const Energy & mB) const; /** * Output the parameters */ virtual void dataBaseOutput(ofstream & output); /** * Read the parameters for a Dalitz resonance */ static DalitzResonancePtr readResonance(string arg, string & error); 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(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DalitzResonance & operator=(const DalitzResonance &) = delete; public: /** * PID of resonant particle */ long id; /** * Type of the resonance */ ResonanceType::Type type; /** * Mass of the resonance */ Energy mass; /** * Width of the resonance */ Energy width; /** * The children */ unsigned int daughter1,daughter2; /** * The spectactor */ unsigned int spectator; /** * The amplitude */ Complex amp; /** * Radius for the Ballt-Weisskopf formfactor */ InvEnergy R; }; } #endif /* Herwig_DalitzResonance_H */ diff --git a/Decay/EvtGen/EvtGenInterface.cc b/Decay/EvtGen/EvtGenInterface.cc --- a/Decay/EvtGen/EvtGenInterface.cc +++ b/Decay/EvtGen/EvtGenInterface.cc @@ -1,1020 +1,1018 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the EvtGenInterface class. // #include "EvtGenInterface.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Decay/DecayVertex.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" #include "EvtGenBase/EvtRandom.hh" #include "EvtGenBase/EvtAbsRadCorr.hh" #include "EvtGenExternal/EvtExternalGenList.hh" #include "EvtGenBase/EvtScalarParticle.hh" #include "EvtGenBase/EvtDiracParticle.hh" #include "EvtGenBase/EvtVectorParticle.hh" #include "EvtGenBase/EvtRaritaSchwingerParticle.hh" #include "EvtGenBase/EvtTensorParticle.hh" #include "EvtGenBase/EvtStringParticle.hh" #include "EvtGenBase/EvtHighSpinParticle.hh" #include "EvtGenBase/EvtDecayTable.hh" #ifndef EVTGEN_SHARE #error Makefile.am needs to define EVTGEN_SHARE #endif using namespace Herwig; namespace { const string prefix=EVTGEN_SHARE ""; const string p8data=PYTHIA8DATA ""; } EvtGenInterface::EvtGenInterface() : decayName_(prefix+"/DECAY_2010.DEC"), pdtName_(prefix+"/evt.pdl"), reDirect_(true), checkConv_(false), p8Data_(p8data) {} EvtGenInterface::EvtGenInterface(const EvtGenInterface & x) : Interfaced(x), decayName_(x.decayName_), pdtName_(x.pdtName_), userDecays_(x.userDecays_), reDirect_(x.reDirect_), checkConv_(x.checkConv_), convID_(x.convID_), p8Data_(x.p8Data_), evtrnd_(x.evtrnd_),evtgen_(x.evtgen_) {} -EvtGenInterface::~EvtGenInterface() {} - IBPtr EvtGenInterface::clone() const { return new_ptr(*this); } IBPtr EvtGenInterface::fullclone() const { return new_ptr(*this); } void EvtGenInterface::persistentOutput(PersistentOStream & os) const { os << decayName_ << pdtName_ << reDirect_ << userDecays_ << checkConv_ << convID_ << p8Data_; } void EvtGenInterface::persistentInput(PersistentIStream & is, int) { is >> decayName_ >> pdtName_ >> reDirect_ >> userDecays_ >> checkConv_ >> convID_ >> p8Data_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigEvtGenInterface("Herwig::EvtGenInterface", "HwEvtGenInterface.so"); void EvtGenInterface::Init() { static ClassDocumentation documentation ("The EvtGenInterface class is the main class for the use of the EvtGen " "decay package with Herwig"); static Parameter interfaceDecay_File ("Decay_File", "The name of the file for the EvtGen decays.", &EvtGenInterface::decayName_, prefix+"/share/DECAY_2010.DEC", false, false); static Parameter interfacePDT_File ("PDTFile", "The name of the file for the EvtGen particle data.", &EvtGenInterface::pdtName_, prefix+"/share/evt.pdl", false, false); static Switch interfaceRedirect ("Redirect", "By default cerr and cout are redirected when EvtGen is running to" " allow us to catch errors, due to EvtGen's poor internal error " "handling. This can be a problem for debugging and so can be switched off.", &EvtGenInterface::reDirect_, true, false, false); static SwitchOption interfaceRedirectYes (interfaceRedirect, "Yes", "Redirect the output", true); static SwitchOption interfaceRedirectNo (interfaceRedirect, "No", "Don't redirect the output", false); static Switch interfaceCheckConversion ("CheckConversion", "Check the conversion of particles to and from EvtGen", &EvtGenInterface::checkConv_, false, false, false); static SwitchOption interfaceCheckConversionfalse (interfaceCheckConversion, "No", "Don't check the conversion", false); static SwitchOption interfaceCheckConversionCheck (interfaceCheckConversion, "Yes", "Check the conversion", true); static ParVector interfaceOutputModes ("OutputModes", "Particles for which to output the EvtGen decay modes" " so they can be read into Herwig", &EvtGenInterface::convID_, -1, long(0), 0, 0, false, false, Interface::nolimits); static ParVector interfaceUserDecays ("UserDecays", "List of user decay files to be loaded", &EvtGenInterface::userDecays_, -1, "", "", "", false, false, Interface::nolimits); static Parameter interfacePythia8Data ("Pythia8Data", "Location of the Pythia8 data directory", &EvtGenInterface::p8Data_, p8data, false, false); } void EvtGenInterface::doinitrun() { Interfaced::doinitrun(); // redirect cerr and cout if needed std::streambuf *temp[2]={cout.rdbuf(),cerr.rdbuf()}; if(reDirect_ && ! generator()->useStdOut() ) { const string f = generator()->filename() + "-EvtGen.log"; logFile_.open(f); std::streambuf *psbuf = logFile_.rdbuf(); cout.rdbuf(psbuf); cerr.rdbuf(psbuf); } // output the EvtGen initialization info to the log file cout << "Initializing EvtGen \n"; // set up the random number generator for EvtGen cout << "Setting EvtGen random number generator" << " to the Herwig one.\n"; evtrnd_ = new EvtGenRandom(const_ptr_cast::pointer> (&(UseRandom::current()))); EvtRandom::setRandomEngine(evtrnd_); // PHOTOS STUFF EvtAbsRadCorr* radCorrEngine = 0; std::list extraModels; EvtExternalGenList genList(true,p8Data_,"gamma",true); radCorrEngine = genList.getPhotosModel(); extraModels = genList.getListOfModels(); // Initialize EvtGen evtgen_ = new EvtGen(decayName_.c_str(),pdtName_.c_str(), evtrnd_, radCorrEngine, &extraModels); // additional user decays for(unsigned int ix=0;ixreadUDecay(userDecays_[ix].c_str()); // check the conversion of particles if needed if(checkConv_) checkConversion(); // convert any particle decay modes which are needed for(unsigned int ix=0;ixuseStdOut() ) { cout.rdbuf(temp[0]); cerr.rdbuf(temp[1]); } } void EvtGenInterface::dofinish() { Interfaced::dofinish(); if(logFile_.is_open()) logFile_.close(); } ParticleVector EvtGenInterface::decay(const Particle &parent, bool recursive, const DecayMode & dm) const { // redirect cout to the log file ostringstream stemp; std::streambuf *temp[2]={cout.rdbuf(),cerr.rdbuf()}; if(reDirect_ && ! generator()->useStdOut() ) { std::streambuf *psbuf[2] ={logFile_.rdbuf(),stemp.rdbuf()}; cout.rdbuf(psbuf[0]); cerr.rdbuf(psbuf[1]); } // generate the decay ParticleVector output; EvtId parID(EvtGenID(parent.id())); try { EvtDecayBase *decayer = NULL; // create evtgen particle for the parent EvtParticle* particle = EvtGenParticle(parent); EvtParticle* evtParent = NULL; // special if parent is the same to avoid doing mixing twice if(parent.parents().size()==1 && abs(parent.parents()[0]->id())==abs(parent.id())) { evtParent = EvtGenParticle(*parent.parents()[0]); particle->addDaug(evtParent); } // simplest case, evtgen selects mode and recursively decays, use their standard mechanism if(dm.wildProductMatcher() && recursive) { evtgen_->generateDecay(particle); } // otherwise we're in control else { // select the EvtGen decayer to use if(dm.wildProductMatcher()) { decayer = EvtDecayTable::getInstance()->getDecayFunc(particle); } // otherwise we should pick one else { int imode(EvtGenChannel(dm)); decayer = EvtDecayTable::getInstance()->getDecay(parID.getAlias(),imode); particle->setChannel(imode); } // must be a decayer if(!decayer) throw Exception() << "Could find EvtGen decayer in EvtGen::decay()" << Exception::runerror; // masses of the children bool massTreeOK(true); if ( particle->getNDaug() == 0 ) massTreeOK = particle->generateMassTree(); if ( ! massTreeOK ) { // delete the EvtGen particle particle->deleteDaughters(); delete particle; particle = 0; if(evtParent) { delete evtParent; } throw Exception() << "EvtGen could not decay " << EvtPDL::name(particle->getId()) <<" with mass "<< particle->mass() <<" to decay channel number "<< particle->getChannel() << "\n" << Exception::eventerror; } assert(decayer !=0 ); // perform decay decayer->makeDecay(particle,recursive); } // cast the decayer EvtDecayAmp *damp = dynamic_cast(decayer); // translate the decay products output=decayProducts(particle); // set spin information if needed tSpinPtr pspin(getSpinInfo(parent)); // if has spin information translate it if(damp) { ParticleVector products; unsigned int nbeforerad=decayer->getNDaug(); for(unsigned int ix=0;ixdevelop(); RhoDMatrix rhotemp(pspin->iSpin()); pspin->DMatrix()=rhotemp; } pspin->decay(); if(recursive) { pspin->developed(); pspin->DMatrix()=ThePEGSpinDensity(particle->getSpinDensityBackward(), ThePEGID(particle->getId())); } // delete the EvtGen particle particle->deleteDaughters(); delete particle; if(evtParent) { delete evtParent; } particle = 0; } catch ( ... ) { // change stream back if(reDirect_ && ! generator()->useStdOut() ) { cout.rdbuf(temp[0]); cerr.rdbuf(temp[1]); } throw; } // change stream back if(reDirect_ && ! generator()->useStdOut() ) { cout.rdbuf(temp[0]); cerr.rdbuf(temp[1]); string stemp2=stemp.str(); if(stemp2.length()>0) throw Exception() << "EvtGen report error in EvtGen::decay " << "killing event\n" << "Error was " << stemp2 << Exception::eventerror; } // return the decay products return output; } EvtParticle * EvtGenInterface::EvtGenParticle(const Particle & part) const { // convert the momentum Lorentz5Momentum inmom(part.momentum()); EvtVector4R p4(EvtGenMomentum(inmom)); EvtParticle *evtpart; // EvtGen ID and spin type EvtId id = EvtGenID(part.id()); EvtSpinType::spintype thisSpin=EvtPDL::getSpinType(id); // boost to the rest frame to get the basis states right PPtr decay(const_ptr_cast(new_ptr(part))); decay->transform(LorentzRotation(-inmom.boostVector())); // get spin information so can transfer to EvtGen tcSpinPtr spin(dynamic_ptr_cast(part.spinInfo())); if(spin) spin->decay(); // don't convert neutrinos, aren't decays so waste of time if ( thisSpin == EvtSpinType::NEUTRINO) { throw Exception() << "Tried to convert a neutrino to EvtGen in " << "EvtGen::EvtParticle. This should not be needed as" << "EvtGen does not decay neutrinos" << Exception::eventerror; } // don't convert photons, aren't decays so waste of time else if ( thisSpin == EvtSpinType::PHOTON ) { throw Exception() << "Tried to convert a photon to EvtGen in " << "EvtGen::EvtParticle. This should not be needed as" << "EvtGen does not decay photons" << Exception::eventerror; } // scalar particles else if ( thisSpin == EvtSpinType::SCALAR ) { // create particle EvtScalarParticle * myPart = new EvtScalarParticle; myPart->init(id, p4); // set rho matrix if needed tcScalarSpinPtr sp(dynamic_ptr_cast(spin)); if(sp) { myPart->setSpinDensityForward(EvtGenSpinDensity(sp->rhoMatrix())); } else { EvtSpinDensity rho; rho.setDiag(EvtSpinType::getSpinStates(thisSpin)); myPart->setSpinDensityForward(rho); } evtpart=myPart; } else if ( thisSpin == EvtSpinType::DIRAC ) { EvtDiracParticle *myPart =new EvtDiracParticle; // get the spin info tcFermionSpinPtr sp(dynamic_ptr_cast(spin)); // has spin info transfer if(sp) { vector prod,decay; // transfer spinors for(unsigned int ix=0;ix<2;++ix) { prod .push_back(EvtGenSpinor(sp->getProductionBasisState(ix))); decay.push_back(EvtGenSpinor(sp->getDecayBasisState (ix))); } myPart->init(id, p4,prod[0],prod[1],decay[0],decay[1]); // set the density matrix myPart->setSpinDensityForward(EvtGenSpinDensity(sp->rhoMatrix())); } // no spin info else { myPart->init(id, p4); EvtSpinDensity rho; rho.setDiag(EvtSpinType::getSpinStates(thisSpin)); myPart->setSpinDensityForward(rho); } evtpart=myPart; } // vector particles else if ( thisSpin == EvtSpinType::VECTOR ) { EvtVectorParticle *myPart=new EvtVectorParticle; // get the spin info tcVectorSpinPtr sp(dynamic_ptr_cast(spin)); // has spin info transfer if(sp) { // transfer polarization vectors vector eps; for(unsigned int ix=0;ix<3;++ix) { eps.push_back(EvtGenPolarization(sp->getDecayBasisState(ix))); } myPart->init(id, p4,eps[0],eps[1],eps[2]); // set spin density matrix myPart->setSpinDensityForward(EvtGenSpinDensity(sp->rhoMatrix())); } // no spin info else { myPart->init(id, p4); EvtSpinDensity rho; rho.setDiag(EvtSpinType::getSpinStates(thisSpin)); myPart->setSpinDensityForward(rho); } evtpart=myPart; } // spin 3/2 particles else if ( thisSpin == EvtSpinType::RARITASCHWINGER ) { EvtRaritaSchwingerParticle *myPart=new EvtRaritaSchwingerParticle; // get the spin info tcRSFermionSpinPtr sp(dynamic_ptr_cast(spin)); // has spin info transfer if(sp) { // transfer spinors vector prod,decay; for(unsigned int ix=0;ix<4;++ix) { prod .push_back(EvtGenRSSpinor(sp->getProductionBasisState(ix))); decay.push_back(EvtGenRSSpinor(sp->getDecayBasisState(ix) )); } myPart->init(id, p4, prod[0] ,prod[1] ,prod[2] , prod[3], decay[0],decay[1],decay[2],decay[3]); // set spin density matrix myPart->setSpinDensityForward(EvtGenSpinDensity(sp->rhoMatrix())); } // no spin info else { myPart->init(id, p4); EvtSpinDensity rho; rho.setDiag(EvtSpinType::getSpinStates(thisSpin)); myPart->setSpinDensityForward(rho); } evtpart=myPart; } // spin-2 particles else if ( thisSpin == EvtSpinType::TENSOR ) { EvtTensorParticle *myPart =new EvtTensorParticle; tcTensorSpinPtr sp(dynamic_ptr_cast(spin)); // has spin info transfer if(sp) { // transfer the polarization tensors vector eps; for(unsigned int ix=0;ix<5;++ix) { eps.push_back(EvtGenTensor(sp->getDecayBasisState(ix))); } myPart->init(id, p4,eps[0],eps[1],eps[2],eps[3],eps[4]); // set spin density matrix myPart->setSpinDensityForward(EvtGenSpinDensity(sp->rhoMatrix())); } // no spin info else { myPart->init(id, p4); EvtSpinDensity rho; rho.setDiag(EvtSpinType::getSpinStates(thisSpin)); myPart->setSpinDensityForward(rho); } evtpart=myPart; } // shouldn't be doing this but here for safety else if ( thisSpin == EvtSpinType::STRING ) { EvtStringParticle *myPart; myPart=new EvtStringParticle; myPart->init(id, p4); EvtSpinDensity rho; rho.setDiag(EvtSpinType::getSpinStates(thisSpin)); myPart->setSpinDensityForward(rho); evtpart=myPart; } // high spin particles else if ( thisSpin == EvtSpinType::SPIN3 || thisSpin == EvtSpinType::SPIN5HALF || thisSpin == EvtSpinType::SPIN4 || thisSpin == EvtSpinType::SPIN7HALF) { EvtHighSpinParticle *myPart; myPart=new EvtHighSpinParticle; myPart->init(id, p4); EvtSpinDensity rho; rho.setDiag(EvtSpinType::getSpinStates(thisSpin)); myPart->setSpinDensityForward(rho); evtpart=myPart; } else { throw Exception() << "Can't convert particle to EvtGen " << part << Exception::eventerror; } // boost particle back and return the particle decay->boost(inmom.boostVector()); return evtpart; } // convert from ThePEG to EvtGen EvtId EvtGenInterface::EvtGenID(int id, bool exception) const { EvtId output; int absid=abs(id),ispin(absid%10),isgn(id/absid); // handle the easy cases if( //quarks(+excited) absid<=8|| // leptons(+exicted) (absid>=11&&absid<=18)|| // SM(+extensions) gauge bosons and higgs (absid>=21&&absid<=25)||(absid>=32&&absid<=37)|| // 1 1S0, 1 3S1 and 1 3P2 1 3D3 mesons are the same (absid>100&&absid<600&&ispin%2==1&&ispin<=9)|| // 2 1S0, 2 3S1 are the same (absid>100100&&absid<100600&&(ispin==1||ispin==3))|| // 1 3d1 goes to 3s in evtgen (absid>30100&&absid<30600&&ispin==3) || // 1 1P1 mesons are the same apart from D_s1 (absid>10100&&absid<10600&&(ispin==3)) || // 1 3P1 mesons are the same apart from D_s1 (absid>20100&&absid<20600&&(ispin==3)) || // mixed kaons and diffractive states (absid>=100&&absid<=3000&&ispin==0)) { output = EvtPDL::evtIdFromStdHep(id); } // lowest baryon multiplets and diquarks are almost the same else if(absid>1000&&absid<6000&&ispin>=1&&ispin<=4) { output = EvtPDL::evtIdFromStdHep(id); } // 1 3p0 same apart from f'0 else if (absid>10100&&absid<10600&&ispin==1) { if(absid==10221) output = EvtPDL::evtIdFromStdHep(isgn*30221); else output = EvtPDL::evtIdFromStdHep(id); } // excited baryons else if(((absid>10000&&absid<16000)||(absid>20000&&absid<26000)|| (absid>30000&&absid<36000))&&(ispin==2||ispin==4)) { output=EvtPDL::evtIdFromStdHep(id); } // special for any bottomonium states else if((absid%1000)/10==55) { output=EvtPDL::evtIdFromStdHep(id); } // special meson codes else if (absid>9000000) { // f_0/a_0(980) goes into f_0/a_0(980) if(absid==9000111||absid==9000211||absid==9010221) { output=EvtPDL::evtIdFromStdHep(id); } // sigma else if(absid==9000221) { output=EvtPDL::evtIdFromStdHep(id); } // psi(4040) else if(absid==9000443) { output=EvtPDL::evtIdFromStdHep(50443); } // f_0(1500) else if(absid==9030221) { output=EvtPDL::evtIdFromStdHep(9020221); } } // check its O.K. if(output.getAlias()==-1&&exception) { throw Exception() << "Can't find the EvtGen Id for particle " << getParticleData(id)->PDGName() << " with PDG code = " << id << " in EvtGen::EvtGenID" << Exception::eventerror; } return output; } ParticleVector EvtGenInterface::decayProducts(EvtParticle *part, bool boost) const { ParticleVector output,temp; for(unsigned int ix=0,N=part->getNDaug();ixgetDaug(ix); // may just have been used for mass generation, so check has valid momentum if(!daug->hasValidP4()) continue; // get the Herwig ParticleData object int id=ThePEGID(daug->getId()); tcPDPtr pd=getParticleData(id); // if easy to convert do it if(pd) output.push_back(ThePEGParticle(daug,pd)); // special for EvtGen particles like string we don't need to include else if(id==90) { // check if needs to be decayed by EvtGen if(EvtPDL::getStdHep(daug->getId())==92||daug->isDecayed()) { // add the particles ParticleVector temp(decayProducts(daug,EvtPDL::getStdHep(daug->getId())!=92)); if(EvtPDL::getStdHep(daug->getId())==92) { Lorentz5Momentum pstring(ThePEGMomentum(daug->getP4(),daug->mass())); Boost bv(-pstring.x()/pstring.e(),-pstring.y()/pstring.e(),-pstring.z()/pstring.e()); for(unsigned int ix=0;ixdeepBoost(bv); } } for(unsigned int iy=0;iyisDecayed()) { EvtDecayBase *decayer = EvtDecayTable::getInstance()->getDecayFunc(daug); // must be a decayer if(!decayer) throw Exception() << "Could find EvtGen decayer in " << "EvtGenInterface::decayProducts()" << Exception::runerror; // If there are already daughters, then this step is already done! // figure out the masses if ( daug->getNDaug() == 0 ) daug->generateMassTree(); // perform decay decayer->makeDecay(daug,false); // add the particles ParticleVector temp(decayProducts(daug)); for(unsigned int iy=0;iy0) { if(boost) { Boost bv=ThePEGMomentum(part->getP4(),part->mass()).boostVector(); for(unsigned int ix=0; ixdeepBoost(bv); } } return output; } void EvtGenInterface::ThePEGSpin(PPtr peg,EvtParticle *evt) const { // if no corresponding ThePEG spin type return if(evt->getSpinType()==EvtSpinType::STRING|| evt->getSpinType()==EvtSpinType::SPIN3||evt->getSpinType()==EvtSpinType::SPIN4|| evt->getSpinType()==EvtSpinType::SPIN5HALF|| evt->getSpinType()==EvtSpinType::SPIN7HALF) return; // now deal with the other cases // scalars unsigned int ix; SpinPtr spin; if(evt->getSpinType()==EvtSpinType::SCALAR) { ScalarSpinPtr sca(new_ptr(ScalarSpinInfo(peg->momentum(),true))); spin=sca; } // massless spin 1/2 else if(evt->getSpinType()==EvtSpinType::NEUTRINO) { FermionSpinPtr fer(new_ptr(FermionSpinInfo(peg->momentum(),true))); spin=fer; ix=peg->id()<0; fer->setBasisState(ix,ThePEGSpinor(evt->spParentNeutrino())); ix=peg->id()>0; fer->setBasisState(ix,LorentzSpinor()); } // massive spin-1/2 else if(evt->getSpinType()==EvtSpinType::DIRAC) { FermionSpinPtr fer(new_ptr(FermionSpinInfo(peg->momentum(),true))); spin=fer; for(ix=0;ix<2;++ix) { fer->setBasisState(ix,ThePEGSpinor(evt->spParent(ix))); } } // massless vectors else if(evt->getSpinType()==EvtSpinType::PHOTON) { VectorSpinPtr vec(new_ptr(VectorSpinInfo(peg->momentum(),true))); spin=vec; for(ix=0;ix<1;++ix) { vec->setBasisState(2*ix,ThePEGPolarization(evt->epsParentPhoton(ix)));} vec->setBasisState(1,LorentzVector()); } // massive vectors else if(evt->getSpinType()==EvtSpinType::VECTOR) { VectorSpinPtr vec(new_ptr(VectorSpinInfo(peg->momentum(),true))); spin=vec; for(ix=0;ix<3;++ix) { vec->setBasisState(ix,ThePEGPolarization(evt->epsParent(ix))); } } // massive spin 3/2 else if(evt->getSpinType()==EvtSpinType::RARITASCHWINGER) { RSFermionSpinPtr rs(new_ptr(RSFermionSpinInfo(peg->momentum(),true))); spin=rs; for(ix=0;ix<4;++ix) { rs->setBasisState(ix,ThePEGRSSpinor(evt->spRSParent(ix)));} } // tensors else if(evt->getSpinType()==EvtSpinType::TENSOR) { TensorSpinPtr ten(new_ptr(TensorSpinInfo(peg->momentum(),true))); spin=ten; for(ix=0;ix<5;++ix) { ten->setBasisState(ix,ThePEGTensor(evt->epsTensorParent(ix))); } } else { throw Exception() << "Unknown EvtGen spin type in EvtGen::ThePEGSpin() " << Exception::runerror; } // set the spininfo peg->spinInfo(spin); // final set up if the particle has decayed if(evt->getSpinDensityForward().getDim()!=0) { spin->rhoMatrix()=ThePEGSpinDensity(evt->getSpinDensityForward(),peg->id()); } if(evt->isDecayed()) { spin->decayed(true); spin->develop(); if(evt->getSpinDensityBackward().getDim()!=0) { spin->DMatrix()=ThePEGSpinDensity(evt->getSpinDensityBackward(),peg->id()); } } } // convert from EvtGen to ThePEG int EvtGenInterface::ThePEGID(EvtId eid,bool exception) const { int output(0); int id(EvtPDL::getStdHep(eid)),absid(abs(id)),ispin(absid%10); // handle the easy cases // special particles like string which we delete and include decay products if(absid==92||absid==41||absid==42||absid==43||absid==44|| absid==30343||absid==30353|| absid==30363||absid==30373||absid==30383) { output=90; } //quarks(+excited) else if(absid<=8|| // leptons(+excited) (absid>=11&&absid<=18)|| // SM gauge bosons and higgs (absid>=21&&absid<=25)||(absid>=32&&absid<=37)|| // 1 1S0, 1 3S1 and 1 3P2 mesons are the same (absid>100&&absid<600&&(ispin%2==1&&ispin<9))|| // 2 1S0 and 2 3S1 mesons are the same (absid>100100&&absid<100600&&(ispin==1||ispin==3))|| // 1 3p0 are the same (absid>10100&&absid<10600&&ispin==1) || // 3d1 are the same (absid>30100&&absid<30600&&ispin==3) || // 1 1P1 mesons are the same (absid>10100&&absid<10600&&(ispin==3)) || // 1 3P1 mesons are the same (absid>20100&&absid<20600&&(ispin==3)) || // lowest baryon multiplets and diquarks (absid>1000&&absid<6000&&ispin>=1&&ispin<=4)|| // mixed kaons and diffractive states (absid>=100&&absid<=3000&&ispin==0)) { output=id; } // 1 3P0 special for f'0 else if(absid==30221) output = 10221; // special for the virtual W (we don't distinguish so return W) else if(absid==89) return id/absid*24; // excited baryons else if(((absid>10000&&absid<16000)||(absid>20000&&absid<26000)|| (absid>30000&&absid<36000))&&(ispin==2||ispin==4)) { output=id; } // bottomium else if((absid%1000)/10==55) { output = id; } // special mesons else if(absid>9000000) { // f_0/a_0(980) goes into f_0/a_0(980) if(absid==9000111||absid==9000211||absid==9010221) { output=id; } // sigma else if(absid==9000221) { output=id; } // psi(4040) else if(absid==9000443) { output=id; } // f_0(1500) else if(absid==9020221) { output=9030221; } } // check its O.K. if(output==0&&exception) { throw Exception() << "Can't find the ThePEG id for particle " << EvtPDL::name(eid) << " with PDG code = " << id << " in EvtGen::ThePEGID" << Exception::eventerror; } return output; } RhoDMatrix EvtGenInterface::ThePEGSpinDensity(const EvtSpinDensity & rho, int id) const { RhoDMatrix output; unsigned int ix,iy; // special for neutrinos if(abs(id)%2==0&&abs(id)>=12&&abs(id)<=16) { output = RhoDMatrix(PDT::Spin1Half, false); if(id>0) output(0,0)=ThePEGComplex(rho.get(0,0)); else output(1,1)=ThePEGComplex(rho.get(0,0)); } // special for photons else if(id==ParticleID::gamma) { output = RhoDMatrix(PDT::Spin1, false); for(ix=0;ix<2;++ix) { for(iy=0;iy<2;++iy) output(2*ix,2*iy)=ThePEGComplex(rho.get(ix,iy)); } } // normal behaviour else { unsigned int ndim(abs(rho.getDim())); if(ndim!=0) { output = RhoDMatrix(PDT::Spin(ndim)); for(ix=0;ixparticles().begin(); ParticleMap::const_iterator pend = generator()->particles().end(); cout << "Testing conversion of particles from ThePEG to EvtGen\n"; EvtId etemp; for(;pit!=pend;++pit) { cout << pit->first << " "; etemp=EvtGenID(pit->first,false); Energy mass = pit->second->mass(); Energy width = pit->second->width(); if(etemp.getAlias()>=0) { cout << pit->second->PDGName() << "\t becomes " << EvtPDL::name(etemp) << "\t " << EvtPDL::getStdHep(etemp); if(ThePEGID(etemp,false)-pit->first!=0) { cout << " and converting back to ThePEG fails"; } double mass2 = EvtPDL::getMeanMass(etemp); double width2 = EvtPDL::getWidth(etemp); if(mass!=ZERO) { double delta = (mass-mass2*GeV)/mass; if(abs(delta)>1e-6) cout << " Mass Difference " << mass/GeV-mass2; } if(width>ZERO) { double delta = (width-width2*GeV)/width; if(abs(delta)>1e-6) cout << " Width Difference " << width/GeV-width2; } cout << "\n"; } else { cout << pit->second->PDGName() << " has no match in EvtGen \n"; } } // test the conversion the other way cout << "Testing conversion of particles from EvtGen to ThePEG\n"; int idtemp; tcPDPtr ptemp; for(unsigned int ix=0;ixPDGName() << " " << ptemp->id(); if(EvtGenID(ptemp->id(),false)!=EvtPDL::getEntry(ix)) { cout << " and converting back to EvtGEN fails "; } cout << "\n"; } else { cout << " has no match in ThePEG \n"; } } } void EvtGenInterface::outputEvtGenDecays(long parentid) const { // output the decay modes from EvtGen so we can read them in EvtId parent(EvtGenID(parentid)); // get evtids for children cout << "Outputting decays for " << getParticleData(parentid)->PDGName() << "\n"; for(int ix=0;ixgetNMode(parent.getAlias());++ix) { EvtDecayBase* decayer=EvtDecayTable::getInstance()->getDecay(parent.getAlias(),ix); vector pegid; for(int iy=0;iygetNDaug();++iy) { pegid.push_back(ThePEGID(decayer->getDaug(iy),false)); } for(unsigned int iy=pegid.size();iy<7;++iy) pegid.push_back(0); double br=decayer->getBranchingFraction(); cout << "insert into decay_modes (incomingID,BR,decayon,star,outgoingID1," << "outgoingID2,outgoingID3,outgoingID4,outgoingID5,outgoingID6,outgoingID7," << "description,decayer) values (" << parentid << "," << br << ",'on','*',"; for(int iy=0;iy<7;++iy) { cout << pegid[iy] << ","; } cout << "'Decay of %name% with branching " << "ratio taken from EvtGen.',3);\n"; } } int EvtGenInterface::EvtGenChannel(const DecayMode & dm) const { // get evtid for parent EvtId parent(EvtGenID(dm.parent()->id())); // get evtids for children EvtId daugs[20]; unsigned int ndaug(0); ParticleMSet::const_iterator pit = dm.products().begin(); ParticleMSet::const_iterator pend = dm.products().end(); EvtId etemp; for( ;pit!=pend&&ndaug<20;++pit) { etemp=EvtGenID((**pit).id()); daugs[ndaug]=etemp; ndaug++; } if(ndaug>=20) throw Exception() << "Too many decay products " << "in EvtGen::EvtGenChannel" << Exception::eventerror; // find the channel int output=EvtDecayTable::getInstance()->inChannelList(parent,ndaug,daugs); if(output<0) { string dmode; dmode = "decay of " + dm.parent()->PDGName() + " -> "; pit = dm.products().begin(); pend = dm.products().end(); for( ;pit!=pend&&ndaug<20;++pit) dmode += (**pit).PDGName()+" "; throw Exception() << "Can't find EVtGen decay mode in EvtGenChannel for " << dmode << " in EvtGen::EvtGenChannel" << Exception::runerror; } return output; } // translate the matrix element to our form void EvtGenInterface::constructVertex(const Particle & parent, ParticleVector products, EvtDecayAmp* damp) const { unsigned int ix,iy; vector outspin; for(ix=0;ixdataPtr()->iSpin()); } vector constants(products.size()+2,0); unsigned int nstate(1),idtemp; for(ix=outspin.size();ix>0;--ix) { idtemp=abs(products[ix-1]->id()); if(idtemp==ParticleID::gamma) { nstate*=2; constants[ix]=nstate; } else if(idtemp%2==0&&idtemp>=12&&idtemp<=16) { constants[ix]=nstate; } else { nstate*=outspin[ix-1]; constants[ix]=nstate; } } PDT::Spin inspin(parent.dataPtr()->iSpin()); nstate*=inspin; constants[0]=nstate; constants[outspin.size()+1]=1; int eind[10]={0,0,0,0,0,0,0,0,0,0}; unsigned int iloc; vector hind(outspin.size()+1,0); DecayMEPtr newME = new_ptr(GeneralDecayMatrixElement(inspin,outspin)); for(ix=0;ixid()==ParticleID::gamma) { hind[iy+1]=2*(ix%constants[iy+1])/constants[iy+2]; eind[iloc]=hind[iy+1]/2; ++iloc; } else if(constants[iy+1]==1) { hind[iy+1]=products[iy]->id()<0; } else { hind[iy+1]=(ix%constants[iy+1])/constants[iy+2]; eind[iloc]=hind[iy+1];++iloc; } } if(iloc==0) eind[0]=0; (*newME)(hind)=ThePEGComplex(damp->amplitude().getAmp(eind)); } // create the decay vertex VertexPtr vertex(new_ptr(DecayVertex())); DVertexPtr Dvertex(dynamic_ptr_cast(vertex)); // set the incoming particle for the decay vertex dynamic_ptr_cast(parent.spinInfo())->decayVertex(vertex); for(ix=0;ix(products[ix]->spinInfo()) ->productionVertex(vertex); } // set the matrix element Dvertex->ME(newME); } diff --git a/Decay/EvtGen/EvtGenInterface.h b/Decay/EvtGen/EvtGenInterface.h --- a/Decay/EvtGen/EvtGenInterface.h +++ b/Decay/EvtGen/EvtGenInterface.h @@ -1,486 +1,478 @@ // -*- C++ -*- #ifndef Herwig_EvtGenInterface_H #define Herwig_EvtGenInterface_H // // This is the declaration of the EvtGenInterface class. // #include "EvtGenInterface.fh" #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Helicity/ScalarSpinInfo.h" #include "ThePEG/Helicity/FermionSpinInfo.h" #include "ThePEG/Helicity/VectorSpinInfo.h" #include "ThePEG/Helicity/RSFermionSpinInfo.h" #include "ThePEG/Helicity/TensorSpinInfo.h" #include "ThePEG/EventRecord/Particle.h" #include "EvtGenRandom.h" #include "EvtGen/EvtGen.hh" #include "EvtGenBase/EvtParticle.hh" #include "EvtGenBase/EvtSpinDensity.hh" #include "EvtGenBase/EvtVector4R.hh" #include "EvtGenBase/EvtVector4C.hh" #include "EvtGenBase/EvtTensor4C.hh" #include "EvtGenBase/EvtDiracSpinor.hh" #include "EvtGenBase/EvtRaritaSchwinger.hh" #include "EvtGenBase/EvtDecayAmp.hh" namespace Herwig { using namespace ThePEG; /** * The EvtGenInterface class is the main class for the use of the EvtGen decay * package with Herwig. * * @see \ref EvtGenInterfaceInterfaces "The interfaces" * defined for EvtGenInterface. */ class EvtGenInterface: public Interfaced { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ EvtGenInterface(); /** * The copy constructor (explicit as cannot copy streams) */ EvtGenInterface(const EvtGenInterface &); - /** - * The destructor. - */ - virtual ~EvtGenInterface(); - //@} - public: /** * Use EvtGen to perform a decay * @param parent The decaying particle * @param dm The decaymode * @return The decay products */ ParticleVector decay(const Particle &parent, bool recursive, const DecayMode & dm) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Functions to convert between EvtGen and Herwig classes */ //@{ /** * Convert a particle to an EvtGen particle. * @param part The particle to be converted. */ EvtParticle *EvtGenParticle(const Particle & part) const; /** * Return the decay products of an EvtGen particle in as ThePEG particles * @param evtpart The EvtGen particle */ ParticleVector decayProducts(EvtParticle* evtpart, bool boost=true) const; /** * Convert a Lorentz5Momentum to a real EvtGen 4-vector * @param mom The momentum to be converted */ EvtVector4R EvtGenMomentum(const Lorentz5Momentum & mom) const { return EvtVector4R(mom.t()/GeV,mom.x()/GeV,mom.y()/GeV,mom.z()/GeV); } /** * Convert a PDG code from ThePEG into an EvtGen particle id * @param id The PDG code * @param exception Whether or not to throw an Exception if fails */ EvtId EvtGenID(int id,bool exception=true) const; /** * Convert a LorentzSpinor to an EvtGen one. The spinor is converted to the * EvtGen Dirac representation/ * @param sp The LorentzSpinor */ EvtDiracSpinor EvtGenSpinor(const LorentzSpinor & sp) const { InvSqrtEnergy norm(sqrt(0.5)/sqrt(GeV)); EvtDiracSpinor output; output.set(EvtGenComplex(-norm*( sp.s1()+sp.s3())), EvtGenComplex(-norm*( sp.s2()+sp.s4())), EvtGenComplex(-norm*(-sp.s1()+sp.s3())), EvtGenComplex(-norm*(-sp.s2()+sp.s4()))); return output; } /** * Convert a LorentzPolarizationVector to a complex EvtGen 4-vector * @param eps The polarization vector to be converted */ EvtVector4C EvtGenPolarization(const LorentzPolarizationVector & eps) const { return EvtVector4C(EvtGenComplex(eps.t()),EvtGenComplex(eps.x()), EvtGenComplex(eps.y()),EvtGenComplex(eps.z())); } /** * Convert our Rarita-Schwinger spinor to the EvtGen one * @param sp Our RS Spinor */ EvtRaritaSchwinger EvtGenRSSpinor(const LorentzRSSpinor & sp) const { InvSqrtEnergy norm(sqrt(0.5)/sqrt(GeV)); complex out[4][4]; for(unsigned int ix=0;ix<4;++ix) { out[ix][0] = -Complex(norm*( sp(ix,0)+sp(ix,2))); out[ix][1] = -Complex(norm*( sp(ix,1)+sp(ix,3))); out[ix][2] = -Complex(norm*(-sp(ix,0)+sp(ix,2))); out[ix][3] = -Complex(norm*(-sp(ix,1)+sp(ix,3))); } EvtRaritaSchwinger output; unsigned int ix,iy; // remember we have vec,spin and evtgen spin,vec for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) output.set(ix,iy,EvtGenComplex(out[iy][ix])); } return output; } /** * Convert our tensor to the EvtGen one. * @param ten Our tensor */ EvtTensor4C EvtGenTensor(const LorentzTensor & ten) const { EvtTensor4C output; unsigned int ix,iy; for(ix=0;ix<4;++ix){ for(iy=0;iy<4;++iy) output.set(ix,iy,EvtGenComplex(ten(ix,iy))); } return output; } /** * Convert a spin density matrix to an EvtGen spin density matrix. * @param rho The spin density matrix to be converted. */ EvtSpinDensity EvtGenSpinDensity(const RhoDMatrix & rho) const { EvtSpinDensity rhoout; unsigned int ix,iy,ispin(rho.iSpin()); rhoout.setDim(ispin); for(ix=0;ixset5Momentum(ThePEGMomentum(part->getP4(),part->mass())); if(spin) ThePEGSpin(output,part); // make the daughters ParticleVector daug(decayProducts(part,spin)); for(unsigned int ix=0;ixaddChild(daug[ix]); return output; } /** * Set the SpinInfo for a ThePEG particle using an EvtGen particle * @param pegpart ThePEG particle. * @param evtpart The EvtGen particle. */ void ThePEGSpin(PPtr pegpart,EvtParticle *evtpart) const; /** * Convert an EvtGen EvtId to a PDG code in our conventions * @param id The EvtGen ID. * @param exception Whether or not to throw an Exception if fails */ int ThePEGID(EvtId id,bool exception=true) const; /** * Convert from EvtGen momentum to Lorentz5Momentum * @param mom The EvtGen 4-momentum * @param mass The mass */ Lorentz5Momentum ThePEGMomentum(const EvtVector4R & mom,double mass) const { return Lorentz5Momentum(mom.get(1)*GeV,mom.get(2)*GeV, mom.get(3)*GeV,mom.get(0)*GeV,mass*GeV); } /** * Convert from EvtGen complex to ours */ Complex ThePEGComplex(EvtComplex c) const { return Complex(real(c),imag(c)); } /** * Convert a spin density to a ThePEG one from an EvtGen one * @param rho The spin density matrix to be converted * @param id The PDG code of the particle to get special cases right. */ RhoDMatrix ThePEGSpinDensity(const EvtSpinDensity & rho, int id) const; /** * Convert an EvtDiracSpinor a LorentzSpinor. This spinor is converted to * the default Dirac matrix representation used by ThePEG. * @param sp The EvtDiracSpinor */ LorentzSpinor ThePEGSpinor(const EvtDiracSpinor & sp) const { SqrtEnergy norm(sqrt(0.5)*sqrt(GeV)); vector > evtSpin(4); for(unsigned int ix=0;ix<4;++ix) evtSpin[ix] = -norm*ThePEGComplex(sp.get_spinor(ix)); return LorentzSpinor(evtSpin[0]-evtSpin[2],evtSpin[1]-evtSpin[3], evtSpin[0]+evtSpin[2],evtSpin[1]+evtSpin[3]); } /** * Convert an EvtGen complex 4-vector to a LorentzPolarizationVector * @param eps The complex 4-vector to be converted. */ LorentzPolarizationVector ThePEGPolarization(const EvtVector4C & eps) const { return LorentzPolarizationVector(conj(ThePEGComplex(eps.get(1))), conj(ThePEGComplex(eps.get(2))), conj(ThePEGComplex(eps.get(3))), conj(ThePEGComplex(eps.get(0)))); } /** * Convert an EvtGen Rarita-Schwinger spinor to ours * @param sp The EvtGen RS spinor. */ LorentzRSSpinor ThePEGRSSpinor(const EvtRaritaSchwinger & sp) const { complex evtSpin[4][4]; SqrtEnergy norm(sqrt(0.5)*sqrt(GeV)); // normalisation and swap vec,spin order for(unsigned int ix=0;ix<4;++ix) { for(unsigned int iy=0;iy<4;++iy) evtSpin[ix][iy]=-norm*ThePEGComplex(sp.get(iy,ix)); } LorentzRSSpinor output; for(unsigned int ix=0;ix<4;++ix) { output(ix,0) = evtSpin[ix][0] - evtSpin[ix][2]; output(ix,1) = evtSpin[ix][1] - evtSpin[ix][3]; output(ix,2) = evtSpin[ix][0] + evtSpin[ix][2]; output(ix,3) = evtSpin[ix][1] + evtSpin[ix][3]; } // output.changeRep(Helicity::defaultDRep); return output; } /** * Convert an EvtGen tensor to ThePEG * @param ten The EvtGen tensor */ LorentzTensor ThePEGTensor(const EvtTensor4C & ten) const { LorentzTensor output; unsigned int ix,iy; for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy)output(ix,iy)=conj(ThePEGComplex(ten.get(ix,iy))); } return output; } //@} /** * Check the conversion of particles between Herwig and EvtGen */ void checkConversion() const; /** * Output the EvtGen decay modes for a given particle * @param id The PDG code of the particle to output */ void outputEvtGenDecays(long id) const; /** * Find the location in the EvtGen list of decay channels for * a given decay mode. */ int EvtGenChannel(const DecayMode &dm) const; /** * Check the particle has SpinInfo and if not create it * @param part The particle */ tSpinPtr getSpinInfo(const Particle &part) const { // return spin info if exists if(part.spinInfo()) { return dynamic_ptr_cast(const_ptr_cast(&part)->spinInfo()); } // otherwise make it tPPtr ptemp(const_ptr_cast(&part)); PDT::Spin spin(part.dataPtr()->iSpin()); SpinPtr pspin; if(spin==PDT::Spin0) pspin=new_ptr(ScalarSpinInfo(part.momentum(),true)); else if(spin==PDT::Spin1Half) pspin=new_ptr(FermionSpinInfo(part.momentum(),true)); else if(spin==PDT::Spin1) pspin=new_ptr(VectorSpinInfo(part.momentum(),true)); else if(spin==PDT::Spin3Half) pspin=new_ptr(RSFermionSpinInfo(part.momentum(),true)); else if(spin==PDT::Spin2) pspin=new_ptr(TensorSpinInfo(part.momentum(),true)); else throw Exception() << "Can't create spinInfo for decaying particle in " << "EvtGen::checkSpinInfo for spin " << spin << "particle " << Exception::eventerror; ptemp->spinInfo(pspin); return pspin; } /** * Construct the DecayVertex for Herwig using the information from * EvtGen * @param parent The decaying particle * @param products The outgoing particles * @param damp Pointer to the EvtGen decayer */ void constructVertex(const Particle & parent,ParticleVector products, EvtDecayAmp* damp) const; 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. */ //@{ /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ EvtGenInterface & operator=(const EvtGenInterface &) = delete; private: /** * Names of the various EvtGen parameter files */ //@{ /** * The name of the file containing the decays */ string decayName_; /** * The name of the file containing the particle data */ string pdtName_; /** * Names of addition user specified decays */ vector userDecays_; //@} /** * Whether or not to redirect cout and cerr when EvtGen is running */ bool reDirect_; /** * Check the conversion of the particles */ bool checkConv_; /** * Particles for which to output the EvtGen decays */ vector convID_; /** * Location of the PYTHIA8 data directory */ string p8Data_; private: /** * Pointer to the random number generator for EvtGen */ EvtRandomEngine * evtrnd_; /** * Main EvtGen object */ EvtGen * evtgen_; /** * File to output the log info to */ mutable ofstream logFile_; }; } #endif /* Herwig_EvtGenInterface_H */ diff --git a/Decay/Radiation/FFDipole.cc b/Decay/Radiation/FFDipole.cc --- a/Decay/Radiation/FFDipole.cc +++ b/Decay/Radiation/FFDipole.cc @@ -1,950 +1,948 @@ // -*- C++ -*- // // FFDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFDipole class. // #include "FFDipole.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "YFSFormFactors.h" #include "Herwig/Decay/PhaseSpaceMode.h" #include "Herwig/Decay/DecayIntegrator.h" using namespace Herwig; void FFDipole::persistentOutput(PersistentOStream & os) const { os << ounit(_emin,GeV) << ounit(_eminrest,GeV) << ounit(_eminlab,GeV) << _maxwgt << _weightOutput << _mode << _maxtry << _energyopt << _betaopt << _dipoleopt; } void FFDipole::persistentInput(PersistentIStream & is, int) { is >> iunit(_emin,GeV) >> iunit(_eminrest,GeV) >> iunit(_eminlab,GeV) >> _maxwgt >> _weightOutput >> _mode >> _maxtry >> _energyopt >> _betaopt >> _dipoleopt; } -FFDipole::~FFDipole() {} - // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigFFDipole("Herwig::FFDipole", "HwSOPHTY.so"); void FFDipole::Init() { static ClassDocumentation documentation ("The FFDipole class implements the final-final dipole for the SOPTHY algorithm"); static Switch interfaceUnWeight ("UnWeight", "Control the type of unweighting to perform, only one should be used the" " other options are for debugging purposes.", &FFDipole::_mode, 1, false, false); static SwitchOption interfaceUnWeightNoUnweighting (interfaceUnWeight, "NoUnweighting", "Perform no unweighting", 0); static SwitchOption interfaceUnWeightAllWeights (interfaceUnWeight, "AllWeights", "Include all the weights", 1); static SwitchOption interfaceUnWeightNoJacobian (interfaceUnWeight, "NoJacobian", "Only include the dipole and YFS weights", 2); static SwitchOption interfaceUnWeightDipole (interfaceUnWeight, "Dipole", "Only include the dipole weight", 3); static SwitchOption interfaceUnWeightYFS (interfaceUnWeight, "YFS", "Only include the YFS weight", 4); static SwitchOption interfaceUnWeightNLO (interfaceUnWeight, "NLO", "Weight to get the stict NLO rate", 5); static Parameter interfaceMaximumTries ("MaximumTries", "Maximum number of attempts to unweight", &FFDipole::_maxtry, 500, 10, 100000, false, false, Interface::limited); static Parameter interfaceMinimumEnergyBoosted ("MinimumEnergyBoosted", "The minimum energy of the photons in the boosted frame in which" " they are generated.", &FFDipole::_emin, MeV, 1.e-6*MeV, ZERO, 100.0*MeV, false, false, Interface::limited); static Parameter interfaceMinimumEnergyRest ("MinimumEnergyRest", "The minimum energy of the photons in the rest frame of the decaying particle", &FFDipole::_eminrest, MeV, 100.0*MeV, 1.0*MeV, 10000.0*MeV, false, false, Interface::limited); static Parameter interfaceMinimumEnergyLab ("MinimumEnergyLab", "The minimum energy of the photons in the lab frame", &FFDipole::_eminlab, MeV, 100.0*MeV, 1.0*MeV, 10000.0*MeV, false, false, Interface::limited); static Parameter interfaceMaximumWeight ("MaximumWeight", "The maximum weight for unweighting", &FFDipole::_maxwgt, 7.0, 0.0, 100.0, false, false, Interface::limited); static Switch interfaceEnergyCutOff ("EnergyCutOff", "The type of cut-off on the photon energy to apply", &FFDipole::_energyopt, 1, false, false); static SwitchOption interfaceEnergyCutOffBoostedFrame (interfaceEnergyCutOff, "BoostedFrame", "Only apply cut-off in boosted frame", 0); static SwitchOption interfaceEnergyCutOffRestFrame (interfaceEnergyCutOff, "RestFrame", "Apply cut-off in rest frame", 1); static SwitchOption interfaceEnergyCutOff2 (interfaceEnergyCutOff, "LabFrame", "Apply cut-off in lab frame", 2); static Switch interfaceBetaOption ("BetaOption", "Option for the inclusive of the higher beta coefficients", &FFDipole::_betaopt, 4, false, false); static SwitchOption interfaceBetaOptionNone (interfaceBetaOption, "None", "No higher betas included", 0); static SwitchOption interfaceBetaOptionCollinear (interfaceBetaOption, "Collinear", "Include the collinear approx", 1); static SwitchOption interfaceBetaOptionCollinearVirtA (interfaceBetaOption, "CollinearVirtualA", "Include the collinear approx with virtual corrections", 2); static SwitchOption interfaceBetaOptionCollinearVirtB (interfaceBetaOption, "CollinearVirtualB", "Include the collinear approx with virtual corrections", 3); static SwitchOption interfaceBetaOptionExact (interfaceBetaOption, "Exact", "Include the exact higher order terms if available", 4); static Switch interfaceDipoleOption ("DipoleOption", "Option for generating the primary dipole distribution", &FFDipole::_dipoleopt, 0, false, false); static SwitchOption interfaceDipoleOptionNoMass (interfaceDipoleOption, "NoMass", "Don't include the mass terms in the primary distribution", 0); static SwitchOption interfaceDipoleOptionMass (interfaceDipoleOption, "Mass", "Include the mass terms in the primary distribution", 1); static Switch interfaceWeightOutput ("WeightOutput", "Whether or not to output the average weight for testing", &FFDipole::_weightOutput, false, false, false); static SwitchOption interfaceWeightOutputNo (interfaceWeightOutput, "No", "Don't output the average", false); static SwitchOption interfaceWeightOutputYes (interfaceWeightOutput, "Yes", "Output the average", true); } void FFDipole::printDebugInfo(const Particle & p, const ParticleVector & children, double wgt) const { generator()->log() << "Input masses " << p.mass()/GeV << " -> " << children[0]->mass()/GeV << " " << children[1]->mass()/GeV << '\n'; generator()->log() << "Momenta\n"; generator()->log() << "parent " << p.momentum()/GeV << '\n'; for(unsigned int ix=0;ix<2;++ix) generator()->log() << "charged " << ix << " " << _qnewlab[ix]/GeV << " " << children[ix]->momentum()/GeV << '\n'; for(unsigned int ix=0;ix<_multiplicity;++ix) { generator()->log() << "photons " << ix << " " << "phocut " << _photcut[ix] << ' ' << _llab[ix]/GeV << '\n'; } generator()->log() << "wgt : " << wgt << '\n'; generator()->log() << "_mewgt : " << _mewgt << '\n'; generator()->log() << "_jacobianwgt: " << _jacobianwgt << '\n'; generator()->log() << "_yfswgt : " << _yfswgt << '\n'; generator()->log() << "_dipolewgt : " << _dipolewgt << '\n'; generator()->log() << "dipoleopt : " << _dipoleopt << '\n'; } ParticleVector FFDipole::generatePhotons(const Particle & p, ParticleVector children, tDecayIntegratorPtr decayer) { _parent = const_ptr_cast(&p); // set the decayer _decayer=decayer; // set parameters which won't change in the event loop // masses of the particles _m[0] = p.mass(); _m[1] = children[0]->mass(); _m[2] = children[1]->mass(); // set the maximum photon energy (exact - no approximations here). _emax=(0.5*(_m[0]-sqr(_m[1]+_m[2])/_m[0]))*_m[0]/(_m[1]+_m[2]); // check masses non-zero for(unsigned int ix=0;ix<2;++ix) { if(children[ix]->mass()<1e-4*GeV) { ostringstream message; message << "FFDipole::generatePhotons() trying to generate QED radiation from " << children[ix]->dataPtr()->PDGName() << "\n with mass " << children[ix]->mass()/GeV << "which is much smaller than the mass of the electron.\n" << "This is probably due to reading events from a LHEF,\nskipping radiation in this case.\n"; generator()->logWarning( Exception(message.str(), Exception::warning)); return children; } } // momenta before radiation in lab for(unsigned int ix=0;ix<2;++ix) _qlab[ix]=children[ix]->momentum(); // get the charges of the particles in units of the positron charge _charge=children[0]->dataPtr()->iCharge()*children[1]->dataPtr()->iCharge()/9.; // boost the momenta to the rest frame Boost boostv(-p.momentum().boostVector()); // boost the particles to the parent rest frame // and set the initial momenta of the charged particles // in the dipole rest frame: currently this is the same // as the boson rest frame... for(unsigned int ix=0;ix<2;++ix) { children[ix]->deepBoost(boostv); _qdrf[ix]=children[ix]->momentum(); _qprf[ix]=children[ix]->momentum(); } _parent->boost(boostv); // perform the unweighting double wgt; unsigned int ntry(0); do { ++ntry; wgt = makePhotons(-boostv,children); // Error checks if ( std::isnan(wgt) ) { generator()->log() << "Infinite weight for decay " << p.PDGName() << " " << children[0]->PDGName() << " " << children[1]->PDGName() << '\n'; wgt = 0.0; } else if ( wgt < 0.0 && _mode != 5 ) { generator()->log() << "Negative weight for decay " << p.PDGName() << " " << children[0]->PDGName() << " " << children[1]->PDGName() << "in FFDipole: Weight = " << wgt << '\n'; if ( Debug::level ) printDebugInfo(p,children,wgt); } else if ( wgt > _maxwgt ) { generator()->log() << "Weight "<< wgt<<" exceeds maximum for decay " << p.PDGName() << ' ' << children[0]->PDGName() << " " << children[1]->PDGName() << " in FFDipole:\nresetting maximum weight.\n" << "Old Maximum = " << _maxwgt; _maxwgt = min(1.1 * wgt, 10.0); generator()->log() << " New Maximum = " << wgt << '\n'; if ( Debug::level && _mode!=5 ) printDebugInfo(p,children,wgt); } // End of error checks _wgtsum += wgt; _wgtsq += sqr(wgt); ++_nweight; } while ( wgt<(_maxwgt*UseRandom::rnd()) && ntry<_maxtry ); if(ntry>=_maxtry) { generator()->log() << "FFDipole failed to generate QED radiation for the decay " << p.PDGName() << " -> " << children[0]->PDGName() << " " << children[1]->PDGName() << '\n'; _parent->boost(-boostv); for(unsigned int ix=0;ix<2;++ix) children[ix]->deepBoost(-boostv); return children; } // produce products after radiation if needed if(_multiplicity>0) { // change the momenta of the children, they are currently // in original rest frame for(unsigned int ix=0;ix<2;++ix) { // unit vector along direction Boost br = children[ix]->momentum().vect().unit(); // calculate the boost vector using expression accurate for beta->1 double beta(sqrt((_qdrf[ix].e()+_m[ix+1])*(_qdrf[ix].e()-_m[ix+1]))/ _qdrf[ix].e()); double ombeta(sqr(_m[ix+1]/_qdrf[ix].e())/(1.+beta)); double betap(sqrt((_qnewdrf[ix].e()+_m[ix+1])*(_qnewdrf[ix].e()-_m[ix+1])) /_qnewdrf[ix].e()); double ombetap(sqr(_m[ix+1]/_qnewdrf[ix].e())/(1.+betap)); // boost to get correct momentum in dipole rest frame double bv = -(ombetap-ombeta)/(beta*ombetap + ombeta); br *= bv; children[ix]->deepBoost(br); // boost to the parent rest frame Lorentz5Momentum pnew(_bigLdrf); pnew.setMass(_m[0]); pnew.rescaleEnergy(); br = pnew.findBoostToCM(); children[ix]->deepBoost(br); // boost back to the lab children[ix]->deepBoost(-boostv); } // add the photons to the event record tcPDPtr photon=getParticleData(ParticleID::gamma); for(unsigned int ix=0;ix<_multiplicity;++ix) { // add if not removed because energy too low if(!_photcut[ix]) { PPtr newphoton=new_ptr(Particle(photon)); newphoton->set5Momentum(_llab[ix]); children.push_back(newphoton); } } _parent->boost(-boostv); //printDebugInfo(p, children, wgt); return children; } // otherwise just return the original particles else { for(unsigned int ix=0;ix<2;++ix) children[ix]->deepBoost(-boostv); _parent->boost(-boostv); return children; } } // member which generates the photons double FFDipole::makePhotons(const Boost & boostv, const ParticleVector & children) { // set the initial parameters // number of photons (zero) _multiplicity=0; // zero size of photon vectors _ldrf.clear(); _lprf.clear(); _llab.clear(); // zero size of angle storage _sinphot.clear(); _cosphot.clear(); _photcut.clear(); _photonwgt.clear(); // zero total momenta of the photons _bigLdrf=Lorentz5Momentum(); _bigLprf=Lorentz5Momentum(); // set the initial values of the reweighting factors to one _dipolewgt = 1.0; _yfswgt = 1.0; _jacobianwgt = 1.0; _mewgt = 1.0; // calculate the velocities of the charged particles (crude/overvalued) double beta1(sqrt((_qdrf[0].e()+_m[1])*(_qdrf[0].e()-_m[1]))/_qdrf[0].e()); double beta2(sqrt((_qdrf[1].e()+_m[2])*(_qdrf[1].e()-_m[2]))/_qdrf[1].e()); // calculate 1-beta to avoid numerical problems double ombeta1(sqr(_m[1]/_qdrf[0].e())/(1.+beta1)); double ombeta2(sqr(_m[2]/_qdrf[1].e())/(1.+beta2)); // calculate the average photon multiplicity double aver(YFSFormFactors::nbarFF(beta1,ombeta1,beta2,ombeta2,_charge, _emax,_emin,_dipoleopt==1)); // calculate the number of photons using the poisson _multiplicity = _mode !=5 ? UseRandom::rndPoisson(aver) : 1; // calculate the first part of the YFS factor // (N.B. crude form factor is just exp(-aver) to get a poisson) _yfswgt *= exp(aver); // if photons produced if(_multiplicity>0) { _photonwgt.resize(_multiplicity); // generate the photon momenta with respect to q1 // keeping track of the weight for(unsigned int ix=0;ix<_multiplicity;++ix) _photonwgt[ix] = photon(beta1,ombeta1,beta2,ombeta2); // rotate the photons so in dipole rest frame rather // than angle measured w.r.t q1 first work out the rotation SpinOneLorentzRotation rotation; rotation.setRotateZ(-_qdrf[0].phi()); rotation.rotateY(_qdrf[0].theta()); rotation.rotateZ(_qdrf[0].phi()); // rotate the total _bigLdrf *= rotation; // rotate the photons for(unsigned int ix=0;ix<_multiplicity;++ix) _ldrf[ix]*=rotation; // boost the momenta without any removal of low energy photons // resize arrays _photcut.resize(_multiplicity,false); _lprf.resize(_multiplicity); _llab.resize(_multiplicity); // perform the boost if(!boostMomenta(boostv)){return 0.;} // apply the cut on the photon energy if needed unsigned int nremoved(removePhotons()); // redo the boost if we have removed photons if(nremoved!=0){if(!boostMomenta(boostv)){return 0.;}} // form factor part of the removal term to remove existing cut if(_energyopt!=0) _dipolewgt *= YFSFormFactors::exponentialYFSFF(beta1,ombeta1,beta2,ombeta2, _qdrf[0].e(),_qdrf[1].e(), _m[1],_m[2],_m[0]*_m[0], _charge,_emin); // calculate the new dipole weight // calculate velocities and 1-velocites beta1=sqrt((_qnewdrf[0].e()+_m[1])*(_qnewdrf[0].e()-_m[1]))/_qnewdrf[0].e(); beta2=sqrt((_qnewdrf[1].e()+_m[2])*(_qnewdrf[1].e()-_m[2]))/_qnewdrf[1].e(); ombeta1=sqr(_m[1]/_qnewdrf[0].e())/(1.+beta1); ombeta2=sqr(_m[2]/_qnewdrf[1].e())/(1.+beta2); for(unsigned int ix=0;ix<_multiplicity;++ix) { if(!_photcut[ix]) _dipolewgt *= exactDipoleWeight(beta1,ombeta1,beta2,ombeta2,ix)/ _photonwgt[ix]; } // calculate the weight for the photon removal Energy2 s((_qnewdrf[0]+_qnewdrf[1]).m2()); // calculate the second part of the yfs form factor // this is different for the different photon removal options // option with no removal if(_energyopt==0) { _yfswgt *= YFSFormFactors::exponentialYFSFF(beta1,ombeta1,beta2,ombeta2, _qnewdrf[0].e(),_qnewdrf[1].e(), _m[1],_m[2],s,_charge,_emin); } // weight for option with cut in the rest frame else if(_energyopt==1) { // yfs piece double nbeta1(sqrt( (_qnewprf[0].e()+_m[1])*(_qnewprf[0].e()-_m[1])) /_qnewprf[0].e()); double nbeta2(sqrt( (_qnewprf[1].e()+_m[2])*(_qnewprf[1].e()-_m[2])) /_qnewprf[1].e()); double nomb1 (sqr(_m[1]/_qnewprf[0].e())/(1.+nbeta1)); double nomb2 (sqr(_m[2]/_qnewprf[1].e())/(1.+nbeta2)); _yfswgt *= YFSFormFactors::exponentialYFSFF(nbeta1,nomb1,nbeta2,nomb2, _qnewprf[0].e(),_qnewprf[1].e(), _m[1],_m[2],s,_charge,_eminrest); // dipole piece // Find the momenta of the particles of original particles in new rest frame Lorentz5Momentum pnew(_bigLdrf.x(),_bigLdrf.y(), _bigLdrf.z(),_bigLdrf.e(),_m[0]); pnew.rescaleEnergy(); SpinOneLorentzRotation boost(pnew.findBoostToCM()); Lorentz5Momentum q1=boost*_qdrf[0]; Lorentz5Momentum q2=boost*_qdrf[1]; // use this to calculate the form factor nbeta1=sqrt( (q1.e()+_m[1])*(q1.e()-_m[1]))/q1.e(); nbeta2=sqrt( (q2.e()+_m[2])*(q2.e()-_m[2]))/q2.e(); nomb1 =sqr(_m[1]/q1.e())/(1.+nbeta1); nomb2 =sqr(_m[2]/q2.e())/(1.+nbeta2); _dipolewgt /=YFSFormFactors::exponentialYFSFF(nbeta1,nomb1,nbeta2,nomb2, q1.e(),q2.e(), _m[1],_m[2],_m[0]*_m[0], _charge,_eminrest); } // weight for option with cut in the rest frame else if(_energyopt==2) { // yfs piece double nbeta1(sqrt( (_qnewlab[0].e()+_m[1])*(_qnewlab[0].e()-_m[1])) /_qnewlab[0].e()); double nbeta2(sqrt( (_qnewlab[1].e()+_m[2])*(_qnewlab[1].e()-_m[2])) /_qnewlab[1].e()); double nomb1 (sqr(_m[1]/_qnewlab[0].e())/(1.+nbeta1)); double nomb2 (sqr(_m[2]/_qnewlab[1].e())/(1.+nbeta2)); _yfswgt *= YFSFormFactors::exponentialYFSFF(nbeta1,nomb1,nbeta2,nomb2, _qnewlab[0].e(),_qnewlab[1].e(), _m[1],_m[2],s,_charge,_eminlab); // dipole piece // Find the momenta of the particles of original particles in new rest frame Lorentz5Momentum pnew(_bigLdrf.x(),_bigLdrf.y(), _bigLdrf.z(),_bigLdrf.e(),_m[0]); pnew.rescaleEnergy(); SpinOneLorentzRotation boost(pnew.findBoostToCM()); Lorentz5Momentum q1=boost*_qdrf[0]; Lorentz5Momentum q2=boost*_qdrf[1]; // then boost to the lab boost.setBoost(boostv); q1 *=boost; q2 *=boost; // use this to calculate the form factor nbeta1=sqrt( (q1.e()+_m[1])*(q1.e()-_m[1])) /q1.e(); nbeta2=sqrt( (q2.e()+_m[2])*(q2.e()-_m[2])) /q2.e(); nomb1 =sqr(_m[1]/q1.e())/(1.+nbeta1); nomb2 =sqr(_m[2]/q2.e())/(1.+nbeta2); _dipolewgt /=YFSFormFactors::exponentialYFSFF(nbeta1,nomb1,nbeta2,nomb2, q1.e(),q2.e(),_m[1],_m[2], _m[0]*_m[0],_charge,_eminlab); } // Calculating jacobian weight _jacobianwgt = jacobianWeight(); // Calculate the weight for the corrections _mewgt = meWeight(children); } // otherwise copy momenta else { for(unsigned int ix=0;ix<2;++ix) { _qnewdrf[ix]=_qdrf[ix]; _qnewprf[ix]=_qprf[ix]; _qnewlab[ix]=_qlab[ix]; } _jacobianwgt = 1.0; _yfswgt*=YFSFormFactors::exponentialYFSFF(beta1,ombeta1,beta2,ombeta2, _qdrf[0].e(),_qdrf[1].e(), _m[1],_m[2],_m[0]*_m[0], _charge,_emin); _dipolewgt = 1.0; } double wgt; if(_mode!=5) { // virtual corrections _mewgt += virtualWeight(children); // calculate the weight depending on the option if(_mode==0) wgt = _maxwgt; else if(_mode==1) wgt = _mewgt*_yfswgt*_jacobianwgt*_dipolewgt; else if(_mode==2) wgt = _jacobianwgt*_yfswgt*_dipolewgt; else if(_mode==3) wgt = _yfswgt*_dipolewgt; else wgt = _yfswgt; } // special to test NLO results else { double beta1 = sqrt((_qdrf[0].e()+_m[1])*(_qdrf[0].e()-_m[1]))/_qdrf[0].e(); double beta2 = sqrt((_qdrf[1].e()+_m[2])*(_qdrf[1].e()-_m[2]))/_qdrf[1].e(); double ombeta1 = sqr(_m[1]/_qdrf[0].e())/(1.+beta1); double ombeta2 = sqr(_m[2]/_qdrf[1].e())/(1.+beta2); double yfs = YFSFormFactors::YFSFF(beta1,ombeta1,beta2,ombeta2, _qdrf[0].e(),_qdrf[1].e(), _m[1],_m[2],_m[0]*_m[0], _charge,_emin); double nbar = YFSFormFactors::nbarFF(beta1,ombeta1,beta2,ombeta2,_charge, _emax,_emin,_dipoleopt==1); wgt = 1.+virtualWeight(children)+yfs+nbar*_dipolewgt*_mewgt*_jacobianwgt; } return wgt; } double FFDipole::photon(double beta1,double ombeta1, double beta2,double ombeta2) { // generate the polar angle double r1,r2,costh,sinth,opbc,ombc; // relative weights for the two terms double Pp(log((1+beta2)/ombeta2)); double Pm(log((1+beta1)/ombeta1)); Pp/=(Pp+Pm); // generate the angle double wgt=1.; do { r1=UseRandom::rnd(); r2=UseRandom::rnd(); // 1/(1+bc) branch if(r1<=Pp) { opbc = pow(1.+beta2,r2)*pow(ombeta2,1.-r2); costh = -1./beta2*(1.-opbc); ombc = 1.-beta1*costh; sinth = sqrt(opbc*(2.-opbc)-(1.+beta2)*ombeta2*sqr(costh)); } // 1/(1-bc) branch else { ombc = pow(1.+beta1,1.-r2)*pow(ombeta1,r2); costh = 1./beta1*(1.-ombc); opbc = 1.+beta2*costh; sinth = sqrt(ombc*(2.-ombc)-(1.+beta1)*ombeta1*sqr(costh)); } // wgt for rejection if(_dipoleopt==1) wgt = 1.-0.5/(1.+beta1*beta2)*(ombeta1*(1.+beta1)*opbc/ombc+ ombeta2*(1.+beta2)*ombc/opbc); } while(UseRandom::rnd()>wgt); // generate the polar angle randomly in -pi->+pi double phi(-pi+UseRandom::rnd()*2.*pi); // generate the ln(energy) uniformly in ln(_emin)->ln(_emax) Energy en(pow(_emax/_emin,UseRandom::rnd())*_emin); // calculate the weight (omit the pre and energy factors // which would cancel later anyway) if(_dipoleopt==0) wgt = 0.5*(1.+beta1*beta2)/opbc/ombc; else wgt = 0.25*(2.*(1.+beta1*beta2)/opbc/ombc -ombeta1*(1.+beta1)/sqr(ombc) -ombeta2*(1.+beta2)/sqr(opbc)); // store the angles _cosphot.push_back(costh); _sinphot.push_back(sinth); // store the four vector for the photon _ldrf.push_back(Lorentz5Momentum(en*sinth*cos(phi), en*sinth*sin(phi), en*costh,en, ZERO)); // add the photon momentum to the total _bigLdrf+=_ldrf.back(); // return the weight return wgt; } double FFDipole::meWeight(const ParticleVector & children) { if(_multiplicity==0) return 1.; // option which does nothing if(_betaopt==0) { return 1.; } // collinear approx else if(_betaopt <= 3) { return collinearWeight(children); } else if (_betaopt == 4 ) { if(_decayer&&_decayer->hasRealEmissionME()) { double outwgt=1.; // values of beta etc to evaluate the dipole double beta1(sqrt( (_qnewdrf[0].e()+_m[1])*(_qnewdrf[0].e()-_m[1]))/ _qnewdrf[0].e()); double beta2(sqrt( (_qnewdrf[1].e()+_m[2])*(_qnewdrf[1].e()-_m[2]))/ _qnewdrf[1].e()); double ombeta1(sqr(_m[1]/_qnewdrf[0].e())/(1.+beta1)); double ombeta2(sqr(_m[2]/_qnewdrf[1].e())/(1.+beta2)); // storage of the weights ParticleVector ptemp; for(unsigned int ix=0;ixdataPtr()))); ptemp.push_back(new_ptr(Particle(getParticleData(ParticleID::gamma)))); for(unsigned int i=0;i<_multiplicity;++i) { PPtr new_parent = new_ptr(Particle(*_parent)); if(_photcut[i]) continue; // compute the angle terms // if cos is greater than zero use result accurate as cos->1 double opbc,ombc; if(_cosphot[i]>0) { opbc=1.+beta2*_cosphot[i]; ombc=ombeta1+beta1*sqr(_sinphot[i])/(1.+_cosphot[i]); } // if cos is less than zero use result accurate as cos->-1 else { opbc=ombeta2+beta2*sqr(_sinphot[i])/(1.-_cosphot[i]); ombc=1.-beta1*_cosphot[i]; } // dipole factor for denominator double dipole = 2./opbc/ombc*(1.+beta1*beta2 -0.5*ombeta1*(1.+beta1)*opbc/ombc -0.5*ombeta2*(1.+beta2)*ombc/opbc); // energy and momentum of the photon Energy L0(_ldrf[i].e()),modL(_ldrf[i].rho()); // 3-momenta of charged particles Energy modq(_qdrf[0].rho()); // calculate the energy of the fermion pair Energy newE12(-L0+sqrt(sqr(_m[0])+sqr(modL))); // 3-momentum rescaling factor (NOT energy rescaling). double kappa(Kinematics::pstarTwoBodyDecay(newE12,_m[1],_m[2])/modq); // calculate the rescaled momenta Lorentz5Momentum porig[3]; for(unsigned int ix=0;ix<2;++ix) { porig[ix] = kappa*_qdrf[ix]; porig[ix].setMass(_m[ix+1]); porig[ix].rescaleEnergy(); } porig[2] = _ldrf[i]; // calculate the momentum of the decaying particle in dipole rest frame Lorentz5Momentum pnew(_ldrf[i].x(),_ldrf[i].y(), _ldrf[i].z(),_ldrf[i].e(),_m[0]); pnew.rescaleEnergy(); // Find the momenta of the particles in the rest frame of the parent... // First get the boost from the parent particle Boost boost = pnew.findBoostToCM(); LorentzRotation rot1(-boost, pnew.e()/pnew.mass()); // check the photon energy Lorentz5Momentum ptest = _ldrf[i]; ptest.boost(boost); if(_energyopt==1&&ptest.e()<_eminrest) continue; new_parent->transform(rot1); // rotation to put the emitter along the z axis // first particle emits unsigned int iemit = _cosphot[i]>0. ? 0 : 1; LorentzRotation rot2; rot2.setRotateZ(-porig[iemit].phi()); rot2.rotateY(porig[iemit].theta()); rot2.rotateZ(porig[iemit].phi()); rot2.invert(); // Boost the momenta of the charged particles for(unsigned int ix=0;ix<3;++ix) { porig[ix].transform(rot2); ptemp[ix]->set5Momentum(porig[ix]); } new_parent->transform(rot2); if(_cosphot[i]>0.) { outwgt -= _decayer-> realEmissionME(_decayer->imode(),*new_parent,ptemp, 0,_cosphot[i],_sinphot[i],rot1,rot2)/ (_charge/sqr(_ldrf[i].e())*dipole); } else { outwgt -= _decayer-> realEmissionME(_decayer->imode(),*new_parent,ptemp, 1,-_cosphot[i],_sinphot[i],rot1,rot2)/ (_charge/sqr(_ldrf[i].e())*dipole); } rot1.invert(); rot2.invert(); new_parent->transform(rot2); new_parent->transform(rot1); } return outwgt; } else return collinearWeight(children); } return 1.; } double FFDipole::collinearWeight(const ParticleVector & children) { double outwgt=1.; // spins of the decay products PDT::Spin spin1(children[0]->dataPtr()->iSpin()); PDT::Spin spin2(children[1]->dataPtr()->iSpin()); // values of beta etc to evaluate the dipole double beta1(sqrt( (_qnewdrf[0].e()+_m[1])*(_qnewdrf[0].e()-_m[1]))/ _qnewdrf[0].e()); double beta2(sqrt( (_qnewdrf[1].e()+_m[2])*(_qnewdrf[1].e()-_m[2]))/ _qnewdrf[1].e()); double ombeta1(sqr(_m[1]/_qnewdrf[0].e())/(1.+beta1)); double ombeta2(sqr(_m[2]/_qnewdrf[1].e())/(1.+beta2)); // storage of the weights double twgt,dipole; double opbc,ombc; // compute the collinear approx for(unsigned int i=0;i<_multiplicity;++i) { if(_photcut[i]) continue; // compute the angle terms // if cos is greater than zero use result accurate as cos->1 if(_cosphot[i]>0) { opbc=1.+beta2*_cosphot[i]; ombc=ombeta1+beta1*sqr(_sinphot[i])/(1.+_cosphot[i]); } // if cos is less than zero use result accurate as cos->-1 else { opbc=ombeta2+beta2*sqr(_sinphot[i])/(1.-_cosphot[i]); ombc=1.-beta1*_cosphot[i]; } // dipole factor for denominator dipole = 2.*(1.+beta1*beta2 -0.5*ombeta1*(1.+beta1)*opbc/ombc -0.5*ombeta2*(1.+beta2)*ombc/opbc); twgt=0.; // correction for the first particle double ratio(_ldrf[i].e()/_qnewdrf[0].e()); if(spin1==PDT::Spin0) twgt += 0.; else if(spin1==PDT::Spin1Half) twgt += opbc*ratio/(1.+(1.+beta1*beta2)/ratio/opbc); else twgt += 2.*sqr(opbc*ratio) * (+1./(1+beta1*beta2+_ldrf[i].e()/_qnewdrf[1].e()*ombc) +(1.+beta1*beta2)/sqr(1.+beta1*beta2 +_ldrf[i].e()/_qnewdrf[0].e()*opbc)); // correction for the second particle ratio =_ldrf[i].e()/_qnewdrf[1].e(); if(spin2==PDT::Spin0) twgt += 0.; else if(spin2==PDT::Spin1Half) twgt += ombc*ratio/(1.+(1.+beta1*beta2)/ratio/ombc); else twgt += 2.*sqr(ombc*ratio) * (1./(1. + beta1*beta2 + _ldrf[i].e()/_qnewdrf[0].e()*opbc) + (1.+beta1*beta2) / sqr(1. + beta1*beta2 + _ldrf[i].e()/_qnewdrf[1].e()*ombc)); twgt/=dipole; outwgt+=twgt; } return outwgt; } bool FFDipole::boostMomenta(const Boost & boostv) { // total energy and momentum of photons Energy L0(_bigLdrf.e()),modL(_bigLdrf.rho()); // 3-momenta of charged particles Energy modq(_qdrf[0].rho()); // calculate the energy of the fermion pair Energy newE12(-L0+sqrt(_m[0]*_m[0]+modL*modL)); // check this is allowed if(newE12<_m[1]+_m[2]){return false;} // 3-momentum rescaling factor (NOT energy rescaling). double kappa(Kinematics::pstarTwoBodyDecay(newE12,_m[1],_m[2])/modq); // calculate the rescaled momenta for(unsigned int ix=0;ix<2;++ix) { _qnewdrf[ix] = kappa*_qdrf[ix]; _qnewdrf[ix].setMass(_m[ix+1]); _qnewdrf[ix].rescaleEnergy(); } // calculate the momentum of the decaying particle in dipole rest frame Lorentz5Momentum pnew(_bigLdrf.x(),_bigLdrf.y(), _bigLdrf.z(),_bigLdrf.e(),_m[0]); pnew.rescaleEnergy(); // Find the momenta of the particles in the rest frame // of the parent... // First get the boost from the parent particle SpinOneLorentzRotation boost(pnew.findBoostToCM()); // Boost the momenta of the charged particles for(unsigned int ix=0;ix<2;++ix) _qnewprf[ix]=boost*_qnewdrf[ix]; // Boost the total photon momentum _bigLprf=boost*_bigLdrf; // Boost the individual photon momenta for(unsigned int ix=0;ix<_multiplicity;++ix){_lprf[ix]=boost*_ldrf[ix];} // Now boost from the parent rest frame to the lab frame boost.setBoost(boostv); // Boosting charged particles for(unsigned int ix=0;ix<2;++ix){_qnewlab[ix]=boost*_qnewprf[ix];} // Boosting total photon momentum _bigLlab=boost*_bigLprf; // Boosting individual photon momenta for(unsigned int ix=0;ix<_multiplicity;++ix){_llab[ix]=boost*_lprf[ix];} return true; } unsigned int FFDipole::removePhotons() { unsigned int nremoved(0); // apply the cut in the rest frame if(_energyopt==1) { for(unsigned int ix=0;ix<_multiplicity;++ix) { if(_lprf[ix].e()<_eminrest) { ++nremoved; _photcut[ix]=true; _bigLdrf-=_ldrf[ix]; _ldrf[ix]=Lorentz5Momentum(); } } } // apply the cut in the lab frame else if(_energyopt==2) { for(unsigned int ix=0;ix<_multiplicity;++ix) { if(_llab[ix].e()<_eminlab) { ++nremoved; _photcut[ix]=true; _bigLdrf-=_ldrf[ix]; _ldrf[ix]=Lorentz5Momentum(); } } } // correction factor for dipoles if needed if(_dipoleopt==0&&nremoved!=0) { // calculate the velocities of the charged particles (crude/overvalued) double beta1(sqrt((_qdrf[0].e()+_m[1])*(_qdrf[0].e()-_m[1]))/_qdrf[0].e()); double beta2(sqrt((_qdrf[1].e()+_m[2])*(_qdrf[1].e()-_m[2]))/_qdrf[1].e()); // calculate 1-beta to avoid numerical problems double ombeta1(sqr(_m[1]/_qdrf[0].e())/(1.+beta1)); double ombeta2(sqr(_m[2]/_qdrf[1].e())/(1.+beta2)); // calculate the weights for(unsigned int ix=0;ix<_multiplicity;++ix) { if(_photcut[ix]) _dipolewgt *= exactDipoleWeight(beta1,ombeta1,beta2,ombeta2,ix)/_photonwgt[ix]; } } // return number of remove photons return nremoved; } double FFDipole::virtualWeight(const ParticleVector & children) { double output = 0.; // Virtual corrections for beta_0: // These should be zero for the scalar case as there is no // collinear singularity going by the dipoles above... // Use mass of decaying particle... if(_betaopt==2) { if((children[0]->dataPtr()->iSpin())==2&& (children[1]->dataPtr()->iSpin())==2 ) { output += (1.0*YFSFormFactors::_alpha/pi) * log(sqr(_m[0]/_m[1])); } } // OR Use invariant mass of final state children... else if(_betaopt==3) { if((children[0]->dataPtr()->iSpin())==2&& (children[1]->dataPtr()->iSpin())==2 ) { output += (1.0*YFSFormFactors::_alpha/pi) * log((_qnewprf[0]+_qnewprf[1]).m2()/sqr(_m[1])); } } else if (_betaopt==4) { if(_decayer&&_decayer->hasOneLoopME()) { output += _decayer->oneLoopVirtualME(_decayer->imode(),*_parent, children); } else { output += (1.0*YFSFormFactors::_alpha/pi) * log(sqr(_m[0]/_m[1])); } } return output; } void FFDipole::dofinish() { Interfaced::dofinish(); if(_weightOutput) { _wgtsum /= double(_nweight); _wgtsq /= double(_nweight); _wgtsq = max(_wgtsq - sqr(_wgtsum),0.); _wgtsq /= double(_nweight); _wgtsq = sqrt(_wgtsq); generator()->log() << "The average weight for QED Radiation in " << fullName() << " was " << _wgtsum << " +/- " << _wgtsq << '\n'; } } diff --git a/Decay/Radiation/FFDipole.h b/Decay/Radiation/FFDipole.h --- a/Decay/Radiation/FFDipole.h +++ b/Decay/Radiation/FFDipole.h @@ -1,466 +1,461 @@ // -*- C++ -*- // // FFDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFDipole_H #define HERWIG_FFDipole_H // // This is the declaration of the FFDipole class. // #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Decay/DecayIntegrator.fh" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Utilities/Maths.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Interface/Interfaced.h" #include "FFDipole.fh" namespace Herwig { using namespace ThePEG; using ThePEG::Constants::pi; /** \ingroup Decay * * The FFDipole class generates radiation from a final-final dipole for * the generation of photons in decay by the SOPTHY algorithm. * * @see SOPTHY * @see \ref FFDipoleInterfaces "The interfaces" * defined for FFDipole. */ class FFDipole: public Interfaced { public: /** * The default constructor. */ FFDipole() : _emin(1.e-6*MeV), _eminrest(100*MeV), _eminlab(100*MeV), _emax(), _multiplicity(), _m(3), _charge(), _qdrf(2), _qnewdrf(2), _qprf(2), _qnewprf(2), _qlab(2), _qnewlab(2), _dipolewgt(), _yfswgt(), _jacobianwgt(), _mewgt(), _maxwgt(7.0), _mode(1), _maxtry(500), _energyopt(1), _betaopt(4), _dipoleopt(), _nweight(0), _wgtsum(0.), _wgtsq(0.), _weightOutput(false) {} - /** - * Destructor - */ - virtual ~FFDipole(); - public: /** * Member to generate the photons from the dipole * @param p The decaying particle * @param children The decay products * @param decayer The decayer for this mode * @return The decay products with additional radiation */ virtual ParticleVector generatePhotons(const Particle & p, ParticleVector children, tDecayIntegratorPtr decayer); 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 {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** * Generate the momentum of a photon * @param beta1 The velocity, \f$\beta_1\f$, of the first charged particle * @param ombeta1 One minus the velocity, \f$1-\beta_1\f$, of the first * charged particle which is supplied for numerical stability * @param beta2 The velocity, \f$\beta_2\f$, of the second charged particle * @param ombeta2 One minus the velocity, \f$1-\beta_2\f$, of the * second charged particle which is supplied for numerical stability * @return The contribution to the dipole weight */ double photon(double beta1,double ombeta1, double beta2, double ombeta2); /** * Calculate the exact weight for the dipole. * @param beta1 Velocity of the first charged particle, \f$\beta_1\f$ * @param beta2 Velocity of the second charged particle, \f$\beta_2\f$. * @param ombeta1 One minus the velocity of the first particle, \f$1-\beta_1\f$ * @param ombeta2 One minus the velocity of the second particle, \f$1-\beta_2\f$ * @param iphot The number of the photon for which the weight is required * @return The weight */ double exactDipoleWeight(double beta1,double ombeta1, double beta2,double ombeta2,unsigned int iphot) { double opbc,ombc; // if cos is greater than zero use result accurate as cos->1 if(_cosphot[iphot]>0) { opbc=1.+beta2*_cosphot[iphot]; ombc=ombeta1+beta1*sqr(_sinphot[iphot])/(1.+_cosphot[iphot]); } // if cos is less than zero use result accurate as cos->-1 else { opbc=ombeta2+beta2*sqr(_sinphot[iphot])/(1.-_cosphot[iphot]); ombc=1.-beta1*_cosphot[iphot]; } return 0.5/(opbc*ombc)*(1.+beta1*beta2 -0.5*ombeta1*(1.+beta1)*opbc/ombc -0.5*ombeta2*(1.+beta2)*ombc/opbc); } /** * Jacobian factor for the weight */ double jacobianWeight() { Energy pcm1=Kinematics::pstarTwoBodyDecay(_m[0],_m[1],_m[2]); Energy m12 =sqrt((_qnewdrf[0]+_qnewdrf[1]).m2()) ; Energy pcm2=Kinematics::pstarTwoBodyDecay(m12,_m[1],_m[2]) ; double betaprobeta = pcm2*_m[0]/pcm1/m12 ; double spros = sqr(m12/_m[0]) ; double deltafn = m12/(m12+_bigLdrf.e()); return betaprobeta*spros*deltafn ; } /** * Matrix element weight */ double meWeight(const ParticleVector & children); /** * Member which generates the photons * @param boost Boost vector to take the particles produced back from * the decaying particle's rest frame to the lab * @param children The decay products */ double makePhotons(const Boost & boost, const ParticleVector & children); /** * Boost all the momenta from the dipole rest frame via the parent rest frame * to the lab * @param boost The boost vector from the rest frame to the lab * @return Whether or not it suceeded */ bool boostMomenta(const Boost & boost); /** * Remove any photons which fail the energy cuts * @return Number of photons removed */ unsigned int removePhotons(); /** * The real emission weight in the collinear limit */ double collinearWeight(const ParticleVector & children); /** * The vrtiual correction weight */ double virtualWeight(const ParticleVector & children); protected: /** @name Standard Interfaced functions. */ //@{ /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFDipole & operator=(const FFDipole &) = delete; private: /** * Debug output **/ void printDebugInfo(const Particle & p, const ParticleVector & children, double wgt) const; private: /** * The minimum photon energy in the boosted frame */ Energy _emin; /** * The minimum photon energy in the rest frame */ Energy _eminrest; /** * The minimum photon energy in the lab frame */ Energy _eminlab; /** * The maximum photon energy */ Energy _emax; /** * Photon multiplicity being generated */ unsigned int _multiplicity; /** * Masses of the particles involved */ vector _m; /** * Produce of the particles charges */ double _charge; /** * Momenta of the particles in the dipole rest frame */ //@{ /** * Momenta of the charged particles in the dipole rest frame before radiation */ vector _qdrf; /** * Momenta of the charged particles in the dipole rest frame after radiation */ vector _qnewdrf; /** * Momenta of the photons in the dipole rest frame */ vector _ldrf; /** * Total momentum of the photons in the dipole rest frame */ Lorentz5Momentum _bigLdrf; //@} /** * Momentum of the particles in the parent's rest frame */ //@{ /** * Momenta of the charged particles in the parent's rest frame before radiation */ vector _qprf; /** * Momenta of the charged particles in the parent's rest frame after radiation */ vector _qnewprf; /** * Momenta of the photons in the parent rest frame */ vector _lprf; /** * Total momentum of the photons in the parent rest frame */ Lorentz5Momentum _bigLprf; //@} /** * Momentum of the particles in the lab frame */ //@{ /** * Momenta of the charged particles in the lab frame before radiation */ vector _qlab; /** * Momenta of the charged particles in the lab frame after radiation */ vector _qnewlab; /** * Momenta of the photons in the lab frame */ vector _llab; /** * Total momentum of the photons in the lab frame */ Lorentz5Momentum _bigLlab; //@} /** * Reweighting factors due to differences between the true and crude * distributions */ //@{ /** * Reweighting factor for the real emission */ double _dipolewgt; /** * Reweighting factor for the YFS form-factor */ double _yfswgt; /** * Reweighting factor due to phase space */ double _jacobianwgt; /** * Reweighting factor due to matrix element corrections */ double _mewgt; /** * Maximum weight */ double _maxwgt; //@} /** * Angles of the photons with respect to the first charged particle * which are stored for numerical accuracy */ //@{ /** * Cosine of the photon angles */ vector _cosphot; /** * Sine of the photon angles */ vector _sinphot; //@} /** * Weights for the individual photons */ vector _photonwgt; /** * Whether a given photon passes the energy cut */ vector _photcut; /** * Type of unweighting to perform */ unsigned int _mode; /** * Maximum number of attempts to generate a result */ unsigned int _maxtry; /** * Option for the energy cut-off */ unsigned int _energyopt; /** * Option for the inclusion of higher order corrections */ unsigned int _betaopt; /** * Option for the form of the primary distribution */ unsigned int _dipoleopt; /** * The decayer */ tDecayIntegratorPtr _decayer; /** * The decaying particle */ tPPtr _parent; /** * Storage of averages etc for testing */ //@{ /** * Number of attempts */ unsigned int _nweight; /** * Sum of weights */ double _wgtsum; /** * Sum of squares of weights */ double _wgtsq; /** * Whether or not to output the averages */ bool _weightOutput; //@} }; } #endif /* HERWIG_FFDipole_H */ diff --git a/Decay/WeakCurrents/WeakBaryonCurrent.cc b/Decay/WeakCurrents/WeakBaryonCurrent.cc --- a/Decay/WeakCurrents/WeakBaryonCurrent.cc +++ b/Decay/WeakCurrents/WeakBaryonCurrent.cc @@ -1,202 +1,202 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the WeakBaryonCurrent class. // #include "WeakBaryonCurrent.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/HelicityFunctions.h" using namespace Herwig; WeakBaryonCurrent::WeakBaryonCurrent() {} IBPtr WeakBaryonCurrent::clone() const { return new_ptr(*this); } IBPtr WeakBaryonCurrent::fullclone() const { return new_ptr(*this); } void WeakBaryonCurrent::persistentOutput(PersistentOStream & os) const { os << formFactor_; } void WeakBaryonCurrent::persistentInput(PersistentIStream & is, int) { is >> formFactor_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigWeakBaryonCurrent("Herwig::WeakBaryonCurrent", "Herwig.so"); void WeakBaryonCurrent::Init() { static ClassDocumentation documentation ("The WeakBaryonCurrent class is a wrapper for the BaryonFormFactor" " so it can be used as a WeakCurrent"); static Reference interfaceFormFactor ("FormFactor", "The baryon form factor", &WeakBaryonCurrent::formFactor_, false, false, true, false, false); } void WeakBaryonCurrent::doinit() { // initialize the form factor formFactor_->init(); // set the modes for(unsigned int iloc=0;ilocnumberOfFactors();++iloc) { int ispin(0), ospin(0), spect1(0), spect2(0), inquark(0), outquark(0); formFactor_->formFactorInfo(iloc,ispin,ospin,spect1,spect2,inquark,outquark); addDecayMode(outquark,-inquark); } setInitialModes(formFactor_->numberOfFactors()); WeakCurrent::doinit(); } // complete the construction of the decay mode for integration bool WeakBaryonCurrent::createMode(int icharge, tcPDPtr , - FlavourInfo flavour, + FlavourInfo , unsigned int imode,PhaseSpaceModePtr mode, unsigned int iloc,int ires, PhaseSpaceChannel phase, Energy upp ) { unsigned int iq(0),ia(0); tPDVector out = particles(icharge,imode,iq,ia); // make sure the the decays are kinematically allowed Energy min =out[0]->massMin()+out[1]->massMin(); if(min>=upp) return false; // set the resonances and check charge tPDPtr res; if(icharge==3) res=getParticleData(ParticleID::Wplus ); else if(icharge==-3) res=getParticleData(ParticleID::Wminus); else res=getParticleData(ParticleID::gamma ); // create the channel mode->addChannel((PhaseSpaceChannel(phase),ires,res,ires+1,iloc+1,ires+1,iloc+2)); // return if successful return true; } // the particles produced by the current tPDVector WeakBaryonCurrent::particles(int icharge, unsigned int imode, int , int ) { tPDVector extpart(2); int id0(0),id1(0); formFactor_->particleID(imode,id0,id1); extpart[0] = getParticleData(id0); if(extpart[0]->CC()) extpart[0]=extpart[0]->CC(); extpart[1] = getParticleData(id1); int charge = extpart[0]->iCharge()+extpart[1]->iCharge(); if(charge==icharge) return extpart; else if(charge==-icharge) { for(unsigned int ix=0;ix<2;++ix) if(extpart[ix]->CC()) extpart[ix]=extpart[ix]->CC(); return extpart; } else return tPDVector(); } void WeakBaryonCurrent::constructSpinInfo(ParticleVector decay) const { if(decay[0]->id()>0) { SpinorWaveFunction ::constructSpinInfo(wave_ ,decay[1],outgoing,true); SpinorBarWaveFunction::constructSpinInfo(wavebar_,decay[0],outgoing,true); } else { SpinorWaveFunction ::constructSpinInfo( wave_,decay[0],outgoing,true); SpinorBarWaveFunction::constructSpinInfo(wavebar_,decay[1],outgoing,true); } } // hadronic current vector WeakBaryonCurrent::current(tcPDPtr , FlavourInfo flavour, const int, const int, Energy & scale, const tPDVector & outgoing, const vector & momenta, DecayIntegrator::MEOption) const { useMe(); Lorentz5Momentum q = momenta[0]+momenta[1]; q.rescaleMass(); scale=q.mass(); int in = abs(outgoing[0]->id()); int out = abs(outgoing[1]->id()); Energy m1 = outgoing[0]->mass(); Energy m2 = outgoing[1]->mass(); bool cc = false; unsigned int imode = formFactor_->formFactorNumber(in,out,cc); // todo generalize to spin != 1/2 assert(outgoing[0]->iSpin()==PDT::Spin1Half && outgoing[1]->iSpin()==PDT::Spin1Half ); wave_.resize(2); wavebar_.resize(2); for(unsigned int ix=0;ix<2;++ix) { wavebar_[ix] = HelicityFunctions::dimensionedSpinorBar(-momenta[0],ix,Helicity::outgoing); wave_[ix] = HelicityFunctions::dimensionedSpinor (-momenta[1],ix,Helicity::outgoing); } // get the form factors Complex f1v(0.),f2v(0.),f3v(0.),f1a(0.),f2a(0.),f3a(0.); formFactor_->SpinHalfSpinHalfFormFactor(sqr(scale),imode,in,out,m1,m2, f1v,f2v,f3v,f1a,f2a,f3a,flavour, BaryonFormFactor::TimeLike); Complex left = f1v - f1a + f2v -double((m1-m2)/(m1+m2))*f2a; Complex right = f1v + f1a + f2v +double((m1-m2)/(m1+m2))*f2a; vector baryon; Lorentz5Momentum diff = momenta[0]-momenta[1]; for(unsigned int ohel1=0;ohel1<2;++ohel1) { for(unsigned int ohel2=0;ohel2<2;++ohel2) { LorentzPolarizationVectorE vtemp = wave_[ohel2].generalCurrent(wavebar_[ohel1],left,right); complex vspin=wave_[ohel2].scalar (wavebar_[ohel1]); complex aspin=wave_[ohel2].pseudoScalar(wavebar_[ohel1]); vtemp-= (f2v*vspin+f2a*aspin)/(m1+m2)*diff; vtemp+= (f3v*vspin+f3a*aspin)/(m1+m2)*q; baryon.push_back(vtemp); } } // return the answer return baryon; } bool WeakBaryonCurrent::accept(vector id) { assert(id.size()==2); int itemp[2] = {id[0],id[1]}; for(unsigned int ix=0;ix<2;++ix) if(itemp[ix]<0) itemp[ix]=-itemp[ix]; bool cc = false; return formFactor_->formFactorNumber(itemp[0],itemp[1],cc)>=0; } // the decay mode unsigned int WeakBaryonCurrent::decayMode(vector idout) { assert(idout.size()==2); int itemp[2] = {idout[0],idout[1]}; for(unsigned int ix=0;ix<2;++ix) if(itemp[ix]<0) itemp[ix]=-itemp[ix]; bool cc = false; return formFactor_->formFactorNumber(itemp[0],itemp[1],cc); } // output the information for the database void WeakBaryonCurrent::dataBaseOutput(ofstream & output,bool header, bool create) const { if(header) output << "update decayers set parameters=\""; if(create) output << "create Herwig::WeakBaryonCurrent " << name() << "\n"; output << "newdef " << name() << ":FormFactor " << formFactor_ << "\n"; WeakCurrent::dataBaseOutput(output,false,false); if(header) output << "\n\" where BINARY ThePEGName=\"" << fullName() << "\";" << endl; } diff --git a/Hadronization/GluonMassGenerator.cc b/Hadronization/GluonMassGenerator.cc --- a/Hadronization/GluonMassGenerator.cc +++ b/Hadronization/GluonMassGenerator.cc @@ -1,63 +1,59 @@ // -*- C++ -*- // // GluonMassGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the GluonMassGenerator class. // #include "GluonMassGenerator.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 "ThePEG/StandardModel/StandardModelBase.h" #include "ClusterHadronizationHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -GluonMassGenerator::GluonMassGenerator() {} - -GluonMassGenerator::~GluonMassGenerator() {} - IBPtr GluonMassGenerator::clone() const { return new_ptr(*this); } IBPtr GluonMassGenerator::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void GluonMassGenerator::persistentOutput(PersistentOStream &) const {} void GluonMassGenerator::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigGluonMassGenerator("Herwig::GluonMassGenerator", ""); void GluonMassGenerator::Init() { static ClassDocumentation documentation ("Dynamic gluon mass generation"); } diff --git a/Hadronization/GluonMassGenerator.h b/Hadronization/GluonMassGenerator.h --- a/Hadronization/GluonMassGenerator.h +++ b/Hadronization/GluonMassGenerator.h @@ -1,171 +1,151 @@ // -*- C++ -*- // // GluonMassGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_GluonMassGenerator_H #define Herwig_GluonMassGenerator_H // // This is the declaration of the GluonMassGenerator class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/EventRecord/Particle.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Hadronization * \brief Dynamic gluon mass generator; the default returns a constant mass. * * @see \ref GluonMassGeneratorInterfaces "The interfaces" * defined for GluonMassGenerator. */ class GluonMassGenerator: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - GluonMassGenerator(); - - /** - * The destructor. - */ - virtual ~GluonMassGenerator(); - //@} - -public: - /** * Generate a single gluon mass with possible reference to a hard * scale Q and up to a maximum value */ virtual Energy generate(Energy, Energy) const { return generate(); } /** * Generate a single gluon mass with possible reference to a hard * scale Q */ virtual Energy generate(Energy) const { return generate(); } /** * Generate a single gluon mass without further constraints */ virtual Energy generate() const { return getParticleData(ThePEG::ParticleID::g)->constituentMass(); } /** * Generate a list of n gluon masses, with a maximum available energy */ list generateMany(size_t n, Energy QMax) const { list res; Energy m0, mu, md, ms, mg, mgmax, summg; mu=getParticleData(ThePEG::ParticleID::u)->constituentMass(); md=getParticleData(ThePEG::ParticleID::d)->constituentMass(); ms=getParticleData(ThePEG::ParticleID::s)->constituentMass(); m0=md; if(mu QMax - 2.0*m0*(n-k-1) ){ repeat=true; break; } } } return res; } 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ - GluonMassGenerator & operator=(const GluonMassGenerator &); + GluonMassGenerator & operator=(const GluonMassGenerator &) = delete; }; } #endif /* Herwig_GluonMassGenerator_H */ diff --git a/MatrixElement/FxFx/FxFxEventHandler.cc b/MatrixElement/FxFx/FxFxEventHandler.cc --- a/MatrixElement/FxFx/FxFxEventHandler.cc +++ b/MatrixElement/FxFx/FxFxEventHandler.cc @@ -1,673 +1,671 @@ // -*- C++ -*- // // Based on: // FxFxEventHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FxFxEventHandler class. // #include "FxFxEventHandler.h" #include "FxFxReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Handlers/LuminosityFunction.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/Utilities/LoopGuard.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; -FxFxEventHandler::~FxFxEventHandler() {} - IBPtr FxFxEventHandler::clone() const { return new_ptr(*this); } IBPtr FxFxEventHandler::fullclone() const { return new_ptr(*this); } void FxFxEventHandler::doinit() { EventHandler::doinit(); for ( int i = 0, N = readers().size(); i < N; ++i ) { readers()[i]->init(); //FxFxReader & reader = *readers()[i]; //reader.initialize(*this); //weightnames = reader.optWeightsNamesFunc(); } /* XSecStat* initxsecs = new XSecStat[weightnames.size()]; for(int ww = 0; ww < weightnames.size(); ww++){ initxsecs[ww].reset(); optstats.insert(std::make_pair(weightnames[ww], initxsecs[ww])); opthistStats.insert(std::make_pair(weightnames[ww], initxsecs[ww])); CrossSection initxs = 0.*picobarn; optxs.insert(std::make_pair(weightnames[ww], initxs)); }*/ ntries = 0; } void FxFxEventHandler::initialize() { if ( lumiFnPtr() ) Repository::clog() << "The LuminosityFunction '" << lumiFnPtr()->name() << "' assigned to the FxFxEventHandler '" << name() << "' will not be active in this run. Instead the incoming " << "particles will be determined by the used FxFxReader objects.\n" << Exception::warning; if ( readers().empty() ) throw FxFxInitError() << "No readers were defined for the FxFxEventHandler '" << name() << "'" << Exception::warning; // Go through all the readers and collect information about cross // sections and processes. typedef map ProcessMap; ProcessMap processes; PDPair incoming; Energy MaxEA = ZERO; Energy MaxEB = ZERO; for ( int i = 0, N = readers().size(); i < N; ++i ) { FxFxReader & reader = *readers()[i]; reader.initialize(*this); weightnames = reader.optWeightsNamesFunc(); // Check that the incoming particles are consistent between the // readers. if ( !incoming.first ) { incoming.first = getParticleData(reader.heprup.IDBMUP.first); if ( !incoming.first ) Throw() << "Unknown beam PID " << reader.heprup.IDBMUP.first << ". Have you created a matching BeamParticle object?" << Exception::runerror; } if ( !incoming.second ) { incoming.second = getParticleData(reader.heprup.IDBMUP.second); if ( !incoming.second ) Throw() << "Unknown beam PID " << reader.heprup.IDBMUP.first << ". Have you created a matching BeamParticle object?" << Exception::runerror; } if ( incoming.first->id() != reader.heprup.IDBMUP.first || incoming.second->id() != reader.heprup.IDBMUP.second ) Repository::clog() << "The different FxFxReader objects in the " << "FxFxEventHandler '" << name() << "' have different " << "types of colliding particles." << Exception::warning; MaxEA = max(MaxEA, reader.heprup.EBMUP.first*GeV); MaxEB = max(MaxEB, reader.heprup.EBMUP.second*GeV); // Check that the weighting of the events in the different readers // is consistent with the ones requested for this event // handler. Also collect the sum of the maximum weights. if ( reader.negativeWeights() && weightOption() > 0 ) throw FxFxInitError() << "The reader '" << reader.name() << "' contains negatively weighted events, " << "which is not allowed for the FxFxEventHandler '" << name() << "'." << Exception::warning; // Check that we do not have the same process numbers in different // readers. for ( int ip = 0; ip < reader.heprup.NPRUP; ++ip ) { if ( reader.heprup.LPRUP[ip] ) { ProcessMap::iterator pit = processes.find(reader.heprup.LPRUP[ip]); if ( pit == processes.end() ) processes[reader.heprup.LPRUP[ip]] = readers()[i]; else if ( warnPNum ) { Throw() << "In the FxFxEventHandler '" << name() << "', both the '" << pit->second->name() << "' and '" << reader.name() << "' contains sub-process number " << pit->first << ". This process may be double-counted in this run." << Exception::warning; } } } selector().insert(reader.stats.maxXSec(), i); } stats.maxXSec(selector().sum()); histStats.maxXSec(selector().sum()); for (map::iterator it= optstats.begin(); it!=optstats.end(); ++it){ (it->second).maxXSec(selector().sum()); } // Check that we have any cross section at all. if ( stats.maxXSec() <= ZERO ) throw FxFxInitError() << "The sum of the cross sections of the readers in the " << "FxFxEventHandler '" << name() << "' was zero." << Exception::warning; // We now create a LuminosityFunction object to inform others about // the energy of the beam. theIncoming = incoming; lumiFn(new_ptr(LuminosityFunction(MaxEA, MaxEB))); } void FxFxEventHandler::doinitrun() { EventHandler::doinitrun(); stats.reset(); histStats.reset(); for ( int i = 0, N = readers().size(); i < N; ++i ) { readers()[i]->init(); FxFxReader & reader = *readers()[i]; reader.initialize(*this); weightnames = reader.optWeightsNamesFunc(); } // XSecStat initxsecs; XSecStat* initxsecs = new XSecStat[weightnames.size()]; for(size_t ww = 0; ww < weightnames.size(); ww++){ initxsecs[ww].reset(); // optstats.insert(std::make_pair(weightnames[ww], initxsecs[ww])); // opthistStats.insert(std::make_pair(weightnames[ww], initxsecs[ww])); CrossSection initxs = 0.*picobarn; //optxs.insert(std::make_pair(weightnames[ww], initxs)); optstats.insert(std::make_pair(weightnames[ww], initxsecs[ww])); opthistStats.insert(std::make_pair(weightnames[ww], initxsecs[ww])); optxs.insert(std::make_pair(weightnames[ww], initxs)); } ntries = 0; } EventPtr FxFxEventHandler::generateEvent() { LoopGuard loopGuard(*this, maxLoop()); while ( true ) { loopGuard(); currentReader(readers()[selector().select(UseRandom::current())]); skipEvents(); currentReader()->reset(); double weight = currentReader()->getEvent(); if ( weightOption() == unitweight && weight < 0.0 ) weight = 0.0; if ( weightOption() == unitweight || weightOption() == unitnegweight ) { CrossSection newmax = selector().reweight(weight); if ( newmax > CrossSection() ) increaseMaxXSec(newmax); } select(weight/currentReader()->preweight); histStats.select(weight); if ( !weighted() ) { if ( weightOption() == unitweight || weightOption() == unitnegweight ) { if ( !rndbool(abs(weight)) ) continue; weight = Math::sign(1.0, weight); } else if ( weight == 0.0 ) continue; } else if ( weight == 0.0 ) continue; accept(); // Divide by the bias introduced by the preweights in the reader. weight /= currentReader()->preweight; // fact for weight normalization double fact = theNormWeight ? double(selector().sum()/picobarn) : 1.; try { theLastXComb = currentReader()->getXComb(); //whether to use the LHE event number or not for the event identification if(UseLHEEvent==0 || currentReader()->LHEEventNum() == -1) { currentEvent(new_ptr(Event(lastParticles(), this, generator()->runName(), generator()->currentEventNumber(), weight*fact ))); } else if(UseLHEEvent==1 && currentReader()->LHEEventNum() != -1) { currentEvent(new_ptr(Event(lastParticles(), this, generator()->runName(), currentReader()->LHEEventNum(), weight*fact ))); } currentEvent()->optionalWeights() = currentReader()->optionalEventWeights(); // normalize the optional weights for(map::iterator it = currentEvent()->optionalWeights().begin(); it!=currentEvent()->optionalWeights().end();++it) { if(it->first!="ecom"&& it->second!=-999 && it->second!=-111 && it->second!=-222 && it->second!=-333) { it->second *= fact; } } //print optional weights here // cout << "event weight = " << weight << " fact = " << fact << endl; /*for (map::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){ std::cout << it->first << " => " << it->second << '\n'; } cout << endl;*/ //print npLO and npNLO // cout << currentReader()->optionalEventnpLO() << "\t" << currentReader()->optionalEventnpNLO() << endl; performCollision(); if ( !currentCollision() ) throw Veto(); return currentEvent(); } catch (Veto) { reject(weight); } catch (Stop) { } catch (Exception &) { reject(weight); throw; } } } void FxFxEventHandler::skipEvents() { if ( weightOption() == 2 || weightOption() == -2 ) return; //does it make sense to skip events if we are using varying weights? // Don't do this for readers which seem to generate events on the fly. if ( currentReader()->active() || currentReader()->NEvents() <= 0 ) return; // Estimate the fration of the total events available from // currentReader() which will be requested. double frac = currentReader()->stats.maxXSec()/stats.maxXSec(); if ( stats.accepted() > 0 ) frac *= double(stats.attempts())/double(stats.accepted()); else frac *= double(stats.attempts() + 1); double xscan = generator()->N()*frac/currentReader()->NEvents(); // Estimate the number of times we need to go through the events for // the currentReader(), and how many events on average we need to // skip for each attempted event to go through the file an integer // number of times. double nscan = ceil(xscan); double meanskip = nscan/xscan - 1.0; // Skip an average numer of steps with a Poissonian distribution. currentReader()-> skip(UseRandom::rndPoisson(meanskip)%currentReader()->NEvents()); } void FxFxEventHandler::select(double weight) { stats.select(weight); currentReader()->select(weight); vector w; for (map::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){ w.push_back(it->second); } int ii = 0; for (map::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){ (it->second).select(w[ii]); ii++; } ii = 0; for (map::iterator it= optstats.begin(); it!=optstats.end(); ++it){ (it->second).select(w[ii]); ii++; } } tCollPtr FxFxEventHandler::performCollision() { lastExtractor()->select(lastXCombPtr()); if ( CKKWHandler() ) CKKWHandler()->setXComb(lastXCombPtr()); currentCollision(new_ptr(Collision(lastParticles(), currentEvent(), this))); if ( currentEvent() ) currentEvent()->addCollision(currentCollision()); currentStep(new_ptr(Step(currentCollision(), this))); currentCollision()->addStep(currentStep()); currentStep()->addSubProcess(currentReader()->getSubProcess()); lastExtractor()->constructRemnants(lastXCombPtr()->partonBinInstances(), subProcess(), currentStep()); if ( !currentReader()->cuts().passCuts(*currentCollision()) ) throw Veto(); initGroups(); if ( ThePEG_DEBUG_ITEM(1) ) { if ( currentEvent() ) generator()->logfile() << *currentEvent(); else generator()->logfile() << *currentCollision(); } return continueCollision(); } EventPtr FxFxEventHandler::continueEvent() { try { continueCollision(); } catch (Veto) { const double fact = theNormWeight ? double(selector().sum()/picobarn) : 1.; reject(currentEvent()->weight()/fact); } catch (Stop) { } catch (Exception &) { const double fact = theNormWeight ? double(selector().sum()/picobarn) : 1.; reject(currentEvent()->weight()/fact); throw; } return currentEvent(); } void FxFxEventHandler::dofinish() { EventHandler::dofinish(); if ( selector().compensating() ) generator()->log() << "Warning: The run was ended while the FxFxEventHandler '" << name() << "' was still trying to compensate for weights larger than 1. " << "The cross section estimates may therefore be statistically " << "inaccurate." << endl; } void FxFxEventHandler::statistics(ostream & os) const { if ( statLevel() == 0 ) return; string line = "=======================================" "=======================================\n"; if ( stats.accepted() <= 0 ) { os << line << "No events generated by event handler '" << name() << "'." << endl; return; } os << line << "Statistics for Les Houches event handler \'" << name() << "\':\n" << " " << "generated number of Cross-section\n" << " " << " events attempts (nb)\n"; os << line << "Total:" << setw(42) << stats.accepted() << setw(13) << stats.attempts() << setw(17) << ouniterr(stats.xSec(), stats.xSecErr(), nanobarn) << endl << line; if ( statLevel() == 1 ) return; if ( statLevel() == 2 ) { os << "Per Les Houches Reader breakdown:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { FxFxReader & reader = *readers()[i]; string n = reader.name(); n.resize(37, ' '); os << n << setw(11) << reader.stats.accepted() << setw(13) << reader.stats.attempts() << setw(17) << ouniterr(reader.stats.xSec(), reader.stats.xSecErr(), nanobarn) << endl; } os << line; } else { os << "Per Les Houches Reader (and process #) breakdown:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { FxFxReader & reader = *readers()[i]; string n = reader.name() + " (all)"; n.resize(37, ' '); os << n << setw(11) << reader.stats.accepted() << setw(13) << reader.stats.attempts() << setw(17) << ouniterr(reader.stats.xSec(), reader.stats.xSecErr(), nanobarn) << endl; CrossSection xsectot = reader.stats.xSec(); if ( xsectot != ZERO ) xsectot /= reader.stats.sumWeights(); typedef FxFxReader::StatMap::const_iterator const_iterator; for ( const_iterator i = reader.statmap.begin(); i != reader.statmap.end(); ++i ) { ostringstream ss; ss << reader.name() << " (" << i->first << ")"; string n = ss.str(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted() << setw(13) << i->second.attempts() << setw(17) << ouniterr(i->second.sumWeights()*xsectot, sqrt(i->second.sumWeights2())*xsectot, nanobarn) << endl; } os << line; } } string warn = "Warning: Result may be statistically incorrect since\n" " the following FxFxReaders were oversampled:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { FxFxReader & reader = *readers()[i]; if ( reader.NEvents() > 0 && reader.stats.attempts() > reader.NEvents() ) { os << warn; warn = ""; os << "'" << reader.name() << "' (by a factor " << double(reader.stats.attempts())/double(reader.NEvents()) << ")" << endl; } } } void FxFxEventHandler::increaseMaxXSec(CrossSection maxxsec) { stats.maxXSec(selector().sum()); histStats.maxXSec(selector().sum()); currentReader()->increaseMaxXSec(maxxsec); } void FxFxEventHandler::accept() { ntries++; stats.accept(); histStats.accept(); currentReader()->accept(); for (map::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){ (it->second).accept(); } for (map::iterator it= optstats.begin(); it!=optstats.end(); ++it){ (it->second).accept(); } } void FxFxEventHandler::reject(double w) { ntries++; stats.reject(w); histStats.reject(w); currentReader()->reject(w); vector wv; for (map::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){ wv.push_back(it->second); } int ii = 0; for (map::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){ (it->second).reject(wv[ii]); ii++; } ii = 0; for (map::iterator it= optstats.begin(); it!=optstats.end(); ++it){ (it->second).reject(wv[ii]); ii++; } } map FxFxEventHandler::optintegratedXSecMap() const { map result; for (map::const_iterator it= optstats.begin(); it!=optstats.end(); ++it){ result[it->first] = (it->second.sumWeights()/it->second.attempts()) * picobarn; } return result; } CrossSection FxFxEventHandler::histogramScale() const { return histStats.xSec()/histStats.sumWeights(); } CrossSection FxFxEventHandler::integratedXSec() const { return histStats.xSec(); } CrossSection FxFxEventHandler::integratedXSecErr() const { return histStats.xSecErr(); } int FxFxEventHandler::ntriesinternal() const { return stats.attempts(); } void FxFxEventHandler::persistentOutput(PersistentOStream & os) const { os << stats << histStats << theReaders << theSelector << oenum(theWeightOption) << theUnitTolerance << theCurrentReader << warnPNum << theNormWeight << UseLHEEvent; } void FxFxEventHandler::persistentInput(PersistentIStream & is, int) { is >> stats >> histStats >> theReaders >> theSelector >> ienum(theWeightOption) >> theUnitTolerance >> theCurrentReader >> warnPNum >> theNormWeight >> UseLHEEvent;; } ClassDescription FxFxEventHandler::initFxFxEventHandler; // Definition of the static class description member. void FxFxEventHandler::setUnitTolerance(double x) { theUnitTolerance = x; selector().tolerance(unitTolerance()); } void FxFxEventHandler::Init() { static ClassDocumentation documentation ("This is the main class administrating the selection of hard " "subprocesses from a set of ThePEG::FxFxReader objects."); static RefVector interfaceFxFxReaders ("FxFxReaders", "Objects capable of reading events from an event file or an " "external matrix element generator.", &FxFxEventHandler::theReaders, -1, false, false, true, false, false); static Switch interfaceWeightOption ("WeightOption", "The different ways to weight events in the Les Houches event handler. " "Whether weighted or not and whether or not negative weights are allowed.", &FxFxEventHandler::theWeightOption, unitweight, true, false); static SwitchOption interfaceWeightOptionUnitWeight (interfaceWeightOption, "UnitWeight", "All events have unit weight.", unitweight); static SwitchOption interfaceWeightOptionNegUnitWeight (interfaceWeightOption, "NegUnitWeight", "All events have weight +1 or maybe -1.", unitnegweight); static SwitchOption interfaceWeightOptionVarWeight (interfaceWeightOption, "VarWeight", "Events may have varying but positive weights.", varweight); static SwitchOption interfaceWeightOptionVarNegWeight (interfaceWeightOption, "VarNegWeight", "Events may have varying weights, both positive and negative.", varnegweight); static Switch interfaceWarnPNum ("WarnPNum", "Warn if the same process number is used in more than one " "FxFxReader.", &FxFxEventHandler::warnPNum, true, true, false); static SwitchOption interfaceWarnPNumWarning (interfaceWarnPNum, "Warning", "Give a warning message.", true); static SwitchOption interfaceWarnPNumNoWarning (interfaceWarnPNum, "NoWarning", "Don't give a warning message.", false); static Parameter interfaceUnitTolerance ("UnitTolerance", "If the WeightOption is set to unit weight, do not start compensating unless the a weight is found to be this much larger than unity.", &FxFxEventHandler::theUnitTolerance, 1.0e-6, 0.0, 0, true, false, Interface::lowerlim, &FxFxEventHandler::setUnitTolerance, (double(FxFxEventHandler::*)()const)(0), (double(FxFxEventHandler::*)()const)(0), (double(FxFxEventHandler::*)()const)(0), (double(FxFxEventHandler::*)()const)(0)); static Switch interfaceWeightNormalization ("WeightNormalization", "How to normalize the output weights", &FxFxEventHandler::theNormWeight, 0, false, false); static SwitchOption interfaceWeightNormalizationUnit (interfaceWeightNormalization, "Normalized", "Standard normalization, i.e. +/- for unweighted events", 0); static SwitchOption interfaceWeightNormalizationCrossSection (interfaceWeightNormalization, "CrossSection", "Normalize the weights to the max cross section in pb", 1); static Switch interfaceEventNumbering ("EventNumbering", "How to number the events", &FxFxEventHandler::UseLHEEvent, 0, false, false); static SwitchOption interfaceEventNumberingIncremental (interfaceEventNumbering, "Incremental", "Standard incremental numbering (i.e. as they are generated)", 0); static SwitchOption interfaceEventNumberingLHE (interfaceEventNumbering, "LHE", "Corresponding to the LHE event number", 1); interfaceFxFxReaders.rank(10); interfaceWeightOption.rank(9); } diff --git a/MatrixElement/FxFx/FxFxEventHandler.h b/MatrixElement/FxFx/FxFxEventHandler.h --- a/MatrixElement/FxFx/FxFxEventHandler.h +++ b/MatrixElement/FxFx/FxFxEventHandler.h @@ -1,452 +1,444 @@ // -*- C++ -*- // // FxFxEventHandler.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_FxFxEventHandler_H #define THEPEG_FxFxEventHandler_H // // This is the declaration of the FxFxEventHandler class. // #include "ThePEG/Handlers/EventHandler.h" #include "FxFxEventHandler.fh" #include "FxFxReader.fh" #include "ThePEG/Utilities/CompSelector.h" #include "ThePEG/Utilities/XSecStat.h" namespace ThePEG { /** * The FxFxEventHandler inherits from the general EventHandler * class and administers the reading of events generated by external * matrix element generator programs according to the Les Houches * accord. * * The class has a list of FxFxReaders which * typically are connected to files with event data produced by * external matrix element generator programs. When an event is * requested by FxFxEventHandler, one of the readers are chosen, * an event is read in and then passed to the different * StepHandler defined in the underlying * EventHandler class. * * @see \ref FxFxEventHandlerInterfaces "The interfaces" * defined for FxFxEventHandler. */ class FxFxEventHandler: public EventHandler { public: /** * A vector of FxFxReader objects. */ typedef vector ReaderVector; /** * A selector of readers. */ typedef CompSelector ReaderSelector; /** * Enumerate the weighting options. */ enum WeightOpt { unitweight = 1, /**< All events have unit weight. */ unitnegweight = -1, /**< All events have wight +/- 1. */ varweight = 2, /**< Varying positive weights. */ varnegweight = -2 /**< Varying positive or negative weights. */ }; friend class FxFxHandler; public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FxFxEventHandler() : theWeightOption(unitweight), theUnitTolerance(1.0e-6), warnPNum(true), theNormWeight(0), UseLHEEvent(0) { selector().tolerance(unitTolerance()); } - /** - * The destructor. - */ - virtual ~FxFxEventHandler(); - //@} - public: /** @name Initialization and finalization functions. */ //@{ /** * Initialize this event handler and all related objects needed to * generate events. */ virtual void initialize(); /** * Write out accumulated statistics about intergrated cross sections * and stuff. */ virtual void statistics(ostream &) const; /** * Histogram scale. A histogram bin which has been filled with the * weights associated with the Event objects should be scaled by * this factor to give the correct cross section. */ virtual CrossSection histogramScale() const; /** * The estimated total integrated cross section of the processes * generated in this run. * @return 0 if no integrated cross section could be estimated. */ virtual CrossSection integratedXSec() const; virtual int ntriesinternal() const; /** * The estimated error in the total integrated cross section of the * processes generated in this run. * @return 0 if no integrated cross section error could be estimated. */ virtual CrossSection integratedXSecErr() const; virtual map optintegratedXSecMap() const; //@} /** @name Functions used for the actual generation */ //@{ /** * Generate an event. */ virtual EventPtr generateEvent(); /** * Create the Event and Collision objects. Used by the * generateEvent() function. */ virtual tCollPtr performCollision(); /** * Continue generating an event if the generation has been stopped * before finishing. */ virtual EventPtr continueEvent(); //@} /** @name Functions to manipulate statistics. */ //@{ /** * An event has been selected. Signal that an event has been * selected with the given \a weight. If unit weights are requested, * the event will be accepted with that weight. This also takes care * of the statistics collection of the selected reader object. */ void select(double weight); /** * Accept the current event, taking care of the statistics * collection of the corresponding reader objects. */ void accept(); /** * Reject the current event, taking care of the statistics * collection of the corresponding reader objects. */ void reject(double weight); /** * Increase the overestimated cross section for the selected reader. */ void increaseMaxXSec(CrossSection maxxsec); /** * Skip some events. To ensure a reader file is scanned an even * number of times, skip a number of events for the selected reader. */ void skipEvents(); //@} /** @name Simple access functions. */ //@{ /** * The way weights are to be treated. */ WeightOpt weightOption() const { return theWeightOption; } /** * If the weight option is set to unit weight, do not start * compensating unless the weight is this much larger than unity. */ double unitTolerance() const { return theUnitTolerance; } /** * Access the list of readers. */ const ReaderVector & readers() const { return theReaders; } /** * The selector to choose readers according to their overestimated * cross section. */ const ReaderSelector & selector() const { return theSelector; } /** * The currently selected reader object. */ tFxFxReaderPtr currentReader() const { return theCurrentReader; } /** * Set the currently selected reader object. */ void currentReader(tFxFxReaderPtr x) { theCurrentReader = x; } //@} 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(); /** * The currently selected reader object. */ tFxFxReaderPtr theCurrentReader; 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. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} protected: /** * Access the list of readers. */ ReaderVector & readers() { return theReaders; } /** * The selector to choose readers according to their overestimated * cross section. */ ReaderSelector & selector() { return theSelector; } /** * Helper function for the interface; */ void setUnitTolerance(double); /** * Collect statistics for this event handler. */ XSecStat stats; map optstats; map optxs; int ntries; map OptStatsFunc() { return optstats; } map OptXsFunc() { return optxs; } /** * Collect statistics for this event handler. To be used for * histogram scaling. */ XSecStat histStats; map opthistStats; /* * The weight identifiers for the events */ vector weightnames; private: /** * The list of readers. */ ReaderVector theReaders; /** * The selector to choose readers according to their overestimated * cross section. */ ReaderSelector theSelector; /** * The way weights are to be treated. */ WeightOpt theWeightOption; /** * If the weight option is set to unit weight, do not start * compensating unless the weight is this much larger than unity. */ double theUnitTolerance; /** * Warn if the same process number is used in more than one * FxFxReader. */ bool warnPNum; /** * How to normalize the weights */ unsigned int theNormWeight; /** * How to number the events */ unsigned int UseLHEEvent; public: /** @cond EXCEPTIONCLASSES */ /** * Exception class used if no readers were assigned. */ class FxFxInitError: public InitException {}; /** * Exception class used if the same process number is used by more * than ne reader. */ class FxFxPNumException: public InitException {}; /** @endcond */ private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFxFxEventHandler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FxFxEventHandler & operator=(const FxFxEventHandler &) = delete; }; } // CLASSDOC OFF #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FxFxEventHandler. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FxFxEventHandler. */ typedef EventHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the FxFxEventHandler class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FxFxEventHandler"; } /** Return the name of the shared library be loaded to get access to * the FxFxEventHandler class and every other class it uses * (except the base class). */ static string library() { return "HwFxFx.so"; } }; /** @endcond */ } #endif /* THEPEG_FxFxEventHandler_H */ diff --git a/MatrixElement/FxFx/FxFxFileReader.cc b/MatrixElement/FxFx/FxFxFileReader.cc --- a/MatrixElement/FxFx/FxFxFileReader.cc +++ b/MatrixElement/FxFx/FxFxFileReader.cc @@ -1,946 +1,944 @@ // -*- C++ -*- // // FxFxFileReader.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FxFxFileReader class. // #include "FxFxFileReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include #include using namespace ThePEG; FxFxFileReader:: FxFxFileReader(const FxFxFileReader & x) : FxFxReader(x), neve(x.neve), ieve(0), LHFVersion(x.LHFVersion), outsideBlock(x.outsideBlock), headerBlock(x.headerBlock), initComments(x.initComments), initAttributes(x.initAttributes), eventComments(x.eventComments), eventAttributes(x.eventAttributes), theFileName(x.theFileName), theQNumbers(x.theQNumbers), theIncludeFxFxTags(x.theIncludeFxFxTags), theIncludeCentral(x.theIncludeCentral), theDecayer(x.theDecayer) {} -FxFxFileReader::~FxFxFileReader() {} - IBPtr FxFxFileReader::clone() const { return new_ptr(*this); } IBPtr FxFxFileReader::fullclone() const { return new_ptr(*this); } bool FxFxFileReader::preInitialize() const { return true; } void FxFxFileReader::doinit() { FxFxReader::doinit(); // are we using QNUMBERS if(!theQNumbers) return; // parse the header block and create // any new particles needed in QNUMBERS blocks string block = headerBlock; string line = ""; bool readingSLHA = false; int (*pf)(int) = tolower; unsigned int newNumber(0); do { line = StringUtils::car(block,"\r\n"); block = StringUtils::cdr(block,"\r\n"); if(line[0]=='#') continue; // are we reading the SLHA block if(readingSLHA) { // reached the end of slha block ? if(line.find(" split = StringUtils::split(line,"#"); // check for a qnumbers block transform(split[0].begin(), split[0].end(), split[0].begin(), pf); // if not contine if(split[0].find("block qnumbers")==string::npos) continue; // get name from comment string name; if(split.size()>=2) { name = StringUtils::stripws(split[1]); } else { ++newNumber; ostringstream tname; tname << "NP" << newNumber; name = tname.str(); } // extract the PDG code split = StringUtils::split(split[0]," "); istringstream is(split[2]); long PDGCode(0); is >> PDGCode; // get the charge, spin, colour and whether an antiparticle int charge(0),spin(0),colour(0),anti(0); for(unsigned int ix=0;ix<4;++ix) { line = StringUtils::car(block,"\r\n"); block = StringUtils::cdr(block,"\r\n"); int dummy[2]; istringstream is(line); is >> dummy[0] >> dummy[1]; switch (dummy[0]) { case 1: charge = dummy[1]; break; case 2: spin = dummy[1]; break; case 3: colour = dummy[1]; break; case 4: anti = dummy[1]; break; default: assert(false); } } // check if particles already exist PDPair newParticle; newParticle.first = getParticleData(PDGCode); if(newParticle.first) Throw() << "Particle with PDG code " << PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists. Retaining the original particle" << Exception::warning; if(anti) { newParticle.second = getParticleData(-PDGCode); if(newParticle.second) Throw() << "Anti-particle with PDG code " << -PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists. Retaining the original particle" << Exception::warning; if(( newParticle.first && !newParticle.second ) || ( newParticle.second && !newParticle.first ) ) Throw() << "Either particle or anti-particle with PDG code " << PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists, but not both the particle and antiparticle. " << " Something dodgy here stopping" << Exception::runerror; } // already exists continue if(newParticle.first) continue; // create the particles // particle with no anti particle if( anti == 0 ) { // construct the name if(name=="") { ostringstream temp; temp << PDGCode; name = temp.str(); } // create the ParticleData object newParticle.first = ParticleData::Create(PDGCode,name); } // particle anti-particle pair else { // construct the names string nameAnti; if(name=="") { ostringstream temp; temp << PDGCode; name = temp.str(); ostringstream temp2; temp << -PDGCode; nameAnti = temp2.str(); } else { nameAnti=name; for(string::iterator it=nameAnti.begin();it!=nameAnti.end();++it) { if(*it=='+') nameAnti.replace(it,it+1,"-"); else if(*it=='-') nameAnti.replace(it,it+1,"+"); } if(nameAnti==name) nameAnti += "bar"; } // create the ParticleData objects newParticle = ParticleData::Create(PDGCode,name,nameAnti); } // set the particle properties if(colour==1) colour = 0; newParticle.first->iColour(PDT::Colour(colour)); newParticle.first->iSpin (PDT::Spin (spin )); newParticle.first->iCharge(PDT::Charge(charge)); // register it generator()->preinitRegister(newParticle.first, "/Herwig/Particles/"+newParticle.first->PDGName()); // set the antiparticle properties if(newParticle.second) { if(colour==3||colour==6) colour *= -1; charge = -charge; newParticle.second->iColour(PDT::Colour(colour)); newParticle.second->iSpin (PDT::Spin (spin )); newParticle.second->iCharge(PDT::Charge(charge)); // register it generator()->preinitRegister(newParticle.second, "/Herwig/Particles/"+newParticle.second->PDGName()); } } // start of SLHA block ? else if(line.find("> id >> mass; // skip resetting masses on SM particles // as it can cause problems later on in event generation if(abs(id)<=6 || (abs(id)>=11 && abs(id)<=16) || abs(id)==23 || abs(id)==24) { // Throw() << "Standard model mass for PID " // << id // << " will not be changed." // << Exception::warning; block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); continue; } // magnitude of mass for susy models mass = abs(mass); // set the mass tPDPtr particle = getParticleData(id); if(!particle) throw SetupException() << "FxFxFileReader::doinit() - Particle with PDG code not" << id << " not found." << Exception::runerror; const InterfaceBase * ifb = BaseRepository::FindInterface(particle, "NominalMass"); ostringstream os; os << mass; ifb->exec(*particle, "set", os.str()); // read the next line block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); }; } // found a decay block else if(line.find("decay") == 0) { // get PGD code and width istringstream iss(line); string dummy; long parent(0); Energy width(ZERO); iss >> dummy >> parent >> iunit(width, GeV); // get the ParticleData object PDPtr inpart = getParticleData(parent); if(!inpart) { throw SetupException() << "FxFxFileReader::doinit() - A ParticleData object with the PDG code " << parent << " does not exist. " << Exception::runerror; return; } if ( abs(inpart->id()) == 6 || abs(inpart->id()) == 15 || abs(inpart->id()) == 23 || abs(inpart->id()) == 24 || abs(inpart->id()) == 25 ) { Throw() << "\n" "************************************************************************\n" "* Your LHE file changes the width of " << inpart->PDGName() << ".\n" "* This can cause serious problems in the event generation!\n" "************************************************************************\n" "\n" << Exception::warning; } else if (inpart->width() > ZERO && width <= ZERO) { Throw() << "\n" "************************************************************************\n" "* Your LHE file zeroes the non-zero width of " << inpart->PDGName() << ".\n" "* If " << inpart->PDGName() << " is a decaying SM particle,\n" "* this can cause serious problems in the event generation!\n" "************************************************************************\n" "\n" << Exception::warning; } // set the width inpart->width(width); if( width > ZERO ) { inpart->cTau(hbarc/width); inpart->widthCut(5.*width); inpart->stable(false); } // construct prefix for DecayModes string prefix(inpart->name() + "->"), tag(prefix),line(""); unsigned int nmode(0); // read any decay modes line = StringUtils::car(block,"\r\n"); while(line[0] != 'D' && line[0] != 'B' && line[0] != 'd' && line[0] != 'b' && line[0] != '<' && line != "") { // skip comments if(line[0] == '#') { block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); continue; } // read decay mode and construct the tag istringstream is(line); double brat(0.); unsigned int nda(0),npr(0); is >> brat >> nda; while( true ) { long t; is >> t; if( is.fail() ) break; if( t == abs(parent) ) throw SetupException() << "An error occurred while read a decay of the " << inpart->PDGName() << ". One of its products has the same PDG code " << "as the parent particle in FxFxFileReader::doinit()." << " Please check the Les Houches file.\n" << Exception::runerror; tcPDPtr p = getParticleData(t); if( !p ) throw SetupException() << "FxFxFileReader::doinit() -" << " An unknown PDG code has been encounterd " << "while reading a decay mode. ID: " << t << Exception::runerror; ++npr; tag += p->name() + ","; } if( npr != nda ) throw SetupException() << "FxFxFileReader::doinit() - While reading a decay of the " << inpart->PDGName() << " from an SLHA file, an inconsistency " << "between the number of decay products and the value in " << "the 'NDA' column was found. Please check if the spectrum " << "file is correct.\n" << Exception::warning; // create the DecayMode if( npr > 1 ) { if( nmode==0 ) { generator()->preinitInterface(inpart, "VariableRatio" , "set","false"); if(inpart->massGenerator()) { ok = false; Throw() << inpart->PDGName() << " already has a WidthGenerator set" << " this is incompatible with using QNUMBERS " << "Use\n" << "set " << inpart->fullName() << ":Width_generator NULL\n" << "to fix this." << Exception::warning; } unsigned int ntemp=0; for(DecaySet::const_iterator dit = inpart->decayModes().begin(); dit != inpart->decayModes().end(); ++dit ) { if((**dit).on()) ++ntemp; } if(ntemp!=0) { ok = false; Throw() << inpart->PDGName() << " already has DecayModes" << " this is incompatible with using QNUMBERS " << "Use\n" << "do " << inpart->fullName() << ":SelectDecayModes none\n" << " to fix this." << Exception::warning; } } inpart->stable(false); tag.replace(tag.size() - 1, 1, ";"); DMPtr dm = generator()->findDecayMode(tag); if(!theDecayer) Throw() << "FxFxFileReader::doinit() Decayer must be set using the " << "FxFxFileReader:Decayer" << " must be set to allow the creation of new" << " decay modes." << Exception::runerror; if(!dm) { dm = generator()->preinitCreateDecayMode(tag); if(!dm) Throw() << "FxFxFileReader::doinit() - Needed to create " << "new decaymode but one could not be created for the tag " << tag << Exception::warning; } generator()->preinitInterface(dm, "Decayer", "set", theDecayer->fullName()); ostringstream br; br << setprecision(13) << brat; generator()->preinitInterface(dm, "BranchingRatio", "set", br.str()); generator()->preinitInterface(dm, "Active", "set", "Yes"); if(dm->CC()) { generator()->preinitInterface(dm->CC(), "BranchingRatio", "set", br.str()); generator()->preinitInterface(dm->CC(), "Active", "set", "Yes"); } ++nmode; } tag=prefix; // read the next line block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); }; if(nmode>0) { inpart->update(); if(inpart->CC()) inpart->CC()->update(); } } } // start of SLHA block ? else if(line.find("() << "The file associated with '" << name() << "' does not contain a " << "proper formatted Les Houches event file. The events may not be " << "properly sampled." << Exception::warning; } //vector FxFxFileReader::optWeightNamesFunc() { return optionalWeightsNames; } vector FxFxFileReader::optWeightsNamesFunc() { return optionalWeightsNames; } void FxFxFileReader::open() { if ( filename().empty() ) throw FxFxFileError() << "No Les Houches file name. " << "Use 'set " << name() << ":FileName'." << Exception::runerror; cfile.open(filename()); if ( !cfile ) throw FxFxFileError() << "The FxFxFileReader '" << name() << "' could not open the " << "event file called '" << theFileName << "'." << Exception::runerror; cfile.readline(); if ( !cfile.find(" attributes = StringUtils::xmlAttributes("LesHouchesEvents", cfile.getline()); LHFVersion = attributes["version"]; //cout << LHFVersion << endl; if ( LHFVersion.empty() ) return; bool readingHeader = false; bool readingInit = false; headerBlock = ""; // char (cwgtinfo_weights_info[250][15]); string hs; // int cwgtinfo_nn(0); // Loop over all lines until we hit the tag. bool readingInitWeights = false, readingInitWeights_sc = false; string weightinfo; while ( cfile.readline() ) { // found the init block for multiple weights if(cfile.find(""; erase_substr(sub, str_arrow); scalename = sub; } ++ws; } while (isc); /* now get the relevant information * e.g. scales or PDF sets used */ string startDEL = ">"; //starting delimiter string stopDEL = ""; //end delimiter unsigned firstLim = hs.find(startDEL); //find start of delimiter // unsigned lastLim = hs.find(stopDEL); //find end of delimitr string scinfo = hs.substr(firstLim); //define the information for the scale erase_substr(scinfo,stopDEL); erase_substr(scinfo,startDEL); scinfo = StringUtils::stripws(scinfo); //cout << "scinfo = " << scinfo << endl; /* fill in the map * indicating the information to be appended to each scale * i.e. scinfo for each scalname */ scalemap[scalename] = scinfo.c_str(); string str_id = "id="; string str_prime = "'"; erase_substr(scalename, str_id); erase_substr(scalename, str_prime); optionalWeightsNames.push_back(scalename); } } if ( cfile.find("") ) { //cout << "found init block" << endl; // We have hit the init block, so we should expect to find the // standard information in the following. But first check for // attributes. initAttributes = StringUtils::xmlAttributes("init", cfile.getline()); readingInit = true; cfile.readline(); if ( !( cfile >> heprup.IDBMUP.first >> heprup.IDBMUP.second >> heprup.EBMUP.first >> heprup.EBMUP.second >> heprup.PDFGUP.first >> heprup.PDFGUP.second >> heprup.PDFSUP.first >> heprup.PDFSUP.second >> heprup.IDWTUP >> heprup.NPRUP ) ) { heprup.NPRUP = -42; LHFVersion = ""; return; } heprup.resize(); for ( int i = 0; i < heprup.NPRUP; ++i ) { cfile.readline(); if ( !( cfile >> heprup.XSECUP[i] >> heprup.XERRUP[i] >> heprup.XMAXUP[i] >> heprup.LPRUP[i] ) ) { heprup.NPRUP = -42; LHFVersion = ""; return; } } } if ( cfile.find("> sub; if(we==2) { npLO = atoi(sub.c_str()); } if(we==5) { npNLO = atoi(sub.c_str()); } ++we; } while (ievat); optionalnpLO = npLO; optionalnpNLO = npNLO; std::stringstream npstringstream; npstringstream << "np " << npLO << " " << npNLO; std::string npstrings = npstringstream.str(); /* the FxFx merging information * becomes part of the optionalWeights, labelled -999 * for future reference */ if(theIncludeFxFxTags) optionalWeights[npstrings.c_str()] = -999; string ecomstring = "ecom"; optionalWeights[ecomstring.c_str()] = heprup.EBMUP.first+heprup.EBMUP.second; if ( !cfile.readline() ) return false; // The first line determines how many subsequent particle lines we // have. if ( !( cfile >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP >> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP ) ) return false; hepeup.resize(); // Read all particle lines. for ( int i = 0; i < hepeup.NUP; ++i ) { if ( !cfile.readline() ) return false; if ( !( cfile >> hepeup.IDUP[i] >> hepeup.ISTUP[i] >> hepeup.MOTHUP[i].first >> hepeup.MOTHUP[i].second >> hepeup.ICOLUP[i].first >> hepeup.ICOLUP[i].second >> hepeup.PUP[i][0] >> hepeup.PUP[i][1] >> hepeup.PUP[i][2] >> hepeup.PUP[i][3] >> hepeup.PUP[i][4] >> hepeup.VTIMUP[i] >> hepeup.SPINUP[i] ) ) return false; if(std::isnan(hepeup.PUP[i][0])||std::isnan(hepeup.PUP[i][1])|| std::isnan(hepeup.PUP[i][2])||std::isnan(hepeup.PUP[i][3])|| std::isnan(hepeup.PUP[i][4])) throw Exception() << "nan's as momenta in Les Houches file " << Exception::eventerror; if(hepeup.MOTHUP[i].first -1==i || hepeup.MOTHUP[i].second-1==i) { throw Exception() << "Particle has itself as a mother in Les Houches " << "file, this is not allowed\n" << Exception::eventerror; } } LHEeventnum = -1; // set the LHEeventnum to -1, this will be the default if the tag is not found // Now read any additional comments and named weights. // read until the end of rwgt is found bool readingWeights = false, readingaMCFast = false, readingMG5ClusInfo = false; while ( cfile.readline() && !cfile.find("")) { if(cfile.find("> sub; if(wi==1) { string str_arrow = ">" ; erase_substr(sub, str_arrow); weightName = sub; } if(wi==2) weightValue = atof(sub.c_str()); ++wi; } while (iss); // store the optional weights found in the temporary map //cout << "weightName, weightValue= " << weightName << ", " << weightValue << endl; optionalWeightsTemp[weightName] = weightValue; } /* reading of aMCFast weights */ if(readingaMCFast) { std::stringstream amcfstringstream; amcfstringstream << "aMCFast " << cfile.getline(); std::string amcfstrings = amcfstringstream.str(); string str_newline = "\n"; erase_substr(amcfstrings,str_newline); optionalWeights[amcfstrings.c_str()] = -111; //for the aMCFast we give them a weight -111 for future identification } /* read additional MG5 Clustering information * used in LO merging */ if(readingMG5ClusInfo) { string hs = cfile.getline(); string startDEL = ""; //end delimiter unsigned firstLim = hs.find(startDEL); //find start of delimiter // unsigned lastLim = hs.find(stopDEL); //find end of delimitr string mg5clusinfo = hs.substr(firstLim); //define the information for the scale erase_substr(mg5clusinfo,stopDEL); erase_substr(mg5clusinfo,startDEL); string str_arrow = ">"; erase_substr(mg5clusinfo,str_arrow); string str_quotation = "\""; erase_substr(mg5clusinfo,str_quotation); string str_newline= "\n"; erase_substr(mg5clusinfo,str_newline); optionalWeights[mg5clusinfo.c_str()] = -222; //for the mg5 scale info weights we give them a weight -222 for future identification } //the event num tag if(cfile.find("::const_iterator it=optionalWeightsTemp.begin(); it!=optionalWeightsTemp.end(); ++it){ string itfirst = it->first; erase_substr(itfirst, "'"); erase_substr(itfirst, "\""); for (map::const_iterator it2=scalemap.begin(); it2!=scalemap.end(); ++it2){ //find the scale id in the scale information and add this information string it2first = it2->first; erase_substr(it2first, "'"); erase_substr(it2first, "\""); //cout << "itfirst, it2first = " << itfirst << "\t" << it2first << endl; if(itfirst==it2first) { string info = it2->second; string str_newline = "\n"; erase_substr(info, str_newline); //set the optional weights optionalWeights[info] = it->second; } } } /* additionally, we set the "central" scale * this is actually the default event weight */ string central = "central"; if (theIncludeCentral) optionalWeights[central] = hepeup.XWGTUP; if ( !cfile ) return false; return true; } void FxFxFileReader::close() { cfile.close(); } void FxFxFileReader::persistentOutput(PersistentOStream & os) const { os << neve << LHFVersion << outsideBlock << headerBlock << initComments << initAttributes << eventComments << eventAttributes << theFileName << theQNumbers << theIncludeFxFxTags << theIncludeCentral << theDecayer; } void FxFxFileReader::persistentInput(PersistentIStream & is, int) { is >> neve >> LHFVersion >> outsideBlock >> headerBlock >> initComments >> initAttributes >> eventComments >> eventAttributes >> theFileName >> theQNumbers >> theIncludeFxFxTags >> theIncludeCentral >> theDecayer; ieve = 0; } ClassDescription FxFxFileReader::initFxFxFileReader; // Definition of the static class description member. void FxFxFileReader::Init() { static ClassDocumentation documentation ("ThePEG::FxFxFileReader is an base class to be used for objects " "which reads event files from matrix element generators. This class is " "able to read plain event files conforming to the Les Houches Event File " "accord."); static Parameter interfaceFileName ("FileName", "The name of a file containing events conforming to the Les Houches " "protocol to be read into ThePEG. A file name ending in " ".gz will be read from a pipe which uses " "zcat. If a file name ends in | the " "preceeding string is interpreted as a command, the output of which " "will be read through a pipe.", &FxFxFileReader::theFileName, "", false, false); interfaceFileName.fileType(); interfaceFileName.rank(11); static Switch interfaceQNumbers ("QNumbers", "Whether or not to read search for and read a QNUMBERS" " block in the header of the file.", &FxFxFileReader::theQNumbers, false, false, false); static SwitchOption interfaceQNumbersYes (interfaceQNumbers, "Yes", "Use QNUMBERS", true); static SwitchOption interfaceQNumbersNo (interfaceQNumbers, "No", "Don't use QNUMBERS", false); static Switch interfaceIncludeFxFxTags ("IncludeFxFxTags", "Include FxFx tags", &FxFxFileReader::theIncludeFxFxTags, true, true, false); static SwitchOption interfaceIncludeFxFxTagsYes (interfaceIncludeFxFxTags, "Yes", "Use the FxFx tags", true); static SwitchOption interfaceIncludeFxFxTagsNo (interfaceIncludeFxFxTags, "No", "Don't use the FxFx tags", false); static Switch interfaceIncludeCentral ("IncludeCentral", "Include definition of central weight", &FxFxFileReader::theIncludeCentral, false, true, false); static SwitchOption interfaceIncludeCentralYes (interfaceIncludeCentral, "Yes", "include definition of central weight", true); static SwitchOption interfaceIncludeCentralNo (interfaceIncludeCentral, "No", "Don't include definition of central weight", false); static Reference interfaceDecayer ("Decayer", "Decayer to use for any decays read from the QNUMBERS Blocks", &FxFxFileReader::theDecayer, false, false, true, true, false); } void FxFxFileReader::erase_substr(std::string& subject, const std::string& search) { size_t pos = 0; while((pos = subject.find(search, pos)) != std::string::npos) { subject.erase( pos, search.length() ); } } diff --git a/MatrixElement/FxFx/FxFxFileReader.h b/MatrixElement/FxFx/FxFxFileReader.h --- a/MatrixElement/FxFx/FxFxFileReader.h +++ b/MatrixElement/FxFx/FxFxFileReader.h @@ -1,333 +1,325 @@ // -*- C++ -*- // // FxFxFileReader.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_FxFxFileReader_H #define THEPEG_FxFxFileReader_H // This is the declaration of the FxFxFileReader class. #include "FxFxReader.h" #include "FxFxFileReader.fh" #include "ThePEG/PDT/Decayer.h" #include "ThePEG/Utilities/CFileLineReader.h" #include namespace ThePEG { /** * FxFxFileReader is an base class to be used for objects which * reads event files from matrix element generators. It inherits from * FxFxReader and extends it by defining a file handle to be * read from, which is opened and closed by the open() and close() * functions. Note that the file handle is a standard C filehandle and * not a C++ stream. This is because there is no standard way in C++ * to connect a pipe to a stream for reading eg. gzipped files. This * class is able to read plain event files conforming to the Les * Houches Event File accord. * * @see \ref FxFxFileReaderInterfaces "The interfaces" * defined for FxFxFileReader. * @see Event * @see FxFxReader */ class FxFxFileReader: public FxFxReader { public: - /** @name Standard constructors and destructors. */ - //@{ /** * Default constructor. */ FxFxFileReader() : neve(0), ieve(0), theQNumbers(false), theIncludeFxFxTags(true), theIncludeCentral(false) {} /** * Copy-constructor. Note that a file which is opened in the object * copied from will have to be reopened in this. */ FxFxFileReader(const FxFxFileReader &); - /** - * Destructor. - */ - virtual ~FxFxFileReader(); - //@} - public: /** @name Virtual functions specified by the FxFxReader base class. */ //@{ /** * Initialize. This function is called by the FxFxEventHandler * to which this object is assigned. */ virtual void initialize(FxFxEventHandler & eh); /** * Open a file with events. Derived classes should overwrite it and * first calling it before reading in the run information into the * corresponding protected variables. */ virtual void open(); /** * Close the file from which events have been read. */ virtual void close(); /** * Read the next event from the file or stream into the * corresponding protected variables. Return false if there is no * more events or if this was not a LHF event file. */ virtual bool doReadEvent(); //@} /** * Return the name of the file from where to read events. */ string filename() const { return theFileName; } /* vector optionalWeightsNames; virtual vector optWeightNamesFunc();*/ virtual vector optWeightsNamesFunc(); /** * Erases all occurences of a substring from a string */ void erase_substr(std::string& subject, const std::string& search); 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); //@} /** * Standard Init function used to initialize the interfaces. */ 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; //@} /** @name Standard (and non-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(); /** * Return true if this object needs to be initialized before all * other objects because it needs to extract PDFs from the event file. */ virtual bool preInitialize() const; //@ protected: /** * The wrapper around the C FILE stream from which to read */ CFileLineReader cfile; protected: /** * The number of events in this file. */ long neve; /** * The current event number. */ long ieve; /** * If the file is a standard Les Houches formatted file (LHF) this * is its version number. If empty, this is not a Les Houches * formatted file */ string LHFVersion; /** * If LHF. All lines (since the last open() or readEvent()) outside * the header, init and event tags. */ string outsideBlock; /** * If LHF. All lines from the header block. */ string headerBlock; /** * If LHF. Additional comments found in the init block. */ string initComments; /** * If LHF. Map of attributes (name-value pairs) found in the init * tag. */ map initAttributes; /** * If LHF. Additional comments found with the last read event. */ string eventComments; /** * If LHF. Map of attributes (name-value pairs) found in the last * event tag. */ map eventAttributes; private: /** * The name of the file from where to read events. */ string theFileName; /** * Whether or not to search for QNUMBERS stuff */ bool theQNumbers; /** * Include/Read FxFx tags */ bool theIncludeFxFxTags; /** * Include central weight (for backup use) */ bool theIncludeCentral; /** * Decayer for any decay modes read from the file */ DecayerPtr theDecayer; /** * Further information on the weights */ map scalemap; /** * Temporary holder for optional weights */ map optionalWeightsTemp; private: /** * Describe an abstract base class with persistent data. */ static ClassDescription initFxFxFileReader; /** * Private and non-existent assignment operator. */ FxFxFileReader & operator=(const FxFxFileReader &) = delete; public: /** @cond EXCEPTIONCLASSES */ /** Exception class used by FxFxFileReader if reading the file * fails. */ class FxFxFileError: public Exception {}; /** @endcond */ }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of FxFxFileReader. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of FxFxFileReader. */ typedef FxFxReader NthBase; }; /** * This template specialization informs ThePEG about the name of the * FxFxFileReader class and the shared object where it is * defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "Herwig::FxFxFileReader"; } /** * Return the name of the shared library to be loaded to get access * to the FxFxFileReader class and every other class it uses * (except the base class). */ static string library() { return "HwFxFx.so"; } }; /** @endcond */ } #endif /* THEPEG_FxFxFileReader_H */ diff --git a/MatrixElement/Gamma/MEGammaGamma2PiPi.cc b/MatrixElement/Gamma/MEGammaGamma2PiPi.cc --- a/MatrixElement/Gamma/MEGammaGamma2PiPi.cc +++ b/MatrixElement/Gamma/MEGammaGamma2PiPi.cc @@ -1,182 +1,176 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEGammaGamma2PiPi class. // #include "MEGammaGamma2PiPi.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "Herwig/MatrixElement/HardVertex.h" using namespace Herwig; using ThePEG::Helicity::incoming; MEGammaGamma2PiPi::MEGammaGamma2PiPi() { massOption(vector(2,1)); } void MEGammaGamma2PiPi::getDiagrams() const { tcPDPtr gamma = getParticleData(ParticleID::gamma); tcPDPtr pip = getParticleData(ParticleID::piplus); tcPDPtr pim = pip->CC(); // first t-channel add(new_ptr((Tree2toNDiagram(3),gamma,pip,gamma,1,pip, 2,pim,-1))); // interchange add(new_ptr((Tree2toNDiagram(3),gamma,pip,gamma,2,pip, 1,pim,-2))); } Energy2 MEGammaGamma2PiPi::scale() const { return 2.*sHat()*tHat()*uHat()/(sqr(sHat())+sqr(tHat())+sqr(uHat())); } double MEGammaGamma2PiPi::me2() const { VectorWaveFunction p1w(rescaledMomenta()[0],mePartonData()[0],incoming); VectorWaveFunction p2w(rescaledMomenta()[1],mePartonData()[1],incoming); vector p1,p2; for(unsigned int ix=0;ix<2;++ix) { p1w.reset(2*ix);p1.push_back(p1w); p2w.reset(2*ix);p2.push_back(p2w); } // calculate the matrix element return helicityME(p1,p2,rescaledMomenta(),false); } unsigned int MEGammaGamma2PiPi::orderInAlphaS() const { return 0; } unsigned int MEGammaGamma2PiPi::orderInAlphaEW() const { return 2; } Selector MEGammaGamma2PiPi::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 ) sel.insert(meInfo()[0], i); else if ( diags[i]->id() == -2 ) sel.insert(meInfo()[1], i); return sel; } Selector MEGammaGamma2PiPi::colourGeometries(tcDiagPtr ) const { static ColourLines c1(""); Selector sel; sel.insert(1.0, &c1); return sel; } IBPtr MEGammaGamma2PiPi::clone() const { return new_ptr(*this); } IBPtr MEGammaGamma2PiPi::fullclone() const { return new_ptr(*this); } -void MEGammaGamma2PiPi::persistentOutput(PersistentOStream & os) const { -} - -void MEGammaGamma2PiPi::persistentInput(PersistentIStream & is, int) { -} - // The following static variable is needed for the type // description system in ThePEG. -DescribeClass +DescribeNoPIOClass describeHerwigMEGammaGamma2PiPi("Herwig::MEGammaGamma2PiPi", "HwMEGammaGamma.so"); void MEGammaGamma2PiPi::Init() { static ClassDocumentation documentation ("The MEGammaGamma2PiPi class provides a simple matrix element for gamma gamma -> pi+pi-"); } void MEGammaGamma2PiPi::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]); hard.push_back(sub->outgoing()[1]); // order of particles unsigned int order[4]={0,1,2,3}; // identify the process and calculate matrix element vector p1,p2; if(hard[order[2]]->id()<0) swap(order[2],order[3]); VectorWaveFunction (p1 ,hard[order[0]],incoming,false,true); VectorWaveFunction (p2 ,hard[order[1]],incoming,false,true); p1[1]=p1[2]; p2[1]=p2[2]; vector momenta; for(unsigned int ix=0;ix<4;++ix) momenta.push_back(hard[order[ix]]->momentum()); helicityME(p1,p2,momenta,true); // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(me_); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) { if(hard[order[ix]]->spinInfo()) hard[order[ix]]->spinInfo()->productionVertex(hardvertex); } } double MEGammaGamma2PiPi::helicityME(vector &p1, vector &p2, const vector & momenta, bool calc) const { // for(unsigned int ix=0;ix<4;++ix) // cerr << mePartonData()[ix]->PDGName() <<" " << meMomenta()[ix]/GeV << " " << meMomenta()[ix].mass()/GeV << "\n"; // double beta = meMomenta()[2].vect().mag()/meMomenta()[2].t(); // double ct = meMomenta()[2].cosTheta(); // double phi = meMomenta()[2].phi(); // scale (external photons so scale in couplings is 0) Energy2 mt(0.*GeV2); // matrix element to be stored if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1, PDT::Spin0,PDT::Spin0)); // calculate the matrix element double output(0.),sumdiag[2]={0.,0.}; Complex diag[2]; Energy2 d1 = momenta[0]*momenta[2], d2 = momenta[1]*momenta[2]; for(unsigned int ihel1=0;ihel1<2;++ihel1) { complex a1 = momenta[2]*p1[ihel1].wave(); complex a2 = momenta[3]*p1[ihel1].wave(); for(unsigned int ihel2=0;ihel2<2;++ihel2) { complex b1 = momenta[2]*p2[ihel2].wave(); complex b2 = momenta[3]*p2[ihel2].wave(); // t-channel diagram diag[0] = a1*b2/d1; // u-channel diagram diag[1] = a2*b1/d2; sumdiag[0] += norm(diag[0]); sumdiag[1] += norm(diag[1]); Complex amp = p1[ihel1].wave()*p2[ihel2].wave()-diag[0]-diag[1]; output += norm(amp); // store the me if needed if(calc) me_(2*ihel1,2*ihel2,0,0) = amp; } } // diagrams DVector save; save.push_back(sumdiag[0]); save.push_back(sumdiag[1]); meInfo(save); // code to test vs the analytic result // Energy2 m2 = sqr(momenta[2].mass()); // double test = 2. + ((d1 + d2)*m2*(-2*d1*d2 + (d1 + d2)*m2))/(sqr(d1)*sqr(d2)); // cerr << "testing ME " << (output-test)/(output+test) << " " << output << " " << test << " " << output/test << "\n"; // coupling factors return output*sqr(SM().alphaEM()*4.*Constants::pi); } diff --git a/MatrixElement/Gamma/MEGammaGamma2PiPi.h b/MatrixElement/Gamma/MEGammaGamma2PiPi.h --- a/MatrixElement/Gamma/MEGammaGamma2PiPi.h +++ b/MatrixElement/Gamma/MEGammaGamma2PiPi.h @@ -1,168 +1,152 @@ // -*- C++ -*- #ifndef Herwig_MEGammaGamma2PiPi_H #define Herwig_MEGammaGamma2PiPi_H // // This is the declaration of the MEGammaGamma2PiPi class. // #include "Herwig/MatrixElement/HwMEBase.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" namespace Herwig { using namespace ThePEG; using ThePEG::Helicity::VectorWaveFunction; /** * The MEGammaGamma2PiPi class provides a smiple matrix element for \f$\gamma\gamma\to \pi^+\pi^-$ using scalar QED * * @see \ref MEGammaGamma2PiPiInterfaces "The interfaces" * defined for MEGammaGamma2PiPi. */ class MEGammaGamma2PiPi: public HwMEBase { public: /** * The default constructor. */ MEGammaGamma2PiPi(); public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EW}\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; //@} /** * Construct the vertex of spin correlations. */ virtual void constructVertex(tSubProPtr); 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: /** * Matrix element for \f$\gamma\gamma\to q\bar{q}\f$ * @param p1 The wavefunctions for the first incoming photon * @param p2 The wavefunctions for the second incoming photon * @param momenta The momenta * @param calc Whether or not to calculate the matrix element */ double helicityME(vector &p1,vector &p2, const vector & momenta, bool calc) const; 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; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEGammaGamma2PiPi & operator=(const MEGammaGamma2PiPi &) = delete; private: /** * Matrix element */ mutable ProductionMatrixElement me_; }; } #endif /* Herwig_MEGammaGamma2PiPi_H */ diff --git a/MatrixElement/MEMultiChannel.cc b/MatrixElement/MEMultiChannel.cc --- a/MatrixElement/MEMultiChannel.cc +++ b/MatrixElement/MEMultiChannel.cc @@ -1,146 +1,146 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEMultiChannel class. // #include "MEMultiChannel.h" #include "Herwig/Decay/DecayIntegrator.fh" #include "Herwig/Decay/PhaseSpaceMode.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Cuts/Cuts.h" using namespace Herwig; MEMultiChannel::~MEMultiChannel() {} void MEMultiChannel::getDiagrams() const { int ndiag=0; channelMap_.clear(); for(PhaseSpaceModePtr mode : modes_) { channelMap_.push_back(map()); for(unsigned int ix=0;ixchannels().size();++ix) { ThePEG::Ptr::pointer diag = mode->channels()[ix].createDiagram(); ndiag+=1; diag = new_ptr((*diag,-ndiag)); channelMap_.back()[ndiag]= ix; add(diag); } } } Energy2 MEMultiChannel::scale() const { return sHat(); } int MEMultiChannel::nDim() const { return 0; // return modes_[0]->nRand(); } -bool MEMultiChannel::generateKinematics(const double * r) { +bool MEMultiChannel::generateKinematics(const double * ) { // first find the mode int imode = -1; for(unsigned int ix=0;ixoutgoing().size();++iy) { if(mePartonData()[iy+2]!=modes_[ix]->outgoing()[iy]) { matched=false; break; } } if(matched) { imode=ix; break; } } assert(imode>=0); // fill the stack of random numbers modes_[imode]->fillStack(); //modes_[imode]->fillStack(r); // generate the momenta int ichan; vector momenta(meMomenta().size()-2); Lorentz5Momentum pcm=meMomenta()[0]+meMomenta()[1]; Energy wgt = modes_[imode]->weight(ichan,pcm,momenta); // set the jacobian jacobian(wgt/sqrt(sHat())); // and momenta for(unsigned int ix=0;ix out(meMomenta().size()-2); for(unsigned int ix=2;ix MEMultiChannel::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { double wgt = me2(channelMap_[iMode_][-diags[i]->id()] ); sel.insert(wgt, i); } return sel; } Selector MEMultiChannel::colourGeometries(tcDiagPtr ) const { static ColourLines none(""); Selector sel; sel.insert(1.0, &none); return sel; } void MEMultiChannel::persistentOutput(PersistentOStream & os) const { os << modes_ << channelMap_; } void MEMultiChannel::persistentInput(PersistentIStream & is, int) { is >> modes_ >> channelMap_; } // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractClass describeHerwigMEMultiChannel("Herwig::MEMultiChannel", "Herwig.so"); void MEMultiChannel::Init() { static ClassDocumentation documentation ("There is no documentation for the MEMultiChannel class"); } void MEMultiChannel::doinit() { MEBase::doinit(); for(tPhaseSpaceModePtr mode : modes_) mode->init(); } void MEMultiChannel::doinitrun() { MEBase::doinitrun(); for(tPhaseSpaceModePtr mode : modes_) mode->initrun(); } diff --git a/MatrixElement/Matchbox/Base/MatchboxAmplitude.cc b/MatrixElement/Matchbox/Base/MatchboxAmplitude.cc --- a/MatrixElement/Matchbox/Base/MatchboxAmplitude.cc +++ b/MatrixElement/Matchbox/Base/MatchboxAmplitude.cc @@ -1,959 +1,957 @@ // -*- C++ -*- // // MatchboxAmplitude.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitude class. // #include "MatchboxAmplitude.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinorHelicity.h" #include "Herwig/MatrixElement/Matchbox/Utility/SU2Helper.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "ThePEG/Utilities/StringUtils.h" #include "MatchboxMEBase.h" #include #include #include using std::ostream_iterator; using namespace Herwig; MatchboxAmplitude::MatchboxAmplitude() : Amplitude(), theCleanupAfter(20), treeLevelHelicityPoints(0), oneLoopHelicityPoints(0), theTrivialColourLegs(false) { } -MatchboxAmplitude::~MatchboxAmplitude() {} - void MatchboxAmplitude::persistentOutput(PersistentOStream & os) const { os << theLastXComb << theColourBasis << theCleanupAfter << treeLevelHelicityPoints << oneLoopHelicityPoints << theTrivialColourLegs << theReshuffleMasses.size(); if ( !theReshuffleMasses.empty() ) { for (auto const & r : theReshuffleMasses ) os << r.first << ounit(r.second,GeV); } } void MatchboxAmplitude::persistentInput(PersistentIStream & is, int) { size_t reshuffleSize; is >> theLastXComb >> theColourBasis >> theCleanupAfter >> treeLevelHelicityPoints >> oneLoopHelicityPoints >> theTrivialColourLegs >> reshuffleSize; theReshuffleMasses.clear(); while ( reshuffleSize > 0 ) { long id; Energy m; is >> id >> iunit(m,GeV); theReshuffleMasses[id] = m; --reshuffleSize; } lastMatchboxXComb(theLastXComb); } Ptr::tptr MatchboxAmplitude::factory() const { return MatchboxFactory::currentFactory(); } void MatchboxAmplitude::doinit() { Amplitude::doinit(); if ( colourBasis() ) { colourBasis()->init(); } } void MatchboxAmplitude::doinitrun() { Amplitude::doinitrun(); if ( colourBasis()) colourBasis()->initrun(); } void MatchboxAmplitude::cloneDependencies(const std::string&,bool) {} MatchboxMEBasePtr MatchboxAmplitude::makeME(const PDVector&) const { return new_ptr(MatchboxMEBase()); } Selector MatchboxAmplitude::colourGeometries(tcDiagPtr d) const { if ( haveColourFlows() ) return colourBasis()->colourGeometries(d,lastLargeNAmplitudes()); return Selector(); } void MatchboxAmplitude::olpOrderFileHeader(ostream& os) const { os << "# OLP order file created by Herwig/Matchbox\n\n"; os << "InterfaceVersion BLHA2\n\n"; os << "Model SM\n" << "CorrectionType QCD\n" << "IRregularisation " << (isDR() ? "DRED" : "CDR") << "\n" << "Extra HelAvgInitial no\n" << "Extra ColAvgInitial no\n" << "Extra MCSymmetrizeFinal no\n"; os << "\n"; } void MatchboxAmplitude::olpOrderFileProcesses(ostream& os, const map,int>& proc) const { map > sorted; for (auto const & p : proc ) { sorted[p.second] = p.first; } unsigned int currentOrderInAlphaS = sorted.begin()->second.first.orderInAlphaS; unsigned int currentOrderInAlphaEW = sorted.begin()->second.first.orderInAlphaEW; int currentType = sorted.begin()->second.second; os << "AlphasPower " << currentOrderInAlphaS << "\n" << "AlphaPower " << currentOrderInAlphaEW << "\n" << "AmplitudeType "; if ( currentType == ProcessType::treeME2 ) { os << "tree\n"; } else if ( currentType == ProcessType::oneLoopInterference ) { os << "loop\n"; } else if ( currentType == ProcessType::colourCorrelatedME2 ) { os << "cctree\n"; } else if ( currentType == ProcessType::spinColourCorrelatedME2 ) { os << "sctree\n"; } else if ( currentType == ProcessType::loopInducedME2 ) { os << "loopinduced\n"; } else if ( currentType == ProcessType::spinCorrelatedME2 ) { os << "stree\n"; } else assert(false); for ( map >::const_iterator p = sorted.begin(); p != sorted.end(); ++p ) { if ( currentOrderInAlphaS != p->second.first.orderInAlphaS ) { currentOrderInAlphaS = p->second.first.orderInAlphaS; os << "AlphasPower " << currentOrderInAlphaS << "\n"; } if ( currentOrderInAlphaEW != p->second.first.orderInAlphaEW ) { currentOrderInAlphaEW = p->second.first.orderInAlphaEW; os << "AlphaPower " << currentOrderInAlphaEW << "\n"; } if ( currentType != p->second.second ) { currentType = p->second.second; os << "AmplitudeType "; if ( currentType == ProcessType::treeME2 ) { os << "tree\n"; } else if ( currentType == ProcessType::oneLoopInterference ) { os << "loop\n"; } else if ( currentType == ProcessType::colourCorrelatedME2 ) { os << "cctree\n"; } else if ( currentType == ProcessType::spinColourCorrelatedME2 ) { os << "sctree\n"; } else if ( currentType == ProcessType::spinCorrelatedME2 ) { os << "stree\n"; } else assert(false); } os << p->second.first.legs[0]->id() << " " << p->second.first.legs[1]->id() << " -> "; for ( PDVector::const_iterator o = p->second.first.legs.begin() + 2; o != p->second.first.legs.end(); ++o ) { os << (**o).id() << " "; } os << "\n"; } } bool MatchboxAmplitude::startOLP(const map,int>& procs) { string orderFileName = factory()->buildStorage() + name() + ".OLPOrder.lh"; ofstream orderFile(orderFileName.c_str()); olpOrderFileHeader(orderFile); olpOrderFileProcesses(orderFile,procs); string contractFileName = factory()->buildStorage() + name() + ".OLPContract.lh"; signOLP(orderFileName, contractFileName); // TODO check the contract file int status = 0; startOLP(contractFileName, status); if ( status != 1 ) return false; return true; } struct orderPartonData { bool operator()(const pair& a, const pair& b) const { if ( a.first == b.first ) return a.second < b.second; int acolour = a.first->iColour(); int bcolour = b.first->iColour(); if ( abs(acolour) != abs(bcolour) ) return abs(acolour) < abs(bcolour); if ( a.first->iSpin() != b.first->iSpin() ) return a.first->iSpin() < b.first->iSpin(); int acharge = a.first->iCharge(); int bcharge = b.first->iCharge(); if ( abs(acharge) != abs(bcharge) ) return abs(acharge) < abs(bcharge); if ( abs(a.first->id()) != abs(b.first->id()) ) return abs(a.first->id()) < abs(b.first->id()); return a.first->id() > b.first->id(); } }; void MatchboxAmplitude::setXComb(tStdXCombPtr xc) { theLastXComb = xc; lastMatchboxXComb(xc); fillCrossingMap(); if ( ( treeAmplitudes() || oneLoopAmplitudes() ) && hasAmplitudeMomenta() ) for ( size_t k = 0 ; k < meMomenta().size(); ++k ) amplitudeMomenta()[k] = amplitudeMomentum(k); } void MatchboxAmplitude::fillCrossingMap(size_t shift) { if ( !amplitudePartonData().empty() ) return; double csign = 1.; set,orderPartonData > processLegs; for ( unsigned int l = 0; l < mePartonData().size(); ++l ) { if ( l > 1 ) processLegs.insert(make_pair(mePartonData()[l],l)); else { if ( mePartonData()[l]->CC() ) { processLegs.insert(make_pair(mePartonData()[l]->CC(),l)); if ( mePartonData()[l]->iSpin() == PDT::Spin1Half ) csign *= -1.; } else { processLegs.insert(make_pair(mePartonData()[l],l)); } } } crossingSign(csign); set > amplitudeLegs; crossingMap().resize(mePartonData().size()); amplitudePartonData().resize(mePartonData().size()); if ( hasAmplitudeMomenta() ) amplitudeMomenta().resize(mePartonData().size()); int ampCount = 0; // process legs are already sorted, we only need to arrange for // adjacent particles and anti-particles while ( !processLegs.empty() ) { set,orderPartonData >::iterator next = processLegs.begin(); while ( next->first->id() < 0 ) { if ( ++next == processLegs.end() ) break; } //This happens for e.g. p p-> W- gamma & p p->W- W- j j //Still working for pp->W-H-W- e+ nue jj ??? if(next == processLegs.end()){ next = processLegs.begin(); for (;next!=processLegs.end();next++){ assert(next->first->id() < 0 ); crossingMap()[ampCount] = next->second - shift; amplitudeLegs.insert(make_pair(next->first,ampCount)); ++ampCount; processLegs.erase(next); } break; } crossingMap()[ampCount] = next->second - shift; amplitudeLegs.insert(make_pair(next->first,ampCount)); tcPDPtr check = next->first; processLegs.erase(next); ++ampCount; if ( check->CC() ) { set,orderPartonData>::iterator checkcc = processLegs.end(); for ( set,orderPartonData>::iterator c = processLegs.begin(); c != processLegs.end(); ++c ) { if ( c->first == check->CC() ) { checkcc = c; break; } } if ( checkcc == processLegs.end() ) for ( set,orderPartonData>::iterator c = processLegs.begin(); c != processLegs.end(); ++c ) { if ( !SU2Helper::SU2CC(check) ) continue; if ( c->first == SU2Helper::SU2CC(check)->CC() ) { checkcc = c; break; } } if ( checkcc == processLegs.end() ) { int f = SU2Helper::family(check); for ( int i = 1 - f; i < 5 - f; i++ ) { bool gotone = false; for ( set,orderPartonData>::iterator c = processLegs.begin(); c != processLegs.end(); ++c ) { if ( !SU2Helper::SU2CC(check,i) ) continue; if ( c->first == SU2Helper::SU2CC(check,i)->CC() ) { checkcc = c; gotone = true; break; } } if ( gotone ) break; } } // default to just pick the next available anti-particle if ( processLegs.empty() ) break; if ( checkcc == processLegs.end() ) { checkcc = processLegs.begin(); while ( checkcc->first->id() > 0 ) if ( ++checkcc == processLegs.end() ) break; } // if still not there, use whatever is available at the end if ( checkcc == processLegs.end() ) checkcc = processLegs.begin(); crossingMap()[ampCount] = checkcc->second - shift; amplitudeLegs.insert(make_pair(checkcc->first,ampCount)); processLegs.erase(checkcc); ++ampCount; } } for ( set >::const_iterator l = amplitudeLegs.begin(); l != amplitudeLegs.end(); ++l ) amplitudePartonData()[l->second] = l->first; if ( colourBasis() && !colourBasis()->indexMap().empty()) { assert(colourBasis()->indexMap().find(mePartonData()) != colourBasis()->indexMap().end()); const map colourCross = colourBasis()->indexMap().find(mePartonData())->second; for ( size_t k = 0; k < crossingMap().size(); ++k ) { if ( colourCross.find(crossingMap()[k]) != colourCross.end() ) { size_t ccross = colourCross.find(crossingMap()[k])->second; amplitudeToColourMap()[k] = ccross; colourToAmplitudeMap()[ccross] = k; } } } } const string& MatchboxAmplitude::colourOrderingString(size_t id) const { static string empty = ""; if ( !colourBasis() ) { return empty; } return colourBasis()->orderingString(mePartonData(),colourToAmplitudeMap(),id); } const set >& MatchboxAmplitude::colourOrdering(size_t id) const { static set > empty; if ( !colourBasis() ) { return empty; } return colourBasis()->ordering(mePartonData(),colourToAmplitudeMap(),id); } Lorentz5Momentum MatchboxAmplitude::amplitudeMomentum(int i) const { int iCrossed = crossingMap()[i]; Lorentz5Momentum res = meMomenta()[iCrossed]; if ( iCrossed < 2 ) res = -res; res.setMass(meMomenta()[iCrossed].mass()); Energy2 rho = res.t()*res.t() - res.mass2(); res.setRho(sqrt(abs(rho))); return res; } set > MatchboxAmplitude::generateHelicities() const { set > res; vector current(amplitudePartonData().size()); doGenerateHelicities(res,current,0); return res; } void MatchboxAmplitude::doGenerateHelicities(set >& res, vector& current, size_t pos) const { if ( pos == amplitudePartonData().size() ) { res.insert(current); return; } if ( amplitudePartonData()[pos]->iSpin() == PDT::Spin0 ) { current[pos] = 0; doGenerateHelicities(res,current,pos+1); } else if ( amplitudePartonData()[pos]->iSpin() == PDT::Spin1Half ) { current[pos] = 1; doGenerateHelicities(res,current,pos+1); current[pos] = -1; doGenerateHelicities(res,current,pos+1); }else if (amplitudePartonData()[pos]->iSpin() == PDT::Spin1 ) { if (amplitudePartonData()[pos]->hardProcessMass() != ZERO){ current[pos] = 0; doGenerateHelicities(res,current,pos+1); } current[pos] = 1; doGenerateHelicities(res,current,pos+1); current[pos] = -1; doGenerateHelicities(res,current,pos+1); } } vector MatchboxAmplitude::physicalHelicities(const vector&) const { throw Exception() << "MatchboxAmplitude::physicalHelicities(): The amplitude '" << name() << "' does not support the spin correlation algorithm" << Exception::runerror; static vector dummy; return dummy; } void MatchboxAmplitude::prepareAmplitudes(Ptr::tcptr) { if ( !calculateTreeAmplitudes() ) return; bool initialized = !lastAmplitudes().empty() && treeLevelHelicityPoints > theCleanupAfter; if ( !initialized ) { treeLevelHelicityPoints++; map,CVector> all; map,CVector> allLargeN; set > helicities = generateHelicities(); for ( set >::const_iterator h = helicities.begin(); h != helicities.end(); ++h ) { all.insert(make_pair(*h,CVector(max(colourBasisDim(),1)))); allLargeN.insert(make_pair(*h,CVector(max(colourBasisDim(),1)))); } AmplitudeIterator amp = all.begin(); AmplitudeIterator lamp = allLargeN.begin(); for ( ; amp != all.end(); ++amp, ++lamp ) { for ( size_t k = 0; k < max(colourBasisDim(),1); ++k ){ amp->second(k) = evaluate(k,amp->first,lamp->second(k)); if ( amp->second(k) != Complex(0.0) ) { if ( lastAmplitudes().find(amp->first)!=lastAmplitudes().end() ) { lastAmplitudes().find(amp->first)->second = amp->second; lastLargeNAmplitudes().find(lamp->first)->second = lamp->second; } else { lastAmplitudes().insert(*amp); lastLargeNAmplitudes().insert(*lamp); } } else if ( lastAmplitudes().find(amp->first)!=lastAmplitudes().end() ){ lastAmplitudes().find(amp->first)->second = amp->second; lastLargeNAmplitudes().find(lamp->first)->second = lamp->second; } } } } else { AmplitudeIterator amp = lastAmplitudes().begin(); AmplitudeIterator lamp = lastLargeNAmplitudes().begin(); for ( ;amp != lastAmplitudes().end(); ++amp, ++lamp ) { for ( size_t k = 0; k < max(colourBasisDim(),1); ++k ){ amp->second(k) = evaluate(k,amp->first,lamp->second(k)); } } } haveTreeAmplitudes(); } void MatchboxAmplitude::prepareOneLoopAmplitudes(Ptr::tcptr) { if ( !calculateOneLoopAmplitudes() ) return; bool initialized = !lastOneLoopAmplitudes().empty() && oneLoopHelicityPoints > theCleanupAfter; if ( !initialized ) { oneLoopHelicityPoints++; map,CVector> all; set > helicities = generateHelicities(); for ( set >::const_iterator h = helicities.begin(); h != helicities.end(); ++h ) { all.insert(make_pair(*h,CVector(max(colourBasisDim(),1)))); } AmplitudeIterator amp = all.begin(); for ( ; amp != all.end(); ++amp ) { for ( size_t k = 0; k < max(colourBasisDim(),1); ++k ){ amp->second(k) = evaluateOneLoop(k,amp->first); if ( amp->second(k) != Complex(0.0) ) { if ( lastOneLoopAmplitudes().find(amp->first)!=lastOneLoopAmplitudes().end() ) { lastOneLoopAmplitudes().find(amp->first)->second = amp->second; } else{ lastOneLoopAmplitudes().insert(*amp); } } else if ( lastOneLoopAmplitudes().find(amp->first)!=lastOneLoopAmplitudes().end() ){ lastOneLoopAmplitudes().find(amp->first)->second = amp->second; } } } } else { AmplitudeIterator amp = lastOneLoopAmplitudes().begin(); for ( ;amp != lastOneLoopAmplitudes().end(); ++amp ) { for ( size_t k = 0; k < max(colourBasisDim(),1); ++k ){ amp->second(k) = evaluateOneLoop(k,amp->first); } } } haveOneLoopAmplitudes(); } Complex MatchboxAmplitude::value(const tcPDVector&, const vector&, const vector&) { assert(false && "ThePEG::Amplitude interface is not sufficient at the moment."); throw Exception() << "MatchboxAmplitude::value(): ThePEG::Amplitude interface is not sufficient at the moment." << Exception::runerror; return 0.; } double MatchboxAmplitude::me2() const { if ( !calculateTreeME2() ) return lastTreeME2(); lastTreeME2(colourBasis()->me2(mePartonData(),lastAmplitudes())); return lastTreeME2(); } double MatchboxAmplitude::largeNME2(Ptr::tptr largeNBasis) const { if ( !calculateLargeNME2() ) return lastLargeNME2(); double res = 0.; if ( !trivialColourLegs() ) res = largeNBasis->me2(mePartonData(),lastLargeNAmplitudes()); else res = me2(); lastLargeNME2(res); return res; } double MatchboxAmplitude::oneLoopInterference() const { if ( !calculateOneLoopInterference() ) return lastOneLoopInterference(); lastOneLoopInterference(colourBasis()->interference(mePartonData(), lastOneLoopAmplitudes(),lastAmplitudes())); return lastOneLoopInterference(); } double MatchboxAmplitude::colourCharge(tcPDPtr data) const { double cfac = 1.; double Nc = generator()->standardModel()->Nc(); if ( data->iColour() == PDT::Colour8 ) { cfac = Nc; } else if ( data->iColour() == PDT::Colour3 || data->iColour() == PDT::Colour3bar ) { cfac = (sqr(Nc)-1.)/(2.*Nc); } else assert(false); return cfac; } double MatchboxAmplitude::largeNColourCharge(tcPDPtr data) const { double cfac = 1.; double Nc = generator()->standardModel()->Nc(); if ( data->iColour() == PDT::Colour8 ) { cfac = Nc; } else if ( data->iColour() == PDT::Colour3 || data->iColour() == PDT::Colour3bar ) { cfac = 0.5*Nc; } else assert(false); return cfac; } double MatchboxAmplitude::colourCorrelatedME2(pair ij) const { double cfac = colourCharge(mePartonData()[ij.first]); if ( !calculateColourCorrelator(ij) ) return lastColourCorrelator(ij)/cfac; double res = 0.; if ( !trivialColourLegs() ) res = colourBasis()->colourCorrelatedME2(ij,mePartonData(),lastAmplitudes()); else { // two partons TiTj = (-Ti^2-Tj^2)/2 // three partons TiTj = (-Ti^2-Tj^2+Tk^2)/2 int n = mePartonData().size(); for ( int i = 0; i < n; ++i ) { if ( !mePartonData()[i]->coloured() ) continue; if ( i == ij.first || i == ij.second ) res -= colourCharge(mePartonData()[i])*me2(); else res += colourCharge(mePartonData()[i])*me2(); } res *= 0.5; } lastColourCorrelator(ij,res); return res/cfac; } double MatchboxAmplitude::largeNColourCorrelatedME2(pair ij, Ptr::tptr largeNBasis) const { double cfac = largeNColourCharge(mePartonData()[ij.first]); if ( !calculateLargeNColourCorrelator(ij) ) return lastLargeNColourCorrelator(ij)/cfac; double res = 0.; if ( !trivialColourLegs() ) res = largeNBasis->colourCorrelatedME2(ij,mePartonData(),lastLargeNAmplitudes()); else { // two partons TiTj = (-Ti^2-Tj^2)/2 // three partons TiTj = (-Ti^2-Tj^2+Tk^2)/2 int n = mePartonData().size(); for ( int i = 0; i < n; ++i ) { if ( !mePartonData()[i]->coloured() ) continue; if ( i == ij.first || i == ij.second ) res -= largeNColourCharge(mePartonData()[i])*largeNME2(largeNBasis); else res += largeNColourCharge(mePartonData()[i])*largeNME2(largeNBasis); } res *= 0.5; } lastLargeNColourCorrelator(ij,res); return res/cfac; } // compare int vectors modulo certain element // which needs to differe between the two bool equalsModulo(unsigned int i, const vector& a, const vector& 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; } LorentzVector MatchboxAmplitude::plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int) const { using namespace SpinorHelicity; LorentzVector > num = PlusSpinorCurrent(PlusConjugateSpinor(n),MinusSpinor(p)).eval(); complex den = sqrt(2.)*PlusSpinorProduct(PlusConjugateSpinor(n),PlusSpinor(p)).eval(); LorentzVector polarization(num.x()/den,num.y()/den,num.z()/den,num.t()/den); return polarization; } double MatchboxAmplitude::spinColourCorrelatedME2(pair ij, const SpinCorrelationTensor& c) const { Lorentz5Momentum p = meMomenta()[ij.first]; Lorentz5Momentum n = meMomenta()[ij.second]; LorentzVector polarization = plusPolarization(p,n,ij.first); Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale())); double avg = colourCorrelatedME2(ij)*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor)); int iCrossed = -1; for ( unsigned int k = 0; k < crossingMap().size(); ++k ) if ( crossingMap()[k] == ij.first ) { iCrossed = k; break; } assert(iCrossed >= 0); Complex csCorr = 0.0; if ( calculateColourSpinCorrelator(ij) ) { set 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; } double MatchboxAmplitude::spinCorrelatedME2(pair ij, const SpinCorrelationTensor& c) const { Lorentz5Momentum p = meMomenta()[ij.first]; Lorentz5Momentum n = meMomenta()[ij.second]; LorentzVector polarization = plusPolarization(p,n,ij.first); Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale())); double avg = me2()*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor)); int iCrossed = -1; for ( unsigned int k = 0; k < crossingMap().size(); ++k ) if ( crossingMap()[k] == ij.first ) { iCrossed = k; break; } assert(iCrossed >= 0); Complex csCorr = 0.0; if ( calculateSpinCorrelator(ij) ) { set 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()->interference(mePartonData(),a->second,b->second); } lastSpinCorrelator(ij,csCorr); } else { csCorr = lastSpinCorrelator(ij); } double corr = 2.*real(csCorr*sqr(pFactor)); return avg + (c.scale() > ZERO ? 1. : -1.)*corr; } void MatchboxAmplitude::checkReshuffling(Ptr::tptr ps) { set noReshuffle; for ( map::const_iterator m = reshuffleMasses().begin(); m != reshuffleMasses().end(); ++m ) { tcPDPtr data = getParticleData(m->first); assert(data); bool needReshuffle = m->second != data->hardProcessMass(); needReshuffle |= (data->hardProcessWidth() != ZERO || data->massGenerator()) && ps->useMassGenerators(); if ( !needReshuffle ) noReshuffle.insert(m->first); } for ( set::const_iterator rm = noReshuffle.begin(); rm != noReshuffle.end(); ++rm ) theReshuffleMasses.erase(*rm); } string MatchboxAmplitude::doReshuffle(string in) { in = StringUtils::stripws(in); if ( in.empty() ) throw Exception() << "MatchboxAmplitude::doReshuffle(): Expecting PDG id and mass value" << Exception::runerror; istringstream ins(in); long id; ins >> id; if ( ins.eof() ) throw Exception() << "MatchboxAmplitude::doReshuffle(): expecting PDG id and mass value" << Exception::runerror; Energy m; ins >> iunit(m,GeV); theReshuffleMasses[id] = m; return ""; } string MatchboxAmplitude::doMassless(string in) { in = StringUtils::stripws(in); if ( in.empty() ) throw Exception() << "MatchboxAmplitude::doMassless(): Expecting PDG id" << Exception::runerror; istringstream ins(in); long id; ins >> id; theReshuffleMasses[id] = ZERO; return ""; } string MatchboxAmplitude::doOnShell(string in) { in = StringUtils::stripws(in); if ( in.empty() ) throw Exception() << "MatchboxAmplitude::doOnShell(): Expecting PDG id" << Exception::runerror; istringstream ins(in); long id; ins >> id; tcPDPtr data = getParticleData(id); assert(data); theReshuffleMasses[id] = data->hardProcessMass(); return ""; } string MatchboxAmplitude::doClearReshuffling(string) { theReshuffleMasses.clear(); return ""; } void MatchboxAmplitude::Init() { static ClassDocumentation documentation ("MatchboxAmplitude is the base class for amplitude " "implementations inside Matchbox."); static Reference interfaceColourBasis ("ColourBasis", "Set the colour basis implementation.", &MatchboxAmplitude::theColourBasis, false, false, true, true, false); static Parameter interfaceCleanupAfter ("CleanupAfter", "The number of points after which helicity combinations are cleaned up.", &MatchboxAmplitude::theCleanupAfter, 20, 1, 0, false, false, Interface::lowerlim); interfaceCleanupAfter.rank(-1); static Command interfaceReshuffle ("Reshuffle", "Reshuffle the mass for the given PDG id to a different mass shell for amplitude evaluation.", &MatchboxAmplitude::doReshuffle, false); interfaceReshuffle.rank(-1); static Command interfaceMassless ("Massless", "Reshuffle the mass for the given PDG id to be massless for amplitude evaluation.", &MatchboxAmplitude::doMassless, false); interfaceMassless.rank(-1); static Command interfaceOnShell ("OnShell", "Reshuffle the mass for the given PDG id to be the on-shell mass for amplitude evaluation.", &MatchboxAmplitude::doOnShell, false); interfaceOnShell.rank(-1); static Command interfaceClearReshuffling ("ClearReshuffling", "Do not perform any reshuffling.", &MatchboxAmplitude::doClearReshuffling, false); interfaceClearReshuffling.rank(-1); static Switch interfaceTrivialColourLegs ("TrivialColourLegs", "Assume the process considered has trivial colour correllations.", &MatchboxAmplitude::theTrivialColourLegs, false, false, false); static SwitchOption interfaceTrivialColourLegsYes (interfaceTrivialColourLegs, "Yes", "", true); static SwitchOption interfaceTrivialColourLegsNo (interfaceTrivialColourLegs, "No", "", false); interfaceTrivialColourLegs.rank(-1); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeMatchboxAmplitude("Herwig::MatchboxAmplitude", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Base/MatchboxAmplitude.h b/MatrixElement/Matchbox/Base/MatchboxAmplitude.h --- a/MatrixElement/Matchbox/Base/MatchboxAmplitude.h +++ b/MatrixElement/Matchbox/Base/MatchboxAmplitude.h @@ -1,714 +1,706 @@ // -*- C++ -*- // // MatchboxAmplitude.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MatchboxAmplitude_H #define HERWIG_MatchboxAmplitude_H // // This is the declaration of the MatchboxAmplitude class. // #include "ThePEG/MatrixElement/Amplitude.h" #include "ThePEG/Handlers/LastXCombInfo.h" #include "Herwig/MatrixElement/Matchbox/Utility/ColourBasis.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxXComb.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.fh" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.fh" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief Process information with coupling order */ struct Process { PDVector legs; unsigned int orderInAlphaS; unsigned int orderInAlphaEW; Process() : orderInAlphaS(0), orderInAlphaEW(0) {} Process(const PDVector& p, unsigned int oas, unsigned int oae) : legs(p), orderInAlphaS(oas), orderInAlphaEW(oae) {} bool operator==(const Process& other) const { return legs == other.legs && orderInAlphaS == other.orderInAlphaS && orderInAlphaEW == other.orderInAlphaEW; } bool operator<(const Process& other) const { if ( orderInAlphaS != other.orderInAlphaS ) return orderInAlphaS < other.orderInAlphaS; if ( orderInAlphaEW != other.orderInAlphaEW ) return orderInAlphaEW < other.orderInAlphaEW; return legs < other.legs; } void persistentOutput(PersistentOStream & os) const { os << legs << orderInAlphaS << orderInAlphaEW; } void persistentInput(PersistentIStream & is) { is >> legs >> orderInAlphaS >> orderInAlphaEW; } }; /** * \ingroup Matchbox * \author Simon Platzer * * \brief Enumerate the type of calculation required */ namespace ProcessType { enum Types { treeME2 = 0, colourCorrelatedME2, spinColourCorrelatedME2, oneLoopInterference, loopInducedME2, spinCorrelatedME2 }; } /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxAmplitude is the base class for amplitude * implementations inside Matchbox. * * @see \ref MatchboxAmplitudeInterfaces "The interfaces" * defined for MatchboxAmplitude. */ class MatchboxAmplitude: public Amplitude, public LastXCombInfo, public LastMatchboxXCombInfo { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitude(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitude(); - //@} - public: /** * Return the amplitude. Needs to be implemented from * ThePEG::Amplitude but is actually ill-defined, as colours of the * external particles are not specified. To this extent, this * implementation just asserts. */ virtual Complex value(const tcPDVector & particles, const vector & momenta, const vector & helicities); /** * Return the factory which produced this matrix element */ Ptr::tptr factory() const; /** @name Subprocess information */ //@{ /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector& p, Ptr::tptr, bool) const { return canHandle(p); } /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const { return false; } /** * Return the number of random numbers required to evaluate this * amplitude at a fixed phase space point. */ virtual int nDimAdditional() const { return 0; } /** * Return a ME instance appropriate for this amplitude and the given * subprocesses */ virtual Ptr::ptr makeME(const PDVector&) const; /** * Set the (tree-level) order in \f$g_S\f$ in which this matrix * element should be evaluated. */ virtual void orderInGs(unsigned int) {} /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const = 0; /** * Set the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element should be evaluated. */ virtual void orderInGem(unsigned int) {} /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const = 0; /** * Return the Herwig StandardModel object */ Ptr::tcptr standardModel() { if ( !hwStandardModel() ) hwStandardModel(dynamic_ptr_cast::tcptr>(HandlerBase::standardModel())); return hwStandardModel(); } /** * Return true, if this amplitude already includes averaging over * incoming parton's quantum numbers. */ virtual bool hasInitialAverage() const { return false; } /** * Return true, if this amplitude already includes symmetry factors * for identical outgoing particles. */ virtual bool hasFinalStateSymmetry() const { return false; } /** * Return true, if this amplitude is handled by a BLHA one-loop provider */ virtual bool isOLPTree() const { return false; } /** * Return true, if this amplitude is handled by a BLHA one-loop provider */ virtual bool isOLPLoop() const { return false; } /** * Return true, if colour and spin correlated matrix elements should * be ordered from the OLP */ virtual bool needsOLPCorrelators() const { return true; } /** * Write the order file header */ virtual void olpOrderFileHeader(ostream&) const; /** * Write the order file process list */ virtual void olpOrderFileProcesses(ostream&, const map,int>& procs) const; /** * Start the one loop provider, if appropriate, giving order and * contract files */ virtual void signOLP(const string&, const string&) { } /** * Start the one loop provider, if appropriate */ virtual void startOLP(const string&, int& status) { status = -1; } /** * Start the one loop provider, if appropriate. This default * implementation writes an BLHA 2.0 order file and starts the OLP */ virtual bool startOLP(const map,int>& procs); /** * Return true, if this amplitude needs to initialize an external * code. */ virtual bool isExternal() const { return false; } /** * Initialize this amplitude */ virtual bool initializeExternal() { return false; } /** * Return a generic process id for the given process */ virtual int externalId(const cPDVector&) { return 0; } /** * Return the map with masses to be used for amplitude evaluation */ const map& reshuffleMasses() const { return theReshuffleMasses; } /** * Check if reshuffling is needed at all */ void checkReshuffling(Ptr::tptr); /** * Return true, if this amplitude makes use of amplitudeMomenta */ virtual bool hasAmplitudeMomenta() const { return false; } //@} /** @name Colour basis. */ //@{ /** * Return the colour basis. */ virtual Ptr::tptr colourBasis() const { return theColourBasis; } /** * Return true, if the colour basis is capable of assigning colour * flows. */ virtual bool haveColourFlows() const { return colourBasis() ? colourBasis()->haveColourFlows() : false; } /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; /** * Return an ordering identifier for the current subprocess and * colour absis tensor index. */ const string& colourOrderingString(size_t id) const; /** * Return an ordering identifier for the current subprocess and * colour absis tensor index. */ const set >& colourOrdering(size_t id) const; //@} /** @name Phasespace point, crossing and helicities */ //@{ /** * Set the xcomb object. */ virtual void setXComb(tStdXCombPtr xc); /** * Return the momentum as crossed appropriate for this amplitude. */ Lorentz5Momentum amplitudeMomentum(int) const; /** * Perform a normal ordering of external legs and fill the * crossing information as. This default implementation sorts * lexicographically in (abs(colour)/spin/abs(charge)), putting pairs * of particles/anti-particles where possible. */ virtual void fillCrossingMap(size_t shift = 0); /** * Generate the helicity combinations. */ virtual set > generateHelicities() const; /** * Return the helicity combination of the physical process in the * conventions used by the spin correlation algorithm. */ virtual vector physicalHelicities(const vector&) const; //@} /** @name Tree-level amplitudes */ //@{ /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Return the matrix element squared. */ virtual double me2() const; /** * Return the colour charge of a given leg */ double colourCharge(tcPDPtr) const; /** * Return the large-N charge of a given leg */ double largeNColourCharge(tcPDPtr) const; /** * Return the largeN matrix element squared. */ virtual double largeNME2(Ptr::tptr largeNBasis) const; /** * Return the colour correlated matrix element. */ virtual double colourCorrelatedME2(pair ij) const; /** * Return the large-N colour correlated matrix element. */ virtual double largeNColourCorrelatedME2(pair ij, Ptr::tptr largeNBasis) const; /** * Return true if trivial colour configuration. */ bool trivialColourLegs() const { return theTrivialColourLegs; } /** * Return true, if this amplitude is capable of consistently filling * the rho matrices for the spin correllations */ virtual bool canFillRhoMatrix() const { return false; } /** * Return a positive helicity polarization vector for a gluon of * momentum p (with reference vector n) to be used when evaluating * spin correlations. */ virtual LorentzVector plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int id = -1) const; /** * Return the colour and spin correlated matrix element. */ virtual double spinColourCorrelatedME2(pair emitterSpectator, const SpinCorrelationTensor& c) const; /** * Return the spin correlated matrix element. */ virtual double spinCorrelatedME2(pair emitterSpectator, const SpinCorrelationTensor& c) const; /** * Return true, if tree-level contributions will be evaluated at amplitude level. */ virtual bool treeAmplitudes() const { return true; } /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&) { return 0.; } //@} /** @name One-loop amplitudes */ //@{ /** * Return the one-loop amplitude, if applicable. */ virtual Ptr::tptr oneLoopAmplitude() const { return Ptr::tptr(); } /** * Diasble one-loop functionality if not needed. */ virtual void disableOneLoop() {} /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Return true, if this amplitude only provides * one-loop (QCD) corrections. */ virtual bool onlyOneLoop() const { return false; } /** * Return true, if one-loop contributions will be evaluated at amplitude level. */ virtual bool oneLoopAmplitudes() const { return true; } /** * Return true, if one loop corrections have been calculated in * dimensional reduction. Otherwise conventional dimensional * regularization is assumed. Note that renormalization is always * assumed to be MSbar. */ virtual bool isDR() const { return false; } /** * Return true, if the amplitude is DRbar renormalized, otherwise * MSbar is assumed. */ virtual bool isDRbar() const { return true; } /** * Return true, if one loop corrections are given in the conventions * of the integrated dipoles. */ virtual bool isCS() const { return false; } /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return false; } /** * Return true, if one loop corrections are given in the conventions * of everything expanded. */ virtual bool isExpanded() const { return false; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return 0.*GeV2; } /** * Indicate that this amplitude is running alphas by itself. */ virtual bool hasRunningAlphaS() const { return false; } /** * Indicate that this amplitude is running alphaew by itself. */ virtual bool hasRunningAlphaEW() const { return false; } /** * If defined, return the coefficient of the pole in epsilon^2 */ virtual double oneLoopDoublePole() const { return 0.; } /** * If defined, return the coefficient of the pole in epsilon */ virtual double oneLoopSinglePole() const { return 0.; } /** * Calculate the one-loop amplitudes for the phasespace point * stored in lastXComb, if provided. */ virtual void prepareOneLoopAmplitudes(Ptr::tcptr); /** * Return the one-loop/tree interference. */ virtual double oneLoopInterference() const; /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluateOneLoop(size_t, const vector&) { return 0.; } //@} /** @name Caching and helpers to setup amplitude objects. */ //@{ /** * Flush all cashes. */ virtual void flushCaches() {} /** * Clone this amplitude. */ Ptr::ptr cloneMe() const { return dynamic_ptr_cast::ptr>(clone()); } /** * Clone the dependencies, using a given prefix. */ virtual void cloneDependencies(const std::string& prefix="" , bool slim=false); //@} 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). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * Recursively generate helicities */ void doGenerateHelicities(set >& res, vector& current, size_t pos) const; /** * The colour basis implementation to be used. */ Ptr::ptr theColourBasis; /** * The number of points after which helicity combinations wil be * cleaned up */ int theCleanupAfter; /** * The number of points that are calculated before a certain * helicity is excluded. Needed in pp->V */ int treeLevelHelicityPoints; /** * The number of points that are calculated before a certain * helicity is excluded. Needed in pp->V */ int oneLoopHelicityPoints; /** * The map with masses to be used for amplitude evaluation */ map theReshuffleMasses; /** * True if trivial colour configuration. */ bool theTrivialColourLegs; /** * A command to fill the reshuffle mass map */ string doReshuffle(string); /** * A command to fill the reshuffle mass map */ string doMassless(string); /** * A command to fill the reshuffle mass map */ string doOnShell(string); /** * Clear the reshuffling map */ string doClearReshuffling(string); /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitude & operator=(const MatchboxAmplitude &) = delete; }; inline PersistentOStream& operator<<(PersistentOStream& os, const Process& h) { h.persistentOutput(os); return os; } inline PersistentIStream& operator>>(PersistentIStream& is, Process& h) { h.persistentInput(is); return is; } } #endif /* HERWIG_MatchboxAmplitude_H */ diff --git a/MatrixElement/Matchbox/Base/MatchboxHybridAmplitude.cc b/MatrixElement/Matchbox/Base/MatchboxHybridAmplitude.cc --- a/MatrixElement/Matchbox/Base/MatchboxHybridAmplitude.cc +++ b/MatrixElement/Matchbox/Base/MatchboxHybridAmplitude.cc @@ -1,238 +1,236 @@ // -*- C++ -*- // // MatchboxHybridAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxHybridAmplitude class. // #include "MatchboxHybridAmplitude.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.h" using namespace Herwig; MatchboxHybridAmplitude::MatchboxHybridAmplitude() : theUseOLPCorrelators(false) {} -MatchboxHybridAmplitude::~MatchboxHybridAmplitude() {} - IBPtr MatchboxHybridAmplitude::clone() const { return new_ptr(*this); } IBPtr MatchboxHybridAmplitude::fullclone() const { return new_ptr(*this); } bool MatchboxHybridAmplitude::isConsistent() const { assert(oneLoopAmplitude()); return !treeLevelAmplitude()->isOLPTree() && !treeLevelAmplitude()->isOLPLoop() && oneLoopAmplitude()->haveOneLoop() && treeLevelAmplitude()->orderInGs() == oneLoopAmplitude()->orderInGs() && treeLevelAmplitude()->orderInGem() == oneLoopAmplitude()->orderInGem() && treeLevelAmplitude()->hasRunningAlphaS() == oneLoopAmplitude()->hasRunningAlphaS() && treeLevelAmplitude()->hasRunningAlphaEW() == oneLoopAmplitude()->hasRunningAlphaEW() && !(treeLevelAmplitude()->nDimAdditional() != 0 && oneLoopAmplitude()->nDimAdditional() != 0); } bool MatchboxHybridAmplitude::canHandle(const PDVector& p, Ptr::tptr f, bool virt) const { if ( !virt ) return treeLevelAmplitude()->canHandle(p,f,false); if ( treeLevelAmplitude()->canHandle(p,f,false) && oneLoopAmplitude()->canHandle(p,f,true) ) { if ( !isConsistent() ) { generator()->log() << "Warning: Inconsistent settings encountered for MatchboxHybridAmplitude '" << name() << "'\n" << flush; return false; } return true; } return false; } void MatchboxHybridAmplitude::prepareAmplitudes(Ptr::tcptr me) { treeLevelAmplitude()->prepareAmplitudes(me); } void MatchboxHybridAmplitude::prepareOneLoopAmplitudes(Ptr::tcptr me) { assert(oneLoopAmplitude()); oneLoopAmplitude()->prepareOneLoopAmplitudes(me); } double MatchboxHybridAmplitude::symmetryRatio() const { assert(oneLoopAmplitude()); double ifact = 1.; if ( treeLevelAmplitude()->hasInitialAverage() && !oneLoopAmplitude()->hasInitialAverage() ) { 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.); } if ( !treeLevelAmplitude()->hasInitialAverage() && oneLoopAmplitude()->hasInitialAverage() ) { ifact = 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 ( lastMatchboxXComb()->matchboxME()->mePartonData()[1]->iColour() == PDT::Colour8 ) ifact *= (SM().Nc()*SM().Nc()-1.); } if ( treeLevelAmplitude()->hasFinalStateSymmetry() && !oneLoopAmplitude()->hasFinalStateSymmetry() ) { assert(lastMatchboxXComb()->matchboxME()); ifact *= lastMatchboxXComb()->matchboxME()->finalStateSymmetry(); } if ( !treeLevelAmplitude()->hasFinalStateSymmetry() && oneLoopAmplitude()->hasFinalStateSymmetry() ) { assert(lastMatchboxXComb()->matchboxME()); ifact /= lastMatchboxXComb()->matchboxME()->finalStateSymmetry(); } return ifact; } void MatchboxHybridAmplitude::cloneDependencies(const std::string& prefix,bool slim) { if ( treeLevelAmplitude() ) { Ptr::ptr myTreeLevelAmplitude = treeLevelAmplitude()->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << myTreeLevelAmplitude->name(); if ( ! (generator()->preinitRegister(myTreeLevelAmplitude,pname.str()) ) ) throw Exception() << "MatchboxHybridAmplitude::cloneDependencies(): Amplitude " << pname.str() << " already existing." << Exception::runerror; myTreeLevelAmplitude->cloneDependencies(pname.str()); treeLevelAmplitude(myTreeLevelAmplitude); } if ( oneLoopAmplitude() ) { Ptr::ptr myOneLoopAmplitude = oneLoopAmplitude()->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << myOneLoopAmplitude->name(); if ( ! (generator()->preinitRegister(myOneLoopAmplitude,pname.str()) ) ) throw Exception() << "MatchboxHybridAmplitude::cloneDependencies(): Amplitude " << pname.str() << " already existing." << Exception::runerror; myOneLoopAmplitude->cloneDependencies(pname.str()); oneLoopAmplitude(myOneLoopAmplitude); } MatchboxAmplitude::cloneDependencies(prefix,slim); } void MatchboxHybridAmplitude::doinit() { MatchboxAmplitude::doinit(); if ( treeLevelAmplitude() ) treeLevelAmplitude()->init(); if ( oneLoopAmplitude() ) oneLoopAmplitude()->init(); } void MatchboxHybridAmplitude::doinitrun() { MatchboxAmplitude::doinitrun(); if ( treeLevelAmplitude() ) treeLevelAmplitude()->initrun(); if ( oneLoopAmplitude() ) oneLoopAmplitude()->initrun(); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxHybridAmplitude::persistentOutput(PersistentOStream & os) const { os << theTreeLevelAmplitude << theOneLoopAmplitude << theUseOLPCorrelators; } void MatchboxHybridAmplitude::persistentInput(PersistentIStream & is, int) { is >> theTreeLevelAmplitude >> theOneLoopAmplitude >> theUseOLPCorrelators; } // *** 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 describeHerwigMatchboxHybridAmplitude("Herwig::MatchboxHybridAmplitude", "Herwig.so"); void MatchboxHybridAmplitude::Init() { static ClassDocumentation documentation ("MatchboxHybridAmplitude unifies two amplitude objects to " "provide tree and one-loop matrix elements."); static Reference interfaceTreeLevelAmplitude ("TreeLevelAmplitude", "Set the tree level amplitude to be used.", &MatchboxHybridAmplitude::theTreeLevelAmplitude, false, false, true, false, false); static Reference interfaceOneLoopAmplitude ("OneLoopAmplitude", "Set the one-loop amplitude to be used.", &MatchboxHybridAmplitude::theOneLoopAmplitude, false, false, true, true, false); static Switch interfaceUseOLPCorrelators ("UseOLPCorrelators", "Obtain correlated matrix elements from the OLP instead of " "the tree-level amplitude.", &MatchboxHybridAmplitude::theUseOLPCorrelators, false, false, false); static SwitchOption interfaceUseOLPCorrelatorsYes (interfaceUseOLPCorrelators, "Yes", "", true); static SwitchOption interfaceUseOLPCorrelatorsNo (interfaceUseOLPCorrelators, "No", "", false); interfaceUseOLPCorrelators.rank(-1); } diff --git a/MatrixElement/Matchbox/Base/MatchboxHybridAmplitude.h b/MatrixElement/Matchbox/Base/MatchboxHybridAmplitude.h --- a/MatrixElement/Matchbox/Base/MatchboxHybridAmplitude.h +++ b/MatrixElement/Matchbox/Base/MatchboxHybridAmplitude.h @@ -1,637 +1,629 @@ // -*- C++ -*- // // MatchboxHybridAmplitude.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxHybridAmplitude_H #define Herwig_MatchboxHybridAmplitude_H // // This is the declaration of the MatchboxHybridAmplitude class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxHybridAmplitude unifies two amplitude objects to * provide tree and one-loop matrix elements. * * @see \ref MatchboxHybridAmplitudeInterfaces "The interfaces" * defined for MatchboxHybridAmplitude. */ class MatchboxHybridAmplitude: public Herwig::MatchboxAmplitude { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxHybridAmplitude(); - /** - * The destructor. - */ - virtual ~MatchboxHybridAmplitude(); - //@} - public: /** * Return the amplitude object to provide tree-level amplitudes. */ Ptr::tptr treeLevelAmplitude() const { return theTreeLevelAmplitude; } /** * Set the amplitude object to provide tree-level amplitudes. */ void treeLevelAmplitude(Ptr::tptr amp) { theTreeLevelAmplitude = amp; } /** * Return the amplitude object to provide one-loop amplitudes. */ virtual Ptr::tptr oneLoopAmplitude() const { return theOneLoopAmplitude; } /** * Set the amplitude object to provide one-loop amplitudes. */ void oneLoopAmplitude(Ptr::tptr amp) { theOneLoopAmplitude = amp; } /** * Return true, if the two amplitude objects can be used in a * consistent way. */ bool isConsistent() const; public: /** @name Subprocess information */ //@{ /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector& p, Ptr::tptr f, bool virt) const; /** * Return the number of random numbers required to evaluate this * amplitude at a fixed phase space point. */ virtual int nDimAdditional() const { if ( !oneLoopAmplitude() ) return treeLevelAmplitude()->nDimAdditional(); return treeLevelAmplitude()->nDimAdditional() ? treeLevelAmplitude()->nDimAdditional() : oneLoopAmplitude()->nDimAdditional(); } /** * Return a ME instance appropriate for this amplitude and the given * subprocesses */ virtual Ptr::ptr makeME(const PDVector& p) const { return treeLevelAmplitude()->makeME(p); } /** * Set the (tree-level) order in \f$g_S\f$ in which this matrix * element should be evaluated. */ virtual void orderInGs(unsigned int n) { treeLevelAmplitude()->orderInGs(n); if ( oneLoopAmplitude() ) oneLoopAmplitude()->orderInGs(n); } /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return treeLevelAmplitude()->orderInGs(); } /** * Set the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element should be evaluated. */ virtual void orderInGem(unsigned int n) { treeLevelAmplitude()->orderInGem(n); if ( oneLoopAmplitude() ) oneLoopAmplitude()->orderInGem(n); } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return treeLevelAmplitude()->orderInGem(); } /** * Return true, if this amplitude already includes averaging over * incoming parton's quantum numbers. */ virtual bool hasInitialAverage() const { return treeLevelAmplitude()->hasInitialAverage(); } /** * Return true, if this amplitude already includes symmetry factors * for identical outgoing particles. */ virtual bool hasFinalStateSymmetry() const { return treeLevelAmplitude()->hasFinalStateSymmetry(); } /** * Return true, if this amplitude is handled by a BLHA one-loop provider */ virtual bool isOLPTree() const { return false; } /** * Return true, if this amplitude is handled by a BLHA one-loop provider */ virtual bool isOLPLoop() const { if ( !oneLoopAmplitude() ) return false; return oneLoopAmplitude()->isOLPLoop(); } /** * Return true, if colour and spin correlated matrix elements should * be ordered from the OLP */ virtual bool needsOLPCorrelators() const { return theUseOLPCorrelators; } /** * Start the one loop provider, if appropriate. This default * implementation writes an BLHA 2.0 order file and starts the OLP */ virtual bool startOLP(const map,int>& procs) { assert(oneLoopAmplitude()); return oneLoopAmplitude()->startOLP(procs); } /** * Return true, if this amplitude needs to initialize an external * code. */ virtual bool isExternal() const { return treeLevelAmplitude()->isExternal(); } /** * Initialize this amplitude */ virtual bool initializeExternal() { return treeLevelAmplitude()->initializeExternal(); } /** * Return a generic process id for the given process */ virtual int externalId(const cPDVector& proc) { return treeLevelAmplitude()->externalId(proc); } //@} /** @name Colour basis. */ //@{ /** * Return the colour basis. */ virtual Ptr::tptr colourBasis() const { return treeLevelAmplitude()->colourBasis(); } /** * Return true, if the colour basis is capable of assigning colour * flows. */ virtual bool haveColourFlows() const { return treeLevelAmplitude()->haveColourFlows(); } /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const { return treeLevelAmplitude()->colourGeometries(diag); } //@} /** @name Phasespace point, crossing and helicities */ //@{ /** * Set the xcomb object. */ virtual void setXComb(tStdXCombPtr xc) { treeLevelAmplitude()->setXComb(xc); if ( oneLoopAmplitude() ) oneLoopAmplitude()->setXComb(xc); lastMatchboxXComb(xc); } /** * Perform a normal ordering of external legs and fill the * crossing information as. This default implementation sorts * lexicographically in (abs(colour)/spin/abs(charge)), putting pairs * of particles/anti-particles where possible. */ virtual void fillCrossingMap(size_t shift = 0) { treeLevelAmplitude()->fillCrossingMap(shift); } //@} /** @name Tree-level amplitudes */ //@{ /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Return the matrix element squared. */ virtual double me2() const { return treeLevelAmplitude()->me2(); } /** * Return the largeN matrix element squared. */ virtual double largeNME2(Ptr::tptr largeNBasis) const { return treeLevelAmplitude()->largeNME2(largeNBasis); } /** * Return the colour correlated matrix element. */ virtual double colourCorrelatedME2(pair ij) const { return theUseOLPCorrelators ? oneLoopAmplitude()->colourCorrelatedME2(ij) : treeLevelAmplitude()->colourCorrelatedME2(ij); } /** * Return the large-N colour correlated matrix element. */ virtual double largeNColourCorrelatedME2(pair ij, Ptr::tptr largeNBasis) const { return treeLevelAmplitude()->largeNColourCorrelatedME2(ij,largeNBasis); } /** * Return a positive helicity polarization vector for a gluon of * momentum p (with reference vector n) to be used when evaluating * spin correlations. */ virtual LorentzVector plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int id = -1) const { return theUseOLPCorrelators ? oneLoopAmplitude()->plusPolarization(p,n,id) : treeLevelAmplitude()->plusPolarization(p,n,id); } /** * Return the colour and spin correlated matrix element. */ virtual double spinColourCorrelatedME2(pair emitterSpectator, const SpinCorrelationTensor& c) const { return theUseOLPCorrelators ? oneLoopAmplitude()->spinColourCorrelatedME2(emitterSpectator,c) : treeLevelAmplitude()->spinColourCorrelatedME2(emitterSpectator,c); } /** * Return the spin correlated matrix element. */ virtual double spinCorrelatedME2(pair emitterSpectator, const SpinCorrelationTensor& c) const { return theUseOLPCorrelators ? oneLoopAmplitude()->spinCorrelatedME2(emitterSpectator,c) : treeLevelAmplitude()->spinCorrelatedME2(emitterSpectator,c); } /** * Return true, if this amplitude is capable of consistently filling * the rho matrices for the spin correllations */ virtual bool canFillRhoMatrix() const { return treeLevelAmplitude()->canFillRhoMatrix(); } /** * Return the helicity combination of the physical process in the * conventions used by the spin correlation algorithm. */ virtual vector physicalHelicities(const vector& hel) const { return treeLevelAmplitude()->physicalHelicities(hel); } /** * Return true, if tree-level contributions will be evaluated at amplitude level. */ virtual bool treeAmplitudes() const { return treeLevelAmplitude()->treeAmplitudes(); } /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t a, const vector& hel, Complex& largeN) { return treeLevelAmplitude()->evaluate(a,hel,largeN); } //@} /** @name One-loop amplitudes */ //@{ /** * Diasble one-loop functionality if not needed. */ virtual void disableOneLoop() { oneLoopAmplitude(Ptr::ptr()); } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return oneLoopAmplitude(); } /** * Return true, if this amplitude only provides * one-loop (QCD) corrections. */ virtual bool onlyOneLoop() const { return false; } /** * Return true, if one-loop contributions will be evaluated at amplitude level. */ virtual bool oneLoopAmplitudes() const { assert(oneLoopAmplitude()); return oneLoopAmplitude()->oneLoopAmplitudes(); } /** * Return true, if the amplitude is DRbar renormalized, otherwise * MSbar is assumed. */ virtual bool isDRbar() const { assert(oneLoopAmplitude()); return oneLoopAmplitude()->isDRbar(); } /** * Return true, if one loop corrections have been calculated in * dimensional reduction. Otherwise conventional dimensional * regularization is assumed. Note that renormalization is always * assumed to be MSbar. */ virtual bool isDR() const { assert(oneLoopAmplitude()); return oneLoopAmplitude()->isDR(); } /** * Return true, if one loop corrections are given in the conventions * of the integrated dipoles. */ virtual bool isCS() const { assert(oneLoopAmplitude()); return oneLoopAmplitude()->isCS(); } /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { assert(oneLoopAmplitude()); return oneLoopAmplitude()->isBDK(); } /** * Return true, if one loop corrections are given in the conventions * of everything expanded. */ virtual bool isExpanded() const { assert(oneLoopAmplitude()); return oneLoopAmplitude()->isExpanded(); } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { assert(oneLoopAmplitude()); return oneLoopAmplitude()->mu2(); } /** * Adjust the virtual symmetry factor conventions to the tree level * one */ double symmetryRatio() const; /** * Indicate that this amplitude is running alphas by itself. */ virtual bool hasRunningAlphaS() const { return treeLevelAmplitude()->hasRunningAlphaS(); } /** * Indicate that this amplitude is running alphaew by itself. */ virtual bool hasRunningAlphaEW() const { return treeLevelAmplitude()->hasRunningAlphaEW(); } /** * If defined, return the coefficient of the pole in epsilon^2 */ virtual double oneLoopDoublePole() const { assert(oneLoopAmplitude()); return symmetryRatio()*oneLoopAmplitude()->oneLoopDoublePole(); } /** * If defined, return the coefficient of the pole in epsilon */ virtual double oneLoopSinglePole() const { assert(oneLoopAmplitude()); return symmetryRatio()*oneLoopAmplitude()->oneLoopSinglePole(); } /** * Calculate the one-loop amplitudes for the phasespace point * stored in lastXComb, if provided. */ virtual void prepareOneLoopAmplitudes(Ptr::tcptr); /** * Return the one-loop/tree interference. */ virtual double oneLoopInterference() const { assert(oneLoopAmplitude()); return symmetryRatio()*oneLoopAmplitude()->oneLoopInterference(); } /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluateOneLoop(size_t a, const vector& hel) { assert(oneLoopAmplitude()); return oneLoopAmplitude()->evaluateOneLoop(a,hel); } //@} /** @name Caching and helpers to setup amplitude objects. */ //@{ /** * Flush all cashes. */ virtual void flushCaches() { treeLevelAmplitude()->flushCaches(); if ( oneLoopAmplitude() ) oneLoopAmplitude()->flushCaches(); } /** * Clone the dependencies, using a given prefix. */ virtual void cloneDependencies(const std::string& prefix= "" , bool slim=false); //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} 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: /** * The amplitude object to provide tree-level amplitudes. */ Ptr::ptr theTreeLevelAmplitude; /** * The amplitude object to provide one-loop amplitudes. */ Ptr::ptr theOneLoopAmplitude; /** * True, if correlators should be used from the OLP amplitude */ bool theUseOLPCorrelators; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxHybridAmplitude & operator=(const MatchboxHybridAmplitude &) = delete; }; } #endif /* Herwig_MatchboxHybridAmplitude_H */ diff --git a/MatrixElement/Matchbox/Base/MatchboxMEBase.cc b/MatrixElement/Matchbox/Base/MatchboxMEBase.cc --- a/MatrixElement/Matchbox/Base/MatchboxMEBase.cc +++ b/MatrixElement/Matchbox/Base/MatchboxMEBase.cc @@ -1,1680 +1,1678 @@ // -*- C++ -*- // // MatchboxMEBase.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxMEBase class. // #include "MatchboxMEBase.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDF/PDF.h" #include "ThePEG/PDT/PDT.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Handlers/StdXCombGroup.h" #include "ThePEG/EventRecord/SubProcess.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/MatrixElement/Matchbox/Utility/DiagramDrawer.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "Herwig/MatrixElement/Matchbox/Base/MergerBase.h" #include "Herwig/API/RunDirectories.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" #include "Herwig/MatrixElement/HardVertex.h" #include #include using std::ostream_iterator; using namespace Herwig; MatchboxMEBase::MatchboxMEBase() : MEBase(), theOneLoop(false), theOneLoopNoBorn(false), theOneLoopNoLoops(false), theNoCorrelations(false), theHavePDFs(false,false), checkedPDFs(false) {} -MatchboxMEBase::~MatchboxMEBase() {} - Ptr::tptr MatchboxMEBase::factory() const { return MatchboxFactory::currentFactory(); } Ptr::tptr MatchboxMEBase::diagramGenerator() const { return factory()->diagramGenerator(); } Ptr::tptr MatchboxMEBase::processData() const { return factory()->processData(); } unsigned int MatchboxMEBase::getNLight() const { return factory()->nLight(); } vector MatchboxMEBase::getNLightJetVec() const { return factory()->nLightJetVec(); } vector MatchboxMEBase::getNHeavyJetVec() const { return factory()->nHeavyJetVec(); } vector MatchboxMEBase::getNLightProtonVec() const { return factory()->nLightProtonVec(); } double MatchboxMEBase::factorizationScaleFactor() const { return factory()->factorizationScaleFactor(); } double MatchboxMEBase::renormalizationScaleFactor() const { return factory()->renormalizationScaleFactor(); } bool MatchboxMEBase::fixedCouplings() const { return factory()->fixedCouplings(); } bool MatchboxMEBase::fixedQEDCouplings() const { return factory()->fixedQEDCouplings(); } bool MatchboxMEBase::checkPoles() const { return factory()->checkPoles(); } bool MatchboxMEBase::verbose() const { return factory()->verbose(); } bool MatchboxMEBase::initVerbose() const { return factory()->initVerbose(); } void MatchboxMEBase::getDiagrams() const { if ( diagramGenerator() && processData() ) { vector::ptr> diags; vector::ptr>& res = processData()->diagramMap()[subProcess().legs]; if ( res.empty() ) { res = diagramGenerator()->generate(subProcess().legs,orderInAlphaS(),orderInAlphaEW()); } copy(res.begin(),res.end(),back_inserter(diags)); processData()->fillMassGenerators(subProcess().legs); if ( diags.empty() ) return; for (auto const & d : diags ) add(d); return; } throw Exception() << "MatchboxMEBase::getDiagrams() expects a Tree2toNGenerator and ProcessData object.\n" << "Please check your setup." << Exception::runerror; } Selector MatchboxMEBase::diagrams(const DiagramVector & diags) const { if ( phasespace() ) { return phasespace()->selectDiagrams(diags); } throw Exception() << "MatchboxMEBase::diagrams() expects a MatchboxPhasespace object.\n" << "Please check your setup." << Exception::runerror; return Selector(); } Selector MatchboxMEBase::colourGeometries(tcDiagPtr diag) const { if ( matchboxAmplitude() ) { if ( matchboxAmplitude()->haveColourFlows() ) { if ( matchboxAmplitude()->treeAmplitudes() ) matchboxAmplitude()->prepareAmplitudes(this); return matchboxAmplitude()->colourGeometries(diag); } } Ptr::tcptr tdiag = dynamic_ptr_cast::tcptr>(diag); assert(diag && processData()); vector& flows = processData()->colourFlowMap()[tdiag]; if ( flows.empty() ) { list > > > cflows = ColourBasis::colourFlows(tdiag); for ( auto const & fit : cflows) flows.push_back(new ColourLines(ColourBasis::cfstring(fit))); } Selector res; for ( auto const & f : flows ) res.insert(1.0,f); return res; } void MatchboxMEBase::constructVertex(tSubProPtr sub, const ColourLines* cl) { if ( !canFillRhoMatrix() || !factory()->spinCorrelations() ) return; assert(matchboxAmplitude()); assert(matchboxAmplitude()->colourBasis()); // get the colour structure for the selected colour flow size_t cStructure = matchboxAmplitude()->colourBasis()->tensorIdFromFlow(lastXComb().lastDiagram(),cl); // hard process for processing the spin info tPVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); vector out; for ( auto const & p : sub->outgoing() ) { out.push_back(p->data().iSpin()); hard.push_back(p); } // calculate dummy wave functions to fill the spin info static vector dummyPolarizations; static vector dummySpinors; static vector dummyBarSpinors; for ( size_t k = 0; k < hard.size(); ++k ) { if ( hard[k]->data().iSpin() == PDT::Spin1Half ) { if ( hard[k]->id() > 0 && k > 1 ) { SpinorBarWaveFunction(dummyBarSpinors,hard[k], outgoing, true); } else if ( hard[k]->id() < 0 && k > 1 ) { SpinorWaveFunction(dummySpinors,hard[k], outgoing, true); } else if ( hard[k]->id() > 0 && k < 2 ) { SpinorWaveFunction(dummySpinors,hard[k], incoming, false); } else if ( hard[k]->id() < 0 && k < 2 ) { SpinorBarWaveFunction(dummyBarSpinors,hard[k], incoming, false); } } else if ( hard[k]->data().iSpin() == PDT::Spin1 ) { VectorWaveFunction(dummyPolarizations,hard[k], k > 1 ? outgoing : incoming, k > 1 ? true : false, hard[k]->data().hardProcessMass() == ZERO); } else if (hard[k]->data().iSpin() == PDT::Spin0 ) { ScalarWaveFunction(hard[k],k > 1 ? outgoing : incoming, k > 1 ? true : false); } else assert(false); } // fill the production matrix element ProductionMatrixElement pMe(mePartonData()[0]->iSpin(), mePartonData()[1]->iSpin(), out); for ( map,CVector>::const_iterator lamp = lastLargeNAmplitudes().begin(); lamp != lastLargeNAmplitudes().end(); ++lamp ) { vector pMeHelicities = matchboxAmplitude()->physicalHelicities(lamp->first); pMe(pMeHelicities) = lamp->second[cStructure]; } // set the spin information HardVertexPtr hardvertex = new_ptr(HardVertex()); hardvertex->ME(pMe); if ( sub->incoming().first->spinInfo() ) sub->incoming().first->spinInfo()->productionVertex(hardvertex); if ( sub->incoming().second->spinInfo() ) sub->incoming().second->spinInfo()->productionVertex(hardvertex); for ( auto const & p : sub->outgoing() ) if ( p->spinInfo() ) p->spinInfo()->productionVertex(hardvertex); } unsigned int MatchboxMEBase::orderInAlphaS() const { return subProcess().orderInAlphaS; } unsigned int MatchboxMEBase::orderInAlphaEW() const { return subProcess().orderInAlphaEW; } void MatchboxMEBase::setXComb(tStdXCombPtr xc) { MEBase::setXComb(xc); lastMatchboxXComb(xc); if ( phasespace() ) phasespace()->setXComb(xc); if ( scaleChoice() ) scaleChoice()->setXComb(xc); if ( matchboxAmplitude() ) matchboxAmplitude()->setXComb(xc); if (theMerger){ theMerger->setME(this); theMerger->setXComb( xc ); } } double MatchboxMEBase::generateIncomingPartons(const double* r1, const double* r2) { // shamelessly stolen from PartonExtractor.cc Energy2 shmax = lastCuts().sHatMax(); Energy2 shmin = lastCuts().sHatMin(); Energy2 sh = shmin*pow(shmax/shmin, *r1); double ymax = lastCuts().yHatMax(); double ymin = lastCuts().yHatMin(); double km = log(shmax/shmin); ymax = min(ymax, log(lastCuts().x1Max()*sqrt(lastS()/sh))); ymin = max(ymin, -log(lastCuts().x2Max()*sqrt(lastS()/sh))); double y = ymin + (*r2)*(ymax - ymin); double x1 = exp(-0.5*log(lastS()/sh) + y); double x2 = exp(-0.5*log(lastS()/sh) - y); Lorentz5Momentum P1 = lastParticles().first->momentum(); LorentzMomentum p1 = lightCone((P1.rho() + P1.e())*x1, Energy()); p1.rotateY(P1.theta()); p1.rotateZ(P1.phi()); meMomenta()[0] = p1; Lorentz5Momentum P2 = lastParticles().second->momentum(); LorentzMomentum p2 = lightCone((P2.rho() + P2.e())*x2, Energy()); p2.rotateY(P2.theta()); p2.rotateZ(P2.phi()); meMomenta()[1] = p2; lastXCombPtr()->lastX1X2(make_pair(x1,x2)); lastXCombPtr()->lastSHat((meMomenta()[0]+meMomenta()[1]).m2()); return km*(ymax - ymin); } bool MatchboxMEBase::generateKinematics(const double * r) { if ( phasespace() ) { jacobian(phasespace()->generateKinematics(r,meMomenta())); if ( jacobian() == 0.0 ) return false; setScale(); if (theMerger&&!theMerger->generateKinematics(r)){ return false; } logGenerateKinematics(r); assert(lastMatchboxXComb()); if ( nDimAmplitude() > 0 ) { amplitudeRandomNumbers().resize(nDimAmplitude()); copy(r + nDimPhasespace(), r + nDimPhasespace() + nDimAmplitude(), amplitudeRandomNumbers().begin()); } if ( nDimInsertions() > 0 ) { insertionRandomNumbers().resize(nDimInsertions()); copy(r + nDimPhasespace() + nDimAmplitude(), r + nDimPhasespace() + nDimAmplitude() + nDimInsertions(), insertionRandomNumbers().begin()); } return true; } throw Exception() << "MatchboxMEBase::generateKinematics() expects a MatchboxPhasespace object.\n" << "Please check your setup." << Exception::runerror; return false; } int MatchboxMEBase::nDim() const { if ( lastMatchboxXComb() ) return nDimPhasespace() + nDimAmplitude() + nDimInsertions(); int ampAdd = 0; if ( matchboxAmplitude() ) { ampAdd = matchboxAmplitude()->nDimAdditional(); } int insertionAdd = 0; for ( auto const & v : virtuals() ) { insertionAdd = max(insertionAdd,v->nDimAdditional()); } return nDimBorn() + ampAdd + insertionAdd; } int MatchboxMEBase::nDimBorn() const { if ( lastMatchboxXComb() ) return nDimPhasespace(); if ( phasespace() ) return phasespace()->nDim(diagrams().front()->partons()); throw Exception() << "MatchboxMEBase::nDim() expects a MatchboxPhasespace object.\n" << "Please check your setup." << Exception::runerror; return 0; } void MatchboxMEBase::setScale(Energy2 ren, Energy2 fac) const { if ( haveX1X2() ) { lastXCombPtr()->lastSHat((meMomenta()[0]+meMomenta()[1]).m2()); } Energy2 fcscale = (fac == ZERO) ? factorizationScale() : fac; Energy2 fscale = fcscale*sqr(factorizationScaleFactor()); Energy2 rscale = (ren == ZERO ? renormalizationScale() : ren)*sqr(renormalizationScaleFactor()); Energy2 ewrscale = renormalizationScaleQED(); lastXCombPtr()->lastScale(fscale); lastXCombPtr()->lastCentralScale(fcscale); lastXCombPtr()->lastShowerScale(showerScale()); lastMatchboxXComb()->lastRenormalizationScale(rscale); if ( !fixedCouplings() ) { if ( rscale > lastCuts().scaleMin() ) lastXCombPtr()->lastAlphaS(SM().alphaS(rscale)); else lastXCombPtr()->lastAlphaS(SM().alphaS(lastCuts().scaleMin())); } else { lastXCombPtr()->lastAlphaS(SM().alphaS()); } if ( !fixedQEDCouplings() ) { lastXCombPtr()->lastAlphaEM(SM().alphaEMME(ewrscale)); } else { lastXCombPtr()->lastAlphaEM(SM().alphaEMMZ()); } logSetScale(); } Energy2 MatchboxMEBase::factorizationScale() const { if ( scaleChoice() ) { return scaleChoice()->factorizationScale(); } throw Exception() << "MatchboxMEBase::factorizationScale() expects a MatchboxScaleChoice object.\n" << "Please check your setup." << Exception::runerror; return ZERO; } Energy2 MatchboxMEBase::renormalizationScale() const { if ( scaleChoice() ) { return scaleChoice()->renormalizationScale(); } throw Exception() << "MatchboxMEBase::renormalizationScale() expects a MatchboxScaleChoice object.\n" << "Please check your setup." << Exception::runerror; return ZERO; } Energy2 MatchboxMEBase::renormalizationScaleQED() const { if ( scaleChoice() ) { return scaleChoice()->renormalizationScaleQED(); } return renormalizationScale(); } Energy2 MatchboxMEBase::showerScale() const { if ( scaleChoice() ) { return scaleChoice()->showerScale(); } throw Exception() << "MatchboxMEBase::showerScale() expects a MatchboxScaleChoice object.\n" << "Please check your setup." << Exception::runerror; return ZERO; } void MatchboxMEBase::setVetoScales(tSubProPtr) const {} bool MatchboxMEBase::havePDFWeight1() const { if ( checkedPDFs ) return theHavePDFs.first; theHavePDFs.first = factory()->isIncoming(mePartonData()[0]) && lastXCombPtr()->partonBins().first->pdf(); theHavePDFs.second = factory()->isIncoming(mePartonData()[1]) && lastXCombPtr()->partonBins().second->pdf(); checkedPDFs = true; return theHavePDFs.first; } bool MatchboxMEBase::havePDFWeight2() const { if ( checkedPDFs ) return theHavePDFs.second; theHavePDFs.first = factory()->isIncoming(mePartonData()[0]) && lastXCombPtr()->partonBins().first->pdf(); theHavePDFs.second = factory()->isIncoming(mePartonData()[1]) && lastXCombPtr()->partonBins().second->pdf(); checkedPDFs = true; return theHavePDFs.second; } void MatchboxMEBase::getPDFWeight(Energy2 factorizationScale) const { if ( !havePDFWeight1() && !havePDFWeight2() ) { lastMEPDFWeight(1.0); logPDFWeight(); return; } double w = 1.; if ( havePDFWeight1() ) w *= pdf1(factorizationScale); if ( havePDFWeight2() ) w *= pdf2(factorizationScale); lastMEPDFWeight(w); logPDFWeight(); } double MatchboxMEBase::pdf1(Energy2 fscale, double xEx, double xFactor) const { assert(lastXCombPtr()->partonBins().first->pdf()); if ( xEx < 1. && lastX1()*xFactor >= xEx ) { return ( ( 1. - lastX1()*xFactor ) / ( 1. - xEx ) ) * lastXCombPtr()->partonBins().first->pdf()->xfx(lastParticles().first->dataPtr(), lastPartons().first->dataPtr(), fscale == ZERO ? lastScale() : fscale, xEx)/xEx; } return lastXCombPtr()->partonBins().first->pdf()->xfx(lastParticles().first->dataPtr(), lastPartons().first->dataPtr(), fscale == ZERO ? lastScale() : fscale, lastX1()*xFactor)/lastX1()/xFactor; } double MatchboxMEBase::pdf2(Energy2 fscale, double xEx, double xFactor) const { assert(lastXCombPtr()->partonBins().second->pdf()); if ( xEx < 1. && lastX2()*xFactor >= xEx ) { return ( ( 1. - lastX2()*xFactor ) / ( 1. - xEx ) ) * lastXCombPtr()->partonBins().second->pdf()->xfx(lastParticles().second->dataPtr(), lastPartons().second->dataPtr(), fscale == ZERO ? lastScale() : fscale, xEx)/xEx; } return lastXCombPtr()->partonBins().second->pdf()->xfx(lastParticles().second->dataPtr(), lastPartons().second->dataPtr(), fscale == ZERO ? lastScale() : fscale, lastX2()*xFactor)/lastX2()/xFactor; } double MatchboxMEBase::me2() const { if ( matchboxAmplitude() ) { if ( matchboxAmplitude()->treeAmplitudes() ) matchboxAmplitude()->prepareAmplitudes(this); double res = matchboxAmplitude()->me2()* me2Norm(); return res; } throw Exception() << "MatchboxMEBase::me2() expects a MatchboxAmplitude object.\n" << "Please check your setup." << Exception::runerror; return 0.; } double MatchboxMEBase::largeNME2(Ptr::tptr largeNBasis) const { if ( matchboxAmplitude() ) { if ( matchboxAmplitude()->treeAmplitudes() ) { largeNBasis->prepare(mePartonData(),false); matchboxAmplitude()->prepareAmplitudes(this); } double res = matchboxAmplitude()->largeNME2(largeNBasis)* me2Norm(); return res; } throw Exception() << "MatchboxMEBase::largeNME2() expects a MatchboxAmplitude object.\n" << "Please check your setup." << Exception::runerror; return 0.; } double MatchboxMEBase::finalStateSymmetry() const { if ( symmetryFactor() > 0.0 ) return symmetryFactor(); double sFactor = 1.; map counts; cPDVector checkData; copy(mePartonData().begin()+2,mePartonData().end(),back_inserter(checkData)); cPDVector::iterator p = checkData.begin(); while ( !checkData.empty() ) { if ( counts.find((**p).id()) != counts.end() ) { counts[(**p).id()] += 1; } else { counts[(**p).id()] = 1; } checkData.erase(p); p = checkData.begin(); continue; } for ( auto const & c : counts) { if ( c.second == 1 ) continue; if ( c.second == 2 ) sFactor /= 2.; else if ( c.second == 3 ) sFactor /= 6.; else if ( c.second == 4 ) sFactor /= 24.; } symmetryFactor(sFactor); return symmetryFactor(); } double MatchboxMEBase::me2Norm(unsigned int addAlphaS) const { double fac = 1.; if ( !hasInitialAverage() ) { for ( size_t k = 0; k < 2; ++k ) { // Spin 0 does not involve any additional factors if ( mePartonData()[k]->iSpin() == PDT::Spin1Half ) fac *= 1./2.; else if ( mePartonData()[k]->iSpin() == PDT::Spin1 && mePartonData()[k]->hardProcessMass() == ZERO ) fac *= 1./2.; else if ( mePartonData()[k]->iSpin() == PDT::Spin1 && mePartonData()[k]->hardProcessMass() > ZERO ) fac *= 1./3.; else if ( mePartonData()[k]->iSpin() == PDT::Spin3Half ) fac *= 1./4.; else if ( mePartonData()[k]->iSpin() == PDT::Spin2 && mePartonData()[k]->hardProcessMass() == ZERO ) fac *= 1./2.; else if ( mePartonData()[k]->iSpin() == PDT::Spin2 && mePartonData()[k]->hardProcessMass() > ZERO ) fac *= 1./5.; } } double couplings = 1.0; if ( (orderInAlphaS() > 0 || addAlphaS != 0) && !hasRunningAlphaS() ) { fac *= pow(lastAlphaS()/SM().alphaS(),double(orderInAlphaS()+addAlphaS)); couplings *= pow(lastAlphaS(),double(orderInAlphaS()+addAlphaS)); } if ( orderInAlphaEW() > 0 && !hasRunningAlphaEW() ) { fac *= pow(lastAlphaEM()/SM().alphaEMMZ(),double(orderInAlphaEW())); couplings *= pow(lastAlphaEM(),double(orderInAlphaEW())); } lastMECouplings(couplings); if ( !hasInitialAverage() ) { if ( mePartonData()[0]->iColour() == PDT::Colour3 || mePartonData()[0]->iColour() == PDT::Colour3bar ) fac /= SM().Nc(); else if ( mePartonData()[0]->iColour() == PDT::Colour8 ) fac /= (SM().Nc()*SM().Nc()-1.); if ( mePartonData()[1]->iColour() == PDT::Colour3 || mePartonData()[1]->iColour() == PDT::Colour3bar ) fac /= SM().Nc(); else if ( mePartonData()[1]->iColour() == PDT::Colour8 ) fac /= (SM().Nc()*SM().Nc()-1.); } return !hasFinalStateSymmetry() ? finalStateSymmetry()*fac : fac; } CrossSection MatchboxMEBase::prefactor()const{ return (sqr(hbarc)/(2.*lastSHat())) *jacobian()* lastMEPDFWeight(); } CrossSection MatchboxMEBase::dSigHatDRB() const { getPDFWeight(); lastME2(me2()); return oneLoopNoBorn()?ZERO:prefactor() * lastME2(); } CrossSection MatchboxMEBase::dSigHatDRV() const { getPDFWeight(); lastME2(me2()); return ( oneLoop() && !oneLoopNoLoops() )?(prefactor() * oneLoopInterference()):ZERO; } CrossSection MatchboxMEBase::dSigHatDRI() const { getPDFWeight(); lastME2(me2()); CrossSection res=ZERO; if (oneLoop() &&!onlyOneLoop()) { for ( auto const & v : virtuals()) { v->setXComb(lastXCombPtr()); res += v->dSigHatDR(); } if ( checkPoles() && oneLoop() ) logPoles(); } return res; } CrossSection MatchboxMEBase::dSigHatDRAlphaDiff(double alpha) const { getPDFWeight(); lastME2(me2()); CrossSection res=ZERO; for ( auto const & v: virtuals() ) { v->setXComb(lastXCombPtr()); res+=v->dSigHatDRAlphaDiff( alpha); } return res; } CrossSection MatchboxMEBase::dSigHatDR() const { getPDFWeight(); if (theMerger){ lastMECrossSection(theMerger->MergingDSigDR()); return lastMECrossSection(); } else if (lastXCombPtr()->willPassCuts() ) { lastME2(me2()); CrossSection _dSigHatDRB, _dSigHatDRV, _dSigHatDRI, res = ZERO; // ----- dSigHatDRB ----- _dSigHatDRB = oneLoopNoBorn()?ZERO:prefactor() * lastME2(); // ----- dSigHatDRV ----- _dSigHatDRV = ( oneLoop() && !oneLoopNoLoops() )?(prefactor() * oneLoopInterference()):ZERO; // ----- dSigHatDRI ----- if (oneLoop() &&!onlyOneLoop()) { for ( auto const & v : virtuals()) { v->setXComb(lastXCombPtr()); res += v->dSigHatDR(); } if ( checkPoles() && oneLoop() ) logPoles(); } _dSigHatDRI = res; // ----- finalizing ----- lastMECrossSection(_dSigHatDRB + _dSigHatDRV + _dSigHatDRI); return lastMECrossSection(); } else { lastME2(ZERO); lastMECrossSection(ZERO); return lastMECrossSection(); } } double MatchboxMEBase::oneLoopInterference() const { if ( matchboxAmplitude() ) { if ( matchboxAmplitude()->oneLoopAmplitudes() ) matchboxAmplitude()->prepareOneLoopAmplitudes(this); double res = matchboxAmplitude()->oneLoopInterference()* me2Norm(1); return res; } throw Exception() << "MatchboxMEBase::oneLoopInterference() expects a MatchboxAmplitude object.\n" << "Please check your setup." << Exception::runerror; return 0.; } MatchboxMEBase::AccuracyHistogram::AccuracyHistogram(double low, double up, unsigned int nbins) : lower(low), upper(up), sameSign(0), oppositeSign(0), nans(0), overflow(0), underflow(0) { double step = (up-low)/nbins; for ( unsigned int k = 1; k <= nbins; ++k ) bins[lower + k*step] = 0.0; } void MatchboxMEBase::AccuracyHistogram::book(double a, double b) { if ( ! (isfinite(a) && isfinite(b)) ) { ++nans; return; } if ( a*b >= 0. ) ++sameSign; if ( a*b < 0. ) ++oppositeSign; double r = 1.; if ( abs(a) != 0.0 ) r = abs(1.-abs(b/a)); else if ( abs(b) != 0.0 ) r = abs(b); if ( log10(r) < lower || r == 0.0 ) { ++underflow; return; } if ( log10(r) > upper ) { ++overflow; return; } map::iterator bin = bins.upper_bound(log10(r)); if ( bin == bins.end() ) return; bin->second += 1.; } void MatchboxMEBase::AccuracyHistogram::dump(const std::string& folder, const std::string& prefix, const cPDVector& proc) const { ostringstream fname(""); for ( cPDVector::const_iterator p = proc.begin(); p != proc.end(); ++p ) fname << (**p).PDGName(); ofstream out((folder+"/"+prefix+fname.str()+".dat").c_str()); out << "# same sign : " << sameSign << " opposite sign : " << oppositeSign << " nans : " << nans << " overflow : " << overflow << " underflow : " << underflow << "\n"; for ( map::const_iterator b = bins.begin(); b != bins.end(); ++b ) { map::const_iterator bp = b; --bp; if ( b->second != 0. ) { if ( b != bins.begin() ) out << bp->first; else out << lower; out << " " << b->first << " " << b->second << "\n" << flush; } } ofstream gpout((folder+"/"+prefix+fname.str()+".gp").c_str()); gpout << "set terminal png\n" << "set xlabel 'accuracy of pole cancellation [decimal places]'\n" << "set ylabel 'counts\n" << "set xrange [-20:0]\n" << "set output '" << prefix << fname.str() << ".png'\n" << "plot '" << prefix << fname.str() << ".dat' using (0.5*($1+$2)):3 with linespoints pt 7 ps 1 not"; } void MatchboxMEBase::AccuracyHistogram::persistentOutput(PersistentOStream& os) const { os << lower << upper << bins << sameSign << oppositeSign << nans << overflow << underflow; } void MatchboxMEBase::AccuracyHistogram::persistentInput(PersistentIStream& is) { is >> lower >> upper >> bins >> sameSign >> oppositeSign >> nans >> overflow >> underflow; } void MatchboxMEBase::logPoles() const { double res2me = oneLoopDoublePole(); double res1me = oneLoopSinglePole(); double res2i = 0.; double res1i = 0.; for ( auto const & v : virtuals()) { res2i += v->oneLoopDoublePole(); res1i += v->oneLoopSinglePole(); } if (res2me != 0.0 || res2i != 0.0) epsilonSquarePoleHistograms[mePartonData()].book(res2me,res2i); if (res1me != 0.0 || res1i != 0.0) epsilonPoleHistograms[mePartonData()].book(res1me,res1i); } bool MatchboxMEBase::haveOneLoop() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->haveOneLoop(); return false; } bool MatchboxMEBase::onlyOneLoop() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->onlyOneLoop(); return false; } bool MatchboxMEBase::isDRbar() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->isDRbar(); return false; } bool MatchboxMEBase::isDR() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->isDR(); return false; } bool MatchboxMEBase::isCS() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->isCS(); return false; } bool MatchboxMEBase::isBDK() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->isBDK(); return false; } bool MatchboxMEBase::isExpanded() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->isExpanded(); return false; } Energy2 MatchboxMEBase::mu2() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->mu2(); return 0*GeV2; } double MatchboxMEBase::oneLoopDoublePole() const { if ( matchboxAmplitude() ) { return matchboxAmplitude()->oneLoopDoublePole()* me2Norm(1); } return 0.; } double MatchboxMEBase::oneLoopSinglePole() const { if ( matchboxAmplitude() ) { return matchboxAmplitude()->oneLoopSinglePole()* me2Norm(1); } return 0.; } vector MatchboxMEBase::getDipoles(const vector& dipoles, const vector & borns,bool slim) const { vector res; // keep track of the dipoles we already did set up set,int>,pair::tptr,Ptr::tptr> > > done; cPDVector rep = diagrams().front()->partons(); int nreal = rep.size(); // now loop over configs for ( int emitter = 0; emitter < nreal; ++emitter ) { list matchDipoles; for ( auto const & d : dipoles ) { if ( ! d->canHandleEmitter(rep,emitter) ) continue; matchDipoles.push_back(d); } if ( matchDipoles.empty() ) continue; for ( int emission = 2; emission < nreal; ++emission ) { if ( emission == emitter ) continue; list matchDipoles2; for ( auto const & d : matchDipoles ) { if ( !d->canHandleSplitting(rep,emitter,emission) ) continue; matchDipoles2.push_back(d); } if ( matchDipoles2.empty() ) continue; map::ptr,SubtractionDipole::MergeInfo> mergeInfo; for ( auto const & d : diagrams() ) { Ptr::ptr check = new_ptr(Tree2toNDiagram(*dynamic_ptr_cast::ptr>(d))); map theMergeLegs; for ( unsigned int i = 0; i < check->external().size(); ++i ) theMergeLegs[i] = -1; int theEmitter = check->mergeEmission(emitter,emission,theMergeLegs); // no underlying Born if ( theEmitter == -1 ) continue; SubtractionDipole::MergeInfo info; info.diagram = check; info.emitter = theEmitter; info.mergeLegs = theMergeLegs; mergeInfo[d] = info; } if ( mergeInfo.empty() ) continue; for ( int spectator = 0; spectator < nreal; ++spectator ) { if ( spectator == emitter || spectator == emission ) continue; list matchDipoles3; for ( auto const & d : matchDipoles2 ) { if ( ! d->canHandleSpectator(rep,spectator) ) continue; matchDipoles3.push_back(d); } if ( matchDipoles3.empty() ) continue; if ( noDipole(emitter,emission,spectator) ) continue; for ( auto const & d : matchDipoles3 ) { if ( !d->canHandle(rep,emitter,emission,spectator) ) continue; for ( auto const & b : borns ) { if ( b->onlyOneLoop() ) continue; if ( done.find(make_pair(make_pair(make_pair(emitter,emission),spectator),make_pair(b,d))) != done.end() ) continue; // now get to work d->clearBookkeeping(); d->realEmitter(emitter); d->realEmission(emission); d->realSpectator(spectator); d->realEmissionME(const_cast(this)); d->underlyingBornME(b); d->setupBookkeeping(mergeInfo,slim); if ( ! d->empty() ) { res.push_back( d->cloneMe() ); Ptr::tptr nDipole = res.back(); done.insert(make_pair(make_pair(make_pair(emitter,emission),spectator),make_pair(b,d))); if ( nDipole->isSymmetric() ) done.insert(make_pair(make_pair(make_pair(emission,emitter),spectator),make_pair(b,d))); ostringstream dname; if ( theMerger) { dname << fullName(); if (theOneLoopNoBorn) dname << ".virtual" << "." ; dname << b->name() << "." << d->name() << ".[(" << emitter << "," << emission << ")," << spectator << "]"; } else { dname << fullName() << "." << b->name() << "." << d->name() << ".[(" << emitter << "," << emission << ")," << spectator << "]"; } if ( ! (generator()->preinitRegister(nDipole,dname.str()) ) ) throw Exception() << "MatchboxMEBase::getDipoles(): Dipole " << dname.str() << " already existing." << Exception::runerror; if ( !factory()->reweighters().empty() ) { for ( auto const & rw : factory()->reweighters()) nDipole->addReweighter(rw); } if ( !factory()->preweighters().empty() ) { for ( auto const & rw : factory()->preweighters() ) nDipole->addPreweighter(rw); } nDipole->cloneDependencies(dname.str(),slim); } } } } } } vector::tptr> partners; copy(res.begin(),res.end(),back_inserter(partners)); for ( auto const & d : res ) d->partnerDipoles(partners); return res; } double MatchboxMEBase::colourCorrelatedME2(pair ij) const { if ( matchboxAmplitude() ) { if ( matchboxAmplitude()->treeAmplitudes() ) matchboxAmplitude()->prepareAmplitudes(this); double res = matchboxAmplitude()->colourCorrelatedME2(ij)* me2Norm(); return res; } throw Exception() << "MatchboxMEBase::colourCorrelatedME2() expects a MatchboxAmplitude object.\n" << "Please check your setup." << Exception::runerror; return 0.; } double MatchboxMEBase::largeNColourCorrelatedME2(pair ij, Ptr::tptr largeNBasis) const { if ( matchboxAmplitude() ) { if ( matchboxAmplitude()->treeAmplitudes() ) { largeNBasis->prepare(mePartonData(),false); matchboxAmplitude()->prepareAmplitudes(this); } double res = matchboxAmplitude()->largeNColourCorrelatedME2(ij,largeNBasis)* me2Norm(); return res; } throw Exception() << "MatchboxMEBase::largeNColourCorrelatedME2() expects a MatchboxAmplitude object.\n" << "Please check your setup." << Exception::runerror; return 0.; } double MatchboxMEBase::spinColourCorrelatedME2(pair ij, const SpinCorrelationTensor& c) const { if ( matchboxAmplitude() ) { if ( matchboxAmplitude()->treeAmplitudes() ) matchboxAmplitude()->prepareAmplitudes(this); double res = matchboxAmplitude()->spinColourCorrelatedME2(ij,c)* me2Norm(); return res; } throw Exception() << "MatchboxMEBase::spinColourCorrelatedME2() expects a MatchboxAmplitude object.\n" << "Please check your setup." << Exception::runerror; return 0.; } double MatchboxMEBase::spinCorrelatedME2(pair ij, const SpinCorrelationTensor& c) const { if ( matchboxAmplitude() ) { if ( matchboxAmplitude()->treeAmplitudes() ) matchboxAmplitude()->prepareAmplitudes(this); double res = matchboxAmplitude()->spinCorrelatedME2(ij,c)* me2Norm(); return res; } throw Exception() << "MatchboxMEBase::spinCorrelatedME2() expects a MatchboxAmplitude object.\n" << "Please check your setup." << Exception::runerror; return 0.; } void MatchboxMEBase::flushCaches() { if ( theMerger )theMerger->flushCaches(); MEBase::flushCaches(); if ( matchboxAmplitude() ) matchboxAmplitude()->flushCaches(); for ( auto const & r : reweights() ) r->flushCaches(); for ( auto const & v : virtuals()) v->flushCaches(); } void MatchboxMEBase::setKinematics() { MEBase::setKinematics(); if ( theMerger ) theMerger->setKinematics(); } void MatchboxMEBase::clearKinematics() { MEBase::clearKinematics(); if ( theMerger ) theMerger->clearKinematics(); } const MergerBasePtr MatchboxMEBase::merger() const { return theMerger; } MergerBasePtr MatchboxMEBase::merger() { return theMerger; } void MatchboxMEBase::merger(MergerBasePtr v) { theMerger = v; } void MatchboxMEBase::print(ostream& os) const { os << "--- MatchboxMEBase setup -------------------------------------------------------\n"; os << " '" << name() << "' for subprocess:\n"; os << " "; for ( PDVector::const_iterator pp = subProcess().legs.begin(); pp != subProcess().legs.end(); ++pp ) { os << (**pp).PDGName() << " "; if ( pp == subProcess().legs.begin() + 1 ) os << "-> "; } os << "\n"; os << " including " << (oneLoop() ? "" : "no ") << "virtual corrections"; if ( oneLoopNoBorn() ) os << " without Born contributions"; if ( oneLoopNoLoops() ) os << " without loop contributions"; os << "\n"; if ( oneLoop() && !onlyOneLoop() ) { os << " using insertion operators\n"; for ( vector::ptr>::const_iterator v = virtuals().begin(); v != virtuals().end(); ++v ) { os << " '" << (**v).name() << "' with " << ((**v).isDR() ? "" : "C") << "DR/"; if ( (**v).isCS() ) os << "CS"; if ( (**v).isBDK() ) os << "BDK"; if ( (**v).isExpanded() ) os << "expanded"; os << " conventions\n"; } } os << "--------------------------------------------------------------------------------\n"; os << flush; } void MatchboxMEBase::printLastEvent(ostream& os) const { os << "--- MatchboxMEBase last event information --------------------------------------\n"; os << " for matrix element '" << name() << "'\n"; os << " process considered:\n "; int in = 0; for ( cPDVector::const_iterator p = mePartonData().begin(); p != mePartonData().end(); ++p ) { os << (**p).PDGName() << " "; if ( ++in == 2 ) os << " -> "; } os << " kinematic environment as set by the XComb " << lastXCombPtr() << ":\n" << " sqrt(shat)/GeV = " << sqrt(lastSHat()/GeV2) << " x1 = " << lastX1() << " x2 = " << lastX2() << " alphaS = " << lastAlphaS() << "\n"; os << " momenta/GeV generated from random numbers\n "; copy(lastXComb().lastRandomNumbers().begin(), lastXComb().lastRandomNumbers().end(),ostream_iterator(os," ")); os << ":\n "; for ( vector::const_iterator p = meMomenta().begin(); p != meMomenta().end(); ++p ) { os << (*p/GeV) << "\n "; } os << "last cross section/nb calculated was:\n " << (lastMECrossSection()/nanobarn) << " (pdf weight " << lastMEPDFWeight() << ")\n"; os << "--------------------------------------------------------------------------------\n"; os << flush; } void MatchboxMEBase::logGenerateKinematics(const double * r) const { if ( !verbose() ) return; generator()->log() << "'" << name() << "' generated kinematics\nfrom " << nDim() << " random numbers:\n"; copy(r,r+nDim(),ostream_iterator(generator()->log()," ")); generator()->log() << "\n"; generator()->log() << "storing phase space information in XComb " << lastXCombPtr() << "\n"; generator()->log() << "generated phase space point (in GeV):\n"; vector::const_iterator pit = meMomenta().begin(); cPDVector::const_iterator dit = mePartonData().begin(); for ( ; pit != meMomenta().end() ; ++pit, ++dit ) generator()->log() << (**dit).PDGName() << " : " << (*pit/GeV) << "\n"; generator()->log() << "with x1 = " << lastX1() << " x2 = " << lastX2() << "\n" << "and Jacobian = " << jacobian() << " sHat/GeV2 = " << (lastSHat()/GeV2) << "\n" << flush; } void MatchboxMEBase::logSetScale() const { if ( !verbose() ) return; generator()->log() << "'" << name() << "' set scales using XComb " << lastXCombPtr() << ":\n" << "scale/GeV2 = " << (scale()/GeV2) << " xi_R = " << renormalizationScaleFactor() << " xi_F = " << factorizationScaleFactor() << "\n" << "alpha_s = " << lastAlphaS() << "\n" << flush; } void MatchboxMEBase::logPDFWeight() const { if ( !verbose() ) return; generator()->log() << "'" << name() << "' calculated pdf weight = " << lastMEPDFWeight() << " from XComb " << lastXCombPtr() << "\n" << "x1 = " << lastX1() << " (" << (mePartonData()[0]->coloured() ? "" : "not ") << "used) " << "x2 = " << lastX2() << " (" << (mePartonData()[1]->coloured() ? "" : "not ") << "used)\n" << flush; } void MatchboxMEBase::logME2() const { if ( !verbose() ) return; generator()->log() << "'" << name() << "' evaluated me2 using XComb " << lastXCombPtr() << "\n" << "and phase space point (in GeV):\n"; vector::const_iterator pit = meMomenta().begin(); cPDVector::const_iterator dit = mePartonData().begin(); for ( ; pit != meMomenta().end() ; ++pit, ++dit ) generator()->log() << (**dit).PDGName() << " : " << (*pit/GeV) << "\n"; generator()->log() << "with x1 = " << lastX1() << " x2 = " << lastX2() << "\n" << "sHat/GeV2 = " << (lastSHat()/GeV2) << "\n" << flush; } void MatchboxMEBase::logDSigHatDR() const { if ( !verbose() ) return; generator()->log() << "'" << name() << "' evaluated cross section using XComb " << lastXCombPtr() << "\n" << "Jacobian = " << jacobian() << " sHat/GeV2 = " << (lastSHat()/GeV2) << " dsig/nb = " << (lastMECrossSection()/nanobarn) << "\n" << flush; } void MatchboxMEBase::cloneDependencies(const std::string& prefix,bool slim) { if ( phasespace() && !slim ) { Ptr::ptr myPhasespace = phasespace()->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << myPhasespace->name(); if ( ! (generator()->preinitRegister(myPhasespace,pname.str()) ) ) throw Exception() << "MatchboxMEBase::cloneDependencies(): Phasespace generator " << pname.str() << " already existing." << Exception::runerror; myPhasespace->cloneDependencies(pname.str()); phasespace(myPhasespace); } theAmplitude = dynamic_ptr_cast::ptr>(amplitude()); if ( matchboxAmplitude() ) { Ptr::ptr myAmplitude = matchboxAmplitude()->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << myAmplitude->name(); if ( ! (generator()->preinitRegister(myAmplitude,pname.str()) ) ){ throw Exception() << "MatchboxMEBase::cloneDependencies(): Amplitude " << pname.str() << " already existing." << Exception::runerror; } myAmplitude->cloneDependencies(pname.str(),slim); matchboxAmplitude(myAmplitude); amplitude(myAmplitude); matchboxAmplitude()->orderInGs(orderInAlphaS()); matchboxAmplitude()->orderInGem(orderInAlphaEW()); } if ( scaleChoice() &&!slim ) { Ptr::ptr myScaleChoice = scaleChoice()->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << myScaleChoice->name(); if ( ! (generator()->preinitRegister(myScaleChoice,pname.str()) ) ) throw Exception() << "MatchboxMEBase::cloneDependencies(): Scale choice " << pname.str() << " already existing." << Exception::runerror; scaleChoice(myScaleChoice); } for ( auto & rw : theReweights ) { Ptr::ptr myReweight = rw->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << rw->name(); if ( ! (generator()->preinitRegister(myReweight,pname.str()) ) ) throw Exception() << "MatchboxMEBase::cloneDependencies(): Reweight " << pname.str() << " already existing." << Exception::runerror; myReweight->cloneDependencies(pname.str()); rw = myReweight; } for ( auto & v : virtuals()) { Ptr::ptr myIOP = v->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << v->name(); if ( ! (generator()->preinitRegister(myIOP,pname.str()) ) ) throw Exception() << "MatchboxMEBase::cloneDependencies(): Insertion operator " << pname.str() << " already existing." << Exception::runerror; v = myIOP; } } void MatchboxMEBase::prepareXComb(MatchboxXCombData& xc) const { // fixme We need to pass on the partons from the xcmob here, not // assuming one subprocess per matrix element if ( phasespace() ) xc.nDimPhasespace(phasespace()->nDim(diagrams().front()->partons())); if ( matchboxAmplitude() ) { xc.nDimAmplitude(matchboxAmplitude()->nDimAdditional()); if ( matchboxAmplitude()->colourBasis() ) { size_t cdim = matchboxAmplitude()->colourBasis()->prepare(diagrams(),noCorrelations()); xc.colourBasisDim(cdim); } if ( matchboxAmplitude()->isExternal() ) { xc.externalId(matchboxAmplitude()->externalId(diagrams().front()->partons())); } } int insertionAdd = 0; for ( auto const & v : virtuals() ) insertionAdd = max(insertionAdd,v->nDimAdditional()); xc.nDimInsertions(insertionAdd); xc.nLight(getNLight()); if(xc.nLightJetVec().empty()) for (auto const & id : getNLightJetVec()) xc.nLightJetVec( id ); if(xc.nHeavyJetVec().empty()) for (auto const & id :getNHeavyJetVec()) xc.nHeavyJetVec(id); if(xc.nLightProtonVec().empty()) for (auto const & id : getNLightProtonVec()) xc.nLightProtonVec(id); xc.olpId(olpProcess()); if ( initVerbose() ) { ostringstream fname_strm; // only allow alphanumeric, / and _ in filename for (const char c : name()) { switch (c) { case '+' : fname_strm << "+"; break; case '-' : fname_strm << "-"; break; case '~' : fname_strm << "_tilde"; break; case ']' : break; case ',' : fname_strm << "__"; break; default : fname_strm << (isalnum(c) ? c : '_'); break; } } fname_strm << ".diagrams"; const string fname = fname_strm.str(); ifstream test(fname.c_str()); if ( !test ) { test.close(); ofstream out(fname.c_str()); for ( vector::ptr>::const_iterator d = diagrams().begin(); d != diagrams().end(); ++d ) { DiagramDrawer::drawDiag(out,dynamic_cast(**d)); out << "\n"; } } } } StdXCombPtr MatchboxMEBase::makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec&, tStdXCombPtr newHead, tMEPtr newME) { if ( !newME ) newME = this; Ptr::ptr xc = new_ptr(MatchboxXComb(newMaxEnergy, inc, newEventHandler, newSubProcessHandler, newExtractor, newCKKW, newPartonBins, newCuts, newME, newDiagrams, mir, newHead)); prepareXComb(*xc); return xc; } StdXCombPtr MatchboxMEBase::makeXComb(tStdXCombPtr newHead, const PBPair & newPartonBins, const DiagramVector & newDiagrams, tMEPtr newME) { if ( !newME ) newME = this; Ptr::ptr xc = new_ptr(MatchboxXComb(newHead, newPartonBins, newME, newDiagrams)); prepareXComb(*xc); return xc; } void MatchboxMEBase::persistentOutput(PersistentOStream & os) const { os << theLastXComb << thePhasespace << theAmplitude << theScaleChoice << theVirtuals << theReweights << theSubprocess << theOneLoop << theOneLoopNoBorn << theOneLoopNoLoops << epsilonSquarePoleHistograms << epsilonPoleHistograms << theMerger << theOLPProcess << theNoCorrelations << theHavePDFs << checkedPDFs; } void MatchboxMEBase::persistentInput(PersistentIStream & is, int) { is >> theLastXComb >> thePhasespace >> theAmplitude >> theScaleChoice >> theVirtuals >> theReweights >> theSubprocess >> theOneLoop >> theOneLoopNoBorn >> theOneLoopNoLoops >> epsilonSquarePoleHistograms >> epsilonPoleHistograms >> theMerger >> theOLPProcess >> theNoCorrelations >> theHavePDFs >> checkedPDFs; lastMatchboxXComb(theLastXComb); } void MatchboxMEBase::Init() { static ClassDocumentation documentation ("MatchboxMEBase is the base class for matrix elements " "in the context of the matchbox NLO interface."); } IBPtr MatchboxMEBase::clone() const { return new_ptr(*this); } IBPtr MatchboxMEBase::fullclone() const { return new_ptr(*this); } void MatchboxMEBase::doinit() { MEBase::doinit(); if ( !theAmplitude ) theAmplitude = dynamic_ptr_cast::ptr>(amplitude()); if ( matchboxAmplitude() ) matchboxAmplitude()->init(); if ( phasespace() ) { phasespace()->init(); matchboxAmplitude()->checkReshuffling(phasespace()); } if ( scaleChoice() ) { scaleChoice()->init(); } for (auto const & rw : theReweights) rw->init(); for (auto const & v : virtuals() ) v->init(); } void MatchboxMEBase::doinitrun() { MEBase::doinitrun(); if ( matchboxAmplitude() ) matchboxAmplitude()->initrun(); if ( phasespace() ) phasespace()->initrun(); if ( scaleChoice() ) scaleChoice()->initrun(); for (auto const & rw : theReweights) rw->initrun(); for (auto const & v : virtuals() ) v->initrun(); } void MatchboxMEBase::dofinish() { MEBase::dofinish(); for (auto const & b : epsilonSquarePoleHistograms ) { b.second.dump(factory()->poleData(),"epsilonSquarePoles-",b.first); } for (auto const & b : epsilonPoleHistograms ) { b.second.dump(factory()->poleData(),"epsilonPoles-",b.first); } } // *** 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 describeHerwigMatchboxMEBase("Herwig::MatchboxMEBase", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Base/MatchboxMEBase.h b/MatrixElement/Matchbox/Base/MatchboxMEBase.h --- a/MatrixElement/Matchbox/Base/MatchboxMEBase.h +++ b/MatrixElement/Matchbox/Base/MatchboxMEBase.h @@ -1,1211 +1,1203 @@ // -*- C++ -*- // // MatchboxMEBase.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MatchboxMEBase_H #define HERWIG_MatchboxMEBase_H // // This is the declaration of the MatchboxMEBase class. // #include "ThePEG/MatrixElement/MEBase.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h" #include "Herwig/MatrixElement/Matchbox/Utility/ProcessData.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxReweightBase.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.fh" #include "Herwig/MatrixElement/Matchbox/Base/MergerBase.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh" #include "Herwig/MatrixElement/Matchbox/InsertionOperators/MatchboxInsertionOperator.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.fh" #include "Herwig/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxXComb.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxMEBase is the base class for matrix elements * in the context of the matchbox NLO interface. * * @see \ref MatchboxMEBaseInterfaces "The interfaces" * defined for MatchboxMEBase. */ class MatchboxMEBase: public MEBase, public LastMatchboxXCombInfo { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxMEBase(); - /** - * The destructor. - */ - virtual ~MatchboxMEBase(); - //@} - public: /** * Return the factory which produced this matrix element */ Ptr::tptr factory() const; /** @name Subprocess and diagram information. */ //@{ /** * Return the subprocess. */ const Process& subProcess() const { return theSubprocess; } /** * Access the subprocess. */ Process& subProcess() { return theSubprocess; } /** * Return the diagram generator. */ Ptr::tptr diagramGenerator() const; /** * Return the process data. */ Ptr::tptr processData() const; /** * Return true, if this matrix element does not want to * make use of mirroring processes; in this case all * possible partonic subprocesses with a fixed assignment * of incoming particles need to be provided through the diagrams * added with the add(...) method. */ virtual bool noMirror () const { return true; } /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; using MEBase::getDiagrams; /** * With the information previously supplied with the * setKinematics(...) method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. */ virtual Selector diagrams(const DiagramVector &) const; using MEBase::diagrams; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; /** * Return true, if this amplitude is capable of consistently filling * the rho matrices for the spin correllations */ virtual bool canFillRhoMatrix() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->canFillRhoMatrix(); return false; } /** * construct the spin information for the interaction */ virtual void constructVertex(tSubProPtr) {} /** * construct the spin information for the interaction */ virtual void constructVertex(tSubProPtr sub, const ColourLines* cl); /** * Return the order in \f$\alpha_S\f$ in which this matrix element * is given. */ virtual unsigned int orderInAlphaS() const; using MEBase::orderInAlphaS; /** * Return the order in \f$\alpha_{EM}\f$ in which this matrix * element is given. Returns 0. */ virtual unsigned int orderInAlphaEW() const; using MEBase::orderInAlphaEW; /** * Return true, if this amplitude already includes averaging over * incoming parton's quantum numbers. */ virtual bool hasInitialAverage() const { return matchboxAmplitude() ? matchboxAmplitude()->hasInitialAverage() : false; } /** * Return true, if this amplitude already includes symmetry factors * for identical outgoing particles. */ virtual bool hasFinalStateSymmetry() const { return matchboxAmplitude() ? matchboxAmplitude()->hasFinalStateSymmetry() : false; } /** * Return the number of light flavours, this matrix * element is calculated for. */ virtual unsigned int getNLight() const; /** * Return the vector that contains the PDG ids of * the light flavours, which are contained in the * jet particle group. */ virtual vector getNLightJetVec() const; /** * Return the vector that contains the PDG ids of * the heavy flavours, which are contained in the * jet particle group. */ virtual vector getNHeavyJetVec() const; /** * Return the vector that contains the PDG ids of * the light flavours, which are contained in the * proton particle group. */ virtual vector getNLightProtonVec() const; /** * Return true, if this matrix element is handled by a BLHA one-loop provider */ virtual bool isOLPTree() const { return matchboxAmplitude() ? matchboxAmplitude()->isOLPTree() : false; } /** * Return true, if this matrix element is handled by a BLHA one-loop provider */ virtual bool isOLPLoop() const { return matchboxAmplitude() ? matchboxAmplitude()->isOLPLoop() : false; } /** * Return true, if colour and spin correlated matrix elements should * be ordered from the OLP */ virtual bool needsOLPCorrelators() const { return matchboxAmplitude() ? matchboxAmplitude()->needsOLPCorrelators() : true; } /** * Return the process index, if this is an OLP handled matrix element */ const vector& olpProcess() const { return theOLPProcess; } /** * Set the process index, if this is an OLP handled matrix element */ void olpProcess(int pType, int id) { if ( theOLPProcess.empty() ) theOLPProcess.resize(5,0); theOLPProcess[pType] = id; } /** * Return true, if this is a real emission matrix element which does * not require colour correlators. */ bool noCorrelations() const { return theNoCorrelations; } /** * Indicate that this is a real emission matrix element which does * not require colour correlators. */ void needsNoCorrelations() { theNoCorrelations = true; } /** * Indicate that this is a virtual matrix element which does * require colour correlators. */ void needsCorrelations() { theNoCorrelations = false; } //@} /** @name Phasespace generation */ //@{ /** * Return the phase space generator to be used. */ Ptr::tptr phasespace() const { return thePhasespace; } /** * Set the phase space generator to be used. */ void phasespace(Ptr::ptr ps) { thePhasespace = ps; } /** * Set the XComb object to be used in the next call to * generateKinematics() and dSigHatDR(). */ virtual void setXComb(tStdXCombPtr xc); /** * Return true, if the XComb steering this matrix element * should keep track of the random numbers used to generate * the last phase space point */ virtual bool keepRandomNumbers() const { return true; } /** * Generate incoming parton momenta. This default * implementation performs the standard mapping * from x1,x2 -> tau,y making 1/tau flat; incoming * parton momenta are stored in meMomenta()[0,1], * only massless partons are supported so far; * return the Jacobian of the mapping */ double generateIncomingPartons(const double* r1, const double* r2); /** * Generate internal degrees of freedom given nDim() uniform random * numbers in the interval ]0,1[. To help the phase space generator, * the 'dSigHatDR' should be a smooth function of these numbers, * although this is not strictly necessary. The return value should * be true of the generation succeeded. If so the generated momenta * should be stored in the meMomenta() vector. Derived classes * must call this method once internal degrees of freedom are setup * and finally return the result of this method. */ virtual bool generateKinematics(const double * r); /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries() * according to the associated XComb object. If the function is * overridden in a sub class the new function must call the base * class one first. */ virtual void setKinematics(); /** * Clear the information previously provided by a call to * setKinematics(...). */ virtual void clearKinematics(); /** * The number of internal degreed of freedom used in the matrix * element. */ virtual int nDim() const; /** * The number of internal degrees of freedom used in the matrix * element for generating a Born phase space point */ virtual int nDimBorn() const; /** * Return true, if this matrix element will generate momenta for the * incoming partons itself. The matrix element is required to store * the incoming parton momenta in meMomenta()[0,1]. No mapping in * tau and y is performed by the PartonExtractor object, if a * derived class returns true here. The phase space jacobian is to * include a factor 1/(x1 x2). */ virtual bool haveX1X2() const { return (phasespace() ? phasespace()->haveX1X2() : false) || diagrams().front()->partons().size() == 3; } /** * Return true, if this matrix element expects * the incoming partons in their center-of-mass system */ virtual bool wantCMS() const { return (phasespace() ? phasespace()->wantCMS() : true) && diagrams().front()->partons().size() != 3; } /** * Return the meMomenta as generated at the last * phase space point. */ const vector& lastMEMomenta() const { return meMomenta(); } /** * Access the meMomenta. */ vector& lastMEMomenta() { return meMomenta(); } /** * leg size */ int legsize() const {return int(meMomenta().size());} //@} /** @name Scale choices, couplings and PDFs */ //@{ /** * Set the scale choice object */ void scaleChoice(Ptr::ptr sc) { theScaleChoice = sc; } /** * Return the scale choice object */ Ptr::tptr scaleChoice() const { return theScaleChoice; } /** * Set scales and alphaS */ void setScale(Energy2 ren=ZERO,Energy2 fac=ZERO) const; /** * Indicate that this matrix element is running alphas by itself. */ virtual bool hasRunningAlphaS() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->hasRunningAlphaS(); return false; } /** * Indicate that this matrix element is running alphaew by itself. */ virtual bool hasRunningAlphaEW() const { if ( matchboxAmplitude() ) return matchboxAmplitude()->hasRunningAlphaEW(); return false; } /** * Return the scale associated with the phase space point provided * by the last call to setKinematics(). */ virtual Energy2 scale() const { return lastScale(); } /** * Return the renormalization scale for the last generated phasespace point. */ virtual Energy2 factorizationScale() const; /** * Get the factorization scale factor */ virtual double factorizationScaleFactor() const; /** * Get the factorization scale factor */ virtual double facFac() const{return factorizationScaleFactor();} /** * Return the (QCD) renormalization scale for the last generated phasespace point. */ virtual Energy2 renormalizationScale() const; /** * Get the renormalization scale factor */ virtual double renormalizationScaleFactor() const; /** * Get the renormalization scale factor */ virtual double renFac() const{return renormalizationScaleFactor();} /** * Return the QED renormalization scale for the last generated phasespace point. */ virtual Energy2 renormalizationScaleQED() const; /** * Return the shower scale for the last generated phasespace point. */ virtual Energy2 showerScale() const; /** * Set veto scales on the particles at the given * SubProcess which has been generated using this * matrix element. */ virtual void setVetoScales(tSubProPtr) const; /** * Return true, if fixed couplings are used. */ bool fixedCouplings() const; /** * Return true, if fixed couplings are used. */ bool fixedQEDCouplings() const; /** * Return the value of \f$\alpha_S\f$ associated with the phase * space point provided by the last call to setKinematics(). This * versions returns SM().alphaS(scale()). */ virtual double alphaS() const { return lastAlphaS(); } /** * Return the value of \f$\alpha_EM\f$ associated with the phase * space point provided by the last call to setKinematics(). This * versions returns SM().alphaEM(scale()). */ virtual double alphaEM() const { return lastAlphaEM(); } /** * Return true, if this matrix element provides the PDF * weight for the first incoming parton itself. */ virtual bool havePDFWeight1() const; /** * Return true, if this matrix element provides the PDF * weight for the second incoming parton itself. */ virtual bool havePDFWeight2() const; /** * Set the PDF weight. */ void getPDFWeight(Energy2 factorizationScale = ZERO) const; /** * Supply the PDF weight for the first incoming parton. */ double pdf1(Energy2 factorizationScale = ZERO, double xEx = 1., double xFactor = 1.) const; /** * Supply the PDF weight for the second incoming parton. */ double pdf2(Energy2 factorizationScale = ZERO, double xEx = 1., double xFactor = 1.) const; //@} /** @name Amplitude information and matrix element evaluation */ //@{ /** * Return the amplitude. */ Ptr::tptr matchboxAmplitude() const { return theAmplitude; } /** * Set the amplitude. */ void matchboxAmplitude(Ptr::ptr amp) { theAmplitude = amp; } /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double largeNME2(Ptr::tptr largeNBasis) const; /** * Return the symmetry factor for identical final state particles. */ virtual double finalStateSymmetry() const; /** * Return the normalizing factor for the matrix element averaged * over quantum numbers and including running couplings. */ double me2Norm(unsigned int addAlphaS = 0) const; /** * Return the matrix element squared differential in the variables * given by the last call to generateKinematics(). */ virtual CrossSection dSigHatDR() const; /** * Same prefactor for all dSigHat **/ CrossSection prefactor()const; /** * Born part of the cross section **/ CrossSection dSigHatDRB() const ; /** * Virtual corrections of the cross section **/ CrossSection dSigHatDRV() const ; /** * Insertion operators of the cross section **/ CrossSection dSigHatDRI() const ; /** * If diffAlpha is not 1 and the matrix element has insertion operators * this routine adds the difference between the insertion operator calculated * with an alpha-Parameter to the insertion operator without alpha-parameter. */ CrossSection dSigHatDRAlphaDiff(double alpha) const ; //@} /** @name One-loop corrections */ //@{ /** * Return the one-loop/tree interference. */ virtual double oneLoopInterference() const; /** * Return true, if this matrix element is capable of calculating * one-loop (QCD) corrections. */ virtual bool haveOneLoop() const; /** * Return true, if this matrix element only provides * one-loop (QCD) corrections. */ virtual bool onlyOneLoop() const; /** * Return true, if the amplitude is DRbar renormalized, otherwise * MSbar is assumed. */ virtual bool isDRbar() const; /** * Return true, if one loop corrections have been calculated in * dimensional reduction. Otherwise conventional dimensional * regularization is assumed. Note that renormalization is always * assumed to be MSbar. */ virtual bool isDR() const; /** * Return true, if one loop corrections are given in the conventions * of the integrated dipoles. */ virtual bool isCS() const; /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const; /** * Return true, if one loop corrections are given in the conventions * of everything expanded. */ virtual bool isExpanded() const; /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const; /** * If defined, return the coefficient of the pole in epsilon^2 */ virtual double oneLoopDoublePole() const; /** * If defined, return the coefficient of the pole in epsilon */ virtual double oneLoopSinglePole() const; /** * Return true, if cancellationn of epsilon poles should be checked. */ bool checkPoles() const; /** * Simple histogram for accuracy checks */ struct AccuracyHistogram { /** * The lower bound */ double lower; /** * The upper bound */ double upper; /** * The bins, indexed by upper bound. */ map bins; /** * The number of points of same sign */ unsigned long sameSign; /** * The number of points of opposite sign */ unsigned long oppositeSign; /** * The number of points being nan or inf */ unsigned long nans; /** * The overflow */ unsigned long overflow; /** * The underflow */ unsigned long underflow; /** * Constructor */ AccuracyHistogram(double low = -40., double up = 0., unsigned int nbins = 80); /** * Book two values to be checked for numerical compatibility */ void book(double a, double b); /** * Write to file. */ void dump(const std::string& folder, const std::string& prefix, const cPDVector& proc) const; /** * Write to persistent ostream */ void persistentOutput(PersistentOStream&) const; /** * Read from persistent istream */ void persistentInput(PersistentIStream&); }; /** * Perform the check of epsilon pole cancellation. */ void logPoles() const; /** * Return the virtual corrections */ const vector::ptr>& virtuals() const { return theVirtuals; } /** * Return the virtual corrections */ vector::ptr>& virtuals() { return theVirtuals; } /** * Instruct this matrix element to include one-loop corrections */ void doOneLoop() { theOneLoop = true; } /** * Instruct this matrix element not to include one-loop corrections */ void noOneLoop() { theOneLoop = false; } /** * Return true, if this matrix element includes one-loop corrections */ bool oneLoop() const { return theOneLoop; } /** * Instruct this matrix element to include one-loop corrections but * no Born contributions */ void doOneLoopNoBorn() { theOneLoop = true; theOneLoopNoBorn = true; } void noOneLoopNoBorn() { theOneLoop = false; theOneLoopNoBorn = false; } /** * Return true, if this matrix element includes one-loop corrections * but no Born contributions */ bool oneLoopNoBorn() const { return theOneLoopNoBorn || onlyOneLoop(); } /** * Instruct this matrix element to include one-loop corrections but * no actual loop contributions */ void doOneLoopNoLoops() { theOneLoop = true; theOneLoopNoLoops = true; } /** * Return true, if this matrix element includes one-loop corrections * but no actual loop contributions */ bool oneLoopNoLoops() const { return theOneLoopNoLoops; } //@} /** @name Dipole subtraction */ //@{ /** * If this matrix element is considered a real * emission matrix element, return all subtraction * dipoles needed given a set of subtraction terms * and underlying Born matrix elements to choose * from. */ vector::ptr> getDipoles(const vector::ptr>&, const vector::ptr>&,bool slim=false) const; /** * If this matrix element is considered a real emission matrix * element, but actually neglecting a subclass of the contributing * diagrams, return true if the given emitter-emission-spectator * configuration should not be considered when setting up * subtraction dipoles. */ virtual bool noDipole(int,int,int) const { return false; } /** * If this matrix element is considered an underlying Born matrix * element in the context of a subtracted real emission, but * actually neglecting a subclass of the contributing diagrams, * return true if the given emitter-spectator configuration * should not be considered when setting up subtraction dipoles. */ virtual bool noDipole(int,int) const { return false; } /** * Return the colour correlated matrix element squared with * respect to the given two partons as appearing in mePartonData(), * suitably scaled by sHat() to give a dimension-less number. */ virtual double colourCorrelatedME2(pair) const; /** * Return the colour correlated matrix element squared in the * large-N approximation with respect to the given two partons as * appearing in mePartonData(), suitably scaled by sHat() to give a * dimension-less number. */ virtual double largeNColourCorrelatedME2(pair ij, Ptr::tptr largeNBasis) const; /** * Return the colour and spin correlated matrix element squared for * the gluon indexed by the first argument using the given * correlation tensor. */ virtual double spinColourCorrelatedME2(pair emitterSpectator, const SpinCorrelationTensor& c) const; /** * Return the spin correlated matrix element squared for * the vector boson indexed by the first argument using the given * correlation tensor. */ virtual double spinCorrelatedME2(pair emitterSpectator, const SpinCorrelationTensor& c) const; //@} /** @name Caching and diagnostic information */ //@{ /** * Inform this matrix element that a new phase space * point is about to be generated, so all caches should * be flushed. */ virtual void flushCaches(); /** * Return true, if verbose */ bool verbose() const; /** * Return true, if verbose */ bool initVerbose() const; /** * Dump the setup to an ostream */ void print(ostream&) const; /** * Print debug information on the last event */ virtual void printLastEvent(ostream&) const; /** * Write out diagnostic information for * generateKinematics */ void logGenerateKinematics(const double * r) const; /** * Write out diagnostic information for * setting scales */ void logSetScale() const; /** * Write out diagnostic information for * pdf evaluation */ void logPDFWeight() const; /** * Write out diagnostic information for * me2 evaluation */ void logME2() const; /** * Write out diagnostic information * for dsigdr evaluation */ void logDSigHatDR() const; //@} /** @name Reweight objects */ //@{ /** * Insert a reweight object */ void addReweight(Ptr::ptr rw) { theReweights.push_back(rw); } /** * Return the reweights */ const vector::ptr>& reweights() const { return theReweights; } /** * Access the reweights */ vector::ptr>& reweights() { return theReweights; } /** * Return the theMerger. */ const MergerBasePtr merger() const; /** * Return the theMerger. */ MergerBasePtr merger() ; /** * Set the theMerger. */ void merger(MergerBasePtr v); //@} /** @name Methods used to setup MatchboxMEBase objects */ //@{ /** * Return true if this object needs to be initialized before all * other objects (except those for which this function also returns * true). This default version always returns false, but subclasses * may override it to return true. */ virtual bool preInitialize() const { return true; } /** * Clone this matrix element. */ Ptr::ptr cloneMe() const { return dynamic_ptr_cast::ptr>(clone()); } /** * Clone the dependencies, using a given prefix. */ void cloneDependencies(const std::string& prefix = "",bool slim = false ); /** * Prepare an xcomb */ void prepareXComb(MatchboxXCombData&) const; /** * For the given event generation setup return a xcomb object * appropriate to this matrix element. */ virtual StdXCombPtr makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec& allPBins, tStdXCombPtr newHead = tStdXCombPtr(), tMEPtr newME = tMEPtr()); /** * For the given event generation setup return a dependent xcomb object * appropriate to this matrix element. */ virtual StdXCombPtr makeXComb(tStdXCombPtr newHead, const PBPair & newPartonBins, const DiagramVector & newDiagrams, tMEPtr newME = tMEPtr()); //@} 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. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The phase space generator to be used. */ Ptr::ptr thePhasespace; /** * The amplitude to be used */ Ptr::ptr theAmplitude; /** * The scale choice object */ Ptr::ptr theScaleChoice; /** * The virtual corrections. */ vector::ptr> theVirtuals; /** * A vector of reweight objects the sum of which * should be applied to reweight this matrix element */ vector::ptr> theReweights; private: /** * The subprocess to be considered. */ Process theSubprocess; /** * True, if this matrix element includes one-loop corrections */ bool theOneLoop; /** * True, if this matrix element includes one-loop corrections * but no Born contributions */ bool theOneLoopNoBorn; /** * True, if this matrix element includes one-loop corrections * but no actual loop contributions (e.g. finite collinear terms) */ bool theOneLoopNoLoops; /** * The process index, if this is an OLP handled matrix element */ vector theOLPProcess; /** * Histograms of epsilon^2 pole cancellation */ mutable map epsilonSquarePoleHistograms; /** * Histograms of epsilon pole cancellation */ mutable map epsilonPoleHistograms; /** * True, if this is a real emission matrix element which does * not require colour correlators. */ bool theNoCorrelations; /** * Flag which pdfs should be included. */ mutable pair theHavePDFs; /** * True, if already checked for which PDFs to include. */ mutable bool checkedPDFs; /** * The merging helper to be used. * Only the head ME has a pointer to this helper. */ MergerBasePtr theMerger; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxMEBase & operator=(const MatchboxMEBase &) = delete; }; inline PersistentOStream& operator<<(PersistentOStream& os, const MatchboxMEBase::AccuracyHistogram& h) { h.persistentOutput(os); return os; } inline PersistentIStream& operator>>(PersistentIStream& is, MatchboxMEBase::AccuracyHistogram& h) { h.persistentInput(is); return is; } } #endif /* HERWIG_MatchboxMEBase_H */ diff --git a/MatrixElement/Matchbox/Base/MatchboxOLPME.cc b/MatrixElement/Matchbox/Base/MatchboxOLPME.cc --- a/MatrixElement/Matchbox/Base/MatchboxOLPME.cc +++ b/MatrixElement/Matchbox/Base/MatchboxOLPME.cc @@ -1,355 +1,353 @@ // -*- C++ -*- // // MatchboxOLPME.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxOLPME class. // #include "MatchboxOLPME.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 "MatchboxMEBase.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MatchboxOLPME::MatchboxOLPME() : theOrderInGs(0), theOrderInGem(0), theSetMuToMuR(false), theUseRunningAlphaS(false), theUseRunningAlphaEW(false) {} -MatchboxOLPME::~MatchboxOLPME() {} - bool MatchboxOLPME::canHandle(const PDVector& p, Ptr::tptr factory, bool) const { if ( factory->processData()->diagramMap().find(p) != factory->processData()->diagramMap().end() ) return true; vector::ptr> diags = factory->diagramGenerator()->generate(p,orderInGs(),orderInGem()); if ( diags.empty() ) return false; factory->processData()->diagramMap()[p] = diags; return true; } void MatchboxOLPME::setXComb(tStdXCombPtr xc) { theLastXComb = xc; lastMatchboxXComb(xc); } double MatchboxOLPME::me2() const { if ( !calculateTreeME2() ) return lastTreeME2(); evalSubProcess(); return lastTreeME2(); } double MatchboxOLPME::colourCorrelatedME2(pair ij) const { double cfac = 1.; double Nc = generator()->standardModel()->Nc(); 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); if ( !calculateColourCorrelator(ij) ) return lastColourCorrelator(ij)/cfac; evalColourCorrelator(ij); return lastColourCorrelator(ij)/cfac; } double MatchboxOLPME::spinColourCorrelatedME2(pair ij, const SpinCorrelationTensor& c) const { Lorentz5Momentum p = meMomenta()[ij.first]; Lorentz5Momentum n = meMomenta()[ij.second]; LorentzVector polarization = plusPolarization(p,n,ij.first); 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) ) evalSpinColourCorrelator(ij); 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; } double MatchboxOLPME::spinCorrelatedME2(pair ij, const SpinCorrelationTensor& c) const { Lorentz5Momentum p = meMomenta()[ij.first]; Lorentz5Momentum n = meMomenta()[ij.second]; LorentzVector polarization = plusPolarization(p,n,ij.first); Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale())); double avg = me2()*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor)); Complex csCorr = 0.0; if ( calculateSpinCorrelator(ij) ) evalSpinCorrelator(ij); csCorr = lastSpinCorrelator(ij); double corr = 2.*real(csCorr*sqr(pFactor)); return avg + (c.scale() > ZERO ? 1. : -1.)*corr; } void MatchboxOLPME::evalSpinCorrelator(pair) const { throw Exception() << "MatchboxOLPME::spinCorrelatedME2() is not implemented.\n" << "Please check your setup." << Exception::runerror; } double MatchboxOLPME::oneLoopDoublePole() const { if ( !calculateOneLoopPoles() ) return lastOneLoopPoles().first; evalSubProcess(); return lastOneLoopPoles().first; } double MatchboxOLPME::oneLoopSinglePole() const { if ( !calculateOneLoopPoles() ) return lastOneLoopPoles().second; evalSubProcess(); return lastOneLoopPoles().second; } double MatchboxOLPME::oneLoopInterference() const { if ( !calculateOneLoopInterference() ) return lastOneLoopInterference(); evalSubProcess(); return lastOneLoopInterference(); } double MatchboxOLPME::largeNColourCorrelatedME2(pair ij, Ptr::tptr basis) const { if ( trivialColourLegs() ) return MatchboxAmplitude::largeNColourCorrelatedME2(ij,basis); throw Exception() << "MatchboxOLPME::largeNColourCorrelatedME2(): not supported" << Exception::runerror; return 0.; } double MatchboxOLPME::largeNME2(Ptr::tptr basis) const { if ( trivialColourLegs() ) return MatchboxAmplitude::largeNME2(basis); throw Exception() << "MatchboxOLPME::largeNME2(): not supported" << Exception::runerror; return 0.; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxOLPME::doinit() { if ( theUseRunningAlphaS && !theSetMuToMuR ) { throw Exception() << "MatchboxOLPME::doinit(): " << "Amplitude '" << name() << "' " << "uses a running alpha_s but fixed renormalization scale!\n" << Exception::runerror; } if ( !theUseRunningAlphaS && theSetMuToMuR ) { throw Exception() << "MatchboxOLPME::doinit(): " << "Amplitude '" << name() << "' " << "uses a fixed alpha_s but running renormalization scale!\n" << Exception::runerror; } if ( !didStartOLP() ) { string contractFileName = optionalContractFile().empty() ? factory()->buildStorage() + name() + ".OLPContract.lh" : optionalContractFile(); int status = -1; startOLP(contractFileName,status); didStartOLP()=true; if ( status != 1 ) { throw Exception() << "MatchboxOLPME::doinit(): " << "Failed to restart one loop provider for amplitude '" << name() << "'\n" << Exception::runerror; } } MatchboxAmplitude::doinit(); } void MatchboxOLPME::doinitrun() { if ( theUseRunningAlphaS && !theSetMuToMuR ) { throw Exception() << "MatchboxOLPME::doinitrun(): " << "Amplitude '" << name() << "' " << "uses a running alpha_s but fixed renormalization scale!\n" << Exception::runerror; } if ( !theUseRunningAlphaS && theSetMuToMuR ) { throw Exception() << "MatchboxOLPME::doinitrun(): " << "Amplitude '" << name() << "' " << "uses a fixed alpha_s but running renormalization scale!\n" << Exception::runerror; } if ( !didStartOLP() ) { string contractFileName = optionalContractFile().empty() ? factory()->buildStorage() + name() + ".OLPContract.lh" : optionalContractFile(); int status = -1; startOLP(contractFileName,status); didStartOLP()=true; if ( status != 1 ) { throw Exception() << "MatchboxOLPME::doinitrun(): " << "Failed to restart one loop provider for amplitude '" << name() << "'\n" << Exception::runerror; } } MatchboxAmplitude::doinitrun(); } Energy2 MatchboxOLPME::mu2() const { if (theSetMuToMuR) { return lastMatchboxXComb()->lastRenormalizationScale(); } return lastSHat(); } bool MatchboxOLPME::hasRunningAlphaS() const { if (theUseRunningAlphaS) { return true; } return false; } bool MatchboxOLPME::hasRunningAlphaEW() const { if (theUseRunningAlphaEW) { return true; } return false; } void MatchboxOLPME::persistentOutput(PersistentOStream & os) const { os << theOrderInGs << theOrderInGem << theSetMuToMuR << theUseRunningAlphaS << theUseRunningAlphaEW; } void MatchboxOLPME::persistentInput(PersistentIStream & is, int) { is >> theOrderInGs >> theOrderInGem >> theSetMuToMuR >> theUseRunningAlphaS >> theUseRunningAlphaEW; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeHerwigMatchboxOLPME("Herwig::MatchboxOLPME", "Herwig.so"); void MatchboxOLPME::Init() { static ClassDocumentation documentation ("MatchboxOLPME implements OLP interfaces."); static Switch interfaceSetMuToMuR ("SetMuToMuR", "Switch On to set the value of the dimensional regularization parameter mu2 for this OLP" "to the value of the renormalization scale muR2. Default is Off. The restoration for the " "full renormalization scale dependence in the DipoleIOperator isn't needed in this case.", &MatchboxOLPME::theSetMuToMuR, false, false, false); static SwitchOption interfaceSetMuToMuRYes (interfaceSetMuToMuR, "Yes", "Yes", true); static SwitchOption interfaceSetMuToMuRNo (interfaceSetMuToMuR, "No", "No", false); interfaceSetMuToMuR.rank(-1); static Switch interfaceUseRunningAlphaS ("UseRunningAlphaS", "Switch On to set the value of alpha_s for this OLP to the value of the running alpha_s " "instead of to the value of the reference alpha_s. Default is Off. This also sets the value " "for hasRunningAlphaS() to true.", &MatchboxOLPME::theUseRunningAlphaS, false, false, false); static SwitchOption interfaceUseRunningAlphaSYes (interfaceUseRunningAlphaS, "Yes", "Yes", true); static SwitchOption interfaceUseRunningAlphaSNo (interfaceUseRunningAlphaS, "No", "No", false); interfaceUseRunningAlphaS.rank(-1); static Switch interfaceUseRunningAlphaEW ("UseRunningAlphaEW", "Switch On to set the value of alpha_ew for this OLP to the value of the running alpha_ew " "instead of to the value of the reference alpha_ew. Default is Off. This also sets the value " "for hasRunningAlphaEW() to true.", &MatchboxOLPME::theUseRunningAlphaEW, false, false, false); static SwitchOption interfaceUseRunningAlphaEWYes (interfaceUseRunningAlphaEW, "Yes", "Yes", true); static SwitchOption interfaceUseRunningAlphaEWNo (interfaceUseRunningAlphaEW, "No", "No", false); interfaceUseRunningAlphaEW.rank(-1); } diff --git a/MatrixElement/Matchbox/Base/MatchboxOLPME.h b/MatrixElement/Matchbox/Base/MatchboxOLPME.h --- a/MatrixElement/Matchbox/Base/MatchboxOLPME.h +++ b/MatrixElement/Matchbox/Base/MatchboxOLPME.h @@ -1,332 +1,324 @@ // -*- C++ -*- // // MatchboxOLPME.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxOLPME_H #define Herwig_MatchboxOLPME_H // // This is the declaration of the MatchboxOLPME class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxOLPME implements OLP interfaces. */ class MatchboxOLPME: public MatchboxAmplitude { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxOLPME(); - /** - * The destructor. - */ - virtual ~MatchboxOLPME(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector& p, Ptr::tptr, bool) const; /** * Set the (tree-level) order in \f$g_S\f$ in which this matrix * element should be evaluated. */ virtual void orderInGs(unsigned int ogs) { theOrderInGs = ogs; } /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return theOrderInGs; } /** * Set the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element should be evaluated. */ virtual void orderInGem(unsigned int oge) { theOrderInGem = oge; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return theOrderInGem; } /** * Return true, if this amplitude is handled by a BLHA one-loop provider */ virtual bool isOLPTree() const { return true; } /** * Return true, if this amplitude is handled by a BLHA one-loop provider */ virtual bool isOLPLoop() const { return true; } /** * Return true, if the colour basis is capable of assigning colour * flows. */ virtual bool haveColourFlows() const { return false; } /** * Set the xcomb object. */ virtual void setXComb(tStdXCombPtr xc); /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr) {} /** * Return the matrix element squared. */ virtual double me2() const; /** * Return the colour correlated matrix element. */ virtual double colourCorrelatedME2(pair ij) const; /** * Return the large-N colour correlated matrix element. */ virtual double largeNColourCorrelatedME2(pair, Ptr::tptr) const; /** * Return the largeN matrix element squared. */ virtual double largeNME2(Ptr::tptr largeNBasis) const; /** * Return the colour and spin correlated matrix element. */ virtual double spinColourCorrelatedME2(pair ij, const SpinCorrelationTensor& c) const; /** * Return the spin correlated matrix element. */ virtual double spinCorrelatedME2(pair ij, const SpinCorrelationTensor& c) const; /** * Return true, if tree-level contributions will be evaluated at amplitude level. */ virtual bool treeAmplitudes() const { return false; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return true; } /** * Return true, if this amplitude only provides * one-loop (QCD) corrections. */ virtual bool onlyOneLoop() const { return false; } /** * Return true, if one-loop contributions will be evaluated at amplitude level. */ virtual bool oneLoopAmplitudes() const { return false; } /** * Return true, if one loop corrections are given in the conventions * of everything expanded. */ virtual bool isExpanded() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const; /** * Indicate that this amplitude is running alphas by itself. */ virtual bool hasRunningAlphaS() const; /** * Indicate that this amplitude is running alphaew by itself. */ virtual bool hasRunningAlphaEW() const; /** * If defined, return the coefficient of the pole in epsilon^2 */ virtual double oneLoopDoublePole() const; /** * If defined, return the coefficient of the pole in epsilon */ virtual double oneLoopSinglePole() const; /** * Calculate the one-loop amplitudes for the phasespace point * stored in lastXComb, if provided. */ virtual void prepareOneLoopAmplitudes(Ptr::tcptr) {} /** * Return the one-loop/tree interference. */ virtual double oneLoopInterference() const; public: /** * Call OLP_EvalSubProcess and fill in the results */ virtual void evalSubProcess() const = 0; /** * Fill in results for the given colour correlator */ virtual void evalColourCorrelator(pair ij) const = 0; /** * Fill in results for the given colour/spin correlator */ virtual void evalSpinColourCorrelator(pair ij) const = 0; /** * Fill in results for the given spin correlator; may not be supported */ virtual void evalSpinCorrelator(pair ij) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} /** * Set an optional contract file name to be used */ static string& optionalContractFile() { static string s = ""; return s; } /** * Indicate that the OLP has been started */ static bool& didStartOLP() { static bool f = false; return f; } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxOLPME & operator=(const MatchboxOLPME &) = delete; /** * The (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ unsigned int theOrderInGs; /** * The (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ unsigned int theOrderInGem; /** * Set the value of the dimensional regularization parameter * to the value of the renormalization scale */ bool theSetMuToMuR; /** * Use the running alpha_s instead of the reference alpha_s. * This also sets hasRunningAlphaS() to true. */ bool theUseRunningAlphaS; /** * Use the running alpha_ew instead of the reference alpha_ew. * This also sets hasRunningAlphaEW() to true. */ bool theUseRunningAlphaEW; }; } #endif /* Herwig_MatchboxOLPME_H */ diff --git a/MatrixElement/Matchbox/Base/MatchboxReweightBase.cc b/MatrixElement/Matchbox/Base/MatchboxReweightBase.cc --- a/MatrixElement/Matchbox/Base/MatchboxReweightBase.cc +++ b/MatrixElement/Matchbox/Base/MatchboxReweightBase.cc @@ -1,45 +1,38 @@ // -*- C++ -*- // // MatchboxReweightBase.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxReweightBase class. // #include "MatchboxReweightBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -MatchboxReweightBase::MatchboxReweightBase() {} - -MatchboxReweightBase::~MatchboxReweightBase() {} - void MatchboxReweightBase::cloneDependencies(const std::string&) {} void MatchboxReweightBase::persistentOutput(PersistentOStream &) const {} void MatchboxReweightBase::persistentInput(PersistentIStream &, int) {} void MatchboxReweightBase::Init() { static ClassDocumentation documentation ("MatchboxReweightBase"); } -// *** 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). +// The following static variable is needed for the type +// description system in ThePEG. DescribeAbstractClass describeMatchboxReweightBase("Herwig::MatchboxReweightBase", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Base/MatchboxReweightBase.h b/MatrixElement/Matchbox/Base/MatchboxReweightBase.h --- a/MatrixElement/Matchbox/Base/MatchboxReweightBase.h +++ b/MatrixElement/Matchbox/Base/MatchboxReweightBase.h @@ -1,146 +1,131 @@ // -*- C++ -*- // // MatchboxReweightBase.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MatchboxReweightBase_H #define HERWIG_MatchboxReweightBase_H // // This is the declaration of the MatchboxReweightBase class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/StandardXComb.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxReweightBase is the base class * for reweighting MatchboxMEBase matrix elements * as |M|^2 ( w_1 + ... + w_n ) * */ class MatchboxReweightBase: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - MatchboxReweightBase(); - - /** - * The destructor. - */ - virtual ~MatchboxReweightBase(); - //@} - -public: - /** * Clone this reweight. */ Ptr::ptr cloneMe() const { return dynamic_ptr_cast::ptr>(clone()); } /** * Clone the dependencies, using a given prefix. */ virtual void cloneDependencies(const std::string& prefix = ""); /** * Set the XComb object. */ virtual void setXComb(tStdXCombPtr) = 0; /** * Return true, if applies to the process in the xcomb. */ virtual bool apply() const = 0; /** * Inform this matrix element that a new phase space * point is about to be generated, so all caches should * be flushed. */ virtual void flushCaches() = 0; /** * Evaluate the reweight. */ virtual double evaluate() const = 0; /** * Set veto scales on the particles at the given * SubProcess which has been generated using this * matrix element. */ virtual void setVetoScales(tSubProPtr) const {} public: /** * Dump the setup to an ostream */ virtual void print(ostream&) const {} /** * Print debug information on the last event */ virtual void printLastEvent(ostream&) const {} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxReweightBase & operator=(const MatchboxReweightBase &) = delete; }; } #endif /* HERWIG_MatchboxReweightBase_H */ diff --git a/MatrixElement/Matchbox/Base/MergerBase.cc b/MatrixElement/Matchbox/Base/MergerBase.cc --- a/MatrixElement/Matchbox/Base/MergerBase.cc +++ b/MatrixElement/Matchbox/Base/MergerBase.cc @@ -1,44 +1,39 @@ // -*- C++ -*- // // MergerBase.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MergerBase class. // #include "MergerBase.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MergerBase::MergerBase() : HandlerBase() {} -MergerBase::~MergerBase() {} - void MergerBase::Init() { static ClassDocumentation documentation ("MergerBase is the base class for merging helpers."); } -// *** 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). +// The following static variable is needed for the type +// description system in ThePEG. DescribeAbstractNoPIOClass describeHerwigMergerBase("Herwig::MergerBase", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Base/MergerBase.h b/MatrixElement/Matchbox/Base/MergerBase.h --- a/MatrixElement/Matchbox/Base/MergerBase.h +++ b/MatrixElement/Matchbox/Base/MergerBase.h @@ -1,100 +1,94 @@ // -*- C++ -*- // // MergerBase.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MergerBase_H #define HERWIG_MergerBase_H // // This is the declaration of the MergerBase class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/MatrixElement/MEBase.h" #include "Herwig/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxXComb.h" #include "MatchboxMEBase.fh" namespace Herwig { using namespace ThePEG; class MergerBase; ThePEG_DECLARE_POINTERS(MergerBase,MergerBasePtr); /** * \ingroup Matchbox * \author Johannes Bellm * * \brief MergerBase is the base class MergingHelpers. * * @see \ref MergerBaseInterfaces "The interfaces" * defined for MergerBase. */ class MergerBase: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MergerBase(); - /** - * The destructor. - */ - virtual ~MergerBase(); /// define the ME region for a particle vector. virtual bool matrixElementRegion(PVector incoming, PVector outcoming, Energy winnerScale, Energy cutscale) const = 0; /// cross section of as given by the merging virtual CrossSection MergingDSigDR() = 0; /// set the current xcomb, called from ME virtual void setXComb( tStdXCombPtr) = 0; /// set the current ME virtual void setME(Ptr::ptr) = 0; /// set kinematics, called from ME virtual void setKinematics() = 0; /// clear kinematics, called from ME virtual void clearKinematics() = 0; /// generate kinematics, called from ME virtual bool generateKinematics( const double * ) = 0; /** * flush all chaches of the subleading nodes. * Note: this is called not from the ME but before the first * kinematics is generated. **/ virtual void flushCaches() = 0; /// return the current maximum legs, the shower should veto virtual size_t maxLegs() const = 0; /// return the current merging scale, virtual Energy mergingScale() const = 0; //@} public: /** * 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(); }; } #endif /* HERWIG_MergerBase_H */ diff --git a/MatrixElement/Matchbox/Base/SubtractedME.cc b/MatrixElement/Matchbox/Base/SubtractedME.cc --- a/MatrixElement/Matchbox/Base/SubtractedME.cc +++ b/MatrixElement/Matchbox/Base/SubtractedME.cc @@ -1,790 +1,788 @@ // -*- C++ -*- // // SubtractedME.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SubtractedME class. // #include "SubtractedME.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Handlers/StdXCombGroup.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" using namespace Herwig; SubtractedME::SubtractedME() : MEGroup(), theRealShowerSubtraction(false), theVirtualShowerSubtraction(false), theLoopSimSubtraction(false) {} -SubtractedME::~SubtractedME() {} - Ptr::tcptr SubtractedME::factory() const { return MatchboxFactory::currentFactory(); } bool SubtractedME::subProcessGroups() const { return (factory()->subProcessGroups() && !showerApproximation()) || factory()->subtractionData() != ""; } Ptr::tptr SubtractedME::showerApproximation() const { return factory()->showerApproximation(); } const vector::ptr>& SubtractedME::borns() const { return theBorns.empty() ? factory()->bornMEs() : theBorns; } bool SubtractedME::verbose() const { return factory()->verbose(); } bool SubtractedME::initVerbose() const { return factory()->initVerbose(); } IBPtr SubtractedME::clone() const { return new_ptr(*this); } IBPtr SubtractedME::fullclone() const { return new_ptr(*this); } StdXCombPtr SubtractedME::makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec& allPBins, tStdXCombPtr newHead, tMEPtr newME) { tMEGroupPtr newMEGroup = dynamic_ptr_cast(newME); if ( !newMEGroup ) newMEGroup = this; Ptr::ptr res = new_ptr(MatchboxXCombGroup(newMaxEnergy, inc, newEventHandler, newSubProcessHandler, newExtractor, newCKKW, newPartonBins, newCuts, newMEGroup, newDiagrams, mir, newHead)); res->build(allPBins); theReal->prepareXComb(*res); if ( factory()->subtractionData() != "" ) { set procs; for ( DiagramVector::const_iterator d = head()->diagrams().begin(); d != head()->diagrams().end(); ++d ) { if ( procs.find((**d).partons()) == procs.end() ) procs.insert((**d).partons()); } for ( set::const_iterator p = procs.begin(); p != procs.end(); ++p ) { for ( size_t i = 0; i < (*p).size(); ++i ) { if ( !(*p)[i]->coloured() ) continue; if ( i > 1 && (*p)[i]->id() == ParticleID::g ) { softHistograms[SoftSubtractionIndex(*p,i)] = SubtractionHistogram(0.00001,1000.); ostringstream fname(""); fname << factory()->subtractionData(); const cPDVector& myproc = SoftSubtractionIndex(*p,i).first; for (cPDVector::const_iterator pp = myproc.begin(); pp != myproc.end(); ++pp) fname << (**pp).PDGName(); fname << "-" << i << "-" << i << "-scatter.dat"; fnamesSoftSubtraction[SoftSubtractionIndex(*p,i)] = fname.str(); if ( theReal->phasespace() ) res->singularLimits().insert(make_pair(i,i)); } for ( size_t j = i+1; j < (*p).size(); ++j ) { if ( !(*p)[j]->coloured() ) continue; long iid = (*p)[i]->id(); long jid = (*p)[j]->id(); if ( i < 2 && j < 2 ) continue; if ( i < 2 && j > 1 ) { if ( abs(iid) < 7 && abs(jid) < 7 && iid != jid ) continue; } if ( i > 1 && j > 1 ) { if ( abs(iid) < 7 && abs(jid) < 7 && iid + jid != 0 ) continue; } bool haveDipole = false; for ( MEVector::const_iterator k = dependent().begin(); k != dependent().end(); ++k ) { const SubtractionDipole& dip = dynamic_cast(**k); if ( ( (size_t)(dip.realEmitter()) == i && (size_t)(dip.realEmission()) == j ) || ( (size_t)(dip.realEmitter()) == j && (size_t)(dip.realEmission()) == i ) ) { haveDipole = true; break; } } if ( !haveDipole ) continue; collinearHistograms[CollinearSubtractionIndex(*p,make_pair(i,j))] = SubtractionHistogram(0.00001,1000.); ostringstream fname(""); fname << factory()->subtractionData(); const cPDVector& myproc = CollinearSubtractionIndex(*p,make_pair(i,j)).first; for (cPDVector::const_iterator pp = myproc.begin(); pp != myproc.end(); ++pp) fname << (**pp).PDGName(); fname << "-" << i << "-" << j << "-scatter.dat"; fnamesCollinearSubtraction[CollinearSubtractionIndex(*p,make_pair(i,j))] = fname.str(); if ( theReal->phasespace() ) res->singularLimits().insert(make_pair(i,j)); } } } } return res; } void SubtractedME::setXComb(tStdXCombPtr xc) { MEGroup::setXComb(xc); lastMatchboxXComb(xc); } MEBase::DiagramVector SubtractedME::dependentDiagrams(const cPDVector& proc, tMEPtr depME) const { Ptr::tptr dipole = dynamic_ptr_cast::tptr>(depME); if ( !dipole ) { throw Exception() << "SubtractedME: A dependent matrix element of SubtractedME " << "has not been derived from SubtractionDipole. " << "Please check the corresponding input file." << Exception::runerror; } return dipole->underlyingBornDiagrams(proc); } vector::ptr> SubtractedME::dipoles() { if ( dependent().empty() ) getDipoles(); vector::ptr> res; for ( MEVector::const_iterator k = dependent().begin(); k != dependent().end(); ++k ) res.push_back(dynamic_ptr_cast::ptr>(*k)); return res; } void SubtractedME::getDipoles() { if ( !dependent().empty() ) return; Ptr::tptr real = dynamic_ptr_cast::tptr>(head()); if ( borns().empty() || !real ) throw Exception() << "SubtractedME: The SubtractedME '" << name() << "' could not generate " << "subtraction terms for the real emission " << "matrix element '" << real->name() << "'. " << "Please check the corresponding input file." << Exception::runerror; Ptr::ptr myRealEmissionME = real->cloneMe(); ostringstream pname; pname << fullName() << "/" << myRealEmissionME->name(); if ( ! (generator()->preinitRegister(myRealEmissionME,pname.str()) ) ) throw Exception() << "SubtractedME: Matrix element " << pname.str() << " already existing." << Exception::runerror; myRealEmissionME->cloneDependencies(pname.str()); head(myRealEmissionME); real = myRealEmissionME; dependent().clear(); vector::ptr> genDipoles = real->getDipoles(DipoleRepository::dipoles(factory()->dipoleSet()),borns()); if ( factory()->subtractionData() != "" ) { for ( vector::ptr>::const_iterator d = genDipoles.begin(); d != genDipoles.end(); ++d ) (**d).doTestSubtraction(); } if ( genDipoles.empty() && factory()->initVerbose() ) { // probably finite real contribution, but warn generator()->log() << "\nWarning: No subtraction dipoles could be found for the process:\n"; generator()->log() << real->subProcess().legs[0]->PDGName() << " " << real->subProcess().legs[1]->PDGName() << " -> "; for ( PDVector::const_iterator p = real->subProcess().legs.begin() + 2; p != real->subProcess().legs.end(); ++p ) generator()->log() << (**p).PDGName() << " "; generator()->log() << "\n" << flush; generator()->log() << "Assuming finite tree-level O(alphaS) correction.\n"; } dependent().resize(genDipoles.size()); copy(genDipoles.begin(),genDipoles.end(),dependent().begin()); if ( !factory()->reweighters().empty() ) { for ( MEVector::const_iterator d = dependent().begin(); d != dependent().end(); ++d ) { for ( vector::const_iterator rw = factory()->reweighters().begin(); rw != factory()->reweighters().end(); ++rw ) (**d).addReweighter(*rw); } } if ( !factory()->preweighters().empty() ) { for ( MEVector::const_iterator d = dependent().begin(); d != dependent().end(); ++d ) { for ( vector::const_iterator rw = factory()->preweighters().begin(); rw != factory()->preweighters().end(); ++rw ) (**d).addPreweighter(*rw); } } } void SubtractedME::cloneRealME(const string& prefix) { theReal = dynamic_ptr_cast::tptr>(head()); if ( theReal ) { Ptr::ptr myRealEmissionME = theReal->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << myRealEmissionME->name(); if ( ! (generator()->preinitRegister(myRealEmissionME,pname.str()) ) ) throw Exception() << "SubtractedME: Matrix element " << pname.str() << " already existing." << Exception::runerror; myRealEmissionME->cloneDependencies(pname.str()); theReal = myRealEmissionME; } head(theReal); } void SubtractedME::cloneDipoles(const string& prefix) { MEVector dipMEs; for ( MEVector::const_iterator m = dependent().begin(); m != dependent().end(); ++m ) { Ptr::tptr dip = dynamic_ptr_cast::tptr>(*m); assert(dip); Ptr::ptr cloned = dip->cloneMe(); ostringstream pname; pname << (prefix == "" ? fullName() : prefix) << "/" << cloned->name(); if ( ! (generator()->preinitRegister(cloned,pname.str()) ) ) throw Exception() << "SubtractedME: Subtraction dipole " << pname.str() << " already existing." << Exception::runerror; cloned->cloneDependencies(pname.str()); dipMEs.push_back(cloned); } dependent() = dipMEs; } vector::ptr> SubtractedME::splitDipoles(const cPDVector& born) { vector::ptr> dips = dipoles(); vector::ptr> res; for ( vector::ptr>::iterator d = dips.begin(); d != dips.end(); ++d ) { for ( DiagramVector::const_iterator p = (**d).underlyingBornME()->diagrams().begin(); p != (**d).underlyingBornME()->diagrams().end(); ++p ) if ( born == (**p).partons() ) { res.push_back(*d); break; } } return res; } void SubtractedME::doRealEmissionScales() { for ( MEVector::const_iterator m = dependent().begin(); m != dependent().end(); ++m ) { Ptr::tptr dip = dynamic_ptr_cast::tptr>(*m); assert(dip); dip->doRealEmissionScales(); } } void SubtractedME::doRealShowerSubtraction() { theRealShowerSubtraction = true; for ( MEVector::const_iterator m = dependent().begin(); m != dependent().end(); ++m ) { Ptr::tptr dip = dynamic_ptr_cast::tptr>(*m); assert(dip); dip->showerApproximation(showerApproximation()); dip->doRealShowerSubtraction(); } } void SubtractedME::doVirtualShowerSubtraction() { theVirtualShowerSubtraction = true; for ( MEVector::const_iterator m = dependent().begin(); m != dependent().end(); ++m ) { Ptr::tptr dip = dynamic_ptr_cast::tptr>(*m); assert(dip); dip->showerApproximation(showerApproximation()); dip->doVirtualShowerSubtraction(); } } void SubtractedME::doLoopSimSubtraction() { theLoopSimSubtraction = true; for ( MEVector::const_iterator m = dependent().begin(); m != dependent().end(); ++m ) { Ptr::tptr dip = dynamic_ptr_cast::tptr>(*m); assert(dip); dip->showerApproximation(showerApproximation()); dip->doLoopSimSubtraction(); } } void SubtractedME::setVetoScales(tSubProPtr) const {} void SubtractedME::fillProjectors() { if ( !virtualShowerSubtraction() && !loopSimSubtraction() ) return; Ptr::tptr group = dynamic_ptr_cast::tptr>(lastXCombPtr()); for ( vector::const_iterator d = group->dependent().begin(); d != group->dependent().end(); ++d ) { if ( !(**d).matrixElement()->apply() || !(**d).kinematicsGenerated() ) continue; if ( (**d).willPassCuts() && (**d).lastMECrossSection()/picobarn != 0.0 ) { lastXCombPtr()->projectors().insert(abs((**d).cutWeight()*(**d).lastMECrossSection()/picobarn),*d);// } } } double SubtractedME::reweightHead(const vector&) { if ( showerApproximation() ) { if ( realShowerSubtraction() ) return 1.; if ( virtualShowerSubtraction() || loopSimSubtraction() ) return 0.; } return 1.; } double SubtractedME::reweightDependent(tStdXCombPtr xc, const vector& dep) { if ( showerApproximation() ) { if ( realShowerSubtraction() ) return 1.0; if ( virtualShowerSubtraction() || loopSimSubtraction() ) { if ( !lastXComb().lastProjector() ) return 0.0; if ( xc != lastXComb().lastProjector() ) return 0.0; double invPAlpha = 0.; for ( vector::const_iterator d = dep.begin(); d != dep.end(); ++d ) { if ( !(**d).matrixElement()->apply() || !(**d).kinematicsGenerated() ) continue; if ( (**d).willPassCuts() && (**d).lastMECrossSection()/picobarn != 0.0 ) { invPAlpha += abs((**d).cutWeight()*(**d).lastMECrossSection()/picobarn); } } assert(invPAlpha != 0.0 && xc->cutWeight() != 0.0 && xc->lastMECrossSection()/picobarn != 0.0); double palpha = abs((xc->cutWeight())*(xc->lastMECrossSection()/picobarn))/invPAlpha; return 1./palpha; } } return 1.; } void SubtractedME::doinit() { // has been deactivated by the factory if ( !head() ) { MEBase::doinit(); return; } theReal = dynamic_ptr_cast::tptr>(head()); if ( theReal ) { getDipoles(); } for ( vector::ptr>::iterator b = theBorns.begin(); b != theBorns.end(); ++b ) (**b).init(); if ( initVerbose() ) print(Repository::clog()); MEGroup::doinit(); } void SubtractedME::doinitrun() { // has been deactivated by the factory if ( !head() ) { MEBase::doinitrun(); return; } theReal = dynamic_ptr_cast::tptr>(head()); for ( vector::ptr>::iterator b = theBorns.begin(); b != theBorns.end(); ++b ) (**b).initrun(); MEGroup::doinitrun(); } void SubtractedME::dofinish() { // has been deactivated by the factory if ( !head() ) { MEBase::dofinish(); return; } MEGroup::dofinish(); for ( map:: const_iterator b = collinearHistograms.begin(); b != collinearHistograms.end(); ++b ) { b->second.dump(factory()->subtractionData(), factory()->subtractionPlotType(), factory()->subtractionScatterPlot(), b->first.first, b->first.second.first, b->first.second.second); } for ( map:: const_iterator b = softHistograms.begin(); b != softHistograms.end(); ++b ) { b->second.dump(factory()->subtractionData(), factory()->subtractionPlotType(), factory()->subtractionScatterPlot(), b->first.first, b->first.second, b->first.second); } } void SubtractedME::print(ostream& os) const { os << "--- SubtractedME setup ---------------------------------------------------------\n"; os << " '" << name() << "' subtracting real emission\n '" << head()->name() << "' using the dipoles:\n"; for ( MEVector::const_iterator d = dependent().begin(); d != dependent().end(); ++d ) dynamic_ptr_cast::tptr>(*d)->print(os); os << "--------------------------------------------------------------------------------\n"; os << flush; } void SubtractedME::printLastEvent(ostream& os) const { os << "--- SubtractedME last event information ----------------------------------------\n"; os << " for subtracted matrix element '" << name() << "'\n"; os << " real emission event information:\n"; dynamic_ptr_cast::tptr>(head())->printLastEvent(os); os << " dipoles event information:\n"; for ( MEVector::const_iterator d = dependent().begin(); d != dependent().end(); ++d ) dynamic_ptr_cast::tptr>(*d)->printLastEvent(os); os << "--- end SubtractedME last event information ------------------------------------\n\n\n"; os << flush; } void SubtractedME::lastEventStatistics() { MEGroup::lastEventStatistics(); if ( !generator() ) return; /* if ( verbose() ) printLastEvent(generator()->log()); */ if ( !collinearHistograms.empty() ) lastEventSubtraction(); } SubtractedME::SubtractionHistogram:: SubtractionHistogram(double low, double up, unsigned int nbins) : lower(low) { nbins = nbins + 1; double c = log10(up/low) / (nbins-1.); for ( unsigned int k = 1; k < nbins; ++k ) { bins[low*pow(10.0,k*c)] = make_pair(Constants::MaxDouble,0.); } } void SubtractedME::SubtractionHistogram::persistentOutput(PersistentOStream& os) const { os << lower << bins; } void SubtractedME::SubtractionHistogram::persistentInput(PersistentIStream& is) { is >> lower >> bins; } void SubtractedME::SubtractionHistogram:: dump(const std::string& prefix, const int& plottype, const bool& scatterplot, const cPDVector& proc, int i, int j) const { bool bbmin = true; double bmin = bins.begin()->first; double bmax = bins.begin()->first; ostringstream fname(""); for ( cPDVector::const_iterator p = proc.begin(); p != proc.end(); ++p ) fname << (**p).PDGName(); fname << "-" << i << "-" << j; ofstream out((prefix+fname.str()+".dat").c_str()); for ( map >::const_iterator b = bins.begin(); b != bins.end(); ++b ) { map >::const_iterator bp = b; if (bp== bins.begin())continue; --bp; if ( b->second.first != Constants::MaxDouble || b->second.second != 0.0 ) { if ( b != bins.begin() ){ out << bp->first; if (bbmin){ bmin = bp->first; bbmin = false; } } else { out << lower; if (bbmin){ bmin = lower; bbmin = false; } } bmax = b->first; out << " " << b->first << " " << b->second.first << " " << b->second.second << "\n" << flush; } } double xmin = pow(10.0, floor(log10(bmin))); double xmax = pow(10.0, ceil(log10(bmax))); ofstream gpout((prefix+fname.str()+".gp").c_str()); gpout << "set terminal epslatex color solid\n" << "set output '" << fname.str() << "-plot.tex'\n" << "set format x '$10^{%T}$'\n" << "set logscale x\n" << "set xrange [" << xmin << ":" << xmax << "]\n"; if ( i != j ) { gpout << "set xlabel '$\\sqrt{s_{" << i << j << "}}/{\\rm GeV}$'\n"; } else { gpout << "set xlabel '$E_{" << i << "}/{\\rm GeV}$'\n"; } if (plottype == 1){ gpout << "set size 0.5,0.6\n" << "set yrange [0:2]\n"; gpout << "plot 1 w lines lc rgbcolor \"#DDDDDD\" notitle, '" << fname.str() << ".dat' u (($1+$2)/2.):3:($4 < 4. ? $4 : 4.) w filledcurves lc rgbcolor \"#00AACC\" t '$"; } else if (plottype == 2){ gpout << "set key left top Left reverse\n" << "set logscale y\n" << "set format y '$10^{%T}$'\n" << "set size 0.7,0.8\n" << "set yrange [1e-6:1e1]\n" << "set ylabel '$\\max\\left\\{\\left|\\mathcal{D}-\\mathcal{M}\\right|/\\left|\\mathcal{M}\\right|\\right\\}$'\n" << "unset bars\n"; gpout << "plot '"; if (scatterplot) gpout << fname.str() << "-scatter.dat' w points pt 7 ps 0.5 lc rgbcolor \"#00AACC\" not, \\\n'"; gpout << fname.str() << ".dat' u (($1+$2)/2.):4 w lines lw 4 lc rgbcolor \"#00AACC\" t '$"; } for ( size_t k = 0; k < proc.size(); k++ ) { if ( k == 2 ) gpout << "\\to "; gpout << (proc[k]->id() < 0 ? "\\bar{" : "") << (proc[k]->id() < 0 ? proc[k]->CC()->PDGName() : proc[k]->PDGName()) << (proc[k]->id() < 0 ? "}" : "") << " "; } gpout << "$'\n"; gpout << "reset\n"; } void SubtractedME::lastEventSubtraction() { tStdXCombGroupPtr xc = dynamic_ptr_cast(lastXCombPtr()); CrossSection xcme2 = xc->lastHeadCrossSection(); CrossSection xcdip = ZERO; for ( vector::const_iterator d = xc->dependent().begin(); d != xc->dependent().end(); ++d ) { if ( !(*d) ) continue; if ( !(**d).matrixElement()->apply() ) continue; if ( !(**d).willPassCuts() ) continue; xcdip += (**d).lastCrossSection(); } // want a real emission safely above the cut if ( xc->cutWeight() < 1.0 ) return; double delta; if (factory()->subtractionPlotType() == 2) delta = abs(xcdip+xcme2)/abs(xcme2); else delta = abs(xcdip)/abs(xcme2); if ( theReal->phasespace() ) { size_t i = lastSingularLimit()->first; size_t j = lastSingularLimit()->second; if ( i == j && softHistograms.find(SoftSubtractionIndex(head()->mePartonData(),i)) != softHistograms.end() ) { softHistograms[SoftSubtractionIndex(head()->mePartonData(),i)]. book(meMomenta()[i].t()/GeV,delta); if ( factory()->subtractionScatterPlot() ){ ofstream outstream((fnamesSoftSubtraction[SoftSubtractionIndex(head()->mePartonData(),i)]).c_str(),ofstream::app); outstream << meMomenta()[i].t()/GeV << " " << delta << "\n"; } } if ( i != j && collinearHistograms.find(CollinearSubtractionIndex(head()->mePartonData(),make_pair(i,j))) != collinearHistograms.end() ) { double s = sqrt(2.*meMomenta()[i]*meMomenta()[j])/GeV; collinearHistograms[CollinearSubtractionIndex(head()->mePartonData(),make_pair(i,j))]. book(s,delta); if ( factory()->subtractionScatterPlot() ){ ofstream outstream((fnamesCollinearSubtraction[CollinearSubtractionIndex(head()->mePartonData(),make_pair(i,j))]).c_str(),ofstream::app); outstream << s << " " << delta << "\n"; } } return; } for ( size_t i = 0; i < meMomenta().size(); ++i ) { if ( i > 1 ) { if ( softHistograms.find(SoftSubtractionIndex(head()->mePartonData(),i)) != softHistograms.end() ) { softHistograms[SoftSubtractionIndex(head()->mePartonData(),i)]. book(meMomenta()[i].t()/GeV,delta); if ( factory()->subtractionScatterPlot() ){ ofstream outstream((fnamesSoftSubtraction[SoftSubtractionIndex(head()->mePartonData(),i)]).c_str(),ofstream::app); outstream << meMomenta()[i].t()/GeV << " " << delta << "\n"; } } } for ( size_t j = i+1; j < meMomenta().size(); ++j ) { if ( collinearHistograms.find(CollinearSubtractionIndex(head()->mePartonData(),make_pair(i,j))) == collinearHistograms.end() ) continue; double s = sqrt(2.*meMomenta()[i]*meMomenta()[j])/GeV; collinearHistograms[CollinearSubtractionIndex(head()->mePartonData(),make_pair(i,j))]. book(s,delta); if ( factory()->subtractionScatterPlot() ){ ofstream outstream((fnamesCollinearSubtraction[CollinearSubtractionIndex(head()->mePartonData(),make_pair(i,j))]).c_str(),ofstream::app); outstream << s << " " << delta << "\n"; } } } } void SubtractedME::persistentOutput(PersistentOStream & os) const { os << theLastXComb << theBorns << theReal << collinearHistograms << softHistograms << fnamesSoftSubtraction << theRealShowerSubtraction << theVirtualShowerSubtraction << theLoopSimSubtraction; } void SubtractedME::persistentInput(PersistentIStream & is, int) { is >> theLastXComb >> theBorns >> theReal >> collinearHistograms >> softHistograms >> fnamesSoftSubtraction >> theRealShowerSubtraction >> theVirtualShowerSubtraction >> theLoopSimSubtraction; lastMatchboxXComb(theLastXComb); } void SubtractedME::Init() { static ClassDocumentation documentation ("SubtractedME represents a subtracted real emission matrix element."); } // *** 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 describeHerwigSubtractedME("Herwig::SubtractedME", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Base/SubtractedME.h b/MatrixElement/Matchbox/Base/SubtractedME.h --- a/MatrixElement/Matchbox/Base/SubtractedME.h +++ b/MatrixElement/Matchbox/Base/SubtractedME.h @@ -1,536 +1,528 @@ // -*- C++ -*- // // SubtractedME.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_SubtractedME_H #define HERWIG_SubtractedME_H // // This is the declaration of the SubtractedME class. // #include "ThePEG/MatrixElement/MEGroup.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.fh" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief SubtractedME represents a subtracted real emission matrix element. * * @see \ref SubtractedMEInterfaces "The interfaces" * defined for SubtractedME. */ class SubtractedME: public MEGroup, public LastMatchboxXCombInfo { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ SubtractedME(); - /** - * The destructor. - */ - virtual ~SubtractedME(); - //@} - public: /** * Return the factory which produced this matrix element */ Ptr::tcptr factory() const; /** @name Phasespace and subprocess information */ //@{ /** * For the given event generation setup return an xcomb object * appropriate to this matrix element. */ virtual StdXCombPtr makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec& allPBins, tStdXCombPtr newHead = tStdXCombPtr(), tMEPtr newME = tMEPtr()); /** * Set the XComb object to be used in the next call to * generateKinematics() and dSigHatDR(). */ virtual void setXComb(tStdXCombPtr); /** * Return true, if the same additional random numbers * should be presented to any of the dependent * matrix elements. */ virtual bool uniformAdditional() const { return true; } /** * Return true, if the XComb steering this matrix element * should keep track of the random numbers used to generate * the last phase space point */ virtual bool keepRandomNumbers() const { return true; } /** * Given a process from the head matrix element, * return a list of diagrams which should be considered for * the given dependent matrix element. */ virtual MEBase::DiagramVector dependentDiagrams(const cPDVector& proc, tMEPtr depME) const; /** * Return true, if SubProcessGroups should be * setup from this MEGroup. If not, a single SubProcess * is constructed from the data provided by the * head matrix element. */ virtual bool subProcessGroups() const; /** * Return true, if one of the dependent subprocesses should be * constructed in place of the one driven by the head matrix element * or a full subprocess group. */ virtual bool selectDependentSubProcess() const { return false; } /** * Fill the projectors object of xcombs to choose subprocesses * different than the one currently integrated. */ virtual void fillProjectors(); /** * Return true, if projectors will be used */ virtual bool willProject() const { return virtualShowerSubtraction() || loopSimSubtraction(); } /** * Return true, if this MEGroup will reweight the contributing cross * sections. */ virtual bool groupReweighted() const { return showerApproximation(); } /** * Reweight the head cross section */ virtual double reweightHead(const vector&); /** * Reweight the dependent cross section */ virtual double reweightDependent(tStdXCombPtr, const vector&); /** * Switch on or off that scales should be calculated from real emission kinematics */ void doRealEmissionScales(); //@} /** @name Methods relevant to matching */ //@{ /** * Inform this matrix element that a new phase space * point is about to be generated, so all caches should * be flushed. */ virtual void flushCaches() { MEGroup::flushCaches(); if ( showerApproximation() ) showerApproximation()->resetBelowCutoff(); } /** * Return the shower approximation. */ Ptr::tptr showerApproximation() const; /** * Indicate that the shower real emission contribution should be subtracted. */ void doRealShowerSubtraction(); /** * Return true, if the shower real emission contribution should be subtracted. */ bool realShowerSubtraction() const { return theRealShowerSubtraction; } /** * Indicate that the shower virtual contribution should be subtracted. */ void doVirtualShowerSubtraction(); /** * Return true, if the shower virtual contribution should be subtracted. */ bool virtualShowerSubtraction() const { return theVirtualShowerSubtraction; } /** * Indicate that the loopsim matched virtual contribution should be subtracted. */ void doLoopSimSubtraction(); /** * Return true, if the loopsim matched virtual contribution should be subtracted. */ bool loopSimSubtraction() const { return theLoopSimSubtraction; } /** * Return true, if this configuration of cross sections should not * be included due to their relative magnitude. Arguments are head * cross section and dependent cross section, including all * reweights. */ virtual bool discard(const CrossSection&, const CrossSection&) const { return false; } //@} /** @name Matrix element and dipole information */ //@{ /** * Return the subtraction dipoles. */ vector::ptr> dipoles(); /** * Return the underlying born matrix elements. */ const vector::ptr>& borns() const; /** * Access the underlying born matrix elements, * overriding the ones contained in the factory object. */ void setBorns(const vector::ptr>& newBorns) { theBorns = newBorns; } /** * Build up dipoles needed. */ void getDipoles(); /** * Clone all dipoles. */ void cloneDipoles(const string& prefix = ""); /** * Clone the real emission matrix element. */ void cloneRealME(const string& prefix = ""); /** * Clone all dependencies. */ void cloneDependencies(const string& prefix = "") { cloneDipoles(prefix); cloneRealME(prefix); } /** * Return all dipoles matching the given Born process */ vector::ptr> splitDipoles(const cPDVector&); //@} /** @name Veto scale settings */ //@{ /** * Set veto scales on the particles at the given * SubProcess which has been generated using this * matrix element. */ virtual void setVetoScales(tSubProPtr) const; //@} /** @name Diagnostic information */ //@{ /** * Dump the setup to an ostream */ void print(ostream&) const; /** * Collect information on the last evaluated phasespace * point for verification or debugging purposes. This * only called, if the StdXCombGroup did accumulate * a non-zero cross section from this ME group. */ virtual void lastEventStatistics(); /** * Print debug information on the last event */ void printLastEvent(ostream&) const; /** * Check the subtraction for the last event */ void lastEventSubtraction(); /** * Return true, if verbose */ bool verbose() const; /** * Return true, if verbose */ bool initVerbose() const; //@} /** @name Setup of Subtracted ME objects */ //@{ /** * Return true if this object needs to be initialized before all * other objects (except those for which this function also returns * true). This default version always returns false, but subclasses * may override it to return true. */ virtual bool preInitialize() const { return true; } /** * Simple envelope histogram to keep track of subtraction */ struct SubtractionHistogram { /** * The lower bound */ double lower; /** * The bins, indexed by upper bound. */ map > bins; /** * Constructor */ SubtractionHistogram(double low = 0.001, double up = 10., unsigned int nbins = 100); /** * Book an event. */ void book(double inv, double diff) { map >::iterator b = bins.upper_bound(inv); if ( b == bins.end() ) return; b->second.first = min(b->second.first,diff); b->second.second = max(b->second.second,diff); } /** * Write to file given name and invariant. */ void dump(const std::string& prefix, const int& plottype, const bool& scatterplot, const cPDVector& proc, int i, int j) const; /** * Write to persistent ostream */ void persistentOutput(PersistentOStream&) const; /** * Read from persistent istream */ void persistentInput(PersistentIStream&); }; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The underlying born matrix elements, overriding the ones * contained in the factory object. */ vector::ptr> theBorns; /** * Pointer to the head real emission ME casted to a MatchboxMEBase * object. */ Ptr::ptr theReal; /** * Define the key for the collinear subtraction data. */ typedef pair > CollinearSubtractionIndex; /** * subtraction data for collinear limits. */ map collinearHistograms; /** * names of files to which subtraction data is written for all phase space points individually */ map fnamesCollinearSubtraction; /** * Define the key for the soft subtraction data. */ typedef pair SoftSubtractionIndex; /** * subtraction data for soft limits. */ map softHistograms; /** * names of files to which subtraction data is written for all phase space points individually */ map fnamesSoftSubtraction; /** * True, if the shower real emission contribution should be subtracted. */ bool theRealShowerSubtraction; /** * True, if the shower virtual contribution should be subtracted. */ bool theVirtualShowerSubtraction; /** * True, if the loopsim matched virtual contribution should be subtracted. */ bool theLoopSimSubtraction; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SubtractedME & operator=(const SubtractedME &) = delete; }; inline PersistentOStream& operator<<(PersistentOStream& os, const SubtractedME::SubtractionHistogram& h) { h.persistentOutput(os); return os; } inline PersistentIStream& operator>>(PersistentIStream& is, SubtractedME::SubtractionHistogram& h) { h.persistentInput(is); return is; } } #endif /* HERWIG_SubtractedME_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbar.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbar.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbar.cc @@ -1,169 +1,167 @@ // -*- C++ -*- // // MatchboxAmplitudeggttbar.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudeggttbar class. // #include "MatchboxAmplitudeggttbar.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudeggttbar::MatchboxAmplitudeggttbar() {} -MatchboxAmplitudeggttbar::~MatchboxAmplitudeggttbar() {} - IBPtr MatchboxAmplitudeggttbar::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudeggttbar::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudeggttbar::setupParams(map &MGParams){ // create parameter map for adapted Madgraph amplitude to use MGParams["aS"] = SM().alphaS(); MGParams["MZ"] = getParticleData(ParticleID::Z0) -> hardProcessMass()/GeV; MGParams["MW"] = getParticleData(ParticleID::Wplus) -> hardProcessMass()/GeV; MGParams["MH"] = getParticleData(ParticleID::h0) -> hardProcessMass()/GeV; MGParams["WW"] = getParticleData(ParticleID::Wplus) ->hardProcessWidth()/GeV; MGParams["WZ"] = getParticleData(ParticleID::Z0) ->hardProcessWidth()/GeV; MGParams["WH"] = getParticleData(ParticleID::h0) ->hardProcessWidth()/GeV; MGParams["MT"] = getParticleData(ParticleID::t) -> hardProcessMass()/GeV; MGParams["MB"] = getParticleData(ParticleID::b) -> hardProcessMass()/GeV; MGParams["WT"] = getParticleData(ParticleID::t) ->hardProcessWidth()/GeV; MGParams["WB"] = getParticleData(ParticleID::b) ->hardProcessWidth()/GeV; MGParams["MTA"] = getParticleData(ParticleID::tauminus)-> hardProcessMass()/GeV; MGParams["GF"] = SM().fermiConstant()*GeV2; MGParams["aEWM1"] = 1./SM().alphaEMMZ(); return; } void MatchboxAmplitudeggttbar::doinit() { setupParams(MGParams_); MatchboxAmplitude::doinit(); nPoints(4); } void MatchboxAmplitudeggttbar::doinitrun() { setupParams(MGParams_); MatchboxAmplitude::doinitrun(); nPoints(4); } bool MatchboxAmplitudeggttbar::canHandle(const PDVector& proc) const { // check process is gg > ttbar if ( proc.size() != 4 ) return false; PDVector xproc = proc; PDVector::iterator top = xproc.begin(); long topId = 0; for ( ; top != xproc.end(); ++top ) if ( (**top).id() == 6 ) { break; } if ( top == xproc.end() ) return false; topId = (**top).id(); xproc.erase(top); PDVector::iterator antiTop = xproc.begin(); for ( ; antiTop != xproc.end(); ++antiTop ) if ( (**antiTop).id() == -topId ) { break; } if ( antiTop == xproc.end() ) return false; xproc.erase(antiTop); return (xproc[0]->id()==21 && xproc[1]->id()==21); } void MatchboxAmplitudeggttbar::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); momentum(0,amplitudeMomentum(0)); momentum(1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudeggttbar::evaluate(size_t a, const vector& hel, Complex& largeN) { // set up momenta to pass into Madgraph amplitude vector p; p.push_back(mom0); p.push_back(mom1); p.push_back(mom2); p.push_back(mom3); for (int ip=0; ip<4; ++ip){ p[ip][0] = abs(momentum(ip).e())<1.e-13 ? 0.0:double(momentum(ip).e()*amplitudeScale()/GeV); p[ip][1] = abs(momentum(ip).x())<1.e-13 ? 0.0:double(momentum(ip).x()*amplitudeScale()/GeV); p[ip][2] = abs(momentum(ip).y())<1.e-13 ? 0.0:double(momentum(ip).y()*amplitudeScale()/GeV); p[ip][3] = abs(momentum(ip).z())<1.e-13 ? 0.0:double(momentum(ip).z()*amplitudeScale()/GeV); } // calculate amplitudes vector > amplitudes; MG_gg2ttx process; process.initProc(MGParams_); process.setMomenta(p); process.sigmaKin(amplitudes, hel); complex matrixElement; complex i = complex (0, 1); // calculate colour flows if (a==0) matrixElement = 0.; else if (a==1) matrixElement = i*amplitudes[0] - amplitudes[1]; else if (a==2) matrixElement =-i*amplitudes[0] - amplitudes[2]; else assert(false); largeN = matrixElement; return matrixElement; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudeggttbar::persistentOutput(PersistentOStream &) const {} void MatchboxAmplitudeggttbar::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxAmplitudeggttbar("Herwig::MatchboxAmplitudeggttbar", "HwMatchboxBuiltin.so"); void MatchboxAmplitudeggttbar::Init() { static ClassDocumentation documentation ("MatchboxAmplitudeggttbar"); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbar.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbar.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbar.h @@ -1,201 +1,193 @@ // -*- C++ -*- // // MatchboxAmplitudeggttbar.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudeggttbar_H #define Herwig_MatchboxAmplitudeggttbar_H // // This is the declaration of the MatchboxAmplitudeggttbar class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" #include "MG_gg2ttx.h" #include "HelAmps_sm.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Alix Wilcock * * \brief MatchboxAmplitudeggttbar */ class MatchboxAmplitudeggttbar: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudeggttbar(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudeggttbar(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const {return 2; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 0; } /** * Return true, if this amplitude will not require colour correlations. */ virtual bool noCorrelations() const { return false; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudeggttbar & operator=(const MatchboxAmplitudeggttbar &) = delete; /** * Containers for external particle momenta */ double mom0 [4]; double mom1 [4]; double mom2 [4]; double mom3 [4]; /** * Fill MGParams_ with Herwig values of parameters */ void setupParams(map & MGParams); /** * Stores parameters needed in MG_process */ map MGParams_; }; } #endif /* Herwig_MatchboxAmplitudeggttbar_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbarg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbarg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbarg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbarg.cc @@ -1,198 +1,196 @@ // -*- C++ -*- // // MatchboxAmplitudeggttbarg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudeggttbarg class. // #include "MatchboxAmplitudeggttbarg.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudeggttbarg::MatchboxAmplitudeggttbarg() {} -MatchboxAmplitudeggttbarg::~MatchboxAmplitudeggttbarg() {} - IBPtr MatchboxAmplitudeggttbarg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudeggttbarg::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudeggttbarg::setupParams(map &MGParams){ // create parameter map for adapted Madgraph amplitude to use MGParams["aS"] = SM().alphaS(); MGParams["MZ"] = getParticleData(ParticleID::Z0) -> hardProcessMass()/GeV; MGParams["MW"] = getParticleData(ParticleID::Wplus) -> hardProcessMass()/GeV; MGParams["MH"] = getParticleData(ParticleID::h0) -> hardProcessMass()/GeV; MGParams["WW"] = getParticleData(ParticleID::Wplus) ->hardProcessWidth()/GeV; MGParams["WZ"] = getParticleData(ParticleID::Z0) ->hardProcessWidth()/GeV; MGParams["WH"] = getParticleData(ParticleID::h0) ->hardProcessWidth()/GeV; MGParams["MT"] = getParticleData(ParticleID::t) -> hardProcessMass()/GeV; MGParams["MB"] = getParticleData(ParticleID::b) -> hardProcessMass()/GeV; MGParams["WT"] = getParticleData(ParticleID::t) ->hardProcessWidth()/GeV; MGParams["WB"] = getParticleData(ParticleID::b) ->hardProcessWidth()/GeV; MGParams["MTA"] = getParticleData(ParticleID::tauminus)-> hardProcessMass()/GeV; MGParams["GF"] = SM().fermiConstant()*GeV2; MGParams["aEWM1"] = 1./SM().alphaEMMZ(); return; } void MatchboxAmplitudeggttbarg::doinit() { setupParams(MGParams_); MatchboxAmplitude::doinit(); nPoints(5); } void MatchboxAmplitudeggttbarg::doinitrun() { setupParams(MGParams_); MatchboxAmplitude::doinitrun(); nPoints(5); } bool MatchboxAmplitudeggttbarg::canHandle(const PDVector& proc) const { // check process is gg > ttbarg if ( proc.size() != 5 ) return false; PDVector xproc = proc; PDVector::iterator top = xproc.begin(); long topId = 0; for ( ; top != xproc.end(); ++top ) if ( (**top).id() == 6 ) { break; } if ( top == xproc.end() ) return false; topId = (**top).id(); xproc.erase(top); PDVector::iterator antiTop = xproc.begin(); for ( ; antiTop != xproc.end(); ++antiTop ) if ( (**antiTop).id() == -topId ) { break; } if ( antiTop == xproc.end() ) return false; xproc.erase(antiTop); if ( xproc.size() != 3 ) return false; return (xproc[0]->id() == 21 && xproc[1]->id() == 21 && xproc[2]->id() == 21); } void MatchboxAmplitudeggttbarg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); momentum(0,amplitudeMomentum(0)); momentum(1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); momentum(4,amplitudeMomentum(4)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudeggttbarg::evaluate(size_t a, const vector& hel, Complex& largeN) { // set up momenta to pass into Madgraph amplitude vector p; p.push_back(mom0); p.push_back(mom1); p.push_back(mom2); p.push_back(mom3); p.push_back(mom4); for (int ip=0; ip<5; ++ip){ p[ip][0] = abs(momentum(ip).e())<1.e-13 ? 0.0:double(momentum(ip).e()*amplitudeScale()/GeV); p[ip][1] = abs(momentum(ip).x())<1.e-13 ? 0.0:double(momentum(ip).x()*amplitudeScale()/GeV); p[ip][2] = abs(momentum(ip).y())<1.e-13 ? 0.0:double(momentum(ip).y()*amplitudeScale()/GeV); p[ip][3] = abs(momentum(ip).z())<1.e-13 ? 0.0:double(momentum(ip).z()*amplitudeScale()/GeV); } // calculate amplitudes vector > amplitudes; MG_gg2ttxg process; double factor=lastSHat()/GeV2; process.initProc(MGParams_); process.setMomenta(p); process.sigmaKin(amplitudes, hel); for (int iamp=0; iamp matrixElement; complex i = complex(0,1); // calculate colour flows if (a<5) matrixElement = 0.; else if (a==5) matrixElement = (-amplitudes[0] - amplitudes[5] + amplitudes[14] - amplitudes[17] + amplitudes[15] + i*(amplitudes[2] + amplitudes[4])); else if (a==6) matrixElement = (-amplitudes[3] + amplitudes[11] - amplitudes[14] - amplitudes[16] - amplitudes[15] + i*(-amplitudes[4] + amplitudes[10])); else if (a==7) matrixElement = ( amplitudes[0] - amplitudes[11] - amplitudes[12] + amplitudes[17] + amplitudes[16] + i*(-amplitudes[2] + amplitudes[9])); else if (a==8) matrixElement = (-amplitudes[6] + amplitudes[11] - amplitudes[14] - amplitudes[16] - amplitudes[15] + i*(amplitudes[7] - amplitudes[9])); else if (a==9) matrixElement = (amplitudes[0] - amplitudes[11] - amplitudes[13] + amplitudes[17] + amplitudes[16] + i*(amplitudes[1] - amplitudes[10])); else if (a==10) matrixElement = (-amplitudes[0] - amplitudes[8] + amplitudes[14] - amplitudes[17] + amplitudes[15] + i*(-amplitudes[1] - amplitudes[7])); else assert(false); largeN = matrixElement; return matrixElement; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudeggttbarg::persistentOutput(PersistentOStream &) const {} void MatchboxAmplitudeggttbarg::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxAmplitudeggttbarg("Herwig::MatchboxAmplitudeggttbarg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudeggttbarg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudeggttbarg"); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbarg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbarg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbarg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeggttbarg.h @@ -1,202 +1,194 @@ // -*- C++ -*- // // MatchboxAmplitudeggttbarg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudeggttbarg_H #define Herwig_MatchboxAmplitudeggttbarg_H // // This is the declaration of the MatchboxAmplitudeggttbarg class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" #include "MG_gg2ttxg.h" #include "HelAmps_sm.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Alix Wilcock * * \brief MatchboxAmplitudeggttbarg */ class MatchboxAmplitudeggttbarg: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudeggttbarg(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudeggttbarg(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const {return 3; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 0; } /** * Return true, if this amplitude will not require colour correlations. */ virtual bool noCorrelations() const { return true; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudeggttbarg & operator=(const MatchboxAmplitudeggttbarg &) = delete; /** * Containers for external particle momenta */ double mom0 [4]; double mom1 [4]; double mom2 [4]; double mom3 [4]; double mom4 [4]; /** * Fill MGParams_ with Herwig values of parameters */ void setupParams(map & MGParams); /** * Stores parameters needed in MG_process */ map MGParams_; }; } #endif /* Herwig_MatchboxAmplitudeggttbarg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbar.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbar.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbar.cc @@ -1,257 +1,253 @@ // -*- C++ -*- // // MatchboxAmplitudehbbbar.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudehbbbar class. // #include "MatchboxAmplitudehbbbar.h" #include "ThePEG/Interface/Parameter.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudehbbbar::MatchboxAmplitudehbbbar() {} -MatchboxAmplitudehbbbar::~MatchboxAmplitudehbbbar() {} - IBPtr MatchboxAmplitudehbbbar::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudehbbbar::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudehbbbar::doinit() { MatchboxAmplitude::doinit(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(3);; } void MatchboxAmplitudehbbbar::doinitrun() { MatchboxAmplitude::doinitrun(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(3); } bool MatchboxAmplitudehbbbar::canHandle(const PDVector& proc) const { if ( proc.size() != 3 ) return false; PDVector xproc = proc; PDVector::iterator q=xproc.begin(); for (; q!=xproc.end(); ++q){ if ((**q).id()==1 || (**q).id()==2 || (**q).id()==3 || (**q).id()==4 || (**q).id()==5) break; } if(q==xproc.end()) return false; int qid = (**q).id(); xproc.erase(q); PDVector::iterator qb=xproc.begin(); for (; qb!=xproc.end(); ++qb){ if ((**qb).id()==-qid) break; } if(qb==xproc.end()) return false; xproc.erase(qb); PDVector::iterator h0=xproc.begin(); if (xproc.size()==1 && (**h0).id()==25) {return true;} return false; } void MatchboxAmplitudehbbbar::prepareAmplitudes(Ptr::tcptr me) { //cout<<"prepare erreicht"<& hel, Complex& largeN) { unsigned int q=0; unsigned int qbar=0; cPDVector x=amplitudePartonData(); /*for (int i=0;i<3;++i){ cout<<"x["<id()<id()!= 25 && x[q]->id()>0 ) break;} //cout<<"x[q]"<id()<<" hel: "<id() ==-x[q]->id()) break;} //cout<<"x[qbar]"<id()<<" hel: "<id(); Energy Mf = 0*GeV; switch(id){ case 1 : Mf = interfaceDMass; /*cout<<"d"<& hel) { Complex res = 0; int q=0; int qbar=0; cPDVector x=amplitudePartonData(); for (;q<3;++q){if (x[q]->id()!= 25 && x[q]->id()>0 ) break;} for (;qbar<3;++qbar){if (x[qbar]->id() ==-x[q]->id()) break;} double gw = sqrt(4*Constants::pi*SM().alphaEMMZ()) / sqrt(SM().sin2ThetaW()); long id=x[q]->id(); Energy Mf = 0*GeV; switch(id){ case 1 : Mf = interfaceDMass; break; case 2 : Mf = interfaceUMass; break; case 3 : Mf = interfaceSMass; break; case 4 : Mf = interfaceCMass; break; case 5 : Mf = interfaceBMass; break; } if (Mf==0*GeV) throw Exception() << "Invalid settings in MatchboxAmplitudehbbbar -- zero fermion mass." << Exception::runerror; double loop = SM().alphaS()*CF/2/Constants::pi ; //one-loop-Factor double bornim = gw*Mf/2/MW; //constant factor from born double real = loop*bornim; Complex c = Complex(real,0.); if (hel[qbar]==-hel[q]&& hel[q]==1){ res = 0; return(res); } if (hel[qbar]==-hel[q]&& hel[q]==-1){ res = 0; return(res); } if (hel[qbar]==hel[q] && hel[q]==1){ res = c*(plusProduct(qbar,q)); return(res); } if (hel[qbar]==hel[q] && hel[q]==-1){ res = c*(minusProduct(qbar,q)); return(res); } assert(false); return 0; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudehbbbar::persistentOutput(PersistentOStream &os) const { os << ounit(interfaceUMass,GeV)<< ounit(interfaceDMass,GeV)<< ounit(interfaceSMass,GeV)<< ounit(interfaceCMass,GeV)<< ounit(interfaceBMass,GeV); } void MatchboxAmplitudehbbbar::persistentInput(PersistentIStream &is, int) { is >> iunit(interfaceUMass,GeV)>> iunit(interfaceDMass,GeV)>> iunit(interfaceSMass,GeV)>> iunit(interfaceCMass,GeV)>> iunit(interfaceBMass,GeV); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMatchboxAmplitudehbbbar("Herwig::MatchboxAmplitudehbbbar", "HwMatchboxBuiltin.so"); void MatchboxAmplitudehbbbar::Init() { static ClassDocumentation documentation ("MatchboxAmplitudehbbbar"); static Parameter interfaceUMass ("interfaceUMass", "The up quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbar::interfaceUMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceDMass ("interfaceDMass", "The down quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbar::interfaceDMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceSMass ("interfaceSMass", "The strange quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbar::interfaceSMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceCMass ("interfaceCMass", "The charm quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbar::interfaceCMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceBMass ("interfaceBMass", "The bottom quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbar::interfaceBMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbar.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbar.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbar.h @@ -1,208 +1,200 @@ // -*- C++ -*- // // MatchboxAmplitudebbbarh.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudehbbbar_H #define Herwig_MatchboxAmplitudehbbbar_H // // This is the declaration of the MatchboxAmplitudehbbbar class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * * * \brief MatchboxAmplitudehbbbar */ class MatchboxAmplitudehbbbar: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudehbbbar(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudehbbbar(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 0; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 1; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return true; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /* * The interfaced up quark mass */ Energy interfaceUMass; /* * The interfaced down quark mass */ Energy interfaceDMass; /* * The interfaced strange quark mass */ Energy interfaceSMass; /* * The interfaced charm quark mass */ Energy interfaceCMass; /* * The interfaced bottom quark mass */ Energy interfaceBMass; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudehbbbar & operator=(const MatchboxAmplitudehbbbar &) = delete; }; } #endif /* Herwig_MatchboxAmplitudehbbbar_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbarg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbarg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbarg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbarg.cc @@ -1,248 +1,244 @@ // -*- C++ -*- // // MatchboxAmplitudehbbbarg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudehbbbarg class. // #include "MatchboxAmplitudehbbbarg.h" #include "ThePEG/Interface/Parameter.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudehbbbarg::MatchboxAmplitudehbbbarg() {} -MatchboxAmplitudehbbbarg::~MatchboxAmplitudehbbbarg() {} - IBPtr MatchboxAmplitudehbbbarg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudehbbbarg::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudehbbbarg::doinit() { MatchboxAmplitude::doinit(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); nPoints(4);; } void MatchboxAmplitudehbbbarg::doinitrun() { MatchboxAmplitude::doinitrun(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); nPoints(4); } bool MatchboxAmplitudehbbbarg::canHandle(const PDVector& proc) const { if ( proc.size() != 4 ) return false; PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); /*for (PDVector::iterator x=xproc.begin(); x!=xproc.end(); ++x){ cout<<"xproc: "<<(**x).id()<::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); /*setupLeptons(0,amplitudeMomentum(0), 1,amplitudeMomentum(1));*/ momentum(0,amplitudeMomentum(0)); momentum(1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudehbbbarg::evaluate(size_t, const vector& hel, Complex& largeN) { unsigned int q=0; unsigned int qbar=0; unsigned int g=0; cPDVector x=amplitudePartonData(); for (;qid()!= 25 && x[q]->id()>0 ) break;} for (;qbarid() ==-x[q]->id()) break;} for (;gid() == 21) break;} double gw = sqrt(4*Constants::pi*SM().alphaEMMZ()) / sqrt(SM().sin2ThetaW()); double gs = sqrt(4*Constants::pi*SM().alphaS()); //double alphaS = SM().alphaS(); //double v= 2*MW/gw/sqrt(mu2()) ; //Auf mu normierter VakuumErwartungswert //double c = gs*alphaS/3/Constants::pi/v; long id=x[q]->id(); Energy Mf = 0*GeV; switch(id){ case 1 : Mf = interfaceDMass; /*cout<<"d"<& hel) { }*/ // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudehbbbarg::persistentOutput(PersistentOStream &os) const { os << ounit(interfaceUMass,GeV)<< ounit(interfaceDMass,GeV)<< ounit(interfaceSMass,GeV)<< ounit(interfaceCMass,GeV)<< ounit(interfaceBMass,GeV); } void MatchboxAmplitudehbbbarg::persistentInput(PersistentIStream &is, int) { is >> iunit(interfaceUMass,GeV)>> iunit(interfaceDMass,GeV)>> iunit(interfaceSMass,GeV)>> iunit(interfaceCMass,GeV)>> iunit(interfaceBMass,GeV); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMatchboxAmplitudehbbbarg("Herwig::MatchboxAmplitudehbbbarg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudehbbbarg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudehbbbarg"); static Parameter interfaceUMass ("interfaceUMass", "The up quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbarg::interfaceUMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceDMass ("interfaceDMass", "The down quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbarg::interfaceDMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceSMass ("interfaceSMass", "The strange quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbarg::interfaceSMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceCMass ("interfaceCMass", "The charm quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbarg::interfaceCMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceBMass ("interfaceBMass", "The bottom quark mass to be used in the amplitude.", &MatchboxAmplitudehbbbarg::interfaceBMass, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbarg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbarg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbarg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehbbbarg.h @@ -1,208 +1,200 @@ // -*- C++ -*- // // MatchboxAmplitudehbbbarg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudehbbbarg_H #define Herwig_MatchboxAmplitudehbbbarg_H // // This is the declaration of the MatchboxAmplitudehbbbarg class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * * * \brief MatchboxAmplitudehbbbarg */ class MatchboxAmplitudehbbbarg: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudehbbbarg(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudehbbbarg(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 1; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 1; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return true; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ //virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /* * The interfaced up quark mass */ Energy interfaceUMass; /* * The interfaced down quark mass */ Energy interfaceDMass; /* * The interfaced strange quark mass */ Energy interfaceSMass; /* * The interfaced charm quark mass */ Energy interfaceCMass; /* * The interfaced bottom quark mass */ Energy interfaceBMass; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudehbbbarg & operator=(const MatchboxAmplitudehbbbarg &) = delete; }; } #endif /* Herwig_MatchboxAmplitudehbbbarg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehgg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehgg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehgg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehgg.cc @@ -1,156 +1,154 @@ // -*- C++ -*- // // MatchboxAmplitudehgg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudehgg class. // #include "MatchboxAmplitudehgg.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/Utility/SpinorHelicity.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudehgg::MatchboxAmplitudehgg() : interfaceTHooft(126*GeV) {} -MatchboxAmplitudehgg::~MatchboxAmplitudehgg() {} - IBPtr MatchboxAmplitudehgg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudehgg::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudehgg::doinit() { MatchboxAmplitude::doinit(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); nPoints(3); } void MatchboxAmplitudehgg::doinitrun() { MatchboxAmplitude::doinitrun(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); nPoints(3); } bool MatchboxAmplitudehgg::canHandle(const PDVector& proc) const { if ( proc.size() != 3 ) return false; PDVector xproc = proc; for (PDVector::iterator g=xproc.begin(); g!=xproc.end(); ++g){ if ((**g).id()==21) {xproc.erase(g); --g;} } if (xproc.size()==1 && (**xproc.begin()).id()==25) {return true;} return false; } void MatchboxAmplitudehgg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); momentum(0,amplitudeMomentum(0)); momentum(1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudehgg::evaluate(size_t, const vector& hel, Complex& largeN) { unsigned int g1=0; unsigned int g2=0; cPDVector x=amplitudePartonData(); for (;g1id()==21) { for (g2=g1+1;g2id()==21) break;} break; } } // wrong assignement of the particles. g1 and g2 have to be different gluons. assert(g1!=g2); double gw = sqrt(4*Constants::pi*SM().alphaEMMZ()) / sqrt(SM().sin2ThetaW()); double v= 2*MW/gw/sqrt(lastSHat()); Complex c = Complex (0.,-1.*SM().alphaS()/3/Constants::pi/v); if (hel[g1]==-hel[g2]){ largeN=0; return largeN; } if (hel[g1]==hel[g2] && hel[g1]==-1){ largeN=c*plusProduct(g1,g2)*plusProduct(g1,g2); return largeN; } if (hel[g1]==hel[g2] && hel[g1]==1){ largeN=c*minusProduct(g1,g2)*minusProduct(g1,g2); return largeN; } // unknown helicity configuration assert(false); return(0.); } Complex MatchboxAmplitudehgg::evaluateOneLoop(size_t a , const vector& Hel) { Complex E = SM().alphaS()/Constants::pi*11/4; Complex largeN = 0.; return (E*evaluate(a,Hel,largeN)); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudehgg::persistentOutput(PersistentOStream &os) const { os << ounit(interfaceTHooft,GeV); } void MatchboxAmplitudehgg::persistentInput(PersistentIStream &is, int) { is >> iunit(interfaceTHooft,GeV); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMatchboxAmplitudehgg("Herwig::MatchboxAmplitudehgg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudehgg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudehgg"); /* // not used guess leftover from validation (mu2() variation) static Parameter interfaceTHooft ("interfaceTHooft", "The THooft Mass.", &MatchboxAmplitudehgg::interfaceTHooft, GeV, 115.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); */ } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehgg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehgg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehgg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehgg.h @@ -1,190 +1,182 @@ // -*- C++ -*- // // MatchboxAmplitudehgg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudehgg_H #define Herwig_MatchboxAmplitudehgg_H // // This is the declaration of the MatchboxAmplitudehgg class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Benedikt Zimmermann * * \brief MatchboxAmplitudehgg */ class MatchboxAmplitudehgg: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudehgg(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudehgg(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 2; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 1; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return true; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /* * The interfaced THooftMass */ Energy interfaceTHooft; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudehgg & operator=(const MatchboxAmplitudehgg &) = delete; }; } #endif /* Herwig_MatchboxAmplitudehgg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehggg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehggg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehggg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehggg.cc @@ -1,206 +1,204 @@ // -*- C++ -*- // // MatchboxAmplitudehggg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudehggg class. // #include "MatchboxAmplitudehggg.h" #include "ThePEG/Interface/Parameter.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/Utility/SpinorHelicity.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudehggg::MatchboxAmplitudehggg() : interfaceTHooft(126*GeV) {} -MatchboxAmplitudehggg::~MatchboxAmplitudehggg() {} - IBPtr MatchboxAmplitudehggg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudehggg::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudehggg::doinit() { MatchboxAmplitude::doinit(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); nPoints(4); } void MatchboxAmplitudehggg::doinitrun() { MatchboxAmplitude::doinitrun(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); nPoints(4); } bool MatchboxAmplitudehggg::canHandle(const PDVector& proc) const { if ( proc.size() != 4 ) return false; PDVector xproc = proc; for (PDVector::iterator g=xproc.begin(); g!=xproc.end(); ++g){ if ((**g).id()==21) {xproc.erase(g); --g;} } if (xproc.size()==1 && (**xproc.begin()).id()==25) {return true;} return false; } void MatchboxAmplitudehggg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); momentum(0,amplitudeMomentum(0)); momentum(1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudehggg::evaluate(size_t a, const vector& hel, Complex& largeN) { unsigned int p=0; unsigned int q=0; unsigned int r=0; cPDVector x=amplitudePartonData(); for (;pid()==21) { for (q=p+1;qid()==21){ for (r=q+1;rid()==21) break;} } break;} break; } } // Wrong particle assignment. There have to be three distinct Gluons p, q and r. assert(!((p==q) || (p==r) || (q==r))); double gw = sqrt(4*Constants::pi*SM().alphaEMMZ()) / sqrt(SM().sin2ThetaW()); double gs = sqrt(4*Constants::pi*SM().alphaS()); double v= 2*MW/gw/sqrt(lastSHat()) ; Complex c = Complex (0.,0.); // Assertion makes sure that there is no crossing, which causes a relative minus sign. If Assert -> new, more general code is needed assert(amplitudeToColourMap()[1]==0 && amplitudeToColourMap()[2]==1 && amplitudeToColourMap()[3]==2 ); if (a==0){ c = Complex (0.,-1.)*sqrt(2.)*SM().alphaS()/3./Constants::pi/v*gs ; } else { if (a==1){ c = Complex (0.,+1.)*sqrt(2.)*SM().alphaS()/3./Constants::pi/v*gs ; } else{ //The Colourbasis a is not appropriate for this process. // hggg ~ f^{abc} -> ~ tr(t^a,t^b,t^c) - tr(t^a,t^c,t^b) -> a in {0,1} assert(true); } } if(hel[p]==+1 && hel[q]==+1 && hel[r]==+1){ largeN = c*(invariant(p,q)*invariant(p,q)+2*invariant(p,q)*invariant(p,r) +invariant(p,r)*invariant(p,r)+2*invariant(p,q)*invariant(q,r) +2*invariant(p,r)*invariant(q,r)+invariant(q,r)*invariant(q,r)) /plusProduct(p,q)/plusProduct(p,r)/plusProduct(q,r); return(largeN); } if(hel[p]==+1 && hel[q]==+1 && hel[r]==-1){ largeN = -c*minusProduct(p,q)*minusProduct(p,q)*minusProduct(p,q)/minusProduct(p,r)/minusProduct(q,r); return(largeN); } if(hel[p]==+1 && hel[q]==-1 && hel[r]==+1){ largeN = -c*minusProduct(p,r)*minusProduct(p,r)*minusProduct(p,r)/minusProduct(p,q)/minusProduct(q,r); return(largeN); } if(hel[p]==+1 && hel[q]==-1 && hel[r]==-1){ largeN = c*plusProduct(q,r)*plusProduct(q,r)*plusProduct(q,r)/plusProduct(p,q)/plusProduct(p,r); return(largeN); } if(hel[p]==-1 && hel[q]==+1 && hel[r]==+1){ largeN = -c*minusProduct(q,r)*minusProduct(q,r)*minusProduct(q,r)/minusProduct(p,q)/minusProduct(p,r); return(largeN); } if(hel[p]==-1 && hel[q]==+1 && hel[r]==-1){ largeN = c*plusProduct(p,r)*plusProduct(p,r)*plusProduct(p,r)/plusProduct(p,q)/plusProduct(q,r); return(largeN); } if(hel[p]==-1 && hel[q]==-1 && hel[r]==+1){ largeN = c*plusProduct(p,q)*plusProduct(p,q)*plusProduct(p,q)/plusProduct(p,r)/plusProduct(q,r); return(largeN); } if(hel[p]==-1 && hel[q]==-1 && hel[r]==-1){ largeN = -c*(invariant(p,q)*invariant(p,q)+2*invariant(p,q)*invariant(p,r) +invariant(p,r)*invariant(p,r)+2*invariant(p,q)*invariant(q,r) +2*invariant(p,r)*invariant(q,r)+invariant(q,r)*invariant(q,r)) /plusProduct(p,q)/plusProduct(p,r)/plusProduct(q,r); return(largeN); } // Unknown helicity configuration assert(false); return(0.); } /*Complex MatchboxAmplitudehggg::evaluateOneLoop(size_t, const vector& hel) { }*/ // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudehggg::persistentOutput(PersistentOStream &os) const { os << ounit(interfaceTHooft,GeV); } void MatchboxAmplitudehggg::persistentInput(PersistentIStream &is, int) { is >> iunit(interfaceTHooft,GeV); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMatchboxAmplitudehggg("Herwig::MatchboxAmplitudehggg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudehggg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudehggg"); /* // not used guess leftover from validation (mu2() variation) static Parameter interfaceTHooft ("interfaceTHooft", "The THooft Mass.", &MatchboxAmplitudehggg::interfaceTHooft, GeV, 115.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); */ } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehggg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehggg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehggg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehggg.h @@ -1,191 +1,183 @@ // -*- C++ -*- // // MatchboxAmplitudehggg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudehggg_H #define Herwig_MatchboxAmplitudehggg_H // // This is the declaration of the MatchboxAmplitudehggg class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Benedikt Zimmermann * * \brief MatchboxAmplitudehggg */ class MatchboxAmplitudehggg: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudehggg(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudehggg(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 3; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 1; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ //virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /* * The interfaced THooftMass */ Energy interfaceTHooft; /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudehggg & operator=(const MatchboxAmplitudehggg &) = delete; }; } #endif /* Herwig_MatchboxAmplitudehggg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehqqbarg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehqqbarg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehqqbarg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehqqbarg.cc @@ -1,185 +1,183 @@ // -*- C++ -*- // // MatchboxAmplitudehqqbarg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudehqqbarg class. // #include "MatchboxAmplitudehqqbarg.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Parameter.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudehqqbarg::MatchboxAmplitudehqqbarg() : interfaceTHooft(126*GeV) {} -MatchboxAmplitudehqqbarg::~MatchboxAmplitudehqqbarg() {} - IBPtr MatchboxAmplitudehqqbarg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudehqqbarg::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudehqqbarg::doinit() { MatchboxAmplitude::doinit(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); nPoints(4);; } void MatchboxAmplitudehqqbarg::doinitrun() { MatchboxAmplitude::doinitrun(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); nPoints(4); } bool MatchboxAmplitudehqqbarg::canHandle(const PDVector& proc) const { if ( proc.size() != 4 ) return false; PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator q=xproc.begin(); for (; q!=xproc.end(); ++q){ if ((**q).id()==1 || (**q).id()==2 || (**q).id()==3 || (**q).id()==4 || (**q).id()==5) break; } if(q==xproc.end()) return false; int qid = (**q).id(); xproc.erase(q); PDVector::iterator qb=xproc.begin(); for (; qb!=xproc.end(); ++qb){ if ((**qb).id()==-qid ){break;} } if(qb==xproc.end()){ return false;} xproc.erase(qb); for (PDVector::iterator g=xproc.begin(); g!=xproc.end(); ++g){ if ((**g).id()==21){xproc.erase(g); break; } } if (xproc.size()==1 && (**xproc.begin()).id()==25) {return true;} return false; } void MatchboxAmplitudehqqbarg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); momentum(0,amplitudeMomentum(0)); momentum(1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudehqqbarg::evaluate(size_t, const vector& hel, Complex& largeN) { unsigned int q=0; unsigned int qbar=0; unsigned int g=0; cPDVector x=amplitudePartonData(); for (;qid()!= 25 && x[q]->id()>0 ) break;} for (;qbarid() ==-x[q]->id()) break;} for (;gid() == 21) break;} double gw = sqrt(4*Constants::pi*SM().alphaEMMZ()) / sqrt(SM().sin2ThetaW()); double gs = sqrt(4*Constants::pi*SM().alphaS()); double alphaS = SM().alphaS(); double v= 2*MW/gw/sqrt(lastSHat()) ; double c = gs*alphaS/3/sqrt(2.)/Constants::pi/v; if(hel[qbar]==hel[q]){ largeN = 0; return(largeN); } if(hel[qbar]==+1 && hel[q]==-1 && hel[g]==-1){ largeN = -c*plusProduct(qbar,g)*plusProduct(qbar,g)/(plusProduct(q,qbar)); return(largeN); } if(hel[qbar]==1 && hel[q]==-1 && hel[g]==1){ largeN = -c*minusProduct(q,g)*minusProduct(q,g)/(minusProduct(q,qbar)); return(largeN); } if(hel[qbar]==-1 && hel[q]==1 && hel[g]==-1){ largeN = c*plusProduct(q,g)*plusProduct(q,g)/(plusProduct(q,qbar)); return(largeN); } if(hel[qbar]==-1 && hel[q]==1 && hel[g]==1){ largeN = c*minusProduct(qbar,g)*minusProduct(qbar,g)/(minusProduct(q,qbar)); return(largeN); } // Unknown helicity configuration assert(false); return(0.); } /*Complex MatchboxAmplitudehqqbarg::evaluateOneLoop(size_t, const vector& hel) { }*/ // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudehqqbarg::persistentOutput(PersistentOStream &os) const { os << ounit(interfaceTHooft,GeV); } void MatchboxAmplitudehqqbarg::persistentInput(PersistentIStream &is, int) { is >> iunit(interfaceTHooft,GeV); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMatchboxAmplitudehqqbarg("Herwig::MatchboxAmplitudehqqbarg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudehqqbarg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudehqqbarg"); /* // not used guess leftover from validation (mu2() variation) static Parameter interfaceTHooft ("interfaceTHooft", "The THooft Mass.", &MatchboxAmplitudehqqbarg::interfaceTHooft, GeV, 115.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); */ } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehqqbarg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehqqbarg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehqqbarg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudehqqbarg.h @@ -1,189 +1,181 @@ // -*- C++ -*- // // MatchboxAmplitudehqqbarg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudehqqbarg_H #define Herwig_MatchboxAmplitudehqqbarg_H // // This is the declaration of the MatchboxAmplitudehqqbarg class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Benedikt Zimmermann * * \brief MatchboxAmplitudehqqbarg */ class MatchboxAmplitudehqqbarg: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudehqqbarg(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudehqqbarg(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 3; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 1; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ //virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /* * The interfaced THooftMass */ Energy interfaceTHooft; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudehqqbarg & operator=(const MatchboxAmplitudehqqbarg &) = delete; }; } #endif /* Herwig_MatchboxAmplitudehqqbarg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc @@ -1,241 +1,239 @@ // -*- C++ -*- // // MatchboxAmplitudellbarqqbar.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudellbarqqbar class. // #include "MatchboxAmplitudellbarqqbar.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudellbarqqbar::MatchboxAmplitudellbarqqbar() {} -MatchboxAmplitudellbarqqbar::~MatchboxAmplitudellbarqqbar() {} - IBPtr MatchboxAmplitudellbarqqbar::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudellbarqqbar::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudellbarqqbar::doinit() { MatchboxZGammaAmplitude::doinit(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(4); } void MatchboxAmplitudellbarqqbar::doinitrun() { MatchboxZGammaAmplitude::doinitrun(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(4); } bool MatchboxAmplitudellbarqqbar::canHandle(const PDVector& proc) const { if ( proc.size() != 4 ) return false; PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator lepton = xproc.begin(); long leptonId = 0; for ( ; lepton != xproc.end(); ++lepton ) if ( (**lepton).id() == 11 || (**lepton).id() == 13 || (**lepton).id() == 15 ) { break; } if ( lepton == xproc.end() ) return false; leptonId = (**lepton).id(); xproc.erase(lepton); PDVector::iterator antiLepton = xproc.begin(); for ( ; antiLepton != xproc.end(); ++antiLepton ) if ( (**antiLepton).id() == -leptonId ) { break; } if ( antiLepton == xproc.end() ) return false; xproc.erase(antiLepton); PDVector::iterator quark = xproc.begin(); long quarkId = 0; for ( ; quark != xproc.end(); ++quark ) if ( abs((**quark).id()) < 7 && (**quark).id() > 0 ) { break; } if ( quark == xproc.end() ) return false; quarkId = (**quark).id(); xproc.erase(quark); PDVector::iterator antiQuark = xproc.begin(); for ( ; antiQuark != xproc.end(); ++antiQuark ) if ( (**antiQuark).id() == -quarkId ) { break; } if ( antiQuark == xproc.end() ) return false; xproc.erase(antiQuark); return xproc.empty(); } void MatchboxAmplitudellbarqqbar::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxZGammaAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); setupLeptons(0,amplitudeMomentum(0), 1,amplitudeMomentum(1)); setupQuarks(2,amplitudeMomentum(2), 3,amplitudeMomentum(3)); MatchboxZGammaAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudellbarqqbar::evaluate(size_t, const vector& hel, Complex& largeN) { if ( abs(hel[2])+abs(hel[3]) != 2 ) { largeN = 0.; return 0.; } const LorentzVector& leptonLeft = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& leptonRight = llbarRightCurrent(0,hel[0],1,hel[1]); const LorentzVector& quarkLeft = qqbarLeftCurrent(2,hel[2],3,hel[3]); const LorentzVector& quarkRight = qqbarRightCurrent(2,hel[2],3,hel[3]); Complex LL = leptonLeft.dot( quarkLeft ); Complex RL = leptonRight.dot( quarkLeft ); Complex LR = leptonLeft.dot( quarkRight ); Complex RR = leptonRight.dot( quarkRight ); double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat(); Complex gamma = 0.0; if ( includeGamma() ) gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)* (LL + RL + LR + RR)/bProp; bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0; Complex Z = 0.0; if ( includeZ() ) Z = Complex(0.,-1.)* (standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL + standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL + standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR + standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex res = 4.*Constants::pi*SM().alphaEMMZ()*(gamma+Z); largeN = res; return res; } Complex MatchboxAmplitudellbarqqbar::evaluateOneLoop(size_t, const vector& hel) { const LorentzVector& leptonLeft = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& leptonRight = llbarRightCurrent(0,hel[0],1,hel[1]); const LorentzVector& quarkLeft = qqbarLeftOneLoopCurrent(2,hel[2],3,hel[3]); const LorentzVector& quarkRight = qqbarRightOneLoopCurrent(2,hel[2],3,hel[3]); Complex LL = leptonLeft.dot( quarkLeft ); Complex RL = leptonRight.dot( quarkLeft ); Complex LR = leptonLeft.dot( quarkRight ); Complex RR = leptonRight.dot( quarkRight ); double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat(); Complex gamma = 0.0; if ( includeGamma() ) gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)* (LL + RL + LR + RR)/bProp; bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0; Complex Z = 0.0; if ( includeZ() ) Z = Complex(0.,-1.)* (standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL + standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL + standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR + standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex res = (SM().alphaS()/(2.*Constants::pi))*4.*Constants::pi*SM().alphaEMMZ()*(gamma+Z); return res; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudellbarqqbar::persistentOutput(PersistentOStream &) const {} void MatchboxAmplitudellbarqqbar::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxAmplitudellbarqqbar("Herwig::MatchboxAmplitudellbarqqbar", "HwMatchboxBuiltin.so"); void MatchboxAmplitudellbarqqbar::Init() { static ClassDocumentation documentation ("MatchboxAmplitudellbarqqbar"); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h @@ -1,186 +1,178 @@ // -*- C++ -*- // // MatchboxAmplitudellbarqqbar.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudellbarqqbar_H #define Herwig_MatchboxAmplitudellbarqqbar_H // // This is the declaration of the MatchboxAmplitudellbarqqbar class. // #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxAmplitudellbarqqbar */ class MatchboxAmplitudellbarqqbar: public MatchboxZGammaAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudellbarqqbar(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudellbarqqbar(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 0; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 2; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return true; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true if one loop corrections are given in the conventions of everything expanded - this is currently the only convention available in DipoleMIOperator.cc */ virtual bool isExpanded() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxZGammaAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudellbarqqbar & operator=(const MatchboxAmplitudellbarqqbar &) = delete; }; } #endif /* Herwig_MatchboxAmplitudellbarqqbar_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc @@ -1,255 +1,253 @@ // -*- C++ -*- // // MatchboxAmplitudellbarqqbarg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudellbarqqbarg class. // #include "MatchboxAmplitudellbarqqbarg.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudellbarqqbarg::MatchboxAmplitudellbarqqbarg() {} -MatchboxAmplitudellbarqqbarg::~MatchboxAmplitudellbarqqbarg() {} - IBPtr MatchboxAmplitudellbarqqbarg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudellbarqqbarg::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudellbarqqbarg::doinit() { MatchboxZGammaAmplitude::doinit(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(5); } void MatchboxAmplitudellbarqqbarg::doinitrun() { MatchboxZGammaAmplitude::doinitrun(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(5); } bool MatchboxAmplitudellbarqqbarg::canHandle(const PDVector& proc) const { if ( proc.size() != 5 ) return false; PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator lepton = xproc.begin(); long leptonId = 0; for ( ; lepton != xproc.end(); ++lepton ) if ( (**lepton).id() == 11 || (**lepton).id() == 13 || (**lepton).id() == 15 ) { break; } if ( lepton == xproc.end() ) return false; leptonId = (**lepton).id(); xproc.erase(lepton); PDVector::iterator antiLepton = xproc.begin(); for ( ; antiLepton != xproc.end(); ++antiLepton ) if ( (**antiLepton).id() == -leptonId ) { break; } if ( antiLepton == xproc.end() ) return false; xproc.erase(antiLepton); PDVector::iterator quark = xproc.begin(); long quarkId = 0; for ( ; quark != xproc.end(); ++quark ) if ( abs((**quark).id()) < 7 && (**quark).id() > 0 ) { break; } if ( quark == xproc.end() ) return false; quarkId = (**quark).id(); xproc.erase(quark); PDVector::iterator antiQuark = xproc.begin(); for ( ; antiQuark != xproc.end(); ++antiQuark ) if ( (**antiQuark).id() == -quarkId ) { break; } if ( antiQuark == xproc.end() ) return false; xproc.erase(antiQuark); if ( xproc.size() != 1 ) return false; return xproc[0]->id() == 21; } void MatchboxAmplitudellbarqqbarg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxZGammaAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); setupLeptons(0,amplitudeMomentum(0), 1,amplitudeMomentum(1)); setupQuarks(2,amplitudeMomentum(2), 3,amplitudeMomentum(3)); momentum(4,amplitudeMomentum(4)); MatchboxZGammaAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudellbarqqbarg::evaluate(size_t, const vector& hel, Complex& largeN) { assert(nPoints() == 5); if ( abs(hel[2])+abs(hel[3]) != 2 ) { largeN = 0.; return 0.; } const LorentzVector& leptonLeft = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& leptonRight = llbarRightCurrent(0,hel[0],1,hel[1]); const LorentzVector& quarkLeft = qqbargLeftCurrent(2,hel[2],3,hel[3],4,hel[4]); const LorentzVector& quarkRight = qqbargRightCurrent(2,hel[2],3,hel[3],4,hel[4]); Complex LL = leptonLeft.dot( quarkLeft ); Complex RL = leptonRight.dot( quarkLeft ); Complex LR = leptonLeft.dot( quarkRight ); Complex RR = leptonRight.dot( quarkRight ); double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat(); Complex gamma = 0.0; if ( includeGamma() ) gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)* (LL + RL + LR + RR)/bProp; bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0; Complex Z = 0.0; if ( includeZ() ) Z = Complex(0.,-1.)* (standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL + standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL + standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR + standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex res = 4.*Constants::pi*SM().alphaEMMZ()*sqrt(4.*Constants::pi*SM().alphaS())*(gamma+Z); largeN = res; return res; } Complex MatchboxAmplitudellbarqqbarg::evaluateOneLoop(size_t, const vector& hel) { if ( abs(hel[2]+hel[3]) != 2 ) { return 0.; } const LorentzVector& leptonLeft = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& leptonRight = llbarRightCurrent(0,hel[0],1,hel[1]); Complex LL = hel[2] == 1 ? leptonLeft.dot( qqbargLeftOneLoopCurrent (2,hel[2],3,hel[3],4,hel[4])) : 0.; Complex RL = hel[2] == 1 ? leptonRight.dot(qqbargLeftOneLoopCurrent (2,hel[2],3,hel[3],4,hel[4])) : 0.; Complex LR = hel[2] == -1 ? leptonLeft.dot( qqbargRightOneLoopCurrent(2,hel[2],3,hel[3],4,hel[4])) : 0.; Complex RR = hel[2] == -1 ? leptonRight.dot(qqbargRightOneLoopCurrent(2,hel[2],3,hel[3],4,hel[4])) : 0.; double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat(); Complex gamma = 0.0; if ( includeGamma() ) gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)* (LL + RL + LR + RR)/bProp; bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0; Complex Z = 0.0; if ( includeZ() ) Z = Complex(0.,-1.)* (standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL + standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL + standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR + standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex res = (SM().alphaS()/(2.*Constants::pi))* 4.*Constants::pi*SM().alphaEMMZ()*sqrt(4.*Constants::pi*SM().alphaS())*(gamma+Z); return res; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudellbarqqbarg::persistentOutput(PersistentOStream &) const {} void MatchboxAmplitudellbarqqbarg::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxAmplitudellbarqqbarg("Herwig::MatchboxAmplitudellbarqqbarg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudellbarqqbarg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudellbarqqbarg"); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h @@ -1,187 +1,179 @@ // -*- C++ -*- // // MatchboxAmplitudellbarqqbarg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudellbarqqbarg_H #define Herwig_MatchboxAmplitudellbarqqbarg_H // // This is the declaration of the MatchboxAmplitudellbarqqbarg class. // #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxAmplitudellbarqqbarg */ class MatchboxAmplitudellbarqqbarg: public MatchboxZGammaAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudellbarqqbarg(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudellbarqqbarg(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 1; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 2; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return true; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxZGammaAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudellbarqqbarg & operator=(const MatchboxAmplitudellbarqqbarg &) = delete; }; } #endif /* Herwig_MatchboxAmplitudellbarqqbarg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbargg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbargg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbargg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbargg.cc @@ -1,224 +1,220 @@ // -*- C++ -*- // // MatchboxAmplitudellbarqqbargg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudellbarqqbargg class. // #include "MatchboxAmplitudellbarqqbargg.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudellbarqqbargg::MatchboxAmplitudellbarqqbargg() {} -MatchboxAmplitudellbarqqbargg::~MatchboxAmplitudellbarqqbargg() {} - IBPtr MatchboxAmplitudellbarqqbargg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudellbarqqbargg::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudellbarqqbargg::doinit() { MatchboxZGammaAmplitude::doinit(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); nPoints(6); } void MatchboxAmplitudellbarqqbargg::doinitrun() { MatchboxZGammaAmplitude::doinitrun(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); nPoints(6); } bool MatchboxAmplitudellbarqqbargg::canHandle(const PDVector& proc) const { if ( proc.size() != 6 ) return false; PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator lepton = xproc.begin(); long leptonId = 0; for ( ; lepton != xproc.end(); ++lepton ) if ( (**lepton).id() == 11 || (**lepton).id() == 13 || (**lepton).id() == 15 ) { break; } if ( lepton == xproc.end() ) return false; leptonId = (**lepton).id(); xproc.erase(lepton); PDVector::iterator antiLepton = xproc.begin(); for ( ; antiLepton != xproc.end(); ++antiLepton ) if ( (**antiLepton).id() == -leptonId ) { break; } if ( antiLepton == xproc.end() ) return false; xproc.erase(antiLepton); PDVector::iterator quark = xproc.begin(); long quarkId = 0; for ( ; quark != xproc.end(); ++quark ) if ( abs((**quark).id()) < 6 && (**quark).id() > 0 && (**quark).hardProcessMass() == ZERO ) { break; } if ( quark == xproc.end() ) return false; quarkId = (**quark).id(); xproc.erase(quark); PDVector::iterator antiQuark = xproc.begin(); for ( ; antiQuark != xproc.end(); ++antiQuark ) if ( (**antiQuark).id() == -quarkId ) { break; } if ( antiQuark == xproc.end() ) return false; xproc.erase(antiQuark); if ( xproc.size() != 2 ) return false; return xproc[0]->id() == 21 && xproc[1]->id() == 21; } void MatchboxAmplitudellbarqqbargg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxZGammaAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); setupLeptons(0,amplitudeMomentum(0), 1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); momentum(4,amplitudeMomentum(4)); momentum(5,amplitudeMomentum(5)); MatchboxZGammaAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudellbarqqbargg::evaluate(size_t a, const vector& hel, Complex& largeN) { if ( abs(hel[2]+hel[3]) != 2 ) { largeN = 0.; return 0.; } const LorentzVector& leptonLeft = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& leptonRight = llbarRightCurrent(0,hel[0],1,hel[1]); assert(amplitudeToColourMap()[2] == 0 && amplitudeToColourMap()[3] == 1); int g1,hg1,g2,hg2; if ( amplitudeToColourMap()[4] == 2 && amplitudeToColourMap()[5] == 3 ) { if ( a == 0 ) { g1 = 4; hg1 = hel[4]; g2 = 5; hg2 = hel[5]; } else if ( a == 1 ) { g1 = 5; hg1 = hel[5]; g2 = 4; hg2 = hel[4]; } else assert(false); } else if ( amplitudeToColourMap()[4] == 3 && amplitudeToColourMap()[5] == 2 ) { if ( a == 0 ) { g1 = 5; hg1 = hel[5]; g2 = 4; hg2 = hel[4]; } else if ( a == 1 ) { g1 = 4; hg1 = hel[4]; g2 = 5; hg2 = hel[5]; } else assert(false); } else assert(false); Complex LL = hel[2] == 1 ? leptonLeft.dot( qqbarggLeftCurrent (2,hel[2],3,hel[3],g1,hg1,g2,hg2)) : 0.; Complex RL = hel[2] == 1 ? leptonRight.dot(qqbarggLeftCurrent (2,hel[2],3,hel[3],g1,hg1,g2,hg2)) : 0.; Complex LR = hel[2] == -1 ? leptonLeft.dot( qqbarggRightCurrent(2,hel[2],3,hel[3],g1,hg1,g2,hg2)) : 0.; Complex RR = hel[2] == -1 ? leptonRight.dot(qqbarggRightCurrent(2,hel[2],3,hel[3],g1,hg1,g2,hg2)) : 0.; double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat(); Complex gamma = 0.0; if ( includeGamma() ) gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)* (LL + RL + LR + RR)/bProp; bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0; Complex Z = 0.0; if ( includeZ() ) Z = Complex(0.,-1.)* (standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL + standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL + standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR + standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex res = sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*(gamma+Z); largeN = res; return res; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudellbarqqbargg::persistentOutput(PersistentOStream &) const {} void MatchboxAmplitudellbarqqbargg::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxAmplitudellbarqqbargg("Herwig::MatchboxAmplitudellbarqqbargg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudellbarqqbargg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudellbarqqbargg"); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbargg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbargg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbargg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbargg.h @@ -1,168 +1,160 @@ // -*- C++ -*- // // MatchboxAmplitudellbarqqbargg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudellbarqqbargg_H #define Herwig_MatchboxAmplitudellbarqqbargg_H // // This is the declaration of the MatchboxAmplitudellbarqqbargg class. // #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxAmplitudellbarqqbargg */ class MatchboxAmplitudellbarqqbargg: public MatchboxZGammaAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudellbarqqbargg(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudellbarqqbargg(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 2; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 2; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxZGammaAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudellbarqqbargg & operator=(const MatchboxAmplitudellbarqqbargg &) = delete; }; } #endif /* Herwig_MatchboxAmplitudellbarqqbargg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarqqbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarqqbar.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarqqbar.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarqqbar.cc @@ -1,377 +1,373 @@ // -*- C++ -*- // // MatchboxAmplitudellbarqqbarqqbar.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudellbarqqbarqqbar class. // #include "MatchboxAmplitudellbarqqbarqqbar.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudellbarqqbarqqbar::MatchboxAmplitudellbarqqbarqqbar() {} -MatchboxAmplitudellbarqqbarqqbar::~MatchboxAmplitudellbarqqbarqqbar() {} - IBPtr MatchboxAmplitudellbarqqbarqqbar::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudellbarqqbarqqbar::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudellbarqqbarqqbar::doinit() { MatchboxZGammaAmplitude::doinit(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); nPoints(6); } void MatchboxAmplitudellbarqqbarqqbar::doinitrun() { MatchboxZGammaAmplitude::doinitrun(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); nPoints(6); } bool MatchboxAmplitudellbarqqbarqqbar::canHandle(const PDVector& proc) const { if ( proc.size() != 6 ) return false; PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator lepton = xproc.begin(); long leptonId = 0; for ( ; lepton != xproc.end(); ++lepton ) if ( (**lepton).id() == 11 || (**lepton).id() == 13 || (**lepton).id() == 15 ) { break; } if ( lepton == xproc.end() ) return false; leptonId = (**lepton).id(); xproc.erase(lepton); PDVector::iterator antiLepton = xproc.begin(); for ( ; antiLepton != xproc.end(); ++antiLepton ) if ( (**antiLepton).id() == -leptonId ) { break; } if ( antiLepton == xproc.end() ) return false; xproc.erase(antiLepton); PDVector::iterator quark = xproc.begin(); long quarkId = 0; for ( ; quark != xproc.end(); ++quark ) if ( abs((**quark).id()) < 6 && (**quark).id() > 0 && (**quark).hardProcessMass() == ZERO ) { break; } if ( quark == xproc.end() ) return false; quarkId = (**quark).id(); xproc.erase(quark); PDVector::iterator antiQuark = xproc.begin(); for ( ; antiQuark != xproc.end(); ++antiQuark ) if ( (**antiQuark).id() == -quarkId ) { break; } if ( antiQuark == xproc.end() ) return false; xproc.erase(antiQuark); quark = xproc.begin(); quarkId = 0; for ( ; quark != xproc.end(); ++quark ) if ( abs((**quark).id()) < 6 && (**quark).id() > 0 && (**quark).hardProcessMass() == ZERO ) { break; } if ( quark == xproc.end() ) return false; quarkId = (**quark).id(); xproc.erase(quark); antiQuark = xproc.begin(); for ( ; antiQuark != xproc.end(); ++antiQuark ) if ( (**antiQuark).id() == -quarkId ) { break; } if ( antiQuark == xproc.end() ) return false; xproc.erase(antiQuark); return xproc.empty(); } inline bool leftNonZero(int heli, int helj, int helk, int hell) { return heli == 1 && helj == 1 && abs(helk+hell) == 2; } inline bool rightNonZero(int heli, int helj, int helk, int hell) { return heli == -1 && helj == -1 && abs(helk+hell) == 2; } void MatchboxAmplitudellbarqqbarqqbar::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxZGammaAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); setupLeptons(0,amplitudeMomentum(0), 1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); momentum(4,amplitudeMomentum(4)); momentum(5,amplitudeMomentum(5)); MatchboxZGammaAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudellbarqqbarqqbar::evaluate(size_t a, const vector& hel, Complex& largeN) { const LorentzVector& leptonLeft = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& leptonRight = llbarRightCurrent(0,hel[0],1,hel[1]); Complex LL2345 = leftNonZero(hel[2],hel[3],hel[4],hel[5]) && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[5]->id()) ? leptonLeft.dot(qqbarqqbarLeftCurrent(2,hel[2],3,hel[3],4,hel[4],5,hel[5])) : 0.; Complex LL4523 = leftNonZero(hel[4],hel[5],hel[2],hel[3]) && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[3]->id()) ? leptonLeft.dot(qqbarqqbarLeftCurrent(4,hel[4],5,hel[5],2,hel[2],3,hel[3])) : 0.; Complex LL2543 = leftNonZero(hel[2],hel[5],hel[4],hel[3]) && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[3]->id()) ? -leptonLeft.dot(qqbarqqbarLeftCurrent(2,hel[2],5,hel[5],4,hel[4],3,hel[3])) : 0.; Complex LL4325 = leftNonZero(hel[4],hel[3],hel[2],hel[5]) && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[5]->id()) ? -leptonLeft.dot(qqbarqqbarLeftCurrent(4,hel[4],3,hel[3],2,hel[2],5,hel[5])) : 0.; Complex LR2345 = rightNonZero(hel[2],hel[3],hel[4],hel[5]) && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[5]->id()) ? leptonLeft.dot(qqbarqqbarRightCurrent(2,hel[2],3,hel[3],4,hel[4],5,hel[5])) : 0.; Complex LR4523 = rightNonZero(hel[4],hel[5],hel[2],hel[3]) && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[3]->id()) ? leptonLeft.dot(qqbarqqbarRightCurrent(4,hel[4],5,hel[5],2,hel[2],3,hel[3])) : 0.; Complex LR2543 = rightNonZero(hel[2],hel[5],hel[4],hel[3]) && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[3]->id()) ? -leptonLeft.dot(qqbarqqbarRightCurrent(2,hel[2],5,hel[5],4,hel[4],3,hel[3])) : 0.; Complex LR4325 = rightNonZero(hel[4],hel[3],hel[2],hel[5]) && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[5]->id()) ? -leptonLeft.dot(qqbarqqbarRightCurrent(4,hel[4],3,hel[3],2,hel[2],5,hel[5])) : 0.; Complex RL2345 = leftNonZero(hel[2],hel[3],hel[4],hel[5]) && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[5]->id()) ? leptonRight.dot(qqbarqqbarLeftCurrent(2,hel[2],3,hel[3],4,hel[4],5,hel[5])) : 0.; Complex RL4523 = leftNonZero(hel[4],hel[5],hel[2],hel[3]) && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[3]->id()) ? leptonRight.dot(qqbarqqbarLeftCurrent(4,hel[4],5,hel[5],2,hel[2],3,hel[3])) : 0.; Complex RL2543 = leftNonZero(hel[2],hel[5],hel[4],hel[3]) && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[3]->id()) ? -leptonRight.dot(qqbarqqbarLeftCurrent(2,hel[2],5,hel[5],4,hel[4],3,hel[3])) : 0.; Complex RL4325 = leftNonZero(hel[4],hel[3],hel[2],hel[5]) && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[5]->id()) ? -leptonRight.dot(qqbarqqbarLeftCurrent(4,hel[4],3,hel[3],2,hel[2],5,hel[5])) : 0.; Complex RR2345 = rightNonZero(hel[2],hel[3],hel[4],hel[5]) && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[5]->id()) ? leptonRight.dot(qqbarqqbarRightCurrent(2,hel[2],3,hel[3],4,hel[4],5,hel[5])) : 0.; Complex RR4523 = rightNonZero(hel[4],hel[5],hel[2],hel[3]) && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[3]->id()) ? leptonRight.dot(qqbarqqbarRightCurrent(4,hel[4],5,hel[5],2,hel[2],3,hel[3])) : 0.; Complex RR2543 = rightNonZero(hel[2],hel[5],hel[4],hel[3]) && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[3]->id()) ? -leptonRight.dot(qqbarqqbarRightCurrent(2,hel[2],5,hel[5],4,hel[4],3,hel[3])) : 0.; Complex RR4325 = rightNonZero(hel[4],hel[3],hel[2],hel[5]) && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[5]->id()) ? -leptonRight.dot(qqbarqqbarRightCurrent(4,hel[4],3,hel[3],2,hel[2],5,hel[5])) : 0.; double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat(); Complex gamma2345 = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)* (LL2345 + RL2345 + LR2345 + RR2345)/bProp; Complex gamma2543 = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)* (LL2543 + RL2543 + LR2543 + RR2543)/bProp; Complex gamma4523 = Complex(0.,-1.)*(-amplitudePartonData()[4]->iCharge()/3.)* (LL4523 + RL4523 + LR4523 + RR4523)/bProp; Complex gamma4325 = Complex(0.,-1.)*(-amplitudePartonData()[4]->iCharge()/3.)* (LL4325 + RL4325 + LR4325 + RR4325)/bProp; bool up2 = abs(amplitudePartonData()[2]->id()) % 2 == 0; bool up4 = abs(amplitudePartonData()[4]->id()) % 2 == 0; Complex Z2345 = Complex(0.,-1.)* (standardModel()->le()*(up2 ? standardModel()->lu() : standardModel()->ld())*LL2345 + standardModel()->re()*(up2 ? standardModel()->lu() : standardModel()->ld())*RL2345 + standardModel()->le()*(up2 ? standardModel()->ru() : standardModel()->rd())*LR2345 + standardModel()->re()*(up2 ? standardModel()->ru() : standardModel()->rd())*RR2345)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex Z2543 = Complex(0.,-1.)* (standardModel()->le()*(up2 ? standardModel()->lu() : standardModel()->ld())*LL2543 + standardModel()->re()*(up2 ? standardModel()->lu() : standardModel()->ld())*RL2543 + standardModel()->le()*(up2 ? standardModel()->ru() : standardModel()->rd())*LR2543 + standardModel()->re()*(up2 ? standardModel()->ru() : standardModel()->rd())*RR2543)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex Z4523 = Complex(0.,-1.)* (standardModel()->le()*(up4 ? standardModel()->lu() : standardModel()->ld())*LL4523 + standardModel()->re()*(up4 ? standardModel()->lu() : standardModel()->ld())*RL4523 + standardModel()->le()*(up4 ? standardModel()->ru() : standardModel()->rd())*LR4523 + standardModel()->re()*(up4 ? standardModel()->ru() : standardModel()->rd())*RR4523)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex Z4325 = Complex(0.,-1.)* (standardModel()->le()*(up4 ? standardModel()->lu() : standardModel()->ld())*LL4325 + standardModel()->re()*(up4 ? standardModel()->lu() : standardModel()->ld())*RL4325 + standardModel()->le()*(up4 ? standardModel()->ru() : standardModel()->rd())*LR4325 + standardModel()->re()*(up4 ? standardModel()->ru() : standardModel()->rd())*RR4325)/ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat()); Complex sum2345 = 0.0; Complex sum2543 = 0.0; Complex sum4523 = 0.0; Complex sum4325 = 0.0; if ( includeGamma() ) { sum2345 += sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*gamma2345; sum2543 += sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*gamma2543; sum4523 += sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*gamma4523; sum4325 += sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*gamma4325; } if ( includeZ() ) { sum2345 += sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*Z2345; sum2543 += sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*Z2543; sum4523 += sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*Z4523; sum4325 += sqr(4.*Constants::pi)*SM().alphaEMMZ()*SM().alphaS()*Z4325; } double Nc = SM().Nc(); Complex resLeading = 0.; Complex resSubLeading = 0.; if ( amplitudeToColourMap()[2] == 0 && amplitudeToColourMap()[3] == 1 && amplitudeToColourMap()[4] == 2 && amplitudeToColourMap()[5] == 3 ) { if ( a == 0 ) { //(23)(45) resLeading = sum2543 + sum4325; resSubLeading = sum2345 + sum4523; } else if ( a == 1 ) { //(25)(43) resLeading = sum2345 + sum4523; resSubLeading = sum2543 + sum4325; } else assert(false); } else if ( amplitudeToColourMap()[2] == 0 && amplitudeToColourMap()[3] == 3 && amplitudeToColourMap()[4] == 2 && amplitudeToColourMap()[5] == 1 ) { if ( a == 0 ) { // (25)(43) resLeading = sum2345 + sum4523; resSubLeading = sum2543 + sum4325; } else if ( a == 1 ) { // (23)(45) resLeading = sum2543 + sum4325; resSubLeading = sum2345 + sum4523; } else assert(false); } else if ( amplitudeToColourMap()[2] == 2 && amplitudeToColourMap()[3] == 3 && amplitudeToColourMap()[4] == 0 && amplitudeToColourMap()[5] == 1 ) { if ( a == 0 ) { //(23)(45) resLeading = sum2543 + sum4325; resSubLeading = sum2345 + sum4523; } else if ( a == 1 ) { //(25)(43) resLeading = sum2345 + sum4523; resSubLeading = sum2543 + sum4325; } else assert(false); } else if ( amplitudeToColourMap()[2] == 2 && amplitudeToColourMap()[3] == 1 && amplitudeToColourMap()[4] == 0 && amplitudeToColourMap()[5] == 3 ) { if ( a == 0 ) { //(25)(43) resLeading = sum2345 + sum4523; resSubLeading = sum2543 + sum4325; } else if ( a == 1 ) { //(23)(45) resLeading = sum2543 + sum4325; resSubLeading = sum2345 + sum4523; } else assert(false); } else assert(false); resSubLeading *= -1./Nc; largeN = resLeading/2.; return (resLeading + resSubLeading)/2.; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudellbarqqbarqqbar::persistentOutput(PersistentOStream &) const {} void MatchboxAmplitudellbarqqbarqqbar::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxAmplitudellbarqqbarqqbar("Herwig::MatchboxAmplitudellbarqqbarqqbar", "HwMatchboxBuiltin.so"); void MatchboxAmplitudellbarqqbarqqbar::Init() { static ClassDocumentation documentation ("MatchboxAmplitudellbarqqbarqqbar"); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarqqbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarqqbar.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarqqbar.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarqqbar.h @@ -1,168 +1,160 @@ // -*- C++ -*- // // MatchboxAmplitudellbarqqbarqqbar.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudellbarqqbarqqbar_H #define Herwig_MatchboxAmplitudellbarqqbarqqbar_H // // This is the declaration of the MatchboxAmplitudellbarqqbarqqbar class. // #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxAmplitudellbarqqbarqqbar */ class MatchboxAmplitudellbarqqbarqqbar: public MatchboxZGammaAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudellbarqqbarqqbar(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudellbarqqbarqqbar(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 2; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 2; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxZGammaAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudellbarqqbarqqbar & operator=(const MatchboxAmplitudellbarqqbarqqbar &) = delete; }; } #endif /* Herwig_MatchboxAmplitudellbarqqbarqqbar_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.cc @@ -1,192 +1,190 @@ // -*- C++ -*- // // MatchboxAmplitudelnuqqbar.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudelnuqqbar class. // #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" using namespace Herwig; MatchboxAmplitudelnuqqbar::MatchboxAmplitudelnuqqbar() - : theDiagonal(false) {} - -MatchboxAmplitudelnuqqbar::~MatchboxAmplitudelnuqqbar() {} + : theDiagonal(false) {} void MatchboxAmplitudelnuqqbar::doinit() { MatchboxAmplitude::doinit(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); theCKM = standardCKM(SM())->getUnsquaredMatrix(6); nPoints(4); } void MatchboxAmplitudelnuqqbar::doinitrun() { MatchboxAmplitude::doinitrun(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(4); } IBPtr MatchboxAmplitudelnuqqbar::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudelnuqqbar::fullclone() const { return new_ptr(*this); } bool MatchboxAmplitudelnuqqbar::canHandle(const PDVector& proc) const { PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator elektron = xproc.begin(); for ( ; elektron != xproc.end(); ++elektron ) if ( abs((*elektron)->id()) >= 11 && abs((*elektron)->id()) <= 16 && abs((*elektron)->id()) % 2 == 1 ) break; if ( elektron == xproc.end() ) return false; PDPtr e = *elektron; xproc.erase(elektron); PDVector::iterator neutrino = xproc.begin(); for ( ; neutrino != xproc.end(); ++neutrino ) if ( abs((*neutrino)->id()) >= 11 && abs((*neutrino)->id()) <= 16 && abs((*neutrino)->id()) % 2 == 0 ) break; if ( neutrino == xproc.end() ) return false; PDPtr n = *neutrino; xproc.erase(neutrino); PDVector::iterator quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 && abs((*quark)->id()) % 2 == 1 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr d = *quark; xproc.erase(quark); quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 && abs((*quark)->id()) % 2 == 0 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr u = *quark; xproc.erase(quark); if ( u->iCharge() + d->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(u) != SU2Helper::family(d) ) return false; if ( SU2Helper::family(e) != SU2Helper::family(n) ) return false; return xproc.empty(); } void MatchboxAmplitudelnuqqbar::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); setupLeptons(0,amplitudeMomentum(0),1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudelnuqqbar::evaluate(size_t, const vector& hel, Complex& largeN) { if ( abs(hel[2]+hel[3]) != 2 ) { largeN = 0.; return 0.; } Complex ckmelement = 1.; if ( !theDiagonal ) { bool wPlus = ( abs(amplitudePartonData()[0]->id()) % 2 == 0 ) ? amplitudePartonData()[1]->id() < 0: amplitudePartonData()[0]->id() < 0; pair tmp( SU2Helper::family(amplitudePartonData()[2])-1, SU2Helper::family(amplitudePartonData()[3])-1); if ( amplitudePartonData()[3]->id() < 0 ) swap(tmp.first,tmp.second); ckmelement = theCKM[tmp.first][tmp.second]; if ( !wPlus ) ckmelement = conj(ckmelement); } Complex wPropergator = 1./Complex(((amplitudeMomentum(0)+amplitudeMomentum(1)).m2()-sqr(MW))/lastSHat(),MW*GW/lastSHat()); Complex wVertices = 2.*SM().alphaEMMZ()*Constants::pi/SM().sin2ThetaW()*ckmelement; const LorentzVector& leptonCurrent = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& quarkCurrent = qqbarLeftCurrent(2,hel[2],3,hel[3]); Complex current = hel[2] == 1 ? Complex(0.,-1)*leptonCurrent.dot(quarkCurrent): 0.; Complex res = current*wVertices*wPropergator; largeN = res; return res; } Complex MatchboxAmplitudelnuqqbar::evaluateOneLoop(size_t, const vector& hel) { if ( abs(hel[2]+hel[3]) != 2 ) return 0.; Complex ckmelement = 1.; if ( !theDiagonal ) { bool wPlus = ( abs(amplitudePartonData()[0]->id()) % 2 == 0 ) ? amplitudePartonData()[1]->id() < 0: amplitudePartonData()[0]->id() < 0; pair tmp( SU2Helper::family(amplitudePartonData()[2])-1, SU2Helper::family(amplitudePartonData()[3])-1); if ( amplitudePartonData()[3]->id() < 0 ) swap(tmp.first,tmp.second); ckmelement = theCKM[tmp.first][tmp.second]; if ( !wPlus ) ckmelement = conj(ckmelement); } Complex wPropergator = 1./Complex(((amplitudeMomentum(0)+amplitudeMomentum(1)).m2()-sqr(MW))/lastSHat(),MW*GW/lastSHat()); Complex wVertices = 2.*SM().alphaEMMZ()*Constants::pi/SM().sin2ThetaW()*ckmelement; const LorentzVector& leptonCurrent = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& quarkCurrent = qqbarLeftOneLoopCurrent(2,hel[2],3,hel[3]); Complex current = hel[2] == 1 ? Complex(0.,-1)*leptonCurrent.dot(quarkCurrent): 0.; Complex res = (SM().alphaS()/(2.*Constants::pi))*current*wVertices*wPropergator; return res; } void MatchboxAmplitudelnuqqbar::persistentOutput(PersistentOStream & os) const { os << theDiagonal << theCKM ; } void MatchboxAmplitudelnuqqbar::persistentInput(PersistentIStream & is, int) { is >> theDiagonal >> theCKM ; } DescribeClass describeHerwigMatchboxAmplitudelnuqqbar("Herwig::MatchboxAmplitudelnuqqbar", "HwMatchboxBuiltin.so"); void MatchboxAmplitudelnuqqbar::Init() { static ClassDocumentation documentation ("MatchboxAmplitudelnuqqbar"); static Switch interfaceDiagonal ("Diagonal", "Use a diagonal CKM matrix (ignoring the CKM object of the StandardModel).", &MatchboxAmplitudelnuqqbar::theDiagonal, false, false, false); static SwitchOption interfaceDiagonalYes (interfaceDiagonal, "Yes", "Use a diagonal CKM matrix.", true); static SwitchOption interfaceDiagonalNo (interfaceDiagonal, "No", "Use the CKM object as used by the StandardModel.", false); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbar.h @@ -1,185 +1,180 @@ // -*- C++ -*- // // MatchboxAmplitudelnuqqbar.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudelnuqqbar_H #define Herwig_MatchboxAmplitudelnuqqbar_H // // This is the declaration of the MatchboxAmplitudelnuqqbar class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" #include "ThePEG/StandardModel/StandardModelBase.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/MatrixElement/Matchbox/Utility/SU2Helper.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Thomas Schuh * * \brief MatchboxAmplitudelnuqqbar */ class MatchboxAmplitudelnuqqbar: public MatchboxAmplitude, public MatchboxCurrents { public: /** * The default constructor. */ MatchboxAmplitudelnuqqbar(); /** - * The destructor. - */ - virtual ~MatchboxAmplitudelnuqqbar(); - - /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 0; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 2; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return true; } /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } /** * 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: /** * 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; /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); private: /** * True, if a diagonal CKM matrix should be assumed. This ignores * the CKM object of the StandardModel. */ bool theDiagonal; /** * The ckm. */ vector< vector > theCKM; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudelnuqqbar & operator=(const MatchboxAmplitudelnuqqbar &) = delete; }; } #endif /* Herwig_MatchboxAmplitudelnuqqbar_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.cc @@ -1,203 +1,201 @@ // -*- C++ -*- // // MatchboxAmplitudelnuqqbarg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudelnuqqbarg class. // #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" using namespace Herwig; MatchboxAmplitudelnuqqbarg::MatchboxAmplitudelnuqqbarg() - : theDiagonal(false) {} - -MatchboxAmplitudelnuqqbarg::~MatchboxAmplitudelnuqqbarg() {} + : theDiagonal(false) {} void MatchboxAmplitudelnuqqbarg::doinit() { MatchboxAmplitude::doinit(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); theCKM = standardCKM(SM())->getUnsquaredMatrix(6); nPoints(5); } void MatchboxAmplitudelnuqqbarg::doinitrun() { MatchboxAmplitude::doinitrun(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(5); } IBPtr MatchboxAmplitudelnuqqbarg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudelnuqqbarg::fullclone() const { return new_ptr(*this); } bool MatchboxAmplitudelnuqqbarg::canHandle(const PDVector& proc) const { PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator elektron = xproc.begin(); for ( ; elektron != xproc.end(); ++elektron ) if ( abs((*elektron)->id()) >= 11 && abs((*elektron)->id()) <= 16 && abs((*elektron)->id()) % 2 == 1 ) break; if ( elektron == xproc.end() ) return false; PDPtr e = *elektron; xproc.erase(elektron); PDVector::iterator neutrino = xproc.begin(); for ( ; neutrino != xproc.end(); ++neutrino ) if ( abs((*neutrino)->id()) >= 11 && abs((*neutrino)->id()) <= 16 && abs((*neutrino)->id()) % 2 == 0 ) break; if ( neutrino == xproc.end() ) return false; PDPtr n = *neutrino; xproc.erase(neutrino); PDVector::iterator quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 && abs((*quark)->id()) % 2 == 1 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr d = *quark; xproc.erase(quark); quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 && abs((*quark)->id()) % 2 == 0 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr u = *quark; xproc.erase(quark); PDVector::iterator gluon = xproc.begin(); for ( ; gluon != xproc.end(); ++gluon ) if ( (*gluon)->id() == 21 ) break; if ( gluon == xproc.end() ) return false; xproc.erase(gluon); if ( SU2Helper::family(e) != SU2Helper::family(n) ) return false; if ( u->iCharge() + d->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(u) != SU2Helper::family(d) ) return false; return xproc.empty(); } void MatchboxAmplitudelnuqqbarg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); setupLeptons(0,amplitudeMomentum(0),1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); momentum(4,amplitudeMomentum(4)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudelnuqqbarg::evaluate(size_t, const vector& hel, Complex& largeN) { if ( abs(hel[2]+hel[3]) != 2 ) { largeN = 0.; return 0.; } Complex ckmelement = 1.; if ( !theDiagonal ) { bool wPlus = ( abs(amplitudePartonData()[0]->id()) % 2 == 0 ) ? amplitudePartonData()[1]->id() < 0: amplitudePartonData()[0]->id() < 0; pair tmp( SU2Helper::family(amplitudePartonData()[2])-1, SU2Helper::family(amplitudePartonData()[3])-1); if ( amplitudePartonData()[3]->id() < 0 ) swap(tmp.first,tmp.second); ckmelement = theCKM[tmp.first][tmp.second]; if ( !wPlus ) ckmelement = conj(ckmelement); } Complex wPropergator = 1./Complex(((amplitudeMomentum(0)+amplitudeMomentum(1)).m2()-sqr(MW))/lastSHat(),MW*GW/lastSHat()); Complex wVertices = 2.*SM().alphaEMMZ()*Constants::pi/SM().sin2ThetaW()*ckmelement; Complex sVertex = sqrt(4.*Constants::pi*SM().alphaS()); const LorentzVector& leptonCurrent = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& quarkCurrent = qqbargLeftCurrent(2,hel[2],3,hel[3],4,hel[4]); Complex current = hel[2] == 1 ? Complex(0.,-1)*leptonCurrent.dot(quarkCurrent): 0.; Complex res = current*wVertices*wPropergator*sVertex; largeN = res; return res; } Complex MatchboxAmplitudelnuqqbarg::evaluateOneLoop(size_t, const vector& hel) { if ( abs(hel[2]+hel[3]) != 2 ) return 0.; Complex ckmelement = 1.; if ( !theDiagonal ) { bool wPlus = ( abs(amplitudePartonData()[0]->id()) % 2 == 0 ) ? amplitudePartonData()[1]->id() < 0: amplitudePartonData()[0]->id() < 0; pair tmp( SU2Helper::family(amplitudePartonData()[2])-1, SU2Helper::family(amplitudePartonData()[3])-1); if ( amplitudePartonData()[3]->id() < 0 ) swap(tmp.first,tmp.second); ckmelement = theCKM[tmp.first][tmp.second]; if ( !wPlus ) ckmelement = conj(ckmelement); } Complex wPropergator = 1./Complex(((amplitudeMomentum(0)+amplitudeMomentum(1)).m2()-sqr(MW))/lastSHat(),MW*GW/lastSHat()); Complex wVertices = 2.*SM().alphaEMMZ()*Constants::pi/SM().sin2ThetaW()*ckmelement; Complex sVertex = sqrt(4.*Constants::pi*SM().alphaS()); const LorentzVector& leptonCurrent = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& quarkCurrent = qqbargLeftOneLoopCurrent(2,hel[2],3,hel[3],4,hel[4]); Complex current = hel[2] == 1 ? Complex(0.,-1)*leptonCurrent.dot(quarkCurrent): 0.; Complex res = (SM().alphaS()/(2.*Constants::pi))*current*wVertices*wPropergator*sVertex; return res; } void MatchboxAmplitudelnuqqbarg::persistentOutput(PersistentOStream & os) const { os << theDiagonal << theCKM ; } void MatchboxAmplitudelnuqqbarg::persistentInput(PersistentIStream & is, int) { is >> theDiagonal >> theCKM ; } DescribeClass describeHerwigMatchboxAmplitudelnuqqbarg("Herwig::MatchboxAmplitudelnuqqbarg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudelnuqqbarg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudelnuqqbarg"); static Switch interfaceDiagonal ("Diagonal", "Use a diagonal CKM matrix (ignoring the CKM object of the StandardModel).", &MatchboxAmplitudelnuqqbarg::theDiagonal, false, false, false); static SwitchOption interfaceDiagonalYes (interfaceDiagonal, "Yes", "Use a diagonal CKM matrix.", true); static SwitchOption interfaceDiagonalNo (interfaceDiagonal, "No", "Use the CKM object as used by the StandardModel.", false); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarg.h @@ -1,185 +1,180 @@ // -*- C++ -*- // // MatchboxAmplitudelnuqqbarg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudelnuqqbarg_H #define Herwig_MatchboxAmplitudelnuqqbarg_H // // This is the declaration of the MatchboxAmplitudelnuqqbarg class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" #include "ThePEG/StandardModel/StandardModelBase.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/MatrixElement/Matchbox/Utility/SU2Helper.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Thomas Schuh * * \brief MatchboxAmplitudelnuqqbarg */ class MatchboxAmplitudelnuqqbarg: public MatchboxAmplitude, public MatchboxCurrents { public: /** * The default constructor. */ MatchboxAmplitudelnuqqbarg(); /** - * The destructor. - */ - virtual ~MatchboxAmplitudelnuqqbarg(); - - /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 1; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 2; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return true; } /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluateOneLoop(size_t, const vector&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } /** * 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: /** * 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; /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); private: /** * True, if a diagonal CKM matrix should be assumed. This ignores * the CKM object of the StandardModel. */ bool theDiagonal; /** * The ckm. */ vector< vector > theCKM; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudelnuqqbarg & operator=(const MatchboxAmplitudelnuqqbarg &) = delete; }; } #endif /* Herwig_MatchboxAmplitudelnuqqbarg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.cc @@ -1,201 +1,199 @@ // -*- C++ -*- // // MatchboxAmplitudelnuqqbargg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudelnuqqbargg class. // #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" using namespace Herwig; MatchboxAmplitudelnuqqbargg::MatchboxAmplitudelnuqqbargg() - : theDiagonal(false) {} - -MatchboxAmplitudelnuqqbargg::~MatchboxAmplitudelnuqqbargg() {} + : theDiagonal(false) {} void MatchboxAmplitudelnuqqbargg::doinit() { MatchboxAmplitude::doinit(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); theCKM = standardCKM(SM())->getUnsquaredMatrix(6); nPoints(6); } void MatchboxAmplitudelnuqqbargg::doinitrun() { MatchboxAmplitude::doinitrun(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(6); } IBPtr MatchboxAmplitudelnuqqbargg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudelnuqqbargg::fullclone() const { return new_ptr(*this); } bool MatchboxAmplitudelnuqqbargg::canHandle(const PDVector& proc) const { PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator elektron = xproc.begin(); for ( ; elektron != xproc.end(); ++elektron ) if ( abs((*elektron)->id()) >= 11 && abs((*elektron)->id()) <= 16 && abs((*elektron)->id()) % 2 == 1 ) break; if ( elektron == xproc.end() ) return false; PDPtr e = *elektron; xproc.erase(elektron); PDVector::iterator neutrino = xproc.begin(); for ( ; neutrino != xproc.end(); ++neutrino ) if ( abs((*neutrino)->id()) >= 11 && abs((*neutrino)->id()) <= 16 && abs((*neutrino)->id()) % 2 == 0 ) break; if ( neutrino == xproc.end() ) return false; PDPtr n = *neutrino; xproc.erase(neutrino); PDVector::iterator quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 && abs((*quark)->id()) % 2 == 1 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr d = *quark; xproc.erase(quark); quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 && abs((*quark)->id()) % 2 == 0 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr u = *quark; xproc.erase(quark); PDVector::iterator gluon = xproc.begin(); for ( ; gluon != xproc.end(); ++gluon ) if ( (*gluon)->id() == 21 ) break; if ( gluon == xproc.end() ) return false; xproc.erase(gluon); gluon = xproc.begin(); for ( ; gluon != xproc.end(); ++gluon ) if ( (*gluon)->id() == 21 ) break; if ( gluon == xproc.end() ) return false; xproc.erase(gluon); if ( SU2Helper::family(e) != SU2Helper::family(n) ) return false; if ( u->iCharge() + d->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(u) != SU2Helper::family(d) ) return false; return xproc.empty(); } void MatchboxAmplitudelnuqqbargg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); setupLeptons(0,amplitudeMomentum(0),1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); momentum(4,amplitudeMomentum(4)); momentum(5,amplitudeMomentum(5)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudelnuqqbargg::evaluate(size_t a, const vector& hel, Complex& largeN) { if ( abs(hel[2]+hel[3]) != 2 ) { largeN = 0.; return 0.; } assert ( amplitudeToColourMap()[2] == 0 && amplitudeToColourMap()[3] == 1 ); int g1,hg1,g2,hg2; if ( amplitudeToColourMap()[4] == 2 && amplitudeToColourMap()[5] == 3 ) { if ( a == 0 ) { g1 = 4; hg1 = hel[4]; g2 = 5; hg2 = hel[5]; } else if ( a == 1 ) { g1 = 5; hg1 = hel[5]; g2 = 4; hg2 = hel[4]; } else assert ( false ); } else if ( amplitudeToColourMap()[4] == 3 && amplitudeToColourMap()[5] == 2 ) { if ( a == 0 ) { g1 = 5; hg1 = hel[5]; g2 = 4; hg2 = hel[4]; } else if ( a == 1 ) { g1 = 4; hg1 = hel[4]; g2 = 5; hg2 = hel[5]; } else assert ( false ); } else assert ( false ); Complex ckmelement = 1.; if ( !theDiagonal ) { bool wPlus = ( abs(amplitudePartonData()[0]->id()) % 2 == 0 ) ? amplitudePartonData()[1]->id() < 0: amplitudePartonData()[0]->id() < 0; pair tmp( SU2Helper::family(amplitudePartonData()[2]), SU2Helper::family(amplitudePartonData()[3])); if ( amplitudePartonData()[3]->id() < 0 ) swap(tmp.first,tmp.second); ckmelement = theCKM[tmp.first][tmp.second]; if ( !wPlus ) ckmelement = conj(ckmelement); } Complex wPropergator = 1./Complex(((amplitudeMomentum(0)+amplitudeMomentum(1)).m2()-sqr(MW))/lastSHat(),MW*GW/lastSHat()); Complex wVertices = 2.*SM().alphaEMMZ()*Constants::pi/SM().sin2ThetaW()*ckmelement; Complex sVertices = 4.*Constants::pi*SM().alphaS(); const LorentzVector& leptonCurrent = llbarLeftCurrent(0,hel[0],1,hel[1]); const LorentzVector& quarkCurrent = qqbarggLeftCurrent(2,hel[2],3,hel[3],g1,hg1,g2,hg2); Complex current = hel[2] == 1 ? Complex(0.,-1)*leptonCurrent.dot(quarkCurrent): 0.; Complex res = current*wVertices*wPropergator*sVertices; largeN = res; return res; } void MatchboxAmplitudelnuqqbargg::persistentOutput(PersistentOStream & os) const { os << theDiagonal << theCKM ; } void MatchboxAmplitudelnuqqbargg::persistentInput(PersistentIStream & is, int) { is >> theDiagonal >> theCKM ; } DescribeClass describeHerwigMatchboxAmplitudelnuqqbargg("Herwig::MatchboxAmplitudelnuqqbargg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudelnuqqbargg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudelnuqqbargg"); static Switch interfaceDiagonal ("Diagonal", "Use a diagonal CKM matrix (ignoring the CKM object of the StandardModel).", &MatchboxAmplitudelnuqqbargg::theDiagonal, false, false, false); static SwitchOption interfaceDiagonalYes (interfaceDiagonal, "Yes", "Use a diagonal CKM matrix.", true); static SwitchOption interfaceDiagonalNo (interfaceDiagonal, "No", "Use the CKM object as used by the StandardModel.", false); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbargg.h @@ -1,179 +1,174 @@ // -*- C++ -*- // // MatchboxAmplitudelnuqqbargg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudelnuqqbargg_H #define Herwig_MatchboxAmplitudelnuqqbargg_H // // This is the declaration of the MatchboxAmplitudelnuqqbargg class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" #include "ThePEG/StandardModel/StandardModelBase.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/MatrixElement/Matchbox/Utility/SU2Helper.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Thomas Schuh * * \brief MatchboxAmplitudelnuqqbargg */ class MatchboxAmplitudelnuqqbargg: public MatchboxAmplitude, public MatchboxCurrents { public: /** * The default constructor. */ MatchboxAmplitudelnuqqbargg(); /** - * The destructor. - */ - virtual ~MatchboxAmplitudelnuqqbargg(); - - /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 2; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 2; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } /** * 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: /** * 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; /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); private: /** * True, if a diagonal CKM matrix should be assumed. This ignores * the CKM object of the StandardModel. */ bool theDiagonal; /** * The ckm. */ vector< vector > theCKM; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudelnuqqbargg & operator=(const MatchboxAmplitudelnuqqbargg &) = delete; }; } #endif /* Herwig_MatchboxAmplitudelnuqqbargg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.cc @@ -1,275 +1,273 @@ // -*- C++ -*- // // MatchboxAmplitudelnuqqbarqqbar.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudelnuqqbarqqbar class. // #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.h" using namespace Herwig; MatchboxAmplitudelnuqqbarqqbar::MatchboxAmplitudelnuqqbarqqbar() - : theDiagonal(false) {} - -MatchboxAmplitudelnuqqbarqqbar::~MatchboxAmplitudelnuqqbarqqbar() {} + : theDiagonal(false) {} void MatchboxAmplitudelnuqqbarqqbar::doinit() { MatchboxAmplitude::doinit(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); theCKM = standardCKM(SM())->getUnsquaredMatrix(6); nPoints(6); } void MatchboxAmplitudelnuqqbarqqbar::doinitrun() { MatchboxAmplitude::doinitrun(); MZ = getParticleData(ParticleID::Z0)->hardProcessMass(); GZ = getParticleData(ParticleID::Z0)->hardProcessWidth(); MW = getParticleData(ParticleID::Wplus)->hardProcessMass(); GW = getParticleData(ParticleID::Wplus)->hardProcessWidth(); CA = SM().Nc(); CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); nPoints(6); } IBPtr MatchboxAmplitudelnuqqbarqqbar::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudelnuqqbarqqbar::fullclone() const { return new_ptr(*this); } bool MatchboxAmplitudelnuqqbarqqbar::canHandle(const PDVector& proc) const { PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); // Charge charge(ZERO); PDVector::iterator elektron = xproc.begin(); for ( ; elektron != xproc.end(); ++elektron ) if ( abs((*elektron)->id()) >= 11 && abs((*elektron)->id()) <= 16 && abs((*elektron)->id()) % 2 == 1 ) break; if ( elektron == xproc.end() ) return false; PDPtr e = *elektron; xproc.erase(elektron); PDVector::iterator neutrino = xproc.begin(); for ( ; neutrino != xproc.end(); ++neutrino ) if ( abs((*neutrino)->id()) >= 11 && abs((*neutrino)->id()) <= 16 && abs((*neutrino)->id()) % 2 == 0 ) break; if ( neutrino == xproc.end() ) return false; PDPtr n = *neutrino; xproc.erase(neutrino); PDVector::iterator quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr q1 = *quark; xproc.erase(quark); quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr q2 = *quark; xproc.erase(quark); quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr q3 = *quark; xproc.erase(quark); quark = xproc.begin(); for ( ; quark != xproc.end(); ++quark ) if ( abs((*quark)->id()) >= 1 && abs((*quark)->id()) <= 6 ) { assert( (*quark)->hardProcessMass() == ZERO ); break; } if ( quark == xproc.end() ) return false; PDPtr q4 = *quark; xproc.erase(quark); if ( q1->id() == -q2->id() ) { if ( q3->iCharge() + q4->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(q3) != SU2Helper::family(q4) ) return false; } else if ( q1->id() == -q3->id() ) { if ( q2->iCharge() + q4->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(q2) != SU2Helper::family(q4) ) return false; } else if ( q1->id() == -q4->id() ) { if ( q2->iCharge() + q3->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(q2) != SU2Helper::family(q3) ) return false; } else if ( q2->id() == -q3->id() ) { if ( q1->iCharge() + q4->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(q1) != SU2Helper::family(q4) ) return false; } else if ( q2->id() == -q4->id() ) { if ( q1->iCharge() + q3->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(q1) != SU2Helper::family(q3) ) return false; } else if ( q3->id() == -q4->id() ) { if ( q1->iCharge() + q2->iCharge() + e->iCharge() != PDT::ChargeNeutral ) return false; if ( theDiagonal && SU2Helper::family(q1) != SU2Helper::family(q2) ) return false; } else return false; if ( SU2Helper::family(e) != SU2Helper::family(n) ) return false; return xproc.empty(); } void MatchboxAmplitudelnuqqbarqqbar::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); setupLeptons(0,amplitudeMomentum(0),1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); momentum(4,amplitudeMomentum(4)); momentum(5,amplitudeMomentum(5)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudelnuqqbarqqbar::evaluate(size_t a, const vector& hel, Complex& largeN) { const LorentzVector& leptonCurrent = llbarLeftCurrent(0,hel[0],1,hel[1]); Complex Current2345 = hel[2] == 1 && hel[3] == 1 && abs(hel[4]+hel[5]) == 2 && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[5]->id()) ? leptonCurrent.dot(qqbarqqbarLeftCurrent(2,hel[2],3,hel[3],4,hel[4],5,hel[5])) : 0.; Complex Current4523 = hel[4] == 1 && hel[5] == 1 && abs(hel[2]+hel[3]) == 2 && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[3]->id()) ? leptonCurrent.dot(qqbarqqbarLeftCurrent(4,hel[4],5,hel[5],2,hel[2],3,hel[3])) : 0.; Complex Current2543 = hel[2] == 1 && hel[5] == 1 && abs(hel[4]+hel[3]) == 2 && abs(amplitudePartonData()[4]->id()) == abs(amplitudePartonData()[3]->id()) ? -leptonCurrent.dot(qqbarqqbarLeftCurrent(2,hel[2],5,hel[5],4,hel[4],3,hel[3])) : 0.; Complex Current4325 = hel[4] == 1 && hel[3] == 1 && abs(hel[2]+hel[5]) == 2 && abs(amplitudePartonData()[2]->id()) == abs(amplitudePartonData()[5]->id()) ? -leptonCurrent.dot(qqbarqqbarLeftCurrent(4,hel[4],3,hel[3],2,hel[2],5,hel[5])) : 0.; Complex ckmelement23 = 1.; Complex ckmelement45 = 1.; if ( !theDiagonal ) { bool wPlus = ( abs(amplitudePartonData()[0]->id()) % 2 == 0 ) ? amplitudePartonData()[1]->id() < 0: amplitudePartonData()[0]->id() < 0; pair tmp23( SU2Helper::family(amplitudePartonData()[2])-1, SU2Helper::family(amplitudePartonData()[3])-1); pair tmp45( SU2Helper::family(amplitudePartonData()[4])-1, SU2Helper::family(amplitudePartonData()[5])-1); if ( amplitudePartonData()[3]->id() < 0 ) swap(tmp23.first,tmp23.second); if ( amplitudePartonData()[5]->id() < 0 ) swap(tmp45.first,tmp45.second); ckmelement23 = theCKM[tmp23.first][tmp23.second]; ckmelement45 = theCKM[tmp45.first][tmp45.second]; if ( !wPlus ) { ckmelement23 = conj(ckmelement23); ckmelement45 = conj(ckmelement45); } } Complex wPropergator = 1./Complex(((amplitudeMomentum(0)+amplitudeMomentum(1)).m2()-sqr(MW))/lastSHat(),MW*GW/lastSHat()); Complex wVertices23 = 2.*SM().alphaEMMZ()*Constants::pi/SM().sin2ThetaW()*ckmelement23; Complex wVertices45 = 2.*SM().alphaEMMZ()*Constants::pi/SM().sin2ThetaW()*ckmelement45; Complex sVertices = 4.*Constants::pi*SM().alphaS(); Complex res2345 = Complex(0.,-1.)*wPropergator*sVertices*Current2345*wVertices23; Complex res2543 = Complex(0.,-1.)*wPropergator*sVertices*Current2543*wVertices23; Complex res4523 = Complex(0.,-1.)*wPropergator*sVertices*Current4523*wVertices45; Complex res4325 = Complex(0.,-1.)*wPropergator*sVertices*Current4325*wVertices45; double Nc = SM().Nc(); Complex resLeading = 0.; Complex resSubLeading = 0.; if ( amplitudeToColourMap()[2] == 0 && amplitudeToColourMap()[3] == 1 && amplitudeToColourMap()[4] == 2 && amplitudeToColourMap()[5] == 3 ) { if ( a == 0 ) { //(23)(45) resLeading = res2543 + res4325; resSubLeading = res2345 + res4523; } else if ( a == 1 ) { //(25)(43) resLeading = res2345 + res4523; resSubLeading = res2543 + res4325; } else assert(false); } else if ( amplitudeToColourMap()[2] == 0 && amplitudeToColourMap()[3] == 3 && amplitudeToColourMap()[4] == 2 && amplitudeToColourMap()[5] == 1 ) { if ( a == 0 ) { // (25)(43) resLeading = res2345 + res4523; resSubLeading = res2543 + res4325; } else if ( a == 1 ) { // (23)(45) resLeading = res2543 + res4325; resSubLeading = res2345 + res4523; } else assert(false); } else if ( amplitudeToColourMap()[2] == 2 && amplitudeToColourMap()[3] == 3 && amplitudeToColourMap()[4] == 0 && amplitudeToColourMap()[5] == 1 ) { if ( a == 0 ) { //(23)(45) resLeading = res2543 + res4325; resSubLeading = res2345 + res4523; } else if ( a == 1 ) { //(25)(43) resLeading = res2345 + res4523; resSubLeading = res2543 + res4325; } else assert(false); } else if ( amplitudeToColourMap()[2] == 2 && amplitudeToColourMap()[3] == 1 && amplitudeToColourMap()[4] == 0 && amplitudeToColourMap()[5] == 3 ) { if ( a == 0 ) { //(25)(43) resLeading = res2345 + res4523; resSubLeading = res2543 + res4325; } else if ( a == 1 ) { //(23)(45) resLeading = res2543 + res4325; resSubLeading = res2345 + res4523; } else assert(false); } else assert(false); resSubLeading *= -1./Nc; largeN = resLeading/2.; return (resLeading + resSubLeading)/2.; } void MatchboxAmplitudelnuqqbarqqbar::persistentOutput(PersistentOStream & os) const { os << theDiagonal << theCKM ; } void MatchboxAmplitudelnuqqbarqqbar::persistentInput(PersistentIStream & is, int) { is >> theDiagonal >> theCKM ; } DescribeClass describeHerwigMatchboxAmplitudelnuqqbarqqbar("Herwig::MatchboxAmplitudelnuqqbarqqbar", "HwMatchboxBuiltin.so"); void MatchboxAmplitudelnuqqbarqqbar::Init() { static ClassDocumentation documentation ("MatchboxAmplitudelnuqqbarqqbar"); static Switch interfaceDiagonal ("Diagonal", "Use a diagonal CKM matrix (ignoring the CKM object of the StandardModel).", &MatchboxAmplitudelnuqqbarqqbar::theDiagonal, false, false, false); static SwitchOption interfaceDiagonalYes (interfaceDiagonal, "Yes", "Use a diagonal CKM matrix.", true); static SwitchOption interfaceDiagonalNo (interfaceDiagonal, "No", "Use the CKM object as used by the StandardModel.", false); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudelnuqqbarqqbar.h @@ -1,181 +1,176 @@ // -*- C++ -*- // // MatchboxAmplitudelnuqqbarqqbar.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudelnuqqbarqqbar_H #define Herwig_MatchboxAmplitudelnuqqbarqqbar_H // // This is the declaration of the MatchboxAmplitudelnuqqbarqqbar class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" #include "Herwig/MatrixElement/Matchbox/Utility/SU2Helper.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Thomas Schuh * * \brief MatchboxAmplitudelnuqqbarqqbar */ class MatchboxAmplitudelnuqqbarqqbar: public MatchboxAmplitude, public MatchboxCurrents { public: /** * The default constructor. */ MatchboxAmplitudelnuqqbarqqbar(); /** - * The destructor. - */ - virtual ~MatchboxAmplitudelnuqqbarqqbar(); - - /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const { return 2; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 2; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Return true, if one loop corrections are given in the conventions * of BDK. */ virtual bool isBDK() const { return true; } /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } /** * 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: /** * 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; /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); private: /** * True, if a diagonal CKM matrix should be assumed. This ignores * the CKM object of the StandardModel. */ bool theDiagonal; /** * The ckm. */ vector< vector > theCKM; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudelnuqqbarqqbar & operator=(const MatchboxAmplitudelnuqqbarqqbar &) = delete; }; } #endif /* Herwig_MatchboxAmplitudelnuqqbarqqbar_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbar.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbar.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbar.cc @@ -1,188 +1,184 @@ // -*- C++ -*- // // MatchboxAmplitudeqqbarttbar.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudeqqbarttbar class. // #include "MatchboxAmplitudeqqbarttbar.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudeqqbarttbar::MatchboxAmplitudeqqbarttbar() {} -MatchboxAmplitudeqqbarttbar::~MatchboxAmplitudeqqbarttbar() {} - IBPtr MatchboxAmplitudeqqbarttbar::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudeqqbarttbar::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudeqqbarttbar::setupParams(map &MGParams){ // create parameter map for adapted Madgraph amplitude to use MGParams["aS"] = SM().alphaS(); MGParams["MZ"] = getParticleData(ParticleID::Z0) -> hardProcessMass()/GeV; MGParams["MW"] = getParticleData(ParticleID::Wplus) -> hardProcessMass()/GeV; MGParams["MH"] = getParticleData(ParticleID::h0) -> hardProcessMass()/GeV; MGParams["MT"] = getParticleData(ParticleID::t) -> hardProcessMass()/GeV; MGParams["MB"] = getParticleData(ParticleID::b) -> hardProcessMass()/GeV; MGParams["MTA"] = getParticleData(ParticleID::tauminus)-> hardProcessMass()/GeV; MGParams["WW"] = getParticleData(ParticleID::Wplus) ->hardProcessWidth()/GeV; MGParams["WZ"] = getParticleData(ParticleID::Z0) ->hardProcessWidth()/GeV; MGParams["WH"] = getParticleData(ParticleID::h0) ->hardProcessWidth()/GeV; MGParams["WT"] = getParticleData(ParticleID::t) ->hardProcessWidth()/GeV; MGParams["WB"] = getParticleData(ParticleID::b) ->hardProcessWidth()/GeV; MGParams["GF"] = SM().fermiConstant()*GeV2; MGParams["aEWM1"] = 1./SM().alphaEMMZ(); return; } void MatchboxAmplitudeqqbarttbar::doinit() { setupParams(MGParams_); MatchboxAmplitude::doinit(); nPoints(4); } void MatchboxAmplitudeqqbarttbar::doinitrun() { setupParams(MGParams_); MatchboxAmplitude::doinitrun(); nPoints(4); } bool MatchboxAmplitudeqqbarttbar::canHandle(const PDVector& proc) const { // check process is qqbar > ttbar if ( proc.size() != 4 ) return false; PDVector xproc = proc; PDVector::iterator top = xproc.begin(); long topId = 0; for ( ; top != xproc.end(); ++top ) if ( (**top).id() == 6 ) { break; } if ( top == xproc.end() ) return false; topId = (**top).id(); xproc.erase(top); PDVector::iterator antiTop = xproc.begin(); for ( ; antiTop != xproc.end(); ++antiTop ) if ( (**antiTop).id() == -topId ) { break; } if ( antiTop == xproc.end() ) return false; xproc.erase(antiTop); PDVector::iterator quark = xproc.begin(); long quarkId = 0; for ( ; quark != xproc.end(); ++quark ) if ( abs((**quark).id()) < 6 && (**quark).id() > 0 ) { break; } if ( quark == xproc.end() ) return false; quarkId = (**quark).id(); xproc.erase(quark); PDVector::iterator antiQuark = xproc.begin(); for ( ; antiQuark != xproc.end(); ++antiQuark ) if ( (**antiQuark).id() == -quarkId ) { break; } if ( antiQuark == xproc.end() ) return false; xproc.erase(antiQuark); return xproc.empty(); } void MatchboxAmplitudeqqbarttbar::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); momentum(0,amplitudeMomentum(0)); momentum(1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudeqqbarttbar::evaluate(size_t a, const vector& hel, Complex& largeN) { // set up momenta to pass into Madgraph amplitude vector p; p.push_back(mom0); p.push_back(mom1); p.push_back(mom2); p.push_back(mom3); for (int ip=0; ip<4; ++ip){ p[ip][0] = abs(momentum(ip).e())<1.e-13 ? 0.0:double(momentum(ip).e()*amplitudeScale()/GeV); p[ip][1] = abs(momentum(ip).x())<1.e-13 ? 0.0:double(momentum(ip).x()*amplitudeScale()/GeV); p[ip][2] = abs(momentum(ip).y())<1.e-13 ? 0.0:double(momentum(ip).y()*amplitudeScale()/GeV); p[ip][3] = abs(momentum(ip).z())<1.e-13 ? 0.0:double(momentum(ip).z()*amplitudeScale()/GeV); } // calculate amplitudes vector > amplitudes; MG_qqx2ttx process; process.initProc(MGParams_); process.setMomenta(p); process.sigmaKin(amplitudes, hel); // calculate colour flows complex matrixElement; if (a==0) matrixElement = amplitudes[0]*( 1./6.); else if (a==1) matrixElement = amplitudes[0]*(-1./2.); else assert(false); largeN = matrixElement; return matrixElement; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudeqqbarttbar::persistentOutput(PersistentOStream &) const {} void MatchboxAmplitudeqqbarttbar::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxAmplitudeqqbarttbar("Herwig::MatchboxAmplitudeqqbarttbar", "HwMatchboxBuiltin.so"); void MatchboxAmplitudeqqbarttbar::Init() { static ClassDocumentation documentation ("MatchboxAmplitudeqqbarttbar"); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbar.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbar.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbar.h @@ -1,201 +1,193 @@ // -*- C++ -*- // // MatchboxAmplitudeqqbarttbar.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudeqqbarttbar_H #define Herwig_MatchboxAmplitudeqqbarttbar_H // // This is the declaration of the MatchboxAmplitudeqqbarttbar class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" #include "MG_qqx2ttx.h" #include "HelAmps_sm.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Alix Wilcock * * \brief MatchboxAmplitudeqqbarttbar */ class MatchboxAmplitudeqqbarttbar: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudeqqbarttbar(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudeqqbarttbar(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const {return 2; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 0; } /** * Return true, if this amplitude will not require colour correlations. */ virtual bool noCorrelations() const { return false; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudeqqbarttbar & operator=(const MatchboxAmplitudeqqbarttbar &) = delete; /** * Containers for external particle momenta */ double mom0 [4]; double mom1 [4]; double mom2 [4]; double mom3 [4]; /** * Fill MGParams_ with Herwig values of parameters */ void setupParams(map & MGParams); /** * Stores parameters needed in MG_process */ map MGParams_; }; } #endif /* Herwig_MatchboxAmplitudeqqbarttbar_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbarg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbarg.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbarg.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbarg.cc @@ -1,219 +1,217 @@ // -*- C++ -*- // // MatchboxAmplitudeqqbarttbarg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxAmplitudeqqbarttbarg class. // #include "MatchboxAmplitudeqqbarttbarg.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; MatchboxAmplitudeqqbarttbarg::MatchboxAmplitudeqqbarttbarg() {} -MatchboxAmplitudeqqbarttbarg::~MatchboxAmplitudeqqbarttbarg() {} - IBPtr MatchboxAmplitudeqqbarttbarg::clone() const { return new_ptr(*this); } IBPtr MatchboxAmplitudeqqbarttbarg::fullclone() const { return new_ptr(*this); } void MatchboxAmplitudeqqbarttbarg::setupParams(map &MGParams){ // create parameter map for adapted Madgraph amplitude to use MGParams["aS"] = SM().alphaS(); MGParams["MZ"] = getParticleData(ParticleID::Z0) -> hardProcessMass()/GeV; MGParams["MW"] = getParticleData(ParticleID::Wplus) -> hardProcessMass()/GeV; MGParams["MH"] = getParticleData(ParticleID::h0) -> hardProcessMass()/GeV; MGParams["WW"] = getParticleData(ParticleID::Wplus) ->hardProcessWidth()/GeV; MGParams["WZ"] = getParticleData(ParticleID::Z0) ->hardProcessWidth()/GeV; MGParams["WH"] = getParticleData(ParticleID::h0) ->hardProcessWidth()/GeV; MGParams["MT"] = getParticleData(ParticleID::t) -> hardProcessMass()/GeV; MGParams["MB"] = getParticleData(ParticleID::b) -> hardProcessMass()/GeV; MGParams["WT"] = getParticleData(ParticleID::t) ->hardProcessWidth()/GeV; MGParams["WB"] = getParticleData(ParticleID::b) ->hardProcessWidth()/GeV; MGParams["MTA"] = getParticleData(ParticleID::tauminus)-> hardProcessMass()/GeV; MGParams["GF"] = SM().fermiConstant()*GeV2; MGParams["aEWM1"] = 1./SM().alphaEMMZ(); return; } void MatchboxAmplitudeqqbarttbarg::doinit() { setupParams(MGParams_); MatchboxAmplitude::doinit(); nPoints(5); } void MatchboxAmplitudeqqbarttbarg::doinitrun() { setupParams(MGParams_); MatchboxAmplitude::doinitrun(); nPoints(5); } bool MatchboxAmplitudeqqbarttbarg::canHandle(const PDVector& proc) const { // check process is qqbar > ttbarg or some crossing of this if ( proc.size() != 5 ) return false; PDVector xproc = proc; if ( xproc[0]->CC() ) xproc[0] = xproc[0]->CC(); if ( xproc[1]->CC() ) xproc[1] = xproc[1]->CC(); PDVector::iterator top = xproc.begin(); long topId = 0; for ( ; top != xproc.end(); ++top ) if ( (**top).id() == 6 ) { break; } if ( top == xproc.end() ) return false; topId = (**top).id(); xproc.erase(top); PDVector::iterator antiTop = xproc.begin(); for ( ; antiTop != xproc.end(); ++antiTop ) if ( (**antiTop).id() == -topId ) { break; } if ( antiTop == xproc.end() ) return false; xproc.erase(antiTop); PDVector::iterator quark = xproc.begin(); long quarkId = 0; for ( ; quark != xproc.end(); ++quark ) if ( abs((**quark).id()) < 6 && (**quark).id() > 0 ) { break; } if ( quark == xproc.end() ) return false; quarkId = (**quark).id(); xproc.erase(quark); PDVector::iterator antiQuark = xproc.begin(); for ( ; antiQuark != xproc.end(); ++antiQuark ) if ( (**antiQuark).id() == -quarkId ) { break; } if ( antiQuark == xproc.end() ) return false; xproc.erase(antiQuark); return xproc[0]->id() == 21; } void MatchboxAmplitudeqqbarttbarg::prepareAmplitudes(Ptr::tcptr me) { if ( !calculateTreeAmplitudes() ) { MatchboxAmplitude::prepareAmplitudes(me); return; } amplitudeScale(sqrt(lastSHat())); momentum(0,amplitudeMomentum(0)); momentum(1,amplitudeMomentum(1)); momentum(2,amplitudeMomentum(2)); momentum(3,amplitudeMomentum(3)); momentum(4,amplitudeMomentum(4)); MatchboxAmplitude::prepareAmplitudes(me); } Complex MatchboxAmplitudeqqbarttbarg::evaluate(size_t a, const vector& hel, Complex& largeN) { // check if doing qqbar, qg or qbarg initiated process int crossed; cPDVector partons = mePartonData(); if (abs(partons[0]->id())< 6 && partons[1]->id()==-partons[0]->id()) crossed=1; else if (((partons[0]->id()>0 && partons[0]->id()<6) && partons[1]->id()==ParticleID::g) || ((partons[1]->id()>0 && partons[1]->id()<6) && partons[0]->id()==ParticleID::g)) crossed=2; else if (((partons[0]->id()<0 && partons[0]->id()>-6) && partons[1]->id()==ParticleID::g) || ((partons[1]->id()<0 && partons[1]->id()>-6) && partons[0]->id()==ParticleID::g)) crossed=3; else throw Exception() << "MatchboxAmplitudeqqbarststbarg::evaluate(): Unrecognised process\n" << Exception::runerror; // set up momenta to pass into Madgraph amplitude vector p; p.push_back(mom0); p.push_back(mom1); p.push_back(mom2); p.push_back(mom3); p.push_back(mom4); for (int ip=0; ip<5; ++ip){ p[ip][0] = abs(momentum(ip).e())<1.e-13 ? 0.0:double(momentum(ip).e()*amplitudeScale()/GeV); p[ip][1] = abs(momentum(ip).x())<1.e-13 ? 0.0:double(momentum(ip).x()*amplitudeScale()/GeV); p[ip][2] = abs(momentum(ip).y())<1.e-13 ? 0.0:double(momentum(ip).y()*amplitudeScale()/GeV); p[ip][3] = abs(momentum(ip).z())<1.e-13 ? 0.0:double(momentum(ip).z()*amplitudeScale()/GeV); } // calculate amplitudes vector > amplitudes; MG_qqx2ttxg process; double factor=lastSHat()/GeV2; process.initProc(MGParams_); process.setMomenta(p); process.sigmaKin(amplitudes, hel, crossed); for (int iamp=0; iamp matrixElement; complex i = complex(0,1); // calculate colour flows if (a==0) matrixElement = (1./6.)*(amplitudes[1] + amplitudes[2]); else if (a==1) matrixElement = 1./2.*( i*amplitudes[0] - amplitudes[1] - amplitudes[3]); else if (a==2) matrixElement = (1./6.)*( amplitudes[3] + amplitudes[4]); else if (a==3) matrixElement = 1./2.*(-i*amplitudes[0] - amplitudes[2] - amplitudes[4]); else assert(false); largeN = matrixElement; return matrixElement; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxAmplitudeqqbarttbarg::persistentOutput(PersistentOStream &) const {} void MatchboxAmplitudeqqbarttbarg::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxAmplitudeqqbarttbarg("Herwig::MatchboxAmplitudeqqbarttbarg", "HwMatchboxBuiltin.so"); void MatchboxAmplitudeqqbarttbarg::Init() { static ClassDocumentation documentation ("MatchboxAmplitudeqqbarttbarg"); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbarg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbarg.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbarg.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudeqqbarttbarg.h @@ -1,202 +1,194 @@ // -*- C++ -*- // // MatchboxAmplitudeqqbarttbarg.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxAmplitudeqqbarttbarg_H #define Herwig_MatchboxAmplitudeqqbarttbarg_H // // This is the declaration of the MatchboxAmplitudeqqbarttbarg class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h" #include "MG_qqx2ttxg.h" #include "HelAmps_sm.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Alix Wilcock * * \brief MatchboxAmplitudeqqbarttbarg */ class MatchboxAmplitudeqqbarttbarg: public MatchboxAmplitude, public MatchboxCurrents { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxAmplitudeqqbarttbarg(); - /** - * The destructor. - */ - virtual ~MatchboxAmplitudeqqbarttbarg(); - //@} - public: /** * Return true, if this amplitude can handle the given process. */ virtual bool canHandle(const PDVector&) const; /** * Return the (tree-level) order in \f$g_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInGs() const {return 3; } /** * Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix * element is given. */ virtual unsigned int orderInGem() const { return 0; } /** * Return true, if this amplitude will not require colour correlations. */ virtual bool noCorrelations() const { return true; } /** * Return true, if this amplitude is capable of calculating one-loop * (QCD) corrections. */ virtual bool haveOneLoop() const { return false; } /** * Calculate the tree level amplitudes for the phasespace point * stored in lastXComb. */ virtual void prepareAmplitudes(Ptr::tcptr); /** * Evaluate the amplitude for the given colour tensor id and * helicity assignment */ virtual Complex evaluate(size_t, const vector&, Complex&); /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ virtual Energy2 mu2() const { return lastSHat(); } /** * Flush all cashes. */ virtual void flushCaches() { MatchboxCurrents::reset(); MatchboxAmplitude::flushCaches(); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxAmplitudeqqbarttbarg & operator=(const MatchboxAmplitudeqqbarttbarg &) = delete; /** * Containers for external particle momenta */ double mom0 [4]; double mom1 [4]; double mom2 [4]; double mom3 [4]; double mom4 [4]; /** * Fill MGParams_ with Herwig values of parameters */ void setupParams(map & MGParams); /** * Stores parameters needed in MG_process */ map MGParams_; }; } #endif /* Herwig_MatchboxAmplitudeqqbarttbarg_H */ diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.cc --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.cc +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.cc @@ -1,91 +1,89 @@ // -*- C++ -*- // // MatchboxZGammaAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxZGammaAmplitude class. // #include "MatchboxZGammaAmplitude.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MatchboxZGammaAmplitude::MatchboxZGammaAmplitude() : MatchboxAmplitude(), theIncludeZ(true), theIncludeGamma(true) {} -MatchboxZGammaAmplitude::~MatchboxZGammaAmplitude() {} - // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxZGammaAmplitude::persistentOutput(PersistentOStream & os) const { os << theIncludeZ << theIncludeGamma; } void MatchboxZGammaAmplitude::persistentInput(PersistentIStream & is, int) { is >> theIncludeZ >> theIncludeGamma; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeHerwigMatchboxZGammaAmplitude("Herwig::MatchboxZGammaAmplitude", "HwMatchboxBuiltin.so"); void MatchboxZGammaAmplitude::Init() { static ClassDocumentation documentation ("There is no documentation for the MatchboxZGammaAmplitude class"); static Switch interfaceIncludeZ ("IncludeZ", "Include the Z contribution.", &MatchboxZGammaAmplitude::theIncludeZ, true, false, false); static SwitchOption interfaceIncludeZYes (interfaceIncludeZ, "Yes", "", true); static SwitchOption interfaceIncludeZNo (interfaceIncludeZ, "No", "", false); static Switch interfaceIncludeGamma ("IncludeGamma", "Include the photon contribution.", &MatchboxZGammaAmplitude::theIncludeGamma, true, false, false); static SwitchOption interfaceIncludeGammaYes (interfaceIncludeGamma, "Yes", "", true); static SwitchOption interfaceIncludeGammaNo (interfaceIncludeGamma, "No", "", false); } diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h --- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h +++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h @@ -1,109 +1,101 @@ // -*- C++ -*- // // MatchboxZGammaAmplitude.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxZGammaAmplitude_H #define Herwig_MatchboxZGammaAmplitude_H // // This is the declaration of the MatchboxZGammaAmplitude class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the MatchboxZGammaAmplitude class. * * @see \ref MatchboxZGammaAmplitudeInterfaces "The interfaces" * defined for MatchboxZGammaAmplitude. */ class MatchboxZGammaAmplitude: public MatchboxAmplitude { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxZGammaAmplitude(); - /** - * The destructor. - */ - virtual ~MatchboxZGammaAmplitude(); - //@} - public: /** * Return true, if the Z contribution should be taken into account */ bool includeZ() const { return theIncludeZ; } /** * Return true, if the gamma contribution should be taken into account */ bool includeGamma() const { return theIncludeGamma; } 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 assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxZGammaAmplitude & operator=(const MatchboxZGammaAmplitude &) = delete; /** * True, if the Z contribution should be taken into account */ bool theIncludeZ; /** * True, if the gamma contribution should be taken into account */ bool theIncludeGamma; }; } #endif /* Herwig_MatchboxZGammaAmplitude_H */ diff --git a/MatrixElement/Matchbox/Cuts/IdentifiedParticleCut.cc b/MatrixElement/Matchbox/Cuts/IdentifiedParticleCut.cc --- a/MatrixElement/Matchbox/Cuts/IdentifiedParticleCut.cc +++ b/MatrixElement/Matchbox/Cuts/IdentifiedParticleCut.cc @@ -1,151 +1,149 @@ // -*- C++ -*- // // IdentifiedParticleCut.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IdentifiedParticleCut class. // #include "IdentifiedParticleCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IdentifiedParticleCut::IdentifiedParticleCut() : thePtMin(0.*GeV), thePtMax(Constants::MaxEnergy) {} -IdentifiedParticleCut::~IdentifiedParticleCut() {} - IBPtr IdentifiedParticleCut::clone() const { return new_ptr(*this); } IBPtr IdentifiedParticleCut::fullclone() const { return new_ptr(*this); } bool IdentifiedParticleCut::passCuts(tcCutsPtr parent, tcPDPtr ptype, LorentzMomentum p) const { if ( !matcher()->check(*ptype) || ( thePtMin == ZERO && thePtMax == Constants::MaxEnergy && theYRanges.empty() ) ) return true; double weight = 1.0; if ( !parent->isInside(p.perp(),ptMin(),ptMax(),weight) ) { parent->lastCutWeight(0.0); return false; } double y = p.rapidity() + parent->currentYHat(); for ( vector >::const_iterator dy = yRanges().begin(); dy != yRanges().end(); ++dy ) { if ( !parent->isInside(y,dy->first,dy->second,weight) ) { parent->lastCutWeight(0.0); return false; } } parent->lastCutWeight(weight); return true; } void IdentifiedParticleCut::describe() const { CurrentGenerator::log() << "IdentifiedParticleCut '" << name() << "' matching " << "'" << matcher()->name() << "'"; CurrentGenerator::log() << " within:\n"; CurrentGenerator::log() << "pt = " << ptMin()/GeV << " .. " << ptMax()/GeV << " GeV\n"; for ( vector >::const_iterator r = yRanges().begin(); r != yRanges().end(); ++r ) { CurrentGenerator::log() << "y = " << r->first << " .. " << r->second << "\n"; } } string IdentifiedParticleCut::doYRange(string in) { istringstream ins(in); double first, second; ins >> first >> second; if ( first > second ) swap(first,second); theYRanges.push_back(make_pair(first,second)); return ""; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IdentifiedParticleCut::persistentOutput(PersistentOStream & os) const { os << ounit(thePtMin,GeV) << ounit(thePtMax,GeV) << theYRanges << theMatcher; } void IdentifiedParticleCut::persistentInput(PersistentIStream & is, int) { is >> iunit(thePtMin,GeV) >> iunit(thePtMax,GeV) >> theYRanges >> theMatcher; } // *** 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 describeHerwigIdentifiedParticleCut("Herwig::IdentifiedParticleCut", "HwMatchboxCuts.so"); void IdentifiedParticleCut::Init() { static ClassDocumentation documentation ("IdentifiedParticleCut implements cuts on single momenta."); static Parameter interfacePtMin ("PtMin", "The minimum pt required.", &IdentifiedParticleCut::thePtMin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfacePtMax ("PtMax", "The maximum pt allowed.", &IdentifiedParticleCut::thePtMax, GeV, Constants::MaxEnergy, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Command interfaceYRange ("YRange", "Insert a rapidity range.", &IdentifiedParticleCut::doYRange, false); static Reference interfaceMatcher ("Matcher", "A matcher for particles to cut on.", &IdentifiedParticleCut::theMatcher, false, false, true, false, false); } diff --git a/MatrixElement/Matchbox/Cuts/IdentifiedParticleCut.h b/MatrixElement/Matchbox/Cuts/IdentifiedParticleCut.h --- a/MatrixElement/Matchbox/Cuts/IdentifiedParticleCut.h +++ b/MatrixElement/Matchbox/Cuts/IdentifiedParticleCut.h @@ -1,194 +1,186 @@ // -*- C++ -*- // // IdentifiedParticleCut.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_IdentifiedParticleCut_H #define Herwig_IdentifiedParticleCut_H // // This is the declaration of the IdentifiedParticleCut class. // #include "ThePEG/Cuts/OneCutBase.h" #include "ThePEG/PDT/MatcherBase.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IdentifiedParticleCut implements cuts on single momenta. * * @see \ref IdentifiedParticleCutInterfaces "The interfaces" * defined for IdentifiedParticleCut. */ class IdentifiedParticleCut: public OneCutBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IdentifiedParticleCut(); - /** - * The destructor. - */ - virtual ~IdentifiedParticleCut(); - //@} - public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return the minimum allowed value of the transverse momentum of an * outgoing parton. */ virtual Energy minKT(tcPDPtr) const { return ZERO; } /** * Return the minimum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. */ virtual double minEta(tcPDPtr) const { return -Constants::MaxRapidity; } /** * Return the maximum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. */ virtual double maxEta(tcPDPtr) const { return Constants::MaxRapidity; } /** * Return true if a particle with type \a ptype and momentum \a p * passes the cuts. The \a parent contains information about the * kinematics of the hard sub-process. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr ptype, LorentzMomentum p) const; /** * Describe the currently active cuts in the log file. */ virtual void describe() const; //@} public: /** * Return the minimum pt. */ Energy ptMin() const { return thePtMin; } /** * Return the maximum pt. */ Energy ptMax() const { return thePtMax; } /** * Return the rapidity ranges. */ const vector >& yRanges() const { return theYRanges; } /** * Return the matcher for particles to cut on. */ Ptr::tptr matcher() const { return theMatcher; } 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: /** * Command to insert a rapidity range */ string doYRange(string); /** * The minimum pt. */ Energy thePtMin; /** * The maximum pt. */ Energy thePtMax; /** * The rapidity ranges. */ vector > theYRanges; /** * A matcher for particles to cut on. */ Ptr::ptr theMatcher; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IdentifiedParticleCut & operator=(const IdentifiedParticleCut &) = delete; }; } #endif /* Herwig_IdentifiedParticleCut_H */ diff --git a/MatrixElement/Matchbox/Cuts/MatchboxDeltaRCut.cc b/MatrixElement/Matchbox/Cuts/MatchboxDeltaRCut.cc --- a/MatrixElement/Matchbox/Cuts/MatchboxDeltaRCut.cc +++ b/MatrixElement/Matchbox/Cuts/MatchboxDeltaRCut.cc @@ -1,195 +1,193 @@ // -*- C++ -*- // // MatchboxDeltaRCut.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxDeltaRCut class. // #include "MatchboxDeltaRCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MatchboxDeltaRCut::MatchboxDeltaRCut() : theDeltaRMin(0.0), theDeltaRMax(Constants::MaxRapidity), theDeltaYMin(0.0), theDeltaYMax(Constants::MaxRapidity), theDeltaPhiMin(0.0), theDeltaPhiMax(2.0*Constants::pi) {} -MatchboxDeltaRCut::~MatchboxDeltaRCut() {} - IBPtr MatchboxDeltaRCut::clone() const { return new_ptr(*this); } IBPtr MatchboxDeltaRCut::fullclone() const { return new_ptr(*this); } bool MatchboxDeltaRCut::passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci, bool incj) const { bool match = false; if ( theFirstMatcher->check(*pitype) && theSecondMatcher->check(*pjtype) ) match = true; if ( theFirstMatcher->check(*pjtype) && theSecondMatcher->check(*pitype) ) match = true; if ( !match || (theDeltaRMin == 0.0 && theDeltaRMax == Constants::MaxRapidity && theDeltaYMin == 0.0 && theDeltaYMax == Constants::MaxRapidity && theDeltaPhiMin == 0.0 && theDeltaPhiMax == 2.0*Constants::pi) ) return true; if ( inci || incj ) return true; double weight = 1.0; double dY = abs(pi.rapidity() - pj.rapidity()); double dPhi = abs(pi.phi() - pj.phi()); if ( dPhi > Constants::pi ) dPhi = 2.0*Constants::pi - dPhi; double dR = sqrt(sqr(dY) + sqr(dPhi)); if ( !parent->isInside(dY,deltaYMin(),deltaYMax(),weight) ) { parent->lastCutWeight(0.0); return false; } if ( !parent->isInside(dPhi,deltaPhiMin(),deltaPhiMax(),weight) ) { parent->lastCutWeight(0.0); return false; } if ( !parent->isInside(dR,deltaRMin(),deltaRMax(),weight) ) { parent->lastCutWeight(0.0); return false; } parent->lastCutWeight(weight); return true; } void MatchboxDeltaRCut::describe() const { CurrentGenerator::log() << fullName() << "\n" << "matching distances between: '" << theFirstMatcher->name() << "' and '" << theSecondMatcher->name() << "':\n" << "DeltaRMin = " << theDeltaRMin << " \n" << "DeltaRMax = " << theDeltaRMax << " \n" << "DeltaPhiMin = " << theDeltaPhiMin << " \n" << "DeltaPhiMax = " << theDeltaPhiMax << " \n" << "DeltaYMin = " << theDeltaYMin << " \n" << "DeltaYMax = " << theDeltaYMax << " \n\n"; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxDeltaRCut::persistentOutput(PersistentOStream & os) const { os << theDeltaYMin << theDeltaYMax << theDeltaPhiMin << theDeltaPhiMax << theDeltaRMin << theDeltaRMax << theFirstMatcher << theSecondMatcher; } void MatchboxDeltaRCut::persistentInput(PersistentIStream & is, int) { is >> theDeltaYMin >> theDeltaYMax >> theDeltaPhiMin >> theDeltaPhiMax >> theDeltaRMin >> theDeltaRMax >> theFirstMatcher >> theSecondMatcher; } // *** 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 describeHerwigMatchboxDeltaRCut("Herwig::MatchboxDeltaRCut", "HwMatchboxCuts.so"); void MatchboxDeltaRCut::Init() { static ClassDocumentation documentation ("This class implements cuts on legoplot, rapidity and azimuthal separation, " "i.e. on the \\f$\\Delta R\\f$-measure and on \\f$\\Delta Y\\f$ and \\f$\\Delta \\phi\\f$. " "By default the cuts are only applied to coloured particles, but " "may optionally be applied to all particle types. "); static Parameter interfaceDeltaRMin ("DeltaRMin", "The minimum allowed for the legoplot distance " "\\f$\\Delta R_{ij}=\\sqrt{\\Delta \\phi_{ij}^2+\\Delta Y_{ij}^2}\\f$ ", &MatchboxDeltaRCut::theDeltaRMin, 0.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaRMax ("DeltaRMax", "The maximum allowed for the legoplot distance " "\\f$\\Delta R_{ij}=\\sqrt{\\Delta \\phi_{ij}^2+\\Delta Y_{ij}^2}\\f$ ", &MatchboxDeltaRCut::theDeltaRMax, Constants::MaxRapidity, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaPhiMin ("DeltaPhiMin", "The minimum allowed for the azimuthal separation " "\\f$\\Delta \\phi_{ij}\\f$ ", &MatchboxDeltaRCut::theDeltaPhiMin, 0.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaPhiMax ("DeltaPhiMax", "The maximum allowed for the azimuthal separation " "\\f$\\Delta \\phi_{ij}\\f$ ", &MatchboxDeltaRCut::theDeltaPhiMax, 2.0*Constants::pi, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaYMin ("DeltaYMin", "The minimum allowed for the rapidity separation " "\\f$\\Delta Y_{ij}\\f$ ", &MatchboxDeltaRCut::theDeltaYMin, 0.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaYMax ("DeltaYMax", "The maximum allowed for the rapidity separation " "\\f$\\Delta Y_{ij}\\f$ ", &MatchboxDeltaRCut::theDeltaYMax, Constants::MaxRapidity, 0, 0, false, false, Interface::lowerlim); static Reference interfaceFirstMatcher ("FirstMatcher", "Matcher for first particle of type pitype in the pair (pitype,pjtype). " "If non-null only particles matching this object will be affected " "by the cut. ", &MatchboxDeltaRCut::theFirstMatcher, true, false, true, true, false); // &MatchboxDeltaRCut::theFirstMatcher, false, false, true, false, false); static Reference interfaceSecondMatcher ("SecondMatcher", "Matcher for second particle of type pjtype in the pair (pitype,pjtype). " "If non-null only particles matching this object will be affected " "by the cut. ", &MatchboxDeltaRCut::theSecondMatcher, true, false, true, true, false); // &MatchboxDeltaRCut::theSecondMatcher, false, false, true, false, false); } diff --git a/MatrixElement/Matchbox/Cuts/MatchboxDeltaRCut.h b/MatrixElement/Matchbox/Cuts/MatchboxDeltaRCut.h --- a/MatrixElement/Matchbox/Cuts/MatchboxDeltaRCut.h +++ b/MatrixElement/Matchbox/Cuts/MatchboxDeltaRCut.h @@ -1,233 +1,225 @@ // -*- C++ -*- // // MatchboxDeltaRCut.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxDeltaRCut_H #define Herwig_MatchboxDeltaRCut_H // // This is the declaration of the MatchboxDeltaRCut class. // #include "ThePEG/Cuts/TwoCutBase.h" #include "ThePEG/PDT/MatcherBase.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Christian Reuschle * * \brief MatchboxDeltaRCut implements cuts related to the separation in the legoplot plane * * @see \ref MatchboxDeltaRCutInterfaces "The interfaces" * defined for MatchboxDeltaRCut. */ class MatchboxDeltaRCut: public TwoCutBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxDeltaRCut(); - /** - * The destructor. - */ - virtual ~MatchboxDeltaRCut(); - //@} - public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$\min(p_{\perp i}, p_{\perp * j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing * partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a * single outgoing parton. Returns 0 if both partons are incoming. A * null pointer indicates an incoming parton, hence the type of the * incoming parton is irrelevant. */ virtual Energy minDeltaMeasureCuts(tcPDPtr , tcPDPtr ) const { return ZERO; } // virtual Energy minDeltaMeasureCuts(tcPDPtr pi, tcPDPtr pj) const { return ZERO; } /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. Returns ZERO. */ virtual Energy minKTClus(tcPDPtr , tcPDPtr ) const { return ZERO; } // virtual Energy minKTClus(tcPDPtr pi, tcPDPtr pj) const { return ZERO; } /** * Return the minimum allowed squared invariant mass of two outgoing * partons of type \a pi and \a pj. Returns zero. */ virtual Energy2 minSij(tcPDPtr , tcPDPtr ) const { return ZERO; } // virtual Energy2 minSij(tcPDPtr pi, tcPDPtr pj) const { return ZERO; } /** * Return the minimum allowed value of the negative of the squared * invariant mass of an incoming parton of type \a pi and an * outgoing parton of type \a po. Returns zero. */ virtual Energy2 minTij(tcPDPtr , tcPDPtr ) const { return ZERO; } // virtual Energy2 minTij(tcPDPtr pi, tcPDPtr po) const { return ZERO; } /** * Return the minimum allowed value of \f$\Delta * R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two * outgoing partons of type \a pi and \a pj. Returns zero. */ virtual double minDeltaR(tcPDPtr , tcPDPtr ) const { return ZERO; } // virtual double minDeltaR(tcPDPtr pi, tcPDPtr pj) const { return ZERO; } /** * Return the minimum allowed value of the Durham * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two * outgoing partons. Returns zero. */ virtual double minDurham(tcPDPtr , tcPDPtr ) const { return 0.0; } // virtual double minDurham(tcPDPtr pi, tcPDPtr pj) const { return 0.0; } /** * Return true if a pair of particles with type \a pitype and \a * pjtype and momenta \a pi and \a pj respectively passes the * cuts. \a inci and \a inj indicates if the corresponding particles * are incoming. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci = false, bool incj = false) const; /** * Describe the currently active cuts in the log file. */ virtual void describe() const; //@} public: /** * Return the minimum and maximum allowed legoplot separation */ double deltaRMin() const { return theDeltaRMin; } double deltaRMax() const { return theDeltaRMax; } /** * Return the minimum and maximum allowed rapidity separation */ double deltaYMin() const { return theDeltaYMin; } double deltaYMax() const { return theDeltaYMax; } /** * Return the minimum and maximum allowed azimuthal separation */ double deltaPhiMin() const { return theDeltaPhiMin; } double deltaPhiMax() const { return theDeltaPhiMax; } /** * Return the matchers for a pair of particles to cut on. Only a pair * of particles, matching these objects, will be affected. */ Ptr::tptr firstMatcher() const { return theFirstMatcher; } Ptr::tptr secondMatcher() const { return theSecondMatcher; } 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: /** * The minimum and maximum allowed legoplot separation */ double theDeltaRMin; double theDeltaRMax; /** * The minimum and maximum allowed rapidity separation */ double theDeltaYMin; double theDeltaYMax; /** * The minimum and maximum allowed azimuthal separation */ double theDeltaPhiMin; double theDeltaPhiMax; /** * Matchers for a pair of particles to cut on. Only a pair * of particles, matching these objects, will be affected. */ Ptr::ptr theFirstMatcher; Ptr::ptr theSecondMatcher; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxDeltaRCut & operator=(const MatchboxDeltaRCut &) = delete; }; } #endif /* Herwig_MatchboxDeltaRCut_H */ diff --git a/MatrixElement/Matchbox/Cuts/MissingPtCut.cc b/MatrixElement/Matchbox/Cuts/MissingPtCut.cc --- a/MatrixElement/Matchbox/Cuts/MissingPtCut.cc +++ b/MatrixElement/Matchbox/Cuts/MissingPtCut.cc @@ -1,178 +1,176 @@ // -*- C++ -*- // // MissingPtCut.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MissingPtCut class. // #include "MissingPtCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MissingPtCut::MissingPtCut() : thePtMissMin(0.*GeV), thePtMissMax(Constants::MaxEnergy) {} -MissingPtCut::~MissingPtCut() {} - IBPtr MissingPtCut::clone() const { return new_ptr(*this); } IBPtr MissingPtCut::fullclone() const { return new_ptr(*this); } bool MissingPtCut::passCuts(tcCutsPtr parent, const tcPDVector & ptype, const vector & p) const { if ( thePtMissMin == ZERO && thePtMissMax == Constants::MaxEnergy ) return true; // Energy ptMissSum = 0.0*GeV; LorentzMomentum momentumMissSum; bool nonu = true; for ( int i = 0, N = ptype.size(); i < N; ++i ) { if ( invisibleParticles().size() == 0 ) { if ( matcher()->check(*ptype[i]) ) { // ptMissSum = ptMissSum + p[i].perp(); momentumMissSum = momentumMissSum + p[i]; nonu = false; } } else if ( invisibleParticles().size() != 0 ) { for ( vector::const_iterator iID = invisibleParticles().begin(); iID != invisibleParticles().end(); ++iID ) { int iInt = *iID; if ( abs(ptype[i]->id())==iInt ) { // ptMissSum = ptMissSum + p[i].perp(); momentumMissSum = momentumMissSum + p[i]; nonu = false; } } } } if ( nonu ) return true; Energy ptMiss = momentumMissSum.perp(); double weight = 1.0; // if ( !parent->isInside(ptMissSum,ptMissMin(),ptMissMax(),weight) ) { if ( !parent->isInside(ptMiss,ptMissMin(),ptMissMax(),weight) ) { parent->lastCutWeight(0.0); return false; } parent->lastCutWeight(weight); return true; } string MissingPtCut::doInvisibleParticles(string in) { istringstream ins(in); int first; ins >> first; theInvisibleParticles.push_back(first); return ""; } void MissingPtCut::describe() const { CurrentGenerator::log() << "MissingPtCut '" << name() << "' matching " << "'" << matcher()->name() << "'"; CurrentGenerator::log() << " within:\n"; CurrentGenerator::log() << "ptMiss = " << ptMissMin()/GeV << " .. " << ptMissMax()/GeV << " GeV\n"; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MissingPtCut::persistentOutput(PersistentOStream & os) const { // os << ounit(thePtMissMin,GeV) << ounit(thePtMissMax,GeV); os << ounit(thePtMissMin,GeV) << ounit(thePtMissMax,GeV) << theInvisibleParticles << theMatcher; } void MissingPtCut::persistentInput(PersistentIStream & is, int) { // is >> iunit(thePtMissMin,GeV) >> iunit(thePtMissMax,GeV); is >> iunit(thePtMissMin,GeV) >> iunit(thePtMissMax,GeV) >> theInvisibleParticles >> theMatcher; } // *** 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 describeHerwigMissingPtCut("Herwig::MissingPtCut", "HwMatchboxCuts.so"); void MissingPtCut::Init() { static ClassDocumentation documentation // ("MissingPtCut implements a cut on the missing transverse momentum " // "of a set of outgoing particles, i.e. for now the total transverse momentum " // "of all outgoing neutrinos in an event."); ("MissingPtCut implements a cut on the transverse momentum of the four-momentum " "sum of a set of outgoing particles that cannot be detected. By default the three " "standard model neutrinos are considered. If at least one undetectable particle " "is specified through the InvisibleParticles interface, the default choice is " "nullified."); static Command interfaceInvisibleParticles ("InvisibleParticles", "Insert the PDG code of a particle that cannot be detected. If no particle " "is inserted at all, the three standard model neutrinos are considered by " "default. If at least one particle is inserted, the default choice is nullified.", &MissingPtCut::doInvisibleParticles, false); static Parameter interfacePtMissMin ("PtMissMin", "The minimum missing pt required.", &MissingPtCut::thePtMissMin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfacePtMissMax ("PtMissMax", "The maximum missing pt allowed.", &MissingPtCut::thePtMissMax, GeV, Constants::MaxEnergy, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Reference interfaceMatcher ("Matcher", "A matcher for particles to cut on.", &MissingPtCut::theMatcher, false, false, true, false, false); } diff --git a/MatrixElement/Matchbox/Cuts/MissingPtCut.h b/MatrixElement/Matchbox/Cuts/MissingPtCut.h --- a/MatrixElement/Matchbox/Cuts/MissingPtCut.h +++ b/MatrixElement/Matchbox/Cuts/MissingPtCut.h @@ -1,188 +1,180 @@ // -*- C++ -*- // // MissingPtCut.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MissingPtCut_H #define Herwig_MissingPtCut_H // // This is the declaration of the MissingPtCut class. // #include "ThePEG/Cuts/MultiCutBase.h" #include "ThePEG/PDT/MatcherBase.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Christian Reuschle * * \brief MissingPtCut implements a cut on the total missing transverse momentum of a set of outgoing particles, i.e. for now the total transverse momentum of all outgoing neutrinos in an event. * * @see \ref MissingPtCutInterfaces "The interfaces" * defined for MissingPtCut. */ class MissingPtCut: public MultiCutBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MissingPtCut(); - /** - * The destructor. - */ - virtual ~MissingPtCut(); - //@} - public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return the minimum allowed value of the squared invariant mass of * a set of outgoing partons of the given types. Typically used to * cut off the tails of the mass of a resonance for efficiency. */ virtual Energy2 minS(const tcPDVector) const { return ZERO; } /** * Return the maximum allowed value of the squared invariant mass of * a set of outgoing partons of the given types. Typically used to * cut off the tails of the mass of a resonance for efficiency. */ virtual Energy2 maxS(const tcPDVector) const { return Constants::MaxEnergy2; } /** * Return true if a set of outgoing particles with type \a ptype * and corresponding momenta \a p passes the cuts. */ virtual bool passCuts(tcCutsPtr parent, const tcPDVector & ptype, const vector & p) const; /** * Describe the currently active cuts in the log file. */ virtual void describe() const; /** * Return the matcher for particles to cut on. */ Ptr::tptr matcher() const { return theMatcher; } //@} public: /** * Return the PDG codes of those particles that cannot be detected */ const vector& invisibleParticles() const { return theInvisibleParticles; } /** * Command to insert the PDG code of a particle that cannot be detected */ string doInvisibleParticles(string); /** * Return the minimum missing pt. */ Energy ptMissMin() const { return thePtMissMin; } /** * Return the maximum missing pt. */ Energy ptMissMax() const { return thePtMissMax; } 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: /** * The PDG codes of those particles that cannot be detected */ vector theInvisibleParticles; /** * The minimum missing pt. */ Energy thePtMissMin; /** * The maximum missing pt. */ Energy thePtMissMax; /** * A matcher for particles to cut on. */ Ptr::ptr theMatcher; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MissingPtCut & operator=(const MissingPtCut &) = delete; }; } #endif /* Herwig_MissingPtCut_H */ diff --git a/MatrixElement/Matchbox/Cuts/PairRapidityCut.cc b/MatrixElement/Matchbox/Cuts/PairRapidityCut.cc --- a/MatrixElement/Matchbox/Cuts/PairRapidityCut.cc +++ b/MatrixElement/Matchbox/Cuts/PairRapidityCut.cc @@ -1,302 +1,300 @@ // -*- C++ -*- // // PairRapidityCut.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PairRapidityCut class. // #include "PairRapidityCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/MatcherBase.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void PairRapidityCut::describe() const { CurrentGenerator::log() << fullName() << "\n" << "matching between: '" << theFirstMatcher->name() << "' and '" // << theSecondMatcher->name() << "':\n" << theSecondMatcher->name() << "':\n"; // << "y = " << theMinRapidity << " .. " << theMaxRapidity << "\n" for ( vector >::const_iterator r = yRanges().begin(); r != yRanges().end(); ++r ) { CurrentGenerator::log() << "y = " << r->first << " .. " << r->second << "\n"; } // << "same flavour only = " << (theSameFlavourOnly?"Yes":"No") << " \n" CurrentGenerator::log() << "same flavour only = " << (theSameFlavourOnly?"Yes":"No") << " \n" << "opposite sign only = " << (theOppositeSignOnly?"Yes":"No") << " \n\n"; } PairRapidityCut::PairRapidityCut() : thePseudo(false), theSameFlavourOnly(false), theOppositeSignOnly(false) {} -PairRapidityCut::~PairRapidityCut() {} - IBPtr PairRapidityCut::clone() const { return new_ptr(*this); } IBPtr PairRapidityCut::fullclone() const { return new_ptr(*this); } bool PairRapidityCut::passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci, bool incj) const { bool match = false; if ( theFirstMatcher->check(*pitype) && theSecondMatcher->check(*pjtype) ) match = true; if ( theFirstMatcher->check(*pjtype) && theSecondMatcher->check(*pitype) ) match = true; // if ( !match || // ( theMinRapidity == -Constants::MaxRapidity && theMaxRapidity == Constants::MaxRapidity ) ) return true; if ( !match || theYRanges.empty() ) return true; if ( inci || incj ) return true; if ( sameFlavourOnly() || oppositeSignOnly() ) { int fam1 = family(pitype->id()); int fam2 = family(pjtype->id()); if ( fam1 && fam2 ) { if ( sameFlavourOnly() && ( abs(fam1) != abs(fam2) ) ) return true; if ( oppositeSignOnly() && ( fam1*fam2 > 0 ) ) return true; } } double weight = 1.0; // double minv = (pi+pj).rapidity(); // // if ( !parent->isInside(minv,minRapidity(),maxRapidity(),weight) ) // { // parent->lastCutWeight(0.0); // return false; // } //// From IdentifiedParticleCut.cc // double y = p.rapidity() + parent->currentYHat(); // for ( vector >::const_iterator dy = yRanges().begin(); // dy != yRanges().end(); ++dy ) { // if ( !parent->isInside(y,dy->first,dy->second,weight) ) { // parent->lastCutWeight(0.0); // return false; // } // } double y = (pi+pj).rapidity() + parent->currentYHat(); // Actually, why not // double y = (pi+pj).rapidity() + parent->currentYHat() + parent->Y(); // as in ThePEG /Cuts/Cuts.cc, /Cuts/OneCutBase.cc, etc. ??? for ( vector >::const_iterator dy = yRanges().begin(); dy != yRanges().end(); ++dy ) { if (!thePseudo) { if ( !parent->isInside(y,dy->first,dy->second,weight) ) { parent->lastCutWeight(0.0); return false; } } else if (thePseudo) { //// From ThePEG/Cuts/OneCutBase or ThePEG/Cuts/SimpleKTCut // if ( p.mt()*sinh(y) <= p.perp()*sinh(theMinEta) ) return false; // if ( p.mt()*sinh(y) >= p.perp()*sinh(theMaxEta) ) return false; if ( !parent->isInside( (pi+pj).mt()*sinh(y)/GeV , (pi+pj).perp()*sinh(dy->first)/GeV , (pi+pj).perp()*sinh(dy->second)/GeV , weight) ) { parent->lastCutWeight(0.0); return false; } } } parent->lastCutWeight(weight); return true; } int PairRapidityCut::family(long id) const { int sign = (id>0)?-1:1; switch ( id ) { case ParticleID::u: case ParticleID::ubar: case ParticleID::d: case ParticleID::dbar: return 1*sign; break; case ParticleID::c: case ParticleID::cbar: case ParticleID::s: case ParticleID::sbar: return 2*sign; break; case ParticleID::t: case ParticleID::tbar: case ParticleID::b: case ParticleID::bbar: return 3*sign; break; case ParticleID::eminus: case ParticleID::eplus: case ParticleID::nu_e: case ParticleID::nu_ebar: return 11*sign; break; case ParticleID::muminus: case ParticleID::muplus: case ParticleID::nu_mu: case ParticleID::nu_mubar: return 12*sign; break; case ParticleID::tauminus: case ParticleID::tauplus: case ParticleID::nu_tau: case ParticleID::nu_taubar: return 13*sign; break; } return 0; } string PairRapidityCut::doYRange(string in) { istringstream ins(in); double first, second; ins >> first >> second; if ( first > second ) swap(first,second); theYRanges.push_back(make_pair(first,second)); return ""; } void PairRapidityCut::persistentOutput(PersistentOStream & os) const { // os << theMinRapidity << theMaxRapidity os << theYRanges << thePseudo << theSameFlavourOnly << theOppositeSignOnly << theFirstMatcher << theSecondMatcher; } void PairRapidityCut::persistentInput(PersistentIStream & is, int) { // is >> theMinRapidity >> theMaxRapidity is >> theYRanges >> thePseudo >> theSameFlavourOnly >> theOppositeSignOnly >> theFirstMatcher >> theSecondMatcher; } // *** 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 describeHerwigPairRapidityCut("Herwig::PairRapidityCut", "HwMatchboxCuts.so"); void PairRapidityCut::Init() { static ClassDocumentation documentation ("This class implements a rapidity cut on lepton pairs of " "final-state particles."); // static Parameter interfaceMinRapidity // ("MinRapidity", // "The minimal allowed rapditiy of the particle pair ", // &PairRapidityCut::theMinRapidity, -Constants::MaxRapidity, -Constants::MaxRapidity, Constants::MaxRapidity, // false, false, Interface::limited); // // static Parameter interfaceMaxRapidity // ("MaxRapidity", // "The maximal allowed rapidity of the particle pair ", // &PairRapidityCut::theMaxRapidity, Constants::MaxRapidity, -Constants::MaxRapidity, Constants::MaxRapidity, // false, false, Interface::limited); static Command interfaceYRange ("YRange", "Insert a rapidity range.", &PairRapidityCut::doYRange, false); static Switch interfacePseudo ("Pseudo", "Use pseudo rapidity instead of rapidity ", &PairRapidityCut::thePseudo, false, false, false); static SwitchOption interfacePseudoNo (interfacePseudo, "No", "No", false); static SwitchOption interfacePseudoYes (interfacePseudo, "Yes", "Yes", true); static Switch interfaceSameFlavourOnly ("SameFlavourOnly", "Whether cut works on fermion pairs of the same flavour only ", &PairRapidityCut::theSameFlavourOnly, true, false, false); static SwitchOption interfaceSameFlavourOnlyYes (interfaceSameFlavourOnly, "Yes", "Yes", true); static SwitchOption interfaceSameFlavourOnlyNo (interfaceSameFlavourOnly, "No", "No", false); static Switch interfaceOppositeSignOnly ("OppositeSignOnly", "Whether cut works on fermion pairs of opposite sign only ", &PairRapidityCut::theOppositeSignOnly, true, false, false); static SwitchOption interfaceOppositeSignOnlyYes (interfaceOppositeSignOnly, "Yes", "Yes", true); static SwitchOption interfaceOppositeSignOnlyNo (interfaceOppositeSignOnly, "No", "No", false); static Reference interfaceFirstMatcher ("FirstMatcher", "Matcher for first particle of type pitype in the pair (pitype,pjtype). " "Only particles matching this object will be affected by the cut. ", &PairRapidityCut::theFirstMatcher, true, false, true, true, false); static Reference interfaceSecondMatcher ("SecondMatcher", "Matcher for second particle of type pjtype in the pair (pitype,pjtype). " "Only particles matching this object will be affected by the cut. ", &PairRapidityCut::theSecondMatcher, true, false, true, true, false); } diff --git a/MatrixElement/Matchbox/Cuts/PairRapidityCut.h b/MatrixElement/Matchbox/Cuts/PairRapidityCut.h --- a/MatrixElement/Matchbox/Cuts/PairRapidityCut.h +++ b/MatrixElement/Matchbox/Cuts/PairRapidityCut.h @@ -1,242 +1,234 @@ // -*- C++ -*- // // PairRapidityCut.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_PairRapidityCut_H #define Herwig_PairRapidityCut_H // // This is the declaration of the PairRapidityCut class. // #include "ThePEG/Cuts/TwoCutBase.h" #include "ThePEG/PDT/MatcherBase.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Christian Reuschle * * \brief This class implements a cut on the rapidity of a pair of particles * * @see \ref PairRapidityCutInterfaces "The interfaces" * defined for PairRapidityCut. */ class PairRapidityCut: public TwoCutBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ PairRapidityCut(); - /** - * The destructor. - */ - virtual ~PairRapidityCut(); - //@} - public: /** @name Overridden virtual functions defined in the base class. */ //@{ /** * Return true if a pair of particles with type \a pitype and \a * pjtype and momenta \a pi and \a pj respectively passes the * cuts. \a inci and \a inj indicates if the corresponding particles * are incoming. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci = false, bool incj = false) const; /** * Return the minimum allowed squared invariant mass of two outgoing * partons of type \a pi and \a pj. */ virtual Energy2 minSij(tcPDPtr , tcPDPtr ) const { return ZERO; } /** * Return the minimum allowed value of the negative of the squared * invariant mass of an incoming parton of type \a pi and an * outgoing parton of type \a po. */ virtual Energy2 minTij(tcPDPtr , tcPDPtr ) const { return ZERO; } /** * Return the minimum allowed value of \f$\Delta * R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two * outgoing partons of type \a pi and \a pj. */ virtual double minDeltaR(tcPDPtr , tcPDPtr ) const { return ZERO; } /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$\min(p_{\perp i}, p_{\perp * j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing * partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a * single outgoing parton. Returns 0 if both partons are incoming. A * null pointer indicates an incoming parton, hence the type of the * incoming parton is irrelevant. */ virtual Energy minKTClus(tcPDPtr , tcPDPtr ) const { return ZERO; } /** * Return the minimum allowed value of the Durham * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two * outgoing partons. */ virtual double minDurham(tcPDPtr , tcPDPtr ) const { return ZERO; } //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: // /** // * Return the minimal allowed rapidity // */ // double minRapidity() const { return theMinRapidity; } // // /** // * Return the maximal allowed rapidity // */ // double maxRapidity() const { return theMaxRapidity; } /** * Return the rapidity ranges. */ const vector >& yRanges() const { return theYRanges; } /** * Return whether cut acts on same-flavour fermions only */ bool sameFlavourOnly() const { return theSameFlavourOnly; } /** * Return whether cut acts on opposite-sign fermions only */ bool oppositeSignOnly() const { return theOppositeSignOnly; } /** * Return the matchers for a pair of particles to cut on. * Only a pair of particles, matching these objects, will be affected. */ Ptr::tptr firstMatcher() const { return theFirstMatcher; } Ptr::tptr secondMatcher() const { return theSecondMatcher; } protected: /** * Return the family of the given PDG id number. */ int family(long id) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Command to insert a rapidity range */ string doYRange(string); /** * The rapidity ranges. */ vector > theYRanges; /** * Whether to use pseudo rapidity instead of rapidity */ bool thePseudo; /** * Whether the cut is active on same-flavour fermions only * (ignored for pairs not consisting of two fermions) */ bool theSameFlavourOnly; /** * Whether the cut is active on opposite-sign fermions only * (ignored for pairs not consisting of two fermions) */ bool theOppositeSignOnly; /** * Matchers for a pair of particles to cut on. Only a pair * of particles, matching these objects, will be affected. */ Ptr::ptr theFirstMatcher; Ptr::ptr theSecondMatcher; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ PairRapidityCut & operator=(const PairRapidityCut &) = delete; }; } #endif /* Herwig_PairRapidityCut_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FFMggxDipole.cc b/MatrixElement/Matchbox/Dipoles/FFMggxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FFMggxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FFMggxDipole.cc @@ -1,150 +1,148 @@ // -*- C++ -*- // // FFMggxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFMggxDipole class. // #include "FFMggxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h" using namespace Herwig; FFMggxDipole::FFMggxDipole() : SubtractionDipole() {} -FFMggxDipole::~FFMggxDipole() {} - IBPtr FFMggxDipole::clone() const { return new_ptr(*this); } IBPtr FFMggxDipole::fullclone() const { return new_ptr(*this); } bool FFMggxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator > 1 && partons[emission]->id() == ParticleID::g && partons[emitter]->id() == ParticleID::g && partons[spectator]->hardProcessMass() != ZERO; } double FFMggxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; // masses, g->gg all masses zero except spectator double muj2 = sqr( realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass() / lastDipoleScale() ); // massive extra terms, viji = 1 double vijk = sqrt( sqr(2.*muj2+(1.-muj2)*(1.-y))-4.*muj2 ) / ((1.-muj2)*(1.-y)); Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double zp = 0.5*(1.+vijk); double zm = 0.5*(1.-vijk); double res = -ccme2; // extra mass terms all = 0. res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= (1./(1-z*(1-y))+1./(1-(1.-z)*(1.-y))+(z*(1.-z)-zm*zp-2.)/vijk); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FFMggxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; // masses, g->gg all masses zero except spectator double muj2 = sqr( realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass() / lastDipoleScale() ); // massive extra terms double vijk = sqrt( sqr(2.*muj2+(1.-muj2)*(1.-y))-4.*muj2 ) / ((1.-muj2)*(1.-y)); Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double diag = 1./(1-z*(1-y))+1./(1-(1.-z)*(1.-y))-2./vijk; // kappa=0 double zim = z-0.5*(1.-vijk), zjm = (1.-z)-0.5*(1.-vijk); Lorentz5Momentum pc = zim*realEmissionME()->lastXComb().meMomenta()[realEmitter()] - zjm*realEmissionME()->lastXComb().meMomenta()[realEmission()]; SpinCorrelationTensor corr(-diag,pc,prop/2.*vijk); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); // extra mass terms all = 0. res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FFMggxDipole::persistentOutput(PersistentOStream &) const { } void FFMggxDipole::persistentInput(PersistentIStream &, int) { } void FFMggxDipole::Init() { static ClassDocumentation documentation ("FFMggxDipole"); DipoleRepository::registerDipole<0,FFMggxDipole,FFMassiveTildeKinematics,FFMassiveInvertedTildeKinematics> ("FFMggxDipole","FFMassiveTildeKinematics","FFMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigFFMggxDipole("Herwig::FFMggxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FFMggxDipole.h b/MatrixElement/Matchbox/Dipoles/FFMggxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FFMggxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FFMggxDipole.h @@ -1,166 +1,158 @@ // -*- C++ -*- // // FFMggxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFMggxDipole_H #define HERWIG_FFMggxDipole_H // // This is the declaration of the FFMggxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Martin Stoll * * \brief FFMggxDipole implements the D_{g,g;k} subtraction dipole. * */ class FFMggxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFMggxDipole(); - /** - * The destructor. - */ - virtual ~FFMggxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * Return true, if this dipole is symmetric with respect to emitter * and emission. */ virtual bool isSymmetric() const { return true; } /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMggxDipole & operator=(const FFMggxDipole &) = delete; }; } #endif /* HERWIG_FFMggxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FFMqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/FFMqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FFMqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FFMqgxDipole.cc @@ -1,156 +1,154 @@ // -*- C++ -*- // // FFMqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFMqgxDipole class. // #include "FFMqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h" using namespace Herwig; FFMqgxDipole::FFMqgxDipole() : SubtractionDipole() {} -FFMqgxDipole::~FFMqgxDipole() {} - IBPtr FFMqgxDipole::clone() const { return new_ptr(*this); } IBPtr FFMqgxDipole::fullclone() const { return new_ptr(*this); } bool FFMqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator > 1 && partons[emission]->id() == ParticleID::g && // abs(partons[emitter]->id()) < 7 && ( abs(partons[emitter]->id()) < 7 || abs(partons[emitter]->id()) == 1000021 ) && !(partons[emitter]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO); } double FFMqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; // masses double muQ2 = sqr( realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass() / lastDipoleScale() ); double muj2 = sqr( realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass() / lastDipoleScale() ); // massive extra terms double vijk = sqrt( sqr(2.*muj2+(1.-muQ2-muj2)*(1.-y))-4.*muj2 ) / ((1.-muQ2-muj2)*(1.-y)); double vbar = sqrt( 1.+sqr(muQ2)+sqr(muj2)-2.*(muQ2+muj2+muQ2*muj2) ) / (1.-muQ2-muj2); Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); if ( realEmissionME()->lastXComb().mePartonData()[realEmitter()]->id() == 1000021 ) CF = SM().Nc(); // For the SUSY D_{gluino,g;k} subtraction dipole we need to replace CF by CA=Nc // extra mass terms cancel: mi2+m2-Mi2 = mQ2+0-mQ2 double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-z*(1.-y)) - vbar/vijk * ( (1.+z) + muQ2*sqr(lastDipoleScale())*2./prop ) ); res *= -ccme2; res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FFMqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; // masses double muQ2 = sqr( realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass() / lastDipoleScale() ); double muj2 = sqr( realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass() / lastDipoleScale() ); // massive extra terms double vijk = sqrt( sqr(2.*muj2+(1.-muQ2-muj2)*(1.-y))-4.*muj2 ) / ((1.-muQ2-muj2)*(1.-y)); double vbar = sqrt( 1.+sqr(muQ2)+sqr(muj2)-2.*(muQ2+muj2+muQ2*muj2) ) / (1.-muQ2-muj2); Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); if ( realEmissionME()->lastXComb().mePartonData()[realEmitter()]->id() == 1000021 ) CF = SM().Nc(); // For the SUSY D_{gluino,g;k} subtraction dipole we need to replace CF by CA=Nc // extra mass terms cancel: mi2+m2-Mi2 = mQ2+0-mQ2 double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-z*(1.-y)) - vbar/vijk * ( (1.+z) + muQ2*sqr(lastDipoleScale())*2./prop ) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FFMqgxDipole::persistentOutput(PersistentOStream &) const { } void FFMqgxDipole::persistentInput(PersistentIStream &, int) { } void FFMqgxDipole::Init() { static ClassDocumentation documentation ("FFMqgxDipole"); DipoleRepository::registerDipole<0,FFMqgxDipole,FFMassiveTildeKinematics,FFMassiveInvertedTildeKinematics> ("FFMqgxDipole","FFMassiveTildeKinematics","FFMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigFFMqgxDipole("Herwig::FFMqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FFMqgxDipole.h b/MatrixElement/Matchbox/Dipoles/FFMqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FFMqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FFMqgxDipole.h @@ -1,161 +1,153 @@ // -*- C++ -*- // // FFMqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFMqgxDipole_H #define HERWIG_FFMqgxDipole_H // // This is the declaration of the FFMqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Martin Stoll, Christian Reuschle * * \brief FFMqgxDipole implements the D_{Q,g;k} subtraction dipole, * as well as the D_{gluino,g;k} subtraction dipole. * */ class FFMqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFMqgxDipole(); - /** - * The destructor. - */ - virtual ~FFMqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 3;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMqgxDipole & operator=(const FFMqgxDipole &) = delete; }; } #endif /* HERWIG_FFMqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FFMqqxDipole.cc b/MatrixElement/Matchbox/Dipoles/FFMqqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FFMqqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FFMqqxDipole.cc @@ -1,159 +1,157 @@ // -*- C++ -*- // // FFMqqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFMqqxDipole class. // #include "FFMqqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h" using namespace Herwig; FFMqqxDipole::FFMqqxDipole() : SubtractionDipole() {} -FFMqqxDipole::~FFMqqxDipole() {} - IBPtr FFMqqxDipole::clone() const { return new_ptr(*this); } IBPtr FFMqqxDipole::fullclone() const { return new_ptr(*this); } bool FFMqqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator > 1 && abs(partons[emission]->id()) < 7 && abs(partons[emitter]->id()) < 7 && partons[emission]->id() + partons[emitter]->id() == 0 && !(partons[emission]->hardProcessMass() == ZERO && partons[emitter]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO); } double FFMqqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; // masses double muQ2 = sqr( realEmissionME()->lastXComb().mePartonData()[realEmission()]->hardProcessMass() / lastDipoleScale() ); double muj2 = sqr( realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass() / lastDipoleScale() ); Energy2 mQ2 = sqr( realEmissionME()->lastXComb().mePartonData()[realEmission()]->hardProcessMass() ); // massive extra terms double t = 1.-2.*muQ2-muj2; double vijk = sqrt( sqr(2.*muj2+t*(1.-y))-4.*muj2 ) / (t*(1.-y)); double viji = sqrt( sqr(t*y) - 4.*sqr(muQ2) ) / ( t*y + 2.*muQ2); Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double zp = 0.5*(1.+viji*vijk); double zm = 0.5*(1.-viji*vijk); // kappa=0 -- otherwise: extra term double res = -ccme2; res *= (1.-2.*(z*(1-z)-zp*zm)); res *= 4.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/ ((prop+2.*mQ2)*vijk); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FFMqqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; // masses double muQ2 = sqr( realEmissionME()->lastXComb().mePartonData()[realEmission()]->hardProcessMass() / lastDipoleScale() ); double muj2 = sqr( realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass() / lastDipoleScale() ); Energy2 mQ2 = sqr( realEmissionME()->lastXComb().mePartonData()[realEmission()]->hardProcessMass() ); // massive extra terms double vijk = sqrt( sqr(2.*muj2+(1.-2.*muQ2-muj2)*(1.-y))-4.*muj2 ) / ((1.-2.*muQ2-muj2)*(1.-y)); Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double zim = z-0.5*(1.-vijk), zjm = (1.-z)-0.5*(1.-vijk); Lorentz5Momentum pc = zim*realEmissionME()->lastXComb().meMomenta()[realEmitter()] - zjm*realEmissionME()->lastXComb().meMomenta()[realEmission()]; // kappa=0 -- otherwise: extra diagonal term (instead of just -1.) SpinCorrelationTensor corr(-1.,pc,-(prop+2.*mQ2)/4.); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 4.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/ ((prop+2.*mQ2)*vijk); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FFMqqxDipole::persistentOutput(PersistentOStream &) const { } void FFMqqxDipole::persistentInput(PersistentIStream &, int) { } void FFMqqxDipole::Init() { static ClassDocumentation documentation ("FFMqqxDipole"); DipoleRepository::registerDipole<0,FFMqqxDipole,FFMassiveTildeKinematics,FFMassiveInvertedTildeKinematics> ("FFMqqxDipole","FFMassiveTildeKinematics","FFMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigFFMqqxDipole("Herwig::FFMqqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FFMqqxDipole.h b/MatrixElement/Matchbox/Dipoles/FFMqqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FFMqqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FFMqqxDipole.h @@ -1,168 +1,160 @@ // -*- C++ -*- // // FFMqqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFMqqxDipole_H #define HERWIG_FFMqqxDipole_H // // This is the declaration of the FFMqqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Martin Stoll * * \brief FFMqqxDipole implements the D_{q,qbar;k} subtraction dipole. * */ class FFMqqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFMqqxDipole(); - /** - * The destructor. - */ - virtual ~FFMqqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emitter]->id() + partons[emission]->id() == 0; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 1;} /** * Return true, if this dipole is symmetric with respect to emitter * and emission. */ virtual bool isSymmetric() const { return true; } /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMqqxDipole & operator=(const FFMqqxDipole &) = delete; }; } #endif /* HERWIG_FFMqqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FFMsqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/FFMsqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FFMsqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FFMsqgxDipole.cc @@ -1,152 +1,150 @@ // -*- C++ -*- // // FFMsqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFMsqgxDipole class. // #include "FFMsqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h" using namespace Herwig; FFMsqgxDipole::FFMsqgxDipole() : SubtractionDipole() {} -FFMsqgxDipole::~FFMsqgxDipole() {} - IBPtr FFMsqgxDipole::clone() const { return new_ptr(*this); } IBPtr FFMsqgxDipole::fullclone() const { return new_ptr(*this); } bool FFMsqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator > 1 && partons[emission]->id() == ParticleID::g && ((abs(partons[emitter]->id())> 1000000 && abs(partons[emitter]->id())< 1000007) || (abs(partons[emitter]->id())> 2000000 && abs(partons[emitter]->id())< 2000007)) && !(partons[emitter]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO); } double FFMsqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; // masses double muSQ2 = sqr( realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass() / lastDipoleScale() ); double muj2 = sqr( realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass() / lastDipoleScale() ); // massive extra terms double vijk = sqrt( sqr(2.*muj2+(1.-muSQ2-muj2)*(1.-y))-4.*muj2 ) / ((1.-muSQ2-muj2)*(1.-y)); double vbar = sqrt( 1.+sqr(muSQ2)+sqr(muj2)-2.*(muSQ2+muj2+muSQ2*muj2) ) / (1.-muSQ2-muj2); Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-z*(1.-y)) - vbar/vijk * ( 2. + muSQ2*sqr(lastDipoleScale())*2./prop )); res *= -ccme2; res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FFMsqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; // masses double muSQ2 = sqr( realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass() / lastDipoleScale() ); double muj2 = sqr( realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass() / lastDipoleScale() ); // massive extra terms double vijk = sqrt( sqr(2.*muj2+(1.-muSQ2-muj2)*(1.-y))-4.*muj2 ) / ((1.-muSQ2-muj2)*(1.-y)); double vbar = sqrt( 1.+sqr(muSQ2)+sqr(muj2)-2.*(muSQ2+muj2+muSQ2*muj2) ) / (1.-muSQ2-muj2); Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); // extra mass terms cancel: mi2+m2-Mi2 = mQ2+0-mQ2 double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-z*(1.-y)) - vbar/vijk * ( 2. + muSQ2*sqr(lastDipoleScale())*2./prop ) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FFMsqgxDipole::persistentOutput(PersistentOStream &) const { } void FFMsqgxDipole::persistentInput(PersistentIStream &, int) { } void FFMsqgxDipole::Init() { static ClassDocumentation documentation ("FFMsqgxDipole"); DipoleRepository::registerDipole<0,FFMsqgxDipole,FFMassiveTildeKinematics,FFMassiveInvertedTildeKinematics> ("FFMsqgxDipole","FFMassiveTildeKinematics","FFMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigFFMsqgxDipole("Herwig::FFMsqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FFMsqgxDipole.h b/MatrixElement/Matchbox/Dipoles/FFMsqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FFMsqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FFMsqgxDipole.h @@ -1,164 +1,156 @@ // -*- C++ -*- // // FFMsqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFMsqgxDipole_H #define HERWIG_FFMsqgxDipole_H // // This is the declaration of the FFMsqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Alexandra Wilcock, Christian Reuschle * * \brief FFMsqgxDipole implements the D_{sq,g;k} subtraction dipole. * */ class FFMsqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFMsqgxDipole(); - /** - * The destructor. - */ - virtual ~FFMsqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && (abs(abs(partons[emitter]->id()) - 1000000) < 7 || abs(abs(partons[emitter]->id()) - 2000000) < 7); } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 3;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMsqgxDipole & operator=(const FFMsqgxDipole &) = delete; }; } #endif /* HERWIG_FFMsqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FFggxDipole.cc b/MatrixElement/Matchbox/Dipoles/FFggxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FFggxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FFggxDipole.cc @@ -1,138 +1,136 @@ // -*- C++ -*- // // FFggxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFggxDipole class. // #include "FFggxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.h" using namespace Herwig; FFggxDipole::FFggxDipole() : SubtractionDipole() {} -FFggxDipole::~FFggxDipole() {} - IBPtr FFggxDipole::clone() const { return new_ptr(*this); } IBPtr FFggxDipole::fullclone() const { return new_ptr(*this); } bool FFggxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator > 1 && partons[emission]->id() == ParticleID::g && partons[emitter]->id() == ParticleID::g && partons[spectator]->hardProcessMass() == ZERO; } double FFggxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double res = 1./(1.-z*(1.-y)) + 1./(1.-(1.-z)*(1.-y)) - 2. + z*(1.-z); res *= -ccme2; res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FFggxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; if ( alpha() < y ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double diag = 1./(1.-z*(1.-y))+1./(1.-(1.-z)*(1.-y))-2.; Lorentz5Momentum pc = z*realEmissionME()->lastXComb().meMomenta()[realEmitter()] - (1.-z)*realEmissionME()->lastXComb().meMomenta()[realEmission()]; SpinCorrelationTensor corr(-diag,pc,prop/2.); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FFggxDipole::persistentOutput(PersistentOStream &) const { } void FFggxDipole::persistentInput(PersistentIStream &, int) { } void FFggxDipole::Init() { static ClassDocumentation documentation ("FFggxDipole"); DipoleRepository::registerDipole<0,FFggxDipole,FFLightTildeKinematics,FFLightInvertedTildeKinematics> ("FFggxDipole","FFLightTildeKinematics","FFLightInvertedTildeKinematics"); } // *** 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 describeHerwigFFggxDipole("Herwig::FFggxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FFggxDipole.h b/MatrixElement/Matchbox/Dipoles/FFggxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FFggxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FFggxDipole.h @@ -1,167 +1,159 @@ // -*- C++ -*- // // FFggxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFggxDipole_H #define HERWIG_FFggxDipole_H // // This is the declaration of the FFggxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FFggxDipole implements the D_{g,g;k} subtraction dipole. * */ class FFggxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFggxDipole(); - /** - * The destructor. - */ - virtual ~FFggxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * Return true, if this dipole is symmetric with respect to emitter * and emission. */ virtual bool isSymmetric() const { return true; } /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFggxDipole & operator=(const FFggxDipole &) = delete; }; } #endif /* HERWIG_FFggxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FFqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/FFqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FFqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FFqgxDipole.cc @@ -1,137 +1,135 @@ // -*- C++ -*- // // FFqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFqgxDipole class. // #include "FFqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.h" using namespace Herwig; FFqgxDipole::FFqgxDipole() : SubtractionDipole() {} -FFqgxDipole::~FFqgxDipole() {} - IBPtr FFqgxDipole::clone() const { return new_ptr(*this); } IBPtr FFqgxDipole::fullclone() const { return new_ptr(*this); } bool FFqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator > 1 && partons[emission]->id() == ParticleID::g && abs(partons[emitter]->id()) < 6 && partons[emitter]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double FFqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-z*(1.-y)) - (1.+z) ); res *= -ccme2; res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FFqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; if ( alpha() < y ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-z*(1.-y)) - (1.+z) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FFqgxDipole::persistentOutput(PersistentOStream &) const { } void FFqgxDipole::persistentInput(PersistentIStream &, int) { } void FFqgxDipole::Init() { static ClassDocumentation documentation ("FFqgxDipole"); DipoleRepository::registerDipole<0,FFqgxDipole,FFLightTildeKinematics,FFLightInvertedTildeKinematics> ("FFqgxDipole","FFLightTildeKinematics","FFLightInvertedTildeKinematics"); } // *** 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 describeHerwigFFqgxDipole("Herwig::FFqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FFqgxDipole.h b/MatrixElement/Matchbox/Dipoles/FFqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FFqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FFqgxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // FFqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFqgxDipole_H #define HERWIG_FFqgxDipole_H // // This is the declaration of the FFqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FFqgxDipole implements the D_{q,g;k} subtraction dipole. * */ class FFqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFqgxDipole(); - /** - * The destructor. - */ - virtual ~FFqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 3;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFqgxDipole & operator=(const FFqgxDipole &) = delete; }; } #endif /* HERWIG_FFqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FFqqxDipole.cc b/MatrixElement/Matchbox/Dipoles/FFqqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FFqqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FFqqxDipole.cc @@ -1,138 +1,136 @@ // -*- C++ -*- // // FFqqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFqqxDipole class. // #include "FFqqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.h" using namespace Herwig; FFqqxDipole::FFqqxDipole() : SubtractionDipole() {} -FFqqxDipole::~FFqqxDipole() {} - IBPtr FFqqxDipole::clone() const { return new_ptr(*this); } IBPtr FFqqxDipole::fullclone() const { return new_ptr(*this); } bool FFqqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator > 1 && abs(partons[emission]->id()) < 6 && abs(partons[emitter]->id()) < 6 && partons[emission]->id() + partons[emitter]->id() == 0 && partons[emitter]->hardProcessMass() == ZERO && partons[emission]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double FFqqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); double res = 1.-2.*z*(1.-z); res *= -ccme2; res *= 4.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FFqqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; if ( alpha() < y ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()])); Lorentz5Momentum pc = z*realEmissionME()->lastXComb().meMomenta()[realEmitter()] - (1.-z)*realEmissionME()->lastXComb().meMomenta()[realEmission()]; SpinCorrelationTensor corr(-1.,pc,-prop/4.); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 4.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FFqqxDipole::persistentOutput(PersistentOStream &) const { } void FFqqxDipole::persistentInput(PersistentIStream &, int) { } void FFqqxDipole::Init() { static ClassDocumentation documentation ("FFqqxDipole"); DipoleRepository::registerDipole<0,FFqqxDipole,FFLightTildeKinematics,FFLightInvertedTildeKinematics> ("FFqqxDipole","FFLightTildeKinematics","FFLightInvertedTildeKinematics"); } // *** 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 describeHerwigFFqqxDipole("Herwig::FFqqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FFqqxDipole.h b/MatrixElement/Matchbox/Dipoles/FFqqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FFqqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FFqqxDipole.h @@ -1,168 +1,160 @@ // -*- C++ -*- // // FFqqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFqqxDipole_H #define HERWIG_FFqqxDipole_H // // This is the declaration of the FFqqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FFqqxDipole implements the D_{q,qbar;k} subtraction dipole. * */ class FFqqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFqqxDipole(); - /** - * The destructor. - */ - virtual ~FFqqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emitter]->id() + partons[emission]->id() == 0; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 1;} /** * Return true, if this dipole is symmetric with respect to emitter * and emission. */ virtual bool isSymmetric() const { return true; } /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFqqxDipole & operator=(const FFqqxDipole &) = delete; }; } #endif /* HERWIG_FFqqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FIMqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/FIMqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FIMqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FIMqgxDipole.cc @@ -1,167 +1,165 @@ // -*- C++ -*- // // FIqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIMqgxDipole class. // #include "FIMqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" //#include "Herwig/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h" //#include "Herwig/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.h" using namespace Herwig; FIMqgxDipole::FIMqgxDipole() : SubtractionDipole() {} -FIMqgxDipole::~FIMqgxDipole() {} - IBPtr FIMqgxDipole::clone() const { return new_ptr(*this); } IBPtr FIMqgxDipole::fullclone() const { return new_ptr(*this); } bool FIMqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator < 2 && partons[emission]->id() == ParticleID::g && // abs(partons[emitter]->id()) < 7 && ( abs(partons[emitter]->id()) < 7 || abs(partons[emitter]->id()) == 1000021 ) && partons[emitter]->hardProcessMass() != ZERO && partons[spectator]->hardProcessMass() == ZERO; } double FIMqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); if ( realEmissionME()->lastXComb().mePartonData()[realEmitter()]->id() == 1000021 ) CF = SM().Nc(); // For the SUSY D_{gluino,g}^a subtraction dipole we need to replace CF by CA=Nc // extra mass terms cancel double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; // NOTE: extra term taken from FIqgxDipole implementation // NOTE: extra term switched off for the moment in the massive case res *= ( 2./(1.-z+(1.-x)) - (1.+z) // + (1.-x)*(1.+3.*x*z) - sqr(realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass()) / prop * 2.*x ); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FIMqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); if ( realEmissionME()->lastXComb().mePartonData()[realEmitter()]->id() == 1000021 ) CF = SM().Nc(); // For the SUSY D_{gluino,g}^a subtraction dipole we need to replace CF by CA=Nc // extra mass terms cancel double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; // NOTE: extra term taken from FIqgxDipole implementation // NOTE: extra term switched off for the moment in the massive case res *= ( 2./(1.-z+(1.-x)) - (1.+z) // + (1.-x)*(1.+3.*x*z) - sqr(realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass()) / prop * 2.*x ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FIMqgxDipole::persistentOutput(PersistentOStream &) const { } void FIMqgxDipole::persistentInput(PersistentIStream &, int) { } void FIMqgxDipole::Init() { static ClassDocumentation documentation ("FIMqgxDipole"); // DipoleRepository::registerDipole<0,FIMqgxDipole,FILightTildeKinematics,FILightInvertedTildeKinematics> // ("FIMqgxDipole","FILightTildeKinematics","FILightInvertedTildeKinematics"); DipoleRepository::registerDipole<0,FIMqgxDipole,FIMassiveTildeKinematics,FIMassiveInvertedTildeKinematics> ("FIMqgxDipole","FIMassiveTildeKinematics","FIMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigFIMqgxDipole("Herwig::FIMqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FIMqgxDipole.h b/MatrixElement/Matchbox/Dipoles/FIMqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FIMqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FIMqgxDipole.h @@ -1,161 +1,153 @@ // -*- C++ -*- // // FIMqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIMqgxDipole_H #define HERWIG_FIMqgxDipole_H // // This is the declaration of the FIMqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Chrstian Reuschle * * \brief FIMqgxDipole implements the D_{Q,g}^a subtraction dipole, * as well as the D_{gluino,g}^a subtraction dipole. * */ class FIMqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMqgxDipole(); - /** - * The destructor. - */ - virtual ~FIMqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 3;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMqgxDipole & operator=(const FIMqgxDipole &) = delete; }; } #endif /* HERWIG_FIMqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FIMqqxDipole.cc b/MatrixElement/Matchbox/Dipoles/FIMqqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FIMqqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FIMqqxDipole.cc @@ -1,163 +1,161 @@ // -*- C++ -*- // // FIMqqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIqqxDipole class. // #include "FIMqqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.h" using namespace Herwig; FIMqqxDipole::FIMqqxDipole() : SubtractionDipole() {} -FIMqqxDipole::~FIMqqxDipole() {} - IBPtr FIMqqxDipole::clone() const { return new_ptr(*this); } IBPtr FIMqqxDipole::fullclone() const { return new_ptr(*this); } bool FIMqqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator < 2 && abs(partons[emission]->id()) < 7 && abs(partons[emitter]->id()) < 7 && partons[emission]->id() + partons[emitter]->id() == 0 && // !(partons[emitter]->hardProcessMass() == ZERO && // partons[emission]->hardProcessMass() == ZERO && // partons[spectator]->hardProcessMass() == ZERO); !(partons[emitter]->hardProcessMass() == ZERO && partons[emission]->hardProcessMass() == ZERO) && partons[spectator]->hardProcessMass() == ZERO; } double FIMqqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; Energy2 mQ2 = sqr(realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass()); // double muQ2 = x * mQ2 / double muQ2 = 0.5 * z * mQ2 / ((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realSpectator()])); // mu_ij=0, mu_i=mu_j=mu_Q. // double zm = ( 1.-x - sqrt( sqr(1.-x-2.*muQ2) - 4.*muQ2 ) ) / ( 2.*(1.-x) ); // double zp = ( 1.-x + sqrt( sqr(1.-x-2.*muQ2) - 4.*muQ2 ) ) / ( 2.*(1.-x) ); double zm = ( 1.-x - sqrt( sqr(1.-x-2.*muQ2) - 4.*sqr(muQ2) ) ) / ( 2.*(1.-x) ); double zp = ( 1.-x + sqrt( sqr(1.-x-2.*muQ2) - 4.*sqr(muQ2) ) ) / ( 2.*(1.-x) ); double res = 1.-2.*(z-zm)*(zp-z); res *= 4.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/( prop+2.*mQ2*x ); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FIMqqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; Energy2 mQ2 = sqr((realEmissionME()->lastXComb().mePartonData()[realEmitter()])->hardProcessMass()); Lorentz5Momentum pc = z*realEmissionME()->lastXComb().meMomenta()[realEmitter()] - (1.-z)*realEmissionME()->lastXComb().meMomenta()[realEmission()]; SpinCorrelationTensor corr(-1.,pc,-(prop+2.*mQ2*x)/(4.*x)); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 4.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/( prop+2.*mQ2*x ); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FIMqqxDipole::persistentOutput(PersistentOStream &) const { } void FIMqqxDipole::persistentInput(PersistentIStream &, int) { } void FIMqqxDipole::Init() { static ClassDocumentation documentation ("FIMqqxDipole"); // DipoleRepository::registerDipole<0,FIMqqxDipole,FILightTildeKinematics,FILightInvertedTildeKinematics> // ("FIMqqxDipole","FILightTildeKinematics","FILightInvertedTildeKinematics"); DipoleRepository::registerDipole<0,FIMqqxDipole,FIMassiveTildeKinematics,FIMassiveInvertedTildeKinematics> ("FIMqqxDipole","FIMassiveTildeKinematics","FIMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigFIMqqxDipole("Herwig::FIMqqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FIMqqxDipole.h b/MatrixElement/Matchbox/Dipoles/FIMqqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FIMqqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FIMqqxDipole.h @@ -1,168 +1,160 @@ // -*- C++ -*- // // FIMqqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIMqqxDipole_H #define HERWIG_FIMqqxDipole_H // // This is the declaration of the FIMqqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FIMqqxDipole implements the D_{q,qbar}^a subtraction dipole. * */ class FIMqqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMqqxDipole(); - /** - * The destructor. - */ - virtual ~FIMqqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emitter]->id() + partons[emission]->id() == 0; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 1;} /** * Return true, if this dipole is symmetric with respect to emitter * and emission. */ virtual bool isSymmetric() const { return true; } /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMqqxDipole & operator=(const FIMqqxDipole &) = delete; }; } #endif /* HERWIG_FIMqqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FIMsqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/FIMsqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FIMsqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FIMsqgxDipole.cc @@ -1,155 +1,153 @@ // -*- C++ -*- // // FIqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIMsqgxDipole class. // #include "FIMsqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.h" using namespace Herwig; FIMsqgxDipole::FIMsqgxDipole() : SubtractionDipole() {} -FIMsqgxDipole::~FIMsqgxDipole() {} - IBPtr FIMsqgxDipole::clone() const { return new_ptr(*this); } IBPtr FIMsqgxDipole::fullclone() const { return new_ptr(*this); } bool FIMsqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator < 2 && partons[emission]->id() == ParticleID::g && ((abs(partons[emitter]->id())> 1000000 && abs(partons[emitter]->id())< 1000007) || (abs(partons[emitter]->id())> 2000000 && abs(partons[emitter]->id())< 2000007)) && partons[emitter]->hardProcessMass() != ZERO && partons[spectator]->hardProcessMass() == ZERO; } double FIMsqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); // extra mass terms cancel double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; // // NOTE: extra term taken from FIqgxDipole implementation?? // res *= ( 2./(1.-z+(1.-x)) - 2. +(1.-x)*(1.+3.*x*z) - // sqr(realEmissionME()->lastXComb().mePartonData()[realEmission()]->hardProcessMass()) / prop * 2.*x); // NOTE: CR: extra term switched off in massive implementation for the moment, // mass of realEmission changed to mass of realEmitter res *= ( 2./(1.-z+(1.-x)) - 2. - sqr(realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass()) / prop * 2.*x); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FIMsqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); // extra mass terms cancel double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; // // NOTE: extra term taken from FIqgxDipole implementation // res *= ( 2./(1.-z+(1.-x)) -2. +(1.-x)*(1.+3.*x*z) - // sqr(realEmissionME()->lastXComb().mePartonData()[realEmission()]->hardProcessMass()) / prop * 2.*x); // NOTE: CR: extra term switched off in massive implementation for the moment, // mass of realEmission changed to mass of realEmitter res *= ( 2./(1.-z+(1.-x)) - 2. - sqr(realEmissionME()->lastXComb().mePartonData()[realEmitter()]->hardProcessMass()) / prop * 2.*x); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FIMsqgxDipole::persistentOutput(PersistentOStream &) const { } void FIMsqgxDipole::persistentInput(PersistentIStream &, int) { } void FIMsqgxDipole::Init() { static ClassDocumentation documentation ("FIMsqgxDipole"); DipoleRepository::registerDipole<0,FIMsqgxDipole,FIMassiveTildeKinematics,FIMassiveInvertedTildeKinematics> ("FIMsqgxDipole","FIMassiveTildeKinematics","FIMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigFIMsqgxDipole("Herwig::FIMsqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FIMsqgxDipole.h b/MatrixElement/Matchbox/Dipoles/FIMsqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FIMsqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FIMsqgxDipole.h @@ -1,164 +1,156 @@ // -*- C++ -*- // // FIMsqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIMsqgxDipole_H #define HERWIG_FIMsqgxDipole_H // // This is the declaration of the FIMsqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Alexandra Wilcock, Christian Reuschle * * \brief FIMsqgxDipole implements the D_{sq,g}^a subtraction dipole. * */ class FIMsqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMsqgxDipole(); - /** - * The destructor. - */ - virtual ~FIMsqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && (abs(abs(partons[emitter]->id()) - 1000000) < 7 || abs(abs(partons[emitter]->id()) - 2000000) < 7); } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 3;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMsqgxDipole & operator=(const FIMsqgxDipole &) = delete; }; } #endif /* HERWIG_FIMsqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FIggxDipole.cc b/MatrixElement/Matchbox/Dipoles/FIggxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FIggxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FIggxDipole.cc @@ -1,151 +1,149 @@ // -*- C++ -*- // // FIggxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIggxDipole class. // #include "FIggxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.h" using namespace Herwig; FIggxDipole::FIggxDipole() : SubtractionDipole() {} -FIggxDipole::~FIggxDipole() {} - IBPtr FIggxDipole::clone() const { return new_ptr(*this); } IBPtr FIggxDipole::fullclone() const { return new_ptr(*this); } bool FIggxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator < 2 && partons[emission]->id() == ParticleID::g && partons[emitter]->id() == ParticleID::g && partons[spectator]->hardProcessMass() == ZERO; } double FIggxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 1./((1.-z)+(1.-x)) + 1./(z+(1.-x)) - 2.+z*(1.-z) + (1.-x)*(1.+x*z*(1.-z)) ; res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FIggxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; if ( alpha() < (1.-x) ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double diag = 1./(1.-z+1.-x) + 1./(z+1.-x) - 2. //+ (1.-x)*(1.+x*z*(1.-z)) ; Lorentz5Momentum pc = z*realEmissionME()->lastXComb().meMomenta()[realEmitter()] - (1.-z)*realEmissionME()->lastXComb().meMomenta()[realEmission()]; SpinCorrelationTensor corr(-diag,pc,prop/(2.*x)); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FIggxDipole::persistentOutput(PersistentOStream &) const { } void FIggxDipole::persistentInput(PersistentIStream &, int) { } void FIggxDipole::Init() { static ClassDocumentation documentation ("FIggxDipole"); DipoleRepository::registerDipole<0,FIggxDipole,FILightTildeKinematics,FILightInvertedTildeKinematics> ("FIggxDipole","FILightTildeKinematics","FILightInvertedTildeKinematics"); } // *** 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 describeHerwigFIggxDipole("Herwig::FIggxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FIggxDipole.h b/MatrixElement/Matchbox/Dipoles/FIggxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FIggxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FIggxDipole.h @@ -1,166 +1,158 @@ // -*- C++ -*- // // FIggxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIggxDipole_H #define HERWIG_FIggxDipole_H // // This is the declaration of the FIggxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FIggxDipole implements the D_{g,g}^a subtraction dipole. * */ class FIggxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIggxDipole(); - /** - * The destructor. - */ - virtual ~FIggxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return true, if this dipole is symmetric with respect to emitter * and emission. */ virtual bool isSymmetric() const { return true; } /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIggxDipole & operator=(const FIggxDipole &) = delete; }; } #endif /* HERWIG_FIggxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FIqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/FIqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FIqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FIqgxDipole.cc @@ -1,151 +1,149 @@ // -*- C++ -*- // // FIqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIqgxDipole class. // #include "FIqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.h" using namespace Herwig; FIqgxDipole::FIqgxDipole() : SubtractionDipole() {} -FIqgxDipole::~FIqgxDipole() {} - IBPtr FIqgxDipole::clone() const { return new_ptr(*this); } IBPtr FIqgxDipole::fullclone() const { return new_ptr(*this); } bool FIqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator < 2 && partons[emission]->id() == ParticleID::g && abs(partons[emitter]->id()) < 6 && partons[emitter]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double FIqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-z+(1.-x)) -(1.+z) + (1.-x)*(1.+3.*x*z) ); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FIqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; if ( alpha() < (1.-x) ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-z+(1.-x)) - (1.+z) //+ (1.-x)*(1.+3.*x*z) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FIqgxDipole::persistentOutput(PersistentOStream &) const { } void FIqgxDipole::persistentInput(PersistentIStream &, int) { } void FIqgxDipole::Init() { static ClassDocumentation documentation ("FIqgxDipole"); DipoleRepository::registerDipole<0,FIqgxDipole,FILightTildeKinematics,FILightInvertedTildeKinematics> ("FIqgxDipole","FILightTildeKinematics","FILightInvertedTildeKinematics"); } // *** 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 describeHerwigFIqgxDipole("Herwig::FIqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FIqgxDipole.h b/MatrixElement/Matchbox/Dipoles/FIqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FIqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FIqgxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // FIqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIqgxDipole_H #define HERWIG_FIqgxDipole_H // // This is the declaration of the FIqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FIqgxDipole implements the D_{q,g}^a subtraction dipole. * */ class FIqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIqgxDipole(); - /** - * The destructor. - */ - virtual ~FIqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 3;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIqgxDipole & operator=(const FIqgxDipole &) = delete; }; } #endif /* HERWIG_FIqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/FIqqxDipole.cc b/MatrixElement/Matchbox/Dipoles/FIqqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/FIqqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/FIqqxDipole.cc @@ -1,147 +1,145 @@ // -*- C++ -*- // // FIqqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIqqxDipole class. // #include "FIqqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.h" using namespace Herwig; FIqqxDipole::FIqqxDipole() : SubtractionDipole() {} -FIqqxDipole::~FIqqxDipole() {} - IBPtr FIqqxDipole::clone() const { return new_ptr(*this); } IBPtr FIqqxDipole::fullclone() const { return new_ptr(*this); } bool FIqqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter > 1 && spectator < 2 && abs(partons[emission]->id()) < 6 && abs(partons[emitter]->id()) < 6 && partons[emission]->id() + partons[emitter]->id() == 0 && partons[emitter]->hardProcessMass() == ZERO && partons[emission]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double FIqqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 1.-2.*z*(1.-z); res *= 4.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double FIqqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; if ( alpha() < (1.-x) ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; Lorentz5Momentum pc = z*realEmissionME()->lastXComb().meMomenta()[realEmitter()] - (1.-z)*realEmissionME()->lastXComb().meMomenta()[realEmission()]; SpinCorrelationTensor corr(-1.,pc,-prop/(4.*x)); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 4.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void FIqqxDipole::persistentOutput(PersistentOStream &) const { } void FIqqxDipole::persistentInput(PersistentIStream &, int) { } void FIqqxDipole::Init() { static ClassDocumentation documentation ("FIqqxDipole"); DipoleRepository::registerDipole<0,FIqqxDipole,FILightTildeKinematics,FILightInvertedTildeKinematics> ("FIqqxDipole","FILightTildeKinematics","FILightInvertedTildeKinematics"); } // *** 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 describeHerwigFIqqxDipole("Herwig::FIqqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/FIqqxDipole.h b/MatrixElement/Matchbox/Dipoles/FIqqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/FIqqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/FIqqxDipole.h @@ -1,168 +1,160 @@ // -*- C++ -*- // // FIqqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIqqxDipole_H #define HERWIG_FIqqxDipole_H // // This is the declaration of the FIqqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FIqqxDipole implements the D_{q,qbar}^a subtraction dipole. * */ class FIqqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIqqxDipole(); - /** - * The destructor. - */ - virtual ~FIqqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter > 1 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emitter]->id() + partons[emission]->id() == 0; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 1;} /** * Return true, if this dipole is symmetric with respect to emitter * and emission. */ virtual bool isSymmetric() const { return true; } /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIqqxDipole & operator=(const FIqqxDipole &) = delete; }; } #endif /* HERWIG_FIqqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IFMggxDipole.cc b/MatrixElement/Matchbox/Dipoles/IFMggxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IFMggxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IFMggxDipole.cc @@ -1,152 +1,150 @@ // -*- C++ -*- // // IFMggxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFggxDipole class. // #include "IFMggxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveInvertedTildeKinematics.h" using namespace Herwig; IFMggxDipole::IFMggxDipole() : SubtractionDipole() {} -IFMggxDipole::~IFMggxDipole() {} - IBPtr IFMggxDipole::clone() const { return new_ptr(*this); } IBPtr IFMggxDipole::fullclone() const { return new_ptr(*this); } bool IFMggxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator > 1 && partons[emission]->id() == ParticleID::g && partons[emitter]->id() == ParticleID::g && partons[spectator]->hardProcessMass() != ZERO; } double IFMggxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double muj2 = sqr( (realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass()) ) / (2.* (realEmissionME()->lastXComb().meMomenta()[bornSpectator()])* (realEmissionME()->lastXComb().meMomenta()[realEmitter()]) ); double res = 1./(1.-x+u) + (1.-x)/x - 1. + x*(1.-x) - muj2/x*u/(1.-u); res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IFMggxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double diag = 1./(1.-x+u)-1.+x*(1.-x); Lorentz5Momentum pc = realEmissionME()->lastXComb().meMomenta()[realEmission()]/u - realEmissionME()->lastXComb().meMomenta()[realSpectator()]/(1.-u); Energy2 sc = realEmissionME()->lastXComb().meMomenta()[realEmission()]* realEmissionME()->lastXComb().meMomenta()[realSpectator()]; sc /= u*(1.-u)*(1.-x)/x; SpinCorrelationTensor corr(-diag,pc,sc); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IFMggxDipole::persistentOutput(PersistentOStream &) const { } void IFMggxDipole::persistentInput(PersistentIStream &, int) { } void IFMggxDipole::Init() { static ClassDocumentation documentation ("IFMggxDipole"); DipoleRepository::registerDipole<0,IFMggxDipole,IFMassiveTildeKinematics,IFMassiveInvertedTildeKinematics> ("IFMggxDipole","IFMassiveTildeKinematics","IFMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigIFMggxDipole("Herwig::IFMggxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IFMggxDipole.h b/MatrixElement/Matchbox/Dipoles/IFMggxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IFMggxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IFMggxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // IFMggxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFMggxDipole_H #define HERWIG_IFMggxDipole_H // // This is the declaration of the IFMggxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFMggxDipole implements the D^{g,g}_k subtraction dipole. * */ class IFMggxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMggxDipole(); - /** - * The destructor. - */ - virtual ~IFMggxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMggxDipole & operator=(const IFMggxDipole &) = delete; }; } #endif /* HERWIG_IFMggxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IFMgqxDipole.cc b/MatrixElement/Matchbox/Dipoles/IFMgqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IFMgqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IFMgqxDipole.cc @@ -1,136 +1,134 @@ // -*- C++ -*- // // IFMgqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFgqxDipole class. // #include "IFMgqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveInvertedTildeKinematics.h" using namespace Herwig; IFMgqxDipole::IFMgqxDipole() : SubtractionDipole() {} -IFMgqxDipole::~IFMgqxDipole() {} - IBPtr IFMgqxDipole::clone() const { return new_ptr(*this); } IBPtr IFMgqxDipole::fullclone() const { return new_ptr(*this); } bool IFMgqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator > 1 && partons[emitter]->id() == ParticleID::g && abs(partons[emission]->id()) < 7 && partons[emission]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() != ZERO; } double IFMgqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 8.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= .5 * ( 1.-2.*x*(1.-x) ); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IFMgqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 8.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= .5 * ( 1.-2.*x*(1.-x) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IFMgqxDipole::persistentOutput(PersistentOStream &) const { } void IFMgqxDipole::persistentInput(PersistentIStream &, int) { } void IFMgqxDipole::Init() { static ClassDocumentation documentation ("IFMgqxDipole"); DipoleRepository::registerDipole<0,IFMgqxDipole,IFMassiveTildeKinematics,IFMassiveInvertedTildeKinematics> ("IFMgqxDipole","IFMassiveTildeKinematics","IFMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigIFMgqxDipole("Herwig::IFMgqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IFMgqxDipole.h b/MatrixElement/Matchbox/Dipoles/IFMgqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IFMgqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IFMgqxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // IFMgqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFMgqxDipole_H #define HERWIG_IFMgqxDipole_H // // This is the declaration of the IFMgqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFMgqxDipole implements the D_k^{g,q} subtraction dipole. * */ class IFMgqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMgqxDipole(); - /** - * The destructor. - */ - virtual ~IFMgqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && abs(partons[emission]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 2;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMgqxDipole & operator=(const IFMgqxDipole &) = delete; }; } #endif /* HERWIG_IFMgqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IFMqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/IFMqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IFMqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IFMqgxDipole.cc @@ -1,154 +1,152 @@ // -*- C++ -*- // // IFMqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFqgxDipole class. // #include "IFMqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveInvertedTildeKinematics.h" using namespace Herwig; IFMqgxDipole::IFMqgxDipole() : SubtractionDipole() {} -IFMqgxDipole::~IFMqgxDipole() {} - IBPtr IFMqgxDipole::clone() const { return new_ptr(*this); } IBPtr IFMqgxDipole::fullclone() const { return new_ptr(*this); } bool IFMqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator > 1 && partons[emission]->id() == ParticleID::g && abs(partons[emitter]->id()) < 7 && partons[emitter]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() != ZERO; } double IFMqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; // NOTE: extra term same as in IFqgxDipole // NOTE: extra term switched off for the moment in the massive case res *= ( 2./(1.-x+u) - (1.+x) // + u*(1.+3.*x*(1.-u)) ); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IFMqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; // NOTE: extra term same as in IFqgxDipole // NOTE: extra term switched off for the moment in the massive case res *= ( 2./(1.-x+u) - (1.+x) // + u*(1.+3.*x*(1.-u)) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IFMqgxDipole::persistentOutput(PersistentOStream &) const { } void IFMqgxDipole::persistentInput(PersistentIStream &, int) { } void IFMqgxDipole::Init() { static ClassDocumentation documentation ("IFMqgxDipole"); // DipoleRepository::registerDipole<0,IFMqgxDipole,IFLightTildeKinematics,IFLightInvertedTildeKinematics> // ("IFMqgxDipole","IFLightTildeKinematics","IFLightInvertedTildeKinematics"); DipoleRepository::registerDipole<0,IFMqgxDipole,IFMassiveTildeKinematics,IFMassiveInvertedTildeKinematics> ("IFMqgxDipole","IFMassiveTildeKinematics","IFMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigIFMqgxDipole("Herwig::IFMqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IFMqgxDipole.h b/MatrixElement/Matchbox/Dipoles/IFMqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IFMqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IFMqgxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // IFMqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFMqgxDipole_H #define HERWIG_IFMqgxDipole_H // // This is the declaration of the IFMqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFMqgxDipole implements the D^{q,g}_k subtraction dipole * */ class IFMqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMqgxDipole(); - /** - * The destructor. - */ - virtual ~IFMqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMqgxDipole & operator=(const IFMqgxDipole &) = delete; }; } #endif /* HERWIG_IFMqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IFMqqxDipole.cc b/MatrixElement/Matchbox/Dipoles/IFMqqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IFMqqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IFMqqxDipole.cc @@ -1,167 +1,165 @@ // -*- C++ -*- // // IFMqqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFqqxDipole class. // #include "IFMqqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" //#include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h" //#include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFMassiveInvertedTildeKinematics.h" using namespace Herwig; IFMqqxDipole::IFMqqxDipole() : SubtractionDipole() {} -IFMqqxDipole::~IFMqqxDipole() {} - IBPtr IFMqqxDipole::clone() const { return new_ptr(*this); } IBPtr IFMqqxDipole::fullclone() const { return new_ptr(*this); } bool IFMqqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator > 1 && // abs(partons[emission]->id()) < 6 && // abs(partons[emitter]->id()) < 6 && abs(partons[emission]->id()) < 7 && abs(partons[emitter]->id()) < 7 && partons[emission]->id() - partons[emitter]->id() == 0 && // !(partons[emitter]->hardProcessMass() == ZERO && // partons[emission]->hardProcessMass() == ZERO && // partons[spectator]->hardProcessMass() == ZERO); partons[emitter]->hardProcessMass() == ZERO && partons[emission]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() != ZERO; } double IFMqqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double muj2 = sqr( (realEmissionME()->lastXComb().mePartonData()[realSpectator()]->hardProcessMass()) ) / (2.* (realEmissionME()->lastXComb().meMomenta()[bornSpectator()])* (realEmissionME()->lastXComb().meMomenta()[realEmitter()]) ); double res = x + 2.*(1.-x)/x - 2.*muj2/x*u/(1.-u); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); res *= 8.*CF*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IFMqqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; Lorentz5Momentum pc = realEmissionME()->lastXComb().meMomenta()[realEmission()]/u - realEmissionME()->lastXComb().meMomenta()[realSpectator()]/(1.-u); Energy2 sc = realEmissionME()->lastXComb().meMomenta()[realEmission()]* realEmissionME()->lastXComb().meMomenta()[realSpectator()]; sc /= u*(1.-u)*(1.-x)/x; SpinCorrelationTensor corr(-x,pc,sc/2.); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); res *= 8.*CF*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IFMqqxDipole::persistentOutput(PersistentOStream &) const { } void IFMqqxDipole::persistentInput(PersistentIStream &, int) { } void IFMqqxDipole::Init() { static ClassDocumentation documentation ("IFMqqxDipole"); // DipoleRepository::registerDipole<0,IFMqqxDipole,IFLightTildeKinematics,IFLightInvertedTildeKinematics> // ("IFMqqxDipole","IFLightTildeKinematics","IFLightInvertedTildeKinematics"); DipoleRepository::registerDipole<0,IFMqqxDipole,IFMassiveTildeKinematics,IFMassiveInvertedTildeKinematics> ("IFMqqxDipole","IFMassiveTildeKinematics","IFMassiveInvertedTildeKinematics"); } // *** 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 describeHerwigIFMqqxDipole("Herwig::IFMqqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IFMqqxDipole.h b/MatrixElement/Matchbox/Dipoles/IFMqqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IFMqqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IFMqqxDipole.h @@ -1,162 +1,154 @@ // -*- C++ -*- // // IFMqqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFMqqxDipole_H #define HERWIG_IFMqqxDipole_H // // This is the declaration of the IFMqqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFMqqxDipole implements the D^{q,qbar}_k subtraction dipole. * */ class IFMqqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMqqxDipole(); - /** - * The destructor. - */ - virtual ~IFMqqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emitter]->id() == partons[emission]->id(); } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 2;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMqqxDipole & operator=(const IFMqqxDipole &) = delete; }; } #endif /* HERWIG_IFMqqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IFggxDipole.cc b/MatrixElement/Matchbox/Dipoles/IFggxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IFggxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IFggxDipole.cc @@ -1,150 +1,148 @@ // -*- C++ -*- // // IFggxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFggxDipole class. // #include "IFggxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h" using namespace Herwig; IFggxDipole::IFggxDipole() : SubtractionDipole() {} -IFggxDipole::~IFggxDipole() {} - IBPtr IFggxDipole::clone() const { return new_ptr(*this); } IBPtr IFggxDipole::fullclone() const { return new_ptr(*this); } bool IFggxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator > 1 && partons[emission]->id() == ParticleID::g && partons[emitter]->id() == ParticleID::g && partons[spectator]->hardProcessMass() == ZERO; } double IFggxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 1./(1.-x+u) + (1.-x)/x - 1. + x*(1.-x); res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IFggxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; if ( alpha() < u ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double diag = 1./(1.-x+u)-1.+x*(1.-x); Lorentz5Momentum pc = realEmissionME()->lastXComb().meMomenta()[realEmission()]/u - realEmissionME()->lastXComb().meMomenta()[realSpectator()]/(1.-u); Energy2 sc = realEmissionME()->lastXComb().meMomenta()[realEmission()]* realEmissionME()->lastXComb().meMomenta()[realSpectator()]; sc /= u*(1.-u)*(1.-x)/x; SpinCorrelationTensor corr(-diag,pc,sc); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IFggxDipole::persistentOutput(PersistentOStream &) const { } void IFggxDipole::persistentInput(PersistentIStream &, int) { } void IFggxDipole::Init() { static ClassDocumentation documentation ("IFggxDipole"); DipoleRepository::registerDipole<0,IFggxDipole,IFLightTildeKinematics,IFLightInvertedTildeKinematics> ("IFggxDipole","IFLightTildeKinematics","IFLightInvertedTildeKinematics"); } // *** 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 describeHerwigIFggxDipole("Herwig::IFggxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IFggxDipole.h b/MatrixElement/Matchbox/Dipoles/IFggxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IFggxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IFggxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // IFggxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFggxDipole_H #define HERWIG_IFggxDipole_H // // This is the declaration of the IFggxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFggxDipole implements the D^{g,g}_k subtraction dipole. * */ class IFggxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFggxDipole(); - /** - * The destructor. - */ - virtual ~IFggxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFggxDipole & operator=(const IFggxDipole &) = delete; }; } #endif /* HERWIG_IFggxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IFgqxDipole.cc b/MatrixElement/Matchbox/Dipoles/IFgqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IFgqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IFgqxDipole.cc @@ -1,140 +1,138 @@ // -*- C++ -*- // // IFgqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFgqxDipole class. // #include "IFgqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h" using namespace Herwig; IFgqxDipole::IFgqxDipole() : SubtractionDipole() {} -IFgqxDipole::~IFgqxDipole() {} - IBPtr IFgqxDipole::clone() const { return new_ptr(*this); } IBPtr IFgqxDipole::fullclone() const { return new_ptr(*this); } bool IFgqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator > 1 && partons[emitter]->id() == ParticleID::g && abs(partons[emission]->id()) < 6 && partons[emission]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double IFgqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 8.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= .5 * ( 1.-2.*x*(1.-x) ); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IFgqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; if ( alpha() < u ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 8.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= .5 * ( 1.-2.*x*(1.-x) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IFgqxDipole::persistentOutput(PersistentOStream &) const { } void IFgqxDipole::persistentInput(PersistentIStream &, int) { } void IFgqxDipole::Init() { static ClassDocumentation documentation ("IFgqxDipole"); DipoleRepository::registerDipole<0,IFgqxDipole,IFLightTildeKinematics,IFLightInvertedTildeKinematics> ("IFgqxDipole","IFLightTildeKinematics","IFLightInvertedTildeKinematics"); } // *** 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 describeHerwigIFgqxDipole("Herwig::IFgqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IFgqxDipole.h b/MatrixElement/Matchbox/Dipoles/IFgqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IFgqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IFgqxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // IFgqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFgqxDipole_H #define HERWIG_IFgqxDipole_H // // This is the declaration of the IFgqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFgqxDipole implements the D_k^{g,q} subtraction dipole. * */ class IFgqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFgqxDipole(); - /** - * The destructor. - */ - virtual ~IFgqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && abs(partons[emission]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 2;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFgqxDipole & operator=(const IFgqxDipole &) = delete; }; } #endif /* HERWIG_IFgqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IFqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/IFqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IFqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IFqgxDipole.cc @@ -1,151 +1,149 @@ // -*- C++ -*- // // IFqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFqgxDipole class. // #include "IFqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h" using namespace Herwig; IFqgxDipole::IFqgxDipole() : SubtractionDipole() {} -IFqgxDipole::~IFqgxDipole() {} - IBPtr IFqgxDipole::clone() const { return new_ptr(*this); } IBPtr IFqgxDipole::fullclone() const { return new_ptr(*this); } bool IFqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator > 1 && partons[emission]->id() == ParticleID::g && abs(partons[emitter]->id()) < 6 && partons[emitter]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double IFqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-x+u) - (1.+x) + u*(1.+3.*x*(1.-u)) ); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IFqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; if ( alpha() < u ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= ( 2./(1.-x+u) - (1.+x) //+ u*(1.+3.*x*(1.-u)) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IFqgxDipole::persistentOutput(PersistentOStream &) const { } void IFqgxDipole::persistentInput(PersistentIStream &, int) { } void IFqgxDipole::Init() { static ClassDocumentation documentation ("IFqgxDipole"); DipoleRepository::registerDipole<0,IFqgxDipole,IFLightTildeKinematics,IFLightInvertedTildeKinematics> ("IFqgxDipole","IFLightTildeKinematics","IFLightInvertedTildeKinematics"); } // *** 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 describeHerwigIFqgxDipole("Herwig::IFqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IFqgxDipole.h b/MatrixElement/Matchbox/Dipoles/IFqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IFqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IFqgxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // IFqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFqgxDipole_H #define HERWIG_IFqgxDipole_H // // This is the declaration of the IFqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFqgxDipole implements the D^{q,g}_k subtraction dipole * */ class IFqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFqgxDipole(); - /** - * The destructor. - */ - virtual ~IFqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFqgxDipole & operator=(const IFqgxDipole &) = delete; }; } #endif /* HERWIG_IFqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IFqqxDipole.cc b/MatrixElement/Matchbox/Dipoles/IFqqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IFqqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IFqqxDipole.cc @@ -1,155 +1,153 @@ // -*- C++ -*- // // IFqqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFqqxDipole class. // #include "IFqqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h" using namespace Herwig; IFqqxDipole::IFqqxDipole() : SubtractionDipole() {} -IFqqxDipole::~IFqqxDipole() {} - IBPtr IFqqxDipole::clone() const { return new_ptr(*this); } IBPtr IFqqxDipole::fullclone() const { return new_ptr(*this); } bool IFqqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator > 1 && abs(partons[emission]->id()) < 6 && abs(partons[emitter]->id()) < 6 && partons[emission]->id() - partons[emitter]->id() == 0 && partons[emitter]->hardProcessMass() == ZERO && partons[emission]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double IFqqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = x + 2.*(1.-x)/x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); res *= 8.*CF*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IFqqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; if ( alpha() < u ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; Lorentz5Momentum pc = realEmissionME()->lastXComb().meMomenta()[realEmission()]/u - realEmissionME()->lastXComb().meMomenta()[realSpectator()]/(1.-u); Energy2 sc = realEmissionME()->lastXComb().meMomenta()[realEmission()]* realEmissionME()->lastXComb().meMomenta()[realSpectator()]; sc /= u*(1.-u)*(1.-x)/x; SpinCorrelationTensor corr(-x,pc,sc/2.); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); res *= 8.*CF*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IFqqxDipole::persistentOutput(PersistentOStream &) const { } void IFqqxDipole::persistentInput(PersistentIStream &, int) { } void IFqqxDipole::Init() { static ClassDocumentation documentation ("IFqqxDipole"); DipoleRepository::registerDipole<0,IFqqxDipole,IFLightTildeKinematics,IFLightInvertedTildeKinematics> ("IFqqxDipole","IFLightTildeKinematics","IFLightInvertedTildeKinematics"); } // *** 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 describeHerwigIFqqxDipole("Herwig::IFqqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IFqqxDipole.h b/MatrixElement/Matchbox/Dipoles/IFqqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IFqqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IFqqxDipole.h @@ -1,162 +1,154 @@ // -*- C++ -*- // // IFqqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFqqxDipole_H #define HERWIG_IFqqxDipole_H // // This is the declaration of the IFqqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFqqxDipole implements the D^{q,qbar}_k subtraction dipole. * */ class IFqqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFqqxDipole(); - /** - * The destructor. - */ - virtual ~IFqqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emitter]->id() == partons[emission]->id(); } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator > 1 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 2;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFqqxDipole & operator=(const IFqqxDipole &) = delete; }; } #endif /* HERWIG_IFqqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IIggxDipole.cc b/MatrixElement/Matchbox/Dipoles/IIggxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IIggxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IIggxDipole.cc @@ -1,149 +1,147 @@ // -*- C++ -*- // // IIggxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IIggxDipole class. // #include "IIggxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightInvertedTildeKinematics.h" using namespace Herwig; IIggxDipole::IIggxDipole() : SubtractionDipole() {} -IIggxDipole::~IIggxDipole() {} - IBPtr IIggxDipole::clone() const { return new_ptr(*this); } IBPtr IIggxDipole::fullclone() const { return new_ptr(*this); } bool IIggxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator < 2 && partons[emission]->id() == ParticleID::g && partons[emitter]->id() == ParticleID::g && partons[spectator]->hardProcessMass() == ZERO; } double IIggxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = x/(1.-x) + (1.-x)/x + x*(1.-x); res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IIggxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double v = subtractionParameters()[1]; if ( alpha() < v ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double diag = x/(1.-x)+x*(1.-x); Lorentz5Momentum pc = realEmissionME()->lastXComb().meMomenta()[realEmission()] - v*realEmissionME()->lastXComb().meMomenta()[realSpectator()]; Energy2 sc = realEmissionME()->lastXComb().meMomenta()[realEmission()]* realEmissionME()->lastXComb().meMomenta()[realSpectator()]; sc /= (1.-x)/(x*v); SpinCorrelationTensor corr(-diag,pc,sc); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); res *= 16.*Constants::pi*SM().Nc()*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IIggxDipole::persistentOutput(PersistentOStream &) const { } void IIggxDipole::persistentInput(PersistentIStream &, int) { } void IIggxDipole::Init() { static ClassDocumentation documentation ("IIggxDipole"); DipoleRepository::registerDipole<0,IIggxDipole,IILightTildeKinematics,IILightInvertedTildeKinematics> ("IIggxDipole","IILightTildeKinematics","IILightInvertedTildeKinematics"); } // *** 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 describeHerwigIIggxDipole("Herwig::IIggxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IIggxDipole.h b/MatrixElement/Matchbox/Dipoles/IIggxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IIggxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IIggxDipole.h @@ -1,159 +1,151 @@ // -*- C++ -*- // // IIggxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IIggxDipole_H #define HERWIG_IIggxDipole_H // // This is the declaration of the IIggxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IIggxDipole implements the D^{g,g;b} subtraction dipole. * */ class IIggxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IIggxDipole(); - /** - * The destructor. - */ - virtual ~IIggxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IIggxDipole & operator=(const IIggxDipole &) = delete; }; } #endif /* HERWIG_IIggxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IIgqxDipole.cc b/MatrixElement/Matchbox/Dipoles/IIgqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IIgqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IIgqxDipole.cc @@ -1,140 +1,138 @@ // -*- C++ -*- // // IIgqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IIgqxDipole class. // #include "IIgqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightInvertedTildeKinematics.h" using namespace Herwig; IIgqxDipole::IIgqxDipole() : SubtractionDipole() {} -IIgqxDipole::~IIgqxDipole() {} - IBPtr IIgqxDipole::clone() const { return new_ptr(*this); } IBPtr IIgqxDipole::fullclone() const { return new_ptr(*this); } bool IIgqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator < 2 && partons[emitter]->id() == ParticleID::g && abs(partons[emission]->id()) < 6 && partons[emission]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double IIgqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 8.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= .5 * ( 1.-2.*x*(1.-x) ); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IIgqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double v = subtractionParameters()[1]; if ( alpha() < v ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = 8.*Constants::pi*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= .5 * ( 1.-2.*x*(1.-x) ); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IIgqxDipole::persistentOutput(PersistentOStream &) const { } void IIgqxDipole::persistentInput(PersistentIStream &, int) { } void IIgqxDipole::Init() { static ClassDocumentation documentation ("IIgqxDipole"); DipoleRepository::registerDipole<0,IIgqxDipole,IILightTildeKinematics,IILightInvertedTildeKinematics> ("IIgqxDipole","IILightTildeKinematics","IILightInvertedTildeKinematics"); } // *** 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 describeHerwigIIgqxDipole("Herwig::IIgqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IIgqxDipole.h b/MatrixElement/Matchbox/Dipoles/IIgqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IIgqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IIgqxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // IIgqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IIgqxDipole_H #define HERWIG_IIgqxDipole_H // // This is the declaration of the IIgqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IIgqxDipole implements the D^{g,q,k} subtraction dipole * */ class IIgqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IIgqxDipole(); - /** - * The destructor. - */ - virtual ~IIgqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && partons[emitter]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && abs(partons[emission]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 * N.B. not the perturbative result chosen to improve sampling */ virtual int samplingZ() const {return 2;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IIgqxDipole & operator=(const IIgqxDipole &) = delete; }; } #endif /* HERWIG_IIgqxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IIqgxDipole.cc b/MatrixElement/Matchbox/Dipoles/IIqgxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IIqgxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IIqgxDipole.cc @@ -1,144 +1,142 @@ // -*- C++ -*- // // IIqgxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IIqgxDipole class. // #include "IIqgxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightInvertedTildeKinematics.h" using namespace Herwig; IIqgxDipole::IIqgxDipole() : SubtractionDipole() {} -IIqgxDipole::~IIqgxDipole() {} - IBPtr IIqgxDipole::clone() const { return new_ptr(*this); } IBPtr IIqgxDipole::fullclone() const { return new_ptr(*this); } bool IIqgxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator < 2 && partons[emission]->id() == ParticleID::g && abs(partons[emitter]->id()) < 6 && partons[emitter]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double IIqgxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= 2./(1.-x) - (1.+x); res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IIqgxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double v = subtractionParameters()[1]; if ( alpha() < v ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); double res = 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= 2./(1.-x) - (1.+x); res *= -underlyingBornME()->colourCorrelatedME2(make_pair(bornEmitter(),bornSpectator())); res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IIqgxDipole::persistentOutput(PersistentOStream &) const { } void IIqgxDipole::persistentInput(PersistentIStream &, int) { } void IIqgxDipole::Init() { static ClassDocumentation documentation ("IIqgxDipole"); DipoleRepository::registerDipole<0,IIqgxDipole,IILightTildeKinematics,IILightInvertedTildeKinematics> ("IIqgxDipole","IILightTildeKinematics","IILightInvertedTildeKinematics"); } // *** 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 describeHerwigIIqgxDipole("Herwig::IIqgxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IIqgxDipole.h b/MatrixElement/Matchbox/Dipoles/IIqgxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IIqgxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IIqgxDipole.h @@ -1,160 +1,152 @@ // -*- C++ -*- // // IIqgxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IIqgxDipole_H #define HERWIG_IIqgxDipole_H // // This is the declaration of the IIqgxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IIqgxDipole implements the D^{q,g;b} subtraction dipole * */ class IIqgxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IIqgxDipole(); - /** - * The destructor. - */ - virtual ~IIqgxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emission]->id() == ParticleID::g; } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 4;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IIqgxDipole & operator=(const IIqgxDipole &) = delete; }; } #endif /* HERWIG_IIqgxDipole_H */ diff --git a/MatrixElement/Matchbox/Dipoles/IIqqxDipole.cc b/MatrixElement/Matchbox/Dipoles/IIqqxDipole.cc --- a/MatrixElement/Matchbox/Dipoles/IIqqxDipole.cc +++ b/MatrixElement/Matchbox/Dipoles/IIqqxDipole.cc @@ -1,155 +1,153 @@ // -*- C++ -*- // // IIqqxDipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IIqqxDipole class. // #include "IIqqxDipole.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/IILightInvertedTildeKinematics.h" using namespace Herwig; IIqqxDipole::IIqqxDipole() : SubtractionDipole() {} -IIqqxDipole::~IIqqxDipole() {} - IBPtr IIqqxDipole::clone() const { return new_ptr(*this); } IBPtr IIqqxDipole::fullclone() const { return new_ptr(*this); } bool IIqqxDipole::canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const { return emitter < 2 && spectator < 2 && abs(partons[emission]->id()) < 6 && abs(partons[emitter]->id()) < 6 && partons[emission]->id() - partons[emitter]->id() == 0 && partons[emitter]->hardProcessMass() == ZERO && partons[emission]->hardProcessMass() == ZERO && partons[spectator]->hardProcessMass() == ZERO; } double IIqqxDipole::me2Avg(double ccme2) const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; double res = (1.+sqr(1.-x))/x; double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); res *= 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= -ccme2; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } double IIqqxDipole::me2() const { if ( jacobian() == 0.0 ) return 0.0; double x = subtractionParameters()[0]; double v = subtractionParameters()[1]; if ( alpha() < v ) return 0.0; Energy2 prop = 2.*((realEmissionME()->lastXComb().meMomenta()[realEmitter()])* (realEmissionME()->lastXComb().meMomenta()[realEmission()]))*x; Lorentz5Momentum pc = realEmissionME()->lastXComb().meMomenta()[realEmission()] - v*realEmissionME()->lastXComb().meMomenta()[realSpectator()]; Energy2 sc = realEmissionME()->lastXComb().meMomenta()[realEmission()]* realEmissionME()->lastXComb().meMomenta()[realSpectator()]; sc /= (1.-x)/(x*v); SpinCorrelationTensor corr(-x,pc,sc/2.); double res = -underlyingBornME()->spinColourCorrelatedME2(make_pair(bornEmitter(),bornSpectator()), corr); double CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc()); res *= 8.*Constants::pi*CF*(realEmissionME()->lastXComb().lastSHat())* (underlyingBornME()->lastXComb().lastAlphaS())/prop; res *= pow(realEmissionME()->lastXComb().lastSHat() / underlyingBornME()->lastXComb().lastSHat(), underlyingBornME()->lastXComb().mePartonData().size()-4.); res *= realEmissionME()->finalStateSymmetry() / underlyingBornME()->finalStateSymmetry(); return res; } void IIqqxDipole::persistentOutput(PersistentOStream &) const { } void IIqqxDipole::persistentInput(PersistentIStream &, int) { } void IIqqxDipole::Init() { static ClassDocumentation documentation ("IIqqxDipole"); DipoleRepository::registerDipole<0,IIqqxDipole,IILightTildeKinematics,IILightInvertedTildeKinematics> ("IIqqxDipole","IILightTildeKinematics","IILightInvertedTildeKinematics"); } // *** 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 describeHerwigIIqqxDipole("Herwig::IIqqxDipole", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Dipoles/IIqqxDipole.h b/MatrixElement/Matchbox/Dipoles/IIqqxDipole.h --- a/MatrixElement/Matchbox/Dipoles/IIqqxDipole.h +++ b/MatrixElement/Matchbox/Dipoles/IIqqxDipole.h @@ -1,162 +1,154 @@ // -*- C++ -*- // // IIqqxDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IIqqxDipole_H #define HERWIG_IIqqxDipole_H // // This is the declaration of the IIqqxDipole class. // #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IIqqxDipole implements the D^{q,qbar;b} subtraction dipole. * */ class IIqqxDipole: public SubtractionDipole { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IIqqxDipole(); - /** - * The destructor. - */ - virtual ~IIqqxDipole(); - //@} - public: /** * Return true, if this dipole can possibly handle the indicated * emitter. */ virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const { return emitter < 2 && abs(partons[emitter]->id()) < 7; } /** * Return true, if this dipole can possibly handle the indicated * splitting. */ virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const { return canHandleEmitter(partons,emitter) && partons[emitter]->id() == partons[emission]->id(); } /** * Return true, if this dipole can possibly handle the indicated * spectator. */ virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const { return spectator < 2 && partons[spectator]->coloured(); } /** * Return true, if this dipole applies to the selected * configuration. */ virtual bool canHandle(const cPDVector& partons, int emitter, int emission, int spectator) const; /** * How to sample the z-distribution. * FlatZ = 1 * OneOverZ = 2 * OneOverOneMinusZ = 3 * OneOverZOneMinusZ = 4 */ virtual int samplingZ() const {return 2;} /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const; /** * Return the matrix element averaged over spin correlations. */ virtual double me2Avg(double ccme2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IIqqxDipole & operator=(const IIqqxDipole &) = delete; }; } #endif /* HERWIG_IIqqxDipole_H */ diff --git a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc --- a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc +++ b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc @@ -1,1069 +1,1067 @@ // -*- C++ -*- // // GoSamAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the GoSamAmplitude class. // #include "GoSamAmplitude.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 "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/StringUtils.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "Herwig/API/Filesystem.h" #include #include #include #include #include namespace bfs = Herwig::filesystem; 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 GOSAM_PREFIX #error Makefile.am needs to define GOSAM_PREFIX #endif //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// GoSamAmplitude::GoSamAmplitude() : theAccuracyTarget(6),theCodeExists(false),theFormOpt(true),theNinja(true), theHiggsEff(false),theMassiveLeptons(false),theLoopInducedOption(0), isitDR(false),doneGoSamInit(false),doneGoSamInitRun(false), bindir_(HERWIG_BINDIR), pkgdatadir_(HERWIG_PKGDATADIR), GoSamPrefix_(GOSAM_PREFIX) {} -GoSamAmplitude::~GoSamAmplitude() {} - IBPtr GoSamAmplitude::clone() const { return new_ptr(*this); } IBPtr GoSamAmplitude::fullclone() const { return new_ptr(*this); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void GoSamAmplitude::doinit() { optionalContractFile() = name() + ".OLPContract.lh"; MatchboxOLPME::doinit(); doneGoSamInit = true; } void GoSamAmplitude::doinitrun() { optionalContractFile() = name() + ".OLPContract.lh"; MatchboxOLPME::doinitrun(); doneGoSamInitRun = true; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// extern "C" void OLP_Start(const char*, int* i); extern "C" void OLP_Polvec(double*, double*, double*); extern "C" void OLP_SetParameter(char*, double*, double*, int*); extern "C" void OLP_PrintParameter(char*); extern "C" void OLP_EvalSubProcess2(int*, double*, double*, double*, double*); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// bool GoSamAmplitude::startOLP(const map, int>& procs) { char char_cwd[256]; getcwd(char_cwd, sizeof(char_cwd)); string cwd = string(char_cwd); string folderMatchboxBuild = factory()->buildStorage(); folderMatchboxBuild.erase(folderMatchboxBuild.begin()); // set all necessary path and file names gosamPath = gosamPathInterface == "" ? cwd + folderMatchboxBuild + "GoSam" : gosamPathInterface; // When transitioning to C++ 11 this length()-1 workaround can be replaced by string.back() if (gosamPath.at(gosamPath.length()-1) != '/') gosamPath.append("/"); gosamSourcePath = gosamPath + "source/"; gosamInstallPath = gosamPath + "build/"; // create all the directories if (!bfs::is_directory(gosamPath)){ try { bfs::create_directory(gosamPath); } catch (exception& e) { throw Exception() << "--------------------------------------------------------------------------------\n" << "The following exception occured:\n\n" << " " << e.what() << "\n\n" << " -> Please create the parent directory of\n" << " " << gosamPath << "\n" << " manually!\n" << "--------------------------------------------------------------------------------\n" << Exception::runerror; } } if (!bfs::is_directory(gosamSourcePath)) bfs::create_directory(gosamSourcePath); if (!bfs::is_directory(gosamInstallPath)) bfs::create_directory(gosamInstallPath); contractFileTitle = name() + ".OLPContract.lh"; contractFileName = gosamPath + "/" + contractFileTitle; string orderFileName = gosamPath + "/" + name() + ".OLPOrder.lh"; // Set the path variable (plus file name) where to find the GoSam specific input file gosamSetupInFileName = gosamSetupInFileNameInterface == "" ? gosamPath + "/setup.gosam.in" : gosamSetupInFileNameInterface; // Use the python script gosam2herwig to make replacements in the GoSam // specific input file at gosamSetupInFileName. If the GoSam input file // does not exist yet at gosamSetupInFileName the python script will get // it from src/defaults/ before making the replacements. string cmd = "python "+bindir_+"/gosam2herwig "; cmd+=" --usrinfile="+gosamSetupInFileNameInterface; cmd+=" --infile="+gosamSetupInFileName+".tbu"; cmd+=" --definfile="+pkgdatadir_+"/defaults/setup.gosam.in"; cmd+=" --formtempdir="+StringUtils::replace(gosamSourcePath, string("/"), string("\\/")); //@FORMTEMPDIR@ cmd+=" --reduction="+(theNinja ? string("ninja,golem95") : string("samurai,golem95")); //@REDUCTIONPROGRAMS@ cmd+=" --formopt="+(theFormOpt ? string("") : string(", noformopt")); //@FORMOPT@ cmd+=" --higgseff="+(theHiggsEff ? string("smehc") : string("smdiag")); //@MODEL@ std::system(cmd.c_str()); if ( factory()->initVerbose() ) { generator()->log() << "\n\n>>> NOTE: According to the repository settings for the GoSam interface:\n" << flush; if (theHiggsEff) generator()->log() << "\n -- GoSam will use a model with an effective ggH coupling (model=smehc).\n" << flush; else if (!theHiggsEff) generator()->log() << "\n -- GoSam will use its default model (model=smdiag).\n" << flush; if (theNinja) generator()->log() << " -- GoSam will use Ninja as reduction program (reduction_programs=ninja,golem95).\n" << flush; else if (!theNinja) generator()->log() << " -- GoSam will use Samurai as reduction program (reduction_programs=samurai,golem95).\n" << flush; if (theFormOpt) generator()->log() << " -- Form optimization switched on (extensions=autotools).\n" << flush; else if (!theFormOpt) generator()->log() << " -- Form optimization switched off (extensions=autotools, noformopt).\n" << flush; if (theNinja && !theFormOpt) throw Exception() << "GoSamAmplitude: Ninja reduction needs form optimization!\n" << Exception::runerror; if (gosamSetupInFileNameInterface == "") { generator()->log() << "\n Please be aware that you are using a copy of the default GoSam input file!\n" << " Please note that if you need special options to be considered for the specific\n" << " process you are looking at (diagram filtering, etc.) these are not automatically\n" << " set for you. In that case please consider to specify your own GoSam input file\n" << " via 'set " << name() << ":SetupInFilename' in the input file.\n\n" << flush; } // If one uses a custom GoSam input file at gosamSetupInFileName = gosamSetupInFileNameInterface // then please note that not all options in there might match the corresponding Herwig repository // options if (gosamSetupInFileNameInterface != "") { generator()->log() << "\n Please be aware that you are using a custom GoSam input file!\n" << " Please note that if you have set the options for model, reduction_programs,\n" << " extensions and/or form.tempdir manually these will of course not be replaced\n" << " by the corresponding repository settings mentioned above.\n\n" << flush; } generator()->log() << "\n>>> NOTE: GoSam may return the set of used parameters for this process via the OLP_PrintParameter() function:\n\n" << " -- If Debug::level > 1, the OLP parameters are being written to file: at " << factory()->runStorage() + name() + ".OLPParameters.lh.\n\n" << flush; } double accuracyTarget = 1.0/pow(10.0,accuracyTargetNegExp()); time_t rawtime; time (&rawtime); accuracyFileTitle = name() + ".OLPAccuracy.lh"; accuracyFile = factory()->buildStorage() + accuracyFileTitle; ofstream accuracyFileStream; if ( Debug::level > 1 ) { accuracyFileStream.open(accuracyFile.c_str()); // Opening accuracyFile once here removes all previous content before the read step accuracyFileStream << "\nFile to contain those PSPs for which GoSam evaluated one-loop interference terms or loop induced ME2s\n" << "with acc > target accuracy = " << accuracyTarget << ". Date/Time: " << ctime(&rawtime) << endl; } if ( factory()->initVerbose() ) { generator()->log() << "\n>>> NOTE: GoSam will return the accuracy of one-loop interference terms or loop induced ME2s\n" << " at every PSP via the BLHA2 acc parameter:\n\n" << " -- In cases where acc > 10^-AccuracyTarget = " << accuracyTarget << " the corresponding PSPs are being dis-\n" << " carded.\n" << " -- The default value for AccuracyTarget is 6, but you may consider setting it otherwise\n" << " via 'set " << name() << ":AccuracyTarget' in the input file.\n" << " -- Currently the value for AccuracyTarget is set to " << accuracyTargetNegExp() << ".\n" << " -- If Debug::level > 1, the discarded PSPs are being written to file: at " + accuracyFile << ".\n" << " -- If the amount of PSPs with acc > " << accuracyTarget << " is significant, please consider to re-evaluate\n" << " your process setup (accuracy target, masses, cuts, etc.)!\n\n\n" << flush; } // check for old order file and create it if it doesn't already exist fillOrderFile(procs, orderFileName); ifstream ifile(contractFileName.c_str()); if(!ifile){ signOLP(orderFileName, contractFileName); } if ( !checkOLPContract(contractFileName) ) { throw Exception() << "GoSamAmplitude: failed to start GoSam" << Exception::runerror; } if (!( DynamicLoader::load(gosamInstallPath+"/lib/libgolem_olp.so") || DynamicLoader::load(gosamInstallPath+"/lib64/libgolem_olp.so") || DynamicLoader::load(gosamInstallPath+"/lib/libgolem_olp.dylib") || DynamicLoader::load(gosamInstallPath+"/lib64/libgolem_olp.dylib"))) buildGoSam(); int status = -1; startOLP(contractFileTitle, status); if ( status != 1 ) return false; return true; } void GoSamAmplitude::startOLP(const string& contract, int& status) { string tempcontract = contract; char char_cwd[256]; getcwd(char_cwd, sizeof(char_cwd)); string cwd = string(char_cwd); string folderMatchboxBuild = factory()->buildStorage(); folderMatchboxBuild.erase(folderMatchboxBuild.begin()); gosamPath = gosamPathInterface == "" ? cwd + folderMatchboxBuild + "GoSam" : gosamPathInterface; // When transitioning to C++ 11 this length()-1 workaround can be replaced by string.back() if (gosamPath.at(gosamPath.length()-1) != '/') gosamPath.append("/"); if (!( DynamicLoader::load(gosamPath+"build/lib/libgolem_olp.so") || DynamicLoader::load(gosamPath+"build/lib64/libgolem_olp.so") || DynamicLoader::load(gosamPath+"build/lib/libgolem_olp.dylib") || DynamicLoader::load(gosamPath+"build/lib64/libgolem_olp.dylib"))) throw Exception() << "GoSamAmplitude: Failed to load GoSam. Please check the log file.\n" << Exception::runerror; tempcontract = gosamPath + tempcontract; OLP_Start(tempcontract.c_str(), &status); // hand over input parameters for EW scheme considered int pStatus = 0; double zero = 0.0; if ( SM().ewScheme() == 0 || SM().ewScheme() == 6 ) { // EW/Scheme Default and EW/Scheme Independent throw Exception() << "GoSamAmplitude: `Best value' schemes are not supported by GoSam" << Exception::runerror; } else if ( SM().ewScheme() == 4 ) { // EW/Scheme mW (uses mW,GF,sin2thetaW) seems not to be supported by GoSam throw Exception() << "GoSamAmplitude: `mW' scheme is not supported by GoSam" << Exception::runerror; } else if ( SM().ewScheme() == 1 ) { // EW/Scheme GMuScheme (uses mW,mZ,GF) double in1=getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; double in2=getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV; double in3=SM().fermiConstant()*GeV2; OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus); OLP_SetParameter((char *)"mass(24)",&in2,&zero,&pStatus); OLP_SetParameter((char *)"Gf",&in3,&zero,&pStatus); } else if ( SM().ewScheme() == 2 ) { // EW/Scheme alphaMZScheme (uses mW,mZ,alpha(mZ)) double in1=getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; double in2=getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV; double in3=SM().alphaEMMZ(); OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus); OLP_SetParameter((char *)"mass(24)",&in2,&zero,&pStatus); OLP_SetParameter((char *)"alpha",&in3,&zero,&pStatus); } else if ( SM().ewScheme() == 3 ) { // EW/Scheme NoMass (uses alpha(mZ),GF,sin2thetaW) double in1=SM().fermiConstant()*GeV2; double in2=SM().alphaEMMZ(); double in3=SM().sin2ThetaW(); OLP_SetParameter((char *)"Gf",&in1,&zero,&pStatus); OLP_SetParameter((char *)"alpha",&in2,&zero,&pStatus); OLP_SetParameter((char *)"sw2",&in3,&zero,&pStatus); } else if ( SM().ewScheme() == 5 ) { // EW/Scheme mZ (uses mZ,alphaEM,sin2thetaW) double in1=getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; double in2=SM().alphaEMMZ(); double in3=SM().sin2ThetaW(); OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus); OLP_SetParameter((char *)"alpha",&in2,&zero,&pStatus); OLP_SetParameter((char *)"sw2",&in3,&zero,&pStatus); } else if ( SM().ewScheme() == 7 ) { // EW/Scheme FeynRulesUFO (uses mZ,GF,alpha(mZ)) double in1=getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; double in2=SM().alphaEMMZ(); double in3=SM().fermiConstant()*GeV2; OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus); OLP_SetParameter((char *)"alpha",&in2,&zero,&pStatus); OLP_SetParameter((char *)"Gf",&in3,&zero,&pStatus); } // hand over widths of Z and W double wZ = getParticleData(23)->hardProcessWidth()/GeV; double wW = getParticleData(24)->hardProcessWidth()/GeV; OLP_SetParameter((char*)"width(23)",&wZ,&zero,&pStatus); OLP_SetParameter((char*)"width(24)",&wW,&zero,&pStatus); // hand over mass and width of the Higgs double wH = getParticleData(25)->hardProcessWidth()/GeV; double mH = getParticleData(25)->hardProcessMass()/GeV; OLP_SetParameter((char*)"width(25)",&wH,&zero,&pStatus); OLP_SetParameter((char*)"mass(25)",&mH,&zero,&pStatus); // hand over initial input parameter for alphaS double as = SM().alphaS(); OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus); // fill massive Particle vector if (massiveParticles.empty()) { // with quark masses for (int i=1; i<=6; ++i) if (getParticleData(i)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(i); // with lepton masses if (theMassiveLeptons && getParticleData(11)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(11); if (theMassiveLeptons && getParticleData(13)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(13); if (theMassiveLeptons && getParticleData(15)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(15); } // hand over quark (and possibly lepton) masses and widths (iff massive) if ( massiveParticles.size() != 0 ) { for ( vector::const_iterator mID = massiveParticles.begin(); mID != massiveParticles.end(); ++mID ) { string mstr; string wstr; int mInt = *mID; double mass=getParticleData(mInt)->hardProcessMass()/GeV; double width=getParticleData(mInt)->hardProcessWidth()/GeV; std::stringstream ss; ss << mInt; string str = ss.str(); mstr="mass("+str+")"; wstr="width("+str+")"; char * mchar = new char[mstr.size()+1]; char * wchar = new char[wstr.size()+1]; std::copy(mstr.begin(),mstr.end(),mchar); std::copy(wstr.begin(),wstr.end(),wchar); mchar[mstr.size()] = '\0'; wchar[wstr.size()] = '\0'; OLP_SetParameter( mchar, &mass, &zero, &pStatus ); OLP_SetParameter( wchar, &width, &zero, &pStatus ); delete[] mchar; delete[] wchar; // Nicer but not working properly: // double mass=getParticleData(*mID)->hardProcessMass()/GeV; // double width=getParticleData(*mID)->hardProcessWidth()/GeV; // string mstr="mass("+static_cast(&(ostringstream()<<(*mID)))->str()+")"; // string wstr="width("+static_cast(&(ostringstream()<<(*mID)))->str()+")"; // cout<<"\n massiv "< 1 ) { string ppstr = factory()->runStorage() + name() + ".OLPParameters.lh"; OLP_PrintParameter(const_cast(ppstr.c_str())); } didStartOLP() = true; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void GoSamAmplitude::fillOrderFile(const map, int>& procs, string orderFileName) { for ( map, int>::const_iterator p = procs.begin() ; p != procs.end() ; ++p ) { std::stringstream Processstr; std::stringstream Typestr; Processstr << (*p).first.first.legs[0]->id() << " " << (*p).first.first.legs[1]->id() << " -> "; for ( PDVector::const_iterator o = (*p).first.first.legs.begin() + 2 ; o != (*p).first.first.legs.end() ; ++o ) Processstr << (**o).id() << " "; if ( (*p).first.second == ProcessType::treeME2 ) { Typestr << "Tree"; } else if ( (*p).first.second == ProcessType::loopInducedME2 ) { Typestr << "LoopInduced"; } else if ( (*p).first.second == ProcessType::colourCorrelatedME2 ) { Typestr << "ccTree"; } else if ( (*p).first.second == ProcessType::spinColourCorrelatedME2 ) { Typestr << "scTree"; } else if ( (*p).first.second == ProcessType::oneLoopInterference ) { Typestr << "Loop"; } gosamprocinfo pro = gosamprocinfo((*p).second, -1, Processstr.str(), Typestr.str()); pro.setOAs(p->first.first.orderInAlphaS); pro.setOAew(p->first.first.orderInAlphaEW); processmap[(*p).second] = pro; } ifstream oldOrderFileStream(orderFileName.c_str()); if (oldOrderFileStream){ oldOrderFileStream.close(); return; } ofstream orderFile(orderFileName.c_str()); int asPower = 100; int minlegs = 100; int maxlegs = -1; int maxasPower = -1; int aewPower = 100; int maxaewPower = -1; for ( map, int>::const_iterator t = procs.begin() ; t != procs.end() ; ++t ) { asPower = min(asPower, static_cast(t->first.first.orderInAlphaS)); minlegs = min(minlegs, static_cast(t->first.first.legs.size())); maxlegs = max(maxlegs, static_cast(t->first.first.legs.size())); maxasPower = max(maxasPower, static_cast(t->first.first.orderInAlphaS)); aewPower = min(aewPower, static_cast(t->first.first.orderInAlphaEW)); maxaewPower = max(maxaewPower, static_cast(t->first.first.orderInAlphaEW)); } orderFile << "# OLP order file created by Herwig/Matchbox for GoSam\n\n"; orderFile << "InterfaceVersion BLHA2\n"; orderFile << "MatrixElementSquareType CHsummed\n"; orderFile << "CorrectionType QCD\n"; orderFile << "IRregularisation " << (isDR() ? "DRED" : "CDR") << "\n"; // loop over quarks to check if they have non-zero masses for (int i=1; i<=6; ++i) if (getParticleData(i)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(i); // check if leptons have non-zero masses (iff theMassiveLeptons==true) if (theMassiveLeptons && getParticleData(11)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(11); if (theMassiveLeptons && getParticleData(13)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(13); if (theMassiveLeptons && getParticleData(15)->hardProcessMass()/GeV > 0.0) massiveParticles.push_back(15); if ( massiveParticles.size() != 0 ) { orderFile << "MassiveParticles "; for ( vector::const_iterator mID = massiveParticles.begin(); mID != massiveParticles.end(); ++mID ) { int mInt = *mID; orderFile << mInt << " "; } orderFile << "\n"; } orderFile << "\n"; vector < string > types; types.push_back("Tree"); types.push_back("LoopInduced"); types.push_back("ccTree"); types.push_back("scTree"); types.push_back("Loop"); for ( int i = asPower ; i != maxasPower + 1 ; i++ ) { for ( int j = aewPower ; j != maxaewPower + 1 ; j++ ) { orderFile << "\nAlphasPower " << i << "\n"; orderFile << "AlphaPower " << j << "\n"; for ( vector::iterator it = types.begin() ; it != types.end() ; it++ ) { if ( *it == "LoopInduced" ) continue; for ( map::iterator p = processmap.begin() ; p != processmap.end() ; ++p ) if ( (*p).second.Tstr() == *it && i == (*p).second.orderAs() && j == (*p).second.orderAew() ) { orderFile << "\nAmplitudeType " << *it << "\n"; break; } for ( map::iterator p = processmap.begin() ; p != processmap.end() ; ++p ) if ( (*p).second.Tstr() == *it && i == (*p).second.orderAs() && j == (*p).second.orderAew() ) { orderFile << (*p).second.Pstr() << "\n"; } } } } // Write out the loop induced processes separately int asPowerLI = 100; int aewPowerLI = 100; for ( map::iterator p = processmap.begin() ; p != processmap.end() ; ++p ) { if ( (*p).second.Tstr() != "LoopInduced" ) continue; if ( (*p).second.orderAs() != asPowerLI || (*p).second.orderAew() != aewPowerLI ) { asPowerLI = (*p).second.orderAs(); aewPowerLI = (*p).second.orderAew(); // At the moment GoSam requires for qcd loop induced processes the as coupling power // which would correspond to an associated fictitious Born process orderFile << "\nAlphasPower " << (asPowerLI-2) << "\n"; orderFile << "AlphaPower " << aewPowerLI << "\n"; orderFile << "\nAmplitudeType " << "LoopInduced" << "\n"; } orderFile << (*p).second.Pstr() << "\n"; } orderFile << flush; } void GoSamAmplitude::signOLP(const string& order, const string& contract) { if(!theCodeExists){ char char_cwd[256]; getcwd(char_cwd, sizeof(char_cwd)); string cwd = string(char_cwd); string folderMatchboxBuild = factory()->buildStorage(); folderMatchboxBuild.erase(folderMatchboxBuild.begin()); generator()->log() << "\n>>> generating GoSam amplitudes. This may take some time, please be patient.\n" << ">>> see " + cwd + folderMatchboxBuild + "gosam-amplitudes.log for details.\n" << flush; string cmd = GoSamPrefix_+"/bin/gosam.py --olp --output-file=" + contract + " --config=" + gosamSetupInFileName+".tbu" + " --destination=" + gosamSourcePath + " " + order + " > " + cwd + folderMatchboxBuild + "gosam-amplitudes.log 2>&1"; std::system(cmd.c_str()); cmd = "python "+bindir_+"/gosam2herwig "; cmd += " --makelink "; // cmd += " --makelinkfrom=contract "; cmd += " --makelinkfrom="+gosamPath+"/"+name()+".OLPContract.lh"; cmd += " --makelinkto="+factory()->buildStorage() + name() + ".OLPContract.lh"; std::system(cmd.c_str()); } } bool GoSamAmplitude::checkOLPContract(string contractFileName) { ifstream infile(contractFileName.c_str()); string line; vector < string > contractfile; while (std::getline(infile, line)) contractfile.push_back(line); for ( map::iterator p = processmap.begin() ; p != processmap.end() ; p++ ) { bool righttype = false; for ( vector::iterator linex = contractfile.begin() ; linex != contractfile.end() ; ++linex ) { if ( (*linex).find("AmplitudeType ")!= std::string::npos ) { if ( (*linex).find(" " + (*p).second.Tstr() + " ")!= std::string::npos ) { righttype = true; } else { righttype = false; } } if ( righttype ) { if ( (*linex).find((*p).second.Pstr()) != std::string::npos && (*p).second.Pstr().length() == (*linex).find("|") ) { string sub = (*linex).substr((*linex).find("|") + 1, (*linex).find("#") - (*linex).find("|") - 1); // | 1 23 # buggy?? if ( sub.find(" 1 ") != 0 ) throw Exception() << "GoSamAmplitude: Failed to check contractfile. Please check the logfile.\n" << Exception::runerror; string subx = sub.substr(3); int subint; istringstream(subx) >> subint; (*p).second.setGID(subint); } } } } string ids = factory()->buildStorage() + "GoSam.ids.dat"; ofstream IDS(ids.c_str()); idpair.clear(); for ( map::iterator p = processmap.begin() ; p != processmap.end() ; p++ ) idpair.push_back(-1); idpair.push_back(-1); for ( map::iterator p = processmap.begin() ; p != processmap.end() ; p++ ) { idpair[(*p).second.HID()]=(*p).second.GID(); IDS << (*p).second.HID() << " " << (*p).second.GID() << " " << (*p).second.Tstr() << "\n"; if ( (*p).second.GID() == -1 ) return 0; } IDS << flush; return 1; } bool GoSamAmplitude::buildGoSam() { if(!theCodeExists){ generator()->log() << "\n>>> compiling GoSam amplitudes. This may take some time, please be patient.\n" << ">>> see " + gosamSourcePath + "gosam-build.log for details.\n\n" << flush; string cmd = "cd " + gosamSourcePath + " && sh autogen.sh FCFLAGS=-g --prefix=" + gosamInstallPath + " --disable-static > gosam-build.log 2>&1"; std::system(cmd.c_str()); if (!gosamBuildScript.empty()) { cmd = "cd " + gosamSourcePath + " && " + gosamBuildScript + " >> gosam-build.log 2>&1"; std::system(cmd.c_str()); } std::system(cmd.c_str()); cmd = "cd " + gosamSourcePath + " && make install >> gosam-build.log 2>&1"; std::system(cmd.c_str()); } theCodeExists=true; return 1; } void GoSamAmplitude::getids() const { string line = factory()->buildStorage() + "GoSam.ids.dat"; ifstream infile(line.c_str()); int hid; int gid; string type; while (std::getline(infile, line)) { idpair.push_back(-1); idtypepair.push_back(" "); } infile.close(); string line2 = factory()->buildStorage() + "GoSam.ids.dat"; ifstream infile2(line2.c_str()); idpair.push_back(-1); idtypepair.push_back(" "); while (std::getline(infile2, line2)) { istringstream(line2) >> hid >> gid >> type; idpair[hid]=gid; idtypepair[hid]=type; } infile.close(); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void GoSamAmplitude::evalSubProcess() const { useMe(); double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2() / GeV2); if (hasRunningAlphaS()) { int pStatus = 0; double zero = 0.0; double as; as = lastAlphaS(); OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus); } double out[7] = { }; double acc; if ( idpair.size() == 0 ){ getids(); } int id = -99; if ( olpId()[ProcessType::loopInducedME2] ) id = olpId()[ProcessType::loopInducedME2]; else if ( olpId()[ProcessType::oneLoopInterference] ) id = olpId()[ProcessType::oneLoopInterference]; else id = olpId()[ProcessType::treeME2]; int callid(idpair[id]); // If id denotes the Herwig ID, this returns the GoSam ID string calltype(idtypepair[id]); // If id denotes the Herwig ID, this returns the amplitude type OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, out, &acc); double accuracyTarget = 1.0/pow(10.0,accuracyTargetNegExp()); accuracyFileTitle = name() + ".OLPAccuracy.lh"; accuracyFile = factory()->buildStorage() + accuracyFileTitle; ofstream accuracyFileStream; if ( (olpId()[ProcessType::oneLoopInterference]||olpId()[ProcessType::loopInducedME2]) && acc > accuracyTarget ) { if ( Debug::level > 1 ) { accuracyFileStream.open(accuracyFile.c_str(),ios::app); vector currentpsp = lastXComb().meMomenta(); time_t rawtime; time (&rawtime); if (doneGoSamInit) accuracyFileStream << "READ phase: "; else if (doneGoSamInitRun) accuracyFileStream << "RUN phase: "; accuracyFileStream << "Sub-process with Herwig ID = " << id << " and GoSam ID = " << callid << ", " << ctime(&rawtime); accuracyFileStream << "GoSam evaluated one-loop interference or loop induced ME2 with acc = " << acc << " > target accuracy = " << accuracyTarget << ", at PSP [in units of GeV]:" << endl; for (size_t i=0; i!=currentpsp.size(); ++i) { accuracyFileStream << "(t,x,y,z,mass;m)[" << i << "]=(" << currentpsp[i].t()/GeV << "," << currentpsp[i].x()/GeV << "," << currentpsp[i].y()/GeV << "," << currentpsp[i].z()/GeV << "," << currentpsp[i].mass()/GeV << ";" << currentpsp[i].m()/GeV << ")" << endl; } accuracyFileStream << endl; } throw Veto(); // Dispose of PSP } if ( olpId()[ProcessType::oneLoopInterference] ) { if (calculateTreeME2()) lastTreeME2(out[3] * units); lastOneLoopInterference((out[2])* units); lastOneLoopPoles(pair(out[0] * units, out[1] * units)); } else if ( olpId()[ProcessType::treeME2] ) { lastTreeME2(out[3] * units); } else if ( olpId()[ProcessType::loopInducedME2] ) { lastTreeME2(out[2] * units); } } void GoSamAmplitude::evalColourCorrelator(pair ) const { double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2() / GeV2); if (hasRunningAlphaS()) { int pStatus = 0; double zero = 0.0; double as; as = lastAlphaS(); OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus); } int n = lastXComb().meMomenta().size(); colourCorrelatorResults.resize(n * (n - 1) / 2); if ( idpair.size() == 0 ) getids(); int callid(idpair[olpId()[ProcessType::colourCorrelatedME2]]); double acc; OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, &colourCorrelatorResults[0], &acc); cPDVector particles = lastXComb().matrixElement()->mePartonData(); for ( int i = 0 ; i < n ; ++i ) { for ( int j = i + 1 ; j < n ; ++j ) { lastColourCorrelator(make_pair(i, j), colourCorrelatorResults[i+j*(j-1)/2] * units); } } } void GoSamAmplitude::evalSpinColourCorrelator(pair ) const { double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double scale = sqrt(mu2() / GeV2); if (hasRunningAlphaS()) { int pStatus = 0; double zero = 0.0; double as; as = lastAlphaS(); OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus); } int n = lastXComb().meMomenta().size(); spinColourCorrelatorResults.resize(2*n*n); if ( idpair.size() == 0 ) getids(); double acc; int callid(idpair[olpId()[ProcessType::spinColourCorrelatedME2]]); OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, &spinColourCorrelatorResults[0], &acc); for ( int i = 0; i < n; ++i ) { for ( int j = 0; j < n; ++j ) { Complex scc(spinColourCorrelatorResults[2*i+2*n*j]*units, spinColourCorrelatorResults[2*i+2*n*j+1]*units); lastColourSpinCorrelator(make_pair(i,j),scc); } } } LorentzVector GoSamAmplitude::plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int inc) const { double pvec[4] = {p.t()/GeV,p.x()/GeV,p.y()/GeV,p.z()/GeV}; double nvec[4] = {n.t()/GeV,n.x()/GeV,n.y()/GeV,n.z()/GeV}; double out[8] ={ }; OLP_Polvec(pvec,nvec,out); LorentzVector res; Complex a(out[0],out[1]); res.setT(a); Complex b(out[2],out[3]); res.setX(b); Complex c(out[4],out[5]); res.setY(c); Complex d(out[6],out[7]); res.setZ(d); if (inc<2) return res.conjugate(); else return res; } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void GoSamAmplitude::persistentOutput(PersistentOStream & os) const { os << idpair << idtypepair << processmap << gosamPathInterface << gosamSetupInFileNameInterface << gosamBuildScript << gosamPath << gosamSourcePath << gosamInstallPath << gosamSetupInFileName << orderFileTitle << contractFileTitle << contractFileName << orderFileName << theCodeExists << theFormOpt << theNinja << isitDR << massiveParticles << theHiggsEff << theAccuracyTarget << theMassiveLeptons << theLoopInducedOption << doneGoSamInit << doneGoSamInitRun << bindir_ << pkgdatadir_ << GoSamPrefix_; } void GoSamAmplitude::persistentInput(PersistentIStream & is, int) { is >> idpair >> idtypepair >> processmap >> gosamPathInterface >> gosamSetupInFileNameInterface >> gosamBuildScript >> gosamPath >> gosamSourcePath >> gosamInstallPath >> gosamSetupInFileName >> orderFileTitle >> contractFileTitle >> contractFileName >> orderFileName >> theCodeExists >> theFormOpt >> theNinja >> isitDR >> massiveParticles >> theHiggsEff >> theAccuracyTarget >> theMassiveLeptons >> theLoopInducedOption >> doneGoSamInit >> doneGoSamInitRun >> bindir_ >> pkgdatadir_ >> GoSamPrefix_; } // *** 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 describeHerwigGoSamAmplitude("Herwig::GoSamAmplitude", "HwMatchboxGoSam.so"); void GoSamAmplitude::Init() { static ClassDocumentation documentation("GoSamAmplitude implements an interface to GoSam.", "Matrix elements have been calculated using GoSam \\cite{Cullen:2011xs}, \\cite{Cullen:2014yla}", "%\\cite{Cullen:2011xs}\n" "\\bibitem{Cullen:2011xs}\n" "G.~Cullen et al.,\n" "``GoSam: A Program for Automated One-Loop Calculations,''\n" "arXiv:1111.6534 [hep-ph].\n" "%%CITATION = ARXIV:1111.6534;%%\n" "%\\cite{Cullen:2014yla}\n" "\\bibitem{Cullen:2014yla}\n" "G.~Cullen et al.,\n" "``GoSaam-2.0: a tool for automated one-loop calculations within the Standard Model and beyond,''\n" "arXiv:1404.7096 [hep-ph].\n" "%%CITATION = ARXIV:1404.7096;%%"); static Parameter interfaceProcessPath ("ProcessPath", "Prefix for the process source code, include files and library produced by GoSam.", &GoSamAmplitude::gosamPathInterface, "", false, false); static Parameter interfaceSetupInFilename ("SetupInFilename", "File name of the GoSam infile (typically setup.gosam.in) to be used. If left empty a new setup.gosam.in is created in the location specified in Path", &GoSamAmplitude::gosamSetupInFileNameInterface, "", false, false); static Switch interfaceCodeExists ("CodeExists", "Switch on or off if Code already exists/not exists.", &GoSamAmplitude::theCodeExists, true, false, false); static SwitchOption interfaceCodeExistsYes (interfaceCodeExists, "Yes", "Switch True if Code already exists.", true); static SwitchOption interfaceCodeExistsNo (interfaceCodeExists, "No", "Switch False if Code has to be build.", false); static Switch interfaceisitDR ("isDR", "Switch on or off DR.", &GoSamAmplitude::isitDR, false, false, false); static SwitchOption interfaceisitDRYes (interfaceisitDR, "Yes", "Switch True.", true); static SwitchOption interfaceisitDRNo (interfaceisitDR, "No", "Switch False.", false); static Switch interfaceFormOpt ("FormOpt", "Switch On/Off formopt", &GoSamAmplitude::theFormOpt, true, false, false); static SwitchOption interfaceFormOptYes (interfaceFormOpt, "Yes", "Yes", true); static SwitchOption interfaceFormOptNo (interfaceFormOpt, "No", "No", false); static Switch interfaceNinja ("Ninja", "Switch On/Off for reduction with Ninja. If Off then Samurai is used.", &GoSamAmplitude::theNinja, true, false, false); static SwitchOption interfaceNinjaYes (interfaceNinja, "Yes", "Yes", true); static SwitchOption interfaceNinjaNo (interfaceNinja, "No", "No", false); static Switch interfaceHiggsEff ("HiggsEff", "Switch On/Off for effective higgs model.", &GoSamAmplitude::theHiggsEff, false, false, false); static SwitchOption interfaceHiggsEffYes (interfaceHiggsEff, "Yes", "Yes", true); static SwitchOption interfaceHiggsEffNo (interfaceHiggsEff, "No", "No", false); static Parameter interfaceBuildScript ("BuildScript", "File name of a custom build script, which is called between 'autogen.sh'" "and 'make install'. It can be used for parallelization.", &GoSamAmplitude::gosamBuildScript, "", false, false); static Parameter interfaceAccuracyTarget ("AccuracyTarget", "Integer to parametrize the threshold value for the BLHA2 acc parameter, returned by GoSam in the case of " "sub-processes with one-loop intereference terms or loop induced sub-processes." "If acc > 10^-AccuracyTarget the corresponding PSP is being discarded. Discarded PSPs are written to file " "if Debug::level > 1.", &GoSamAmplitude::theAccuracyTarget, 6, 0, 0, false, false, Interface::lowerlim); static Switch interfaceMassiveLeptons ("MassiveLeptons", "If set to Yes, then pass on the light lepton masses - as well as the tau mass - to GoSam." "Otherwise GoSam will use light leptons of zero mass as default, as well as its own default tau mass.", &GoSamAmplitude::theMassiveLeptons, false, false, false); static SwitchOption interfaceMassiveLeptonsNo (interfaceMassiveLeptons, "No", "No", false); static SwitchOption interfaceMassiveLeptonsYes (interfaceMassiveLeptons, "Yes", "Yes", true); static Switch interfaceLoopInducedOption ("LoopInducedOption", "Options for the GoSam interface, in the case that a loop induced process is being considered. The default " "option is 0, for which only the squared one-loop amplitude in the Standard Model is being considered. All " "other options consider additional contributions from a model with an effective interaction, which lead to " "the same final state, such as the squared effective amplitude, or the interference term between the one- " "loop amplitude in the Standard Model and the effective amplitude, or any additive combinations therefrom. " "In order to use those options an appropriate model has to be used.", &GoSamAmplitude::theLoopInducedOption, 0, false, false); static SwitchOption interfaceLoopInducedOptionLI2 (interfaceLoopInducedOption, "LI2", "Only consider the squared one-loop amplitude in the Standard Model.", 0); static SwitchOption interfaceLoopInducedOptionEff2 (interfaceLoopInducedOption, "Eff2", "Only consider the squared effective amplitude.", 1); static SwitchOption interfaceLoopInducedOptionLIEffInterference (interfaceLoopInducedOption, "LIEffInterference", "Only consider the interference term between the one-loop amplitude " "in the Standard Model and the effective amplitude.", 2); static SwitchOption interfaceLoopInducedOptionLI2plusEff2 (interfaceLoopInducedOption, "LI2plusEff2", "Consider the sum of the squared one-loop amplitude in the Standard " "Model plus the squared effective amplitude.", 3); static SwitchOption interfaceLoopInducedOptionLI2plusLIEffInterference (interfaceLoopInducedOption, "LI2plusEffInterference", "Consider the sum of the squared one-loop amplitude in the Standard " "Model plus the interference term between the one-loop amplitude in " "the Standard Model and the effective amplitude.", 4); static SwitchOption interfaceLoopInducedOptionEff2plusLIEffInterference (interfaceLoopInducedOption, "Eff2plusEffInterference", "Consider the sum of the squared effective amplitude plus the inter- " "ference term between the one-loop amplitude in the Standard Model " "and the effective amplitude.", 5); static SwitchOption interfaceLoopInducedOptionAllAdditions (interfaceLoopInducedOption, "AllAdditions", "Consider the sum of the squared one-loop amplitude in the Standard " "Model plus all other contributions, which come with the effective " "Model.", 6); static Parameter interfaceBinDir ("BinDir", "The location for the installed executable", &GoSamAmplitude::bindir_, string(HERWIG_BINDIR), false, false); static Parameter interfacePKGDATADIR ("DataDir", "The location for the installed Herwig data files", &GoSamAmplitude::pkgdatadir_, string(HERWIG_PKGDATADIR), false, false); static Parameter interfaceGoSamPrefix ("GoSamPrefix", "The prefix for the location of GoSam", &GoSamAmplitude::GoSamPrefix_, string(GOSAM_PREFIX), false, false); } diff --git a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.h b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.h --- a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.h +++ b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.h @@ -1,329 +1,318 @@ // -*- C++ -*- // // GoSamAmplitude.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_GoSamAmplitude_H #define Herwig_GoSamAmplitude_H // // This is the declaration of the GoSamAmplitude class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxOLPME.h" #include "ThePEG/Utilities/DynamicLoader.h" namespace Herwig { using namespace ThePEG; class gosamprocinfo{ public: gosamprocinfo(){}; gosamprocinfo(int HID,int GID, string procstr,string typestr): theHOlpId(HID),theGOlpId(GID),theProcstr(procstr),theTypestr(typestr){ } ~gosamprocinfo(){} int HID() const {return theHOlpId;} int GID() const {return theGOlpId;} string Pstr() const {return theProcstr;} string Tstr() const {return theTypestr;} void setGID(int g){theGOlpId=g;} void setOAs(int i){ orderAlphas=i;} int orderAs(){return orderAlphas;} void setOAew(int j){ orderAlphaew=j;} int orderAew(){return orderAlphaew;} private: int theHOlpId; int theGOlpId; string theProcstr; string theTypestr; int orderAlphas; int orderAlphaew; public: void persistentOutput(PersistentOStream & os) const{os<>theHOlpId>>theGOlpId>>theProcstr>>theTypestr>>orderAlphas>>orderAlphaew;} }; /** * \ingroup Matchbox * \author Simon Platzer * * \brief GoSamAmplitude implements an interface to GoSam */ class GoSamAmplitude: public MatchboxOLPME { public: - /** @name Standard constructors and destructors. */ - //@{ - /** * The default constructor. */ GoSamAmplitude(); - /** - * The destructor. - */ - virtual ~GoSamAmplitude(); - - //@} - - public: virtual void fillOrderFile(const map,int>& procs, string OrderFileName); virtual bool isCS() const { return false; } virtual bool isExpanded() const { return true; } virtual bool isBDK() const { return false; } virtual bool isDR() const { return isitDR; } virtual bool isDRbar() const {return false;} /** * Start the one loop provider, if appropriate, giving order and * contract files */ virtual void signOLP(const string&, const string&); virtual bool checkOLPContract(string contractFileName); /** * Return true, if this amplitude already includes symmetry factors * for identical outgoing particles. */ // virtual bool hasFinalStateSymmetry() const { return true; } virtual bool hasFinalStateSymmetry() const { return false; } virtual bool buildGoSam(); /** * Start the one loop provider, if appropriate */ virtual void startOLP(const string&, int& status); /** * Return the value of the dimensional regularization * parameter. Note that renormalization scale dependence is fully * restored in DipoleIOperator. */ // virtual Energy2 mu2() const { return lastSHat(); } /** * Start the one loop provider, if appropriate. This default * implementation writes an BLHA 2.0 order file and starts the OLP */ virtual bool startOLP(const map,int>& procs); /** * Call OLP_EvalSubProcess and fill in the results */ void evalSubProcess() const; /** * Fill in results for the given colour correlator */ virtual void evalColourCorrelator(pair ij) const; /** * Return a positive helicity polarization vector for a gluon of * momentum p (with reference vector n) to be used when evaluating * spin correlations. */ virtual LorentzVector plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int inc) const; /** * Fill in results for the given colour/spin correlator */ virtual void evalSpinColourCorrelator(pair ij) const; void getids() const; int accuracyTargetNegExp() const { return theAccuracyTarget; } 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(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ GoSamAmplitude & operator=(const GoSamAmplitude &) = delete; /** * Store colour correlator results */ mutable vector colourCorrelatorResults; /** * Store spin colour correlator results */ mutable vector spinColourCorrelatorResults; /** * first is the olp id from herwig, second the answer from gosam */ mutable vector idpair; /** * first is the olp id from herwig, second the amplitude type */ mutable vector idtypepair; /** * Map to store all processes handled by this Amplitude */ map processmap; mutable string gosamPathInterface; mutable string gosamSetupInFileNameInterface; mutable string gosamBuildScript; mutable string gosamPath; mutable string gosamSourcePath; mutable string gosamInstallPath; mutable string gosamSetupInFileName; mutable string orderFileTitle; mutable string contractFileTitle; mutable string contractFileName; mutable string orderFileName; mutable string accuracyFileTitle; mutable string accuracyFile; int theAccuracyTarget; bool theCodeExists; bool theFormOpt; bool theNinja; bool theHiggsEff; bool theMassiveLeptons; int theLoopInducedOption; bool isitDR; mutable bool doneGoSamInit; mutable bool doneGoSamInitRun; /** * The PDG codes of those quarks with mass */ vector massiveParticles; //theMassiveParticles; /** * Method to create the setup.in file for GoSam */ void setupGoSamIn(string setupGoSamInFile); protected: /** * Location of the installed executables */ string bindir_; /** * Location of the data files */ string pkgdatadir_; /** * Location of GOSAM */ string GoSamPrefix_; }; // end "class GoSamAmplitude: public MatchboxOLPME" inline PersistentOStream& operator<<(PersistentOStream& os, const gosamprocinfo& p) { p.persistentOutput(os); return os; } inline PersistentIStream& operator>>(PersistentIStream& is, gosamprocinfo& p) { p.persistentInput(is); return is; } } // end "namespace Herwig" #endif /* Herwig_GoSamAmplitude_H */ diff --git a/MatrixElement/Matchbox/External/NJet/NJetsAmplitude.cc b/MatrixElement/Matchbox/External/NJet/NJetsAmplitude.cc --- a/MatrixElement/Matchbox/External/NJet/NJetsAmplitude.cc +++ b/MatrixElement/Matchbox/External/NJet/NJetsAmplitude.cc @@ -1,310 +1,308 @@ // -*- C++ -*- // // NJetsAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the NJetsAmplitude class. // #include "NJetsAmplitude.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "njet.h" #include #ifndef NJET_PREFIX #error Makefile.am needs to define NJET_PREFIX #endif #ifndef NJET_LIBS #error Makefile.am needs to define NJET_LIBS #endif using namespace Herwig; NJetsAmplitude::NJetsAmplitude() : NJetsPrefix_(NJET_PREFIX), NJetsLibs_(NJET_LIBS) {} -NJetsAmplitude::~NJetsAmplitude() {} - IBPtr NJetsAmplitude::clone() const { return new_ptr(*this); } IBPtr NJetsAmplitude::fullclone() const { return new_ptr(*this); } void NJetsAmplitude::signOLP(const string& order, const string& contract) { string cmd = NJetsPrefix_+"/bin/njet.py -o " + contract + " " + order; std::system(cmd.c_str()); } void NJetsAmplitude::startOLP(const string& contract, int& status) { NJet::LH_OLP::OLP_Start(contract.c_str(), &status); if ( status != 1 ) return; status = 0; static double zero = 0.0; double param = 0.0; param = SM().alphaEMMZ(); NJet::LH_OLP::OLP_SetParameter("alpha",¶m,&zero,&status); if ( status != 1 ) return; param = getParticleData(ParticleID::Z0)->hardProcessMass()/GeV; NJet::LH_OLP::OLP_SetParameter("mass(23)",¶m,&zero,&status); if ( status != 1 ) return; param = getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV; NJet::LH_OLP::OLP_SetParameter("mass(24)",¶m,&zero,&status); if ( status != 1 ) return; param = getParticleData(ParticleID::Z0)->hardProcessWidth()/GeV; NJet::LH_OLP::OLP_SetParameter("width(23)",¶m,&zero,&status); if ( status != 1 ) return; param = getParticleData(ParticleID::Wplus)->hardProcessWidth()/GeV; NJet::LH_OLP::OLP_SetParameter("width(24)",¶m,&zero,&status); if ( status != 1 ) return; param = SM().sin2ThetaW(); NJet::LH_OLP::OLP_SetParameter("sw2",¶m,&zero,&status); didStartOLP() = true; } void NJetsAmplitude::loadNJET() { if ( ! (DynamicLoader::load(NJetsLibs_+"/libnjet2.so") || DynamicLoader::load("libnjet2.so") || DynamicLoader::load(NJetsLibs_+"/libnjet2.dylib") || DynamicLoader::load("libnjet2.dylib") ) ) throw Exception() << "NJetsAmplitude: Failed to load libnjet2.so\n" << DynamicLoader::lastErrorMessage << Exception::runerror; } bool NJetsAmplitude::startOLP(const map,int>& procs) { loadNJET(); // TODO throw exception on massive leptons in procs string orderFileName = factory()->buildStorage() + name() + ".OLPOrder.lh"; ofstream orderFile(orderFileName.c_str()); olpOrderFileHeader(orderFile); orderFile << "NJetReturnAccuracy yes\n" << "NJetRenormalize yes\n" #if NJET_VERSION > 1023 << "SetParameter qcd(nf) " << factory()->nLight() << "\n"; // NJet >= 2.1.0: #else << "NJetNf " << factory()->nLight() << "\n"; // NJet <=2.0.0 #endif olpOrderFileProcesses(orderFile,procs); orderFile << flush; orderFile.close(); string contractFileName = factory()->buildStorage() + name() + ".OLPContract.lh"; signOLP(orderFileName, contractFileName); int status = -1; startOLP(contractFileName,status); if ( status != 1 ) return false; return true; } LorentzVector NJetsAmplitude::plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int inc) const { double pvec[4] = {p.t()/GeV,p.x()/GeV,p.y()/GeV,p.z()/GeV}; double nvec[4] = {n.t()/GeV,n.x()/GeV,n.y()/GeV,n.z()/GeV}; double out[8] ={ }; NJet::LH_OLP::OLP_Polvec(pvec,nvec,out); LorentzVector res; Complex a(out[0],out[1]); res.setT(a); Complex b(out[2],out[3]); res.setX(b); Complex c(out[4],out[5]); res.setY(c); Complex d(out[6],out[7]); res.setZ(d); if (inc<2) return res.conjugate(); else return res; } void NJetsAmplitude::evalSubProcess() const { useMe(); double units = pow(lastSHat()/GeV2,mePartonData().size()-4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double as; if (!hasRunningAlphaS()) as = SM().alphaS(); else if (hasRunningAlphaS()) as = lastAlphaS(); double scale = sqrt(mu2()/GeV2); double out[7]={}; int id = olpId()[ProcessType::oneLoopInterference] ? olpId()[ProcessType::oneLoopInterference] : olpId()[ProcessType::treeME2]; NJet::LH_OLP::OLP_EvalSubProcess(id, olpMomenta(), scale, &as, out); if ( olpId()[ProcessType::oneLoopInterference] ) { if(calculateTreeME2())lastTreeME2(out[3]*units); lastOneLoopInterference(out[2]*units); lastOneLoopPoles(pair(out[0]*units,out[1]*units)); } else if ( olpId()[ProcessType::treeME2] ) { lastTreeME2(out[0]*units); } else assert(false); } void NJetsAmplitude::evalColourCorrelator(pair) const { double units = pow(lastSHat()/GeV2,mePartonData().size()-4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double as; if (!hasRunningAlphaS()) as = SM().alphaS(); else if (hasRunningAlphaS()) as = lastAlphaS(); double scale = sqrt(mu2()/GeV2); int n = lastXComb().meMomenta().size(); colourCorrelatorResults.resize(n*(n-1)/2); NJet::LH_OLP::OLP_EvalSubProcess(olpId()[ProcessType::colourCorrelatedME2], olpMomenta(), scale, &as, &colourCorrelatorResults[0]); for ( int i = 0; i < n; ++i ) for ( int j = i+1; j < n; ++j ) { lastColourCorrelator(make_pair(i,j),colourCorrelatorResults[i+j*(j-1)/2]*units); } } void NJetsAmplitude::evalSpinColourCorrelator(pair) const { double units = pow(lastSHat()/GeV2,mePartonData().size()-4.); fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses()); double as; if (!hasRunningAlphaS()) as = SM().alphaS(); else if (hasRunningAlphaS()) as = lastAlphaS(); double scale = sqrt(mu2()/GeV2); int n = lastXComb().meMomenta().size(); spinColourCorrelatorResults.resize(2*n*n); NJet::LH_OLP::OLP_EvalSubProcess(olpId()[ProcessType::spinColourCorrelatedME2], olpMomenta(), scale, &as, &spinColourCorrelatorResults[0]); for ( int i = 0; i < n; ++i ) for ( int j = 0; j < n; ++j ) { if ( i == j || mePartonData()[i]->id() != 21 ) continue; Complex scc(spinColourCorrelatorResults[2*i+2*n*j]*units, spinColourCorrelatorResults[2*i+2*n*j+1]*units); lastColourSpinCorrelator(make_pair(i,j),scc); } } void NJetsAmplitude::doinit() { loadNJET(); MatchboxOLPME::doinit(); } void NJetsAmplitude::doinitrun() { loadNJET(); MatchboxOLPME::doinitrun(); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void NJetsAmplitude::persistentOutput(PersistentOStream & os) const { os << colourCorrelatorResults << spinColourCorrelatorResults << NJetsPrefix_ << NJetsLibs_; } void NJetsAmplitude::persistentInput(PersistentIStream & is, int) { is >> colourCorrelatorResults >> spinColourCorrelatorResults >> NJetsPrefix_ >> NJetsLibs_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigNJetsAmplitude("Herwig::NJetsAmplitude", "HwMatchboxNJet.so"); void NJetsAmplitude::Init() { static ClassDocumentation documentation ("NJetsAmplitude implements an interface to NJets.", "Matrix elements have been calculated using NJet \\cite{Badger:2012pg}", "%\\cite{Badger:2012pg}\n" "\\bibitem{Badger:2012pg}\n" "S.~Badger et al.,\n" "``Numerical evaluation of virtual corrections to multi-jet production in massless QCD,''\n" "arXiv:1209.0100 [hep-ph].\n" "%%CITATION = ARXIV:1209.0100;%%"); static Parameter interfaceNJetsPrefix ("NJetsPrefix", "The prefix for the location of NJets", &NJetsAmplitude::NJetsPrefix_, string(NJET_PREFIX), false, false); static Parameter interfaceNJetsLibs ("NJetsLibs", "The location of the NJets library", &NJetsAmplitude::NJetsLibs_, string(NJET_LIBS), false, false); } diff --git a/MatrixElement/Matchbox/External/NJet/NJetsAmplitude.h b/MatrixElement/Matchbox/External/NJet/NJetsAmplitude.h --- a/MatrixElement/Matchbox/External/NJet/NJetsAmplitude.h +++ b/MatrixElement/Matchbox/External/NJet/NJetsAmplitude.h @@ -1,203 +1,195 @@ // -*- C++ -*- // // NJetsAmplitude.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_NJetsAmplitude_H #define Herwig_NJetsAmplitude_H // // This is the declaration of the NJetsAmplitude class. // #include "Herwig/MatrixElement/Matchbox/Base/MatchboxOLPME.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief NJetsAmplitude implements an interface to NJets */ class NJetsAmplitude: public MatchboxOLPME { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ NJetsAmplitude(); - /** - * The destructor. - */ - virtual ~NJetsAmplitude(); - //@} - public: /** * Return true, if this amplitude already includes averaging over * incoming parton's quantum numbers. */ virtual bool hasInitialAverage() const { return false; } /** * Return true, if this amplitude already includes symmetry factors * for identical outgoing particles. */ virtual bool hasFinalStateSymmetry() const { return false; } /** * Start the one loop provider, if appropriate, giving order and * contract files */ virtual void signOLP(const string&, const string&); /** * Start the one loop provider, if appropriate */ virtual void startOLP(const string&, int& status); /** * Start the one loop provider, if appropriate. This default * implementation writes an BLHA 2.0 order file and starts the OLP */ virtual bool startOLP(const map,int>& procs); /** * Call OLP_EvalSubProcess and fill in the results */ virtual void evalSubProcess() const; /** * Fill in results for the given colour correlator */ virtual void evalColourCorrelator(pair ij) const; /** * Return a positive helicity polarization vector for a gluon of * momentum p (with reference vector n) to be used when evaluating * spin correlations. */ virtual LorentzVector plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int id = -1) const; /** * Fill in results for the given colour/spin correlator */ virtual void evalSpinColourCorrelator(pair ij) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ NJetsAmplitude & operator=(const NJetsAmplitude &) = delete; /** * Store colour correlator results */ mutable vector colourCorrelatorResults; /** * Store spin colour correlator results */ mutable vector spinColourCorrelatorResults; /** * Location of NJETs */ string NJetsPrefix_; /** * Location of NJET librarys */ string NJetsLibs_; /** * Load the NJET library */ void loadNJET(); }; } #endif /* Herwig_NJetsAmplitude_H */ diff --git a/MatrixElement/Matchbox/MatchboxFactory.cc b/MatrixElement/Matchbox/MatchboxFactory.cc --- a/MatrixElement/Matchbox/MatchboxFactory.cc +++ b/MatrixElement/Matchbox/MatchboxFactory.cc @@ -1,2106 +1,2104 @@ // -*- C++ -*- // // MatchboxFactory.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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/API/RunDirectories.h" #include "Herwig/Utilities/Progress.h" #include 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), theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0), theFixedCouplings(false), theFixedQEDCouplings(false), theVetoScales(false), theDipoleSet(0), theVerbose(false), 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(false), theEnforceLeptonNumberConservation(false), theEnforceQuarkNumberConservation(false), theLeptonFlavourDiagonal(false), theQuarkFlavourDiagonal(false) {} -MatchboxFactory::~MatchboxFactory() {} - Ptr::tptr MatchboxFactory::theCurrentFactory = Ptr::tptr(); 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::ptr me) { Ptr::ptr amp = dynamic_ptr_cast::ptr>((*me).amplitude()); me->matchboxAmplitude(amp); if ( phasespace() && !me->phasespace() ) me->phasespace(phasespace()); if ( scaleChoice() && !me->scaleChoice() ) me->scaleChoice(scaleChoice()); if ( !reweighters().empty() ) { for ( vector::const_iterator rw = reweighters().begin(); rw != reweighters().end(); ++rw ) me->addReweighter(*rw); } if ( !preweighters().empty() ) { for ( vector::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> MatchboxFactory:: makeMEs(const vector& proc, unsigned int orderas, bool virt) { generator()->log() << "determining subprocesses for "; copy(proc.begin(),proc.end(),ostream_iterator(generator()->log()," ")); generator()->log() << "\n" << flush; map::ptr,set > ampProcs; map::ptr> > procAmps; set processes = makeSubProcesses(proc); set colouredProcesses; for ( set::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() && (virtualContributions() || realContributions()) ) { // NLO not working for non coloured legs throw Exception() << "Found processes without coloured legs.\n" << "We currently do not support NLO corrections for those processes.\n" << "Please switch to a setup for LO production." << Exception::runerror; } // detect external particles with non-zero width for the hard process bool trouble = false; string troubleMaker; for ( set::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> 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>::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; progress_display progressBar{ combinations, generator()->log() }; for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) { for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) { for ( vector::ptr>::const_iterator amp = matchAmplitudes.begin(); amp != matchAmplitudes.end(); ++amp ) { (**amp).orderInGs(oas); (**amp).orderInGem(oae); for ( set::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); } } } } generator()->log() << flush; bool clash = false; for ( map::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>::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> res; for ( map::ptr,set >::const_iterator ap = ampProcs.begin(); ap != ampProcs.end(); ++ap ) { canDoSpinCorrelations &= ap->first->canFillRhoMatrix(); for ( set::const_iterator m = ap->second.begin(); m != ap->second.end(); ++m ) { Ptr::ptr me = ap->first->makeME(m->legs); me->subProcess() = *m; me->amplitude(ap->first); me->matchboxAmplitude(ap->first); prepareME(me); string pname = "ME" + 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::tptr amp, int type) { map,int>& procs = olpProcesses()[amp]; map,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>::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::tptr()); } if ( showerApproximation() && (subtractionData() != "" || subProcessGroups()) ) { Repository::clog() << "Warning: Matching requested for plain NLO run. Matching disabled.\n" << flush; showerApproximation(Ptr::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(); 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::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> mes; for ( vector >::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 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 >::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 >::const_iterator p = loopInducedProcesses.begin(); p != loopInducedProcesses.end(); ++p ) { vector::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>::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>::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>::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 the real emission matrix elements if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { for ( vector::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>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { if ( (**born).onlyOneLoop() ) continue; Ptr::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>::iterator looped = loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) { Ptr::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(); progress_display progressBar{ bornMEs().size(), generator()->log() }; if ( thePoleData != "" ) if ( thePoleData[thePoleData.size()-1] != '/' ) thePoleData += "/"; for ( vector::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { Ptr::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>::const_iterator virt = virtuals().begin(); virt != virtuals().end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlo->virtuals().push_back(*virt); } for ( vector::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>::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::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>::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; } generator()->log() << "---------------------------------------------------\n" << flush; } theSplittingDipoles.clear(); set bornProcs; if ( showerApproximation() ) { if ( showerApproximation()->needsSplittingGenerator() ) { for ( vector::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>::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); } } } progress_display progressBar{ realEmissionMEs().size(), generator()->log() }; for ( vector::ptr>::iterator real = realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) { Ptr::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; (**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::ptr fme = dynamic_ptr_cast::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::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::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::const_iterator p = bornProcs.begin(); p != bornProcs.end(); ++p ) { vector::ptr> sdip = sub->splitDipoles(*p); set::ptr>& dips = theSplittingDipoles[*p]; copy(sdip.begin(),sdip.end(),inserter(dips,dips.begin())); } } ++progressBar; } generator()->log() << "---------------------------------------------------\n" << flush; } if ( !theSplittingDipoles.empty() ) { map::ptr,Ptr::ptr> cloneMap; for ( map::ptr> >::const_iterator sd = theSplittingDipoles.begin(); sd != theSplittingDipoles.end(); ++sd ) { for ( set::ptr>::const_iterator d = sd->second.begin(); d != sd->second.end(); ++d ) { cloneMap[*d] = Ptr::ptr(); } } for ( map::ptr,Ptr::ptr>::iterator cd = cloneMap.begin(); cd != cloneMap.end(); ++cd ) { Ptr::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::tptr()); cloned->doSplitting(); cd->second = cloned; } for ( map::ptr> >::iterator sd = theSplittingDipoles.begin(); sd != theSplittingDipoles.end(); ++sd ) { set::ptr> cloned; for ( set::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::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::tptr,map,int> > olps; for ( map::tptr,map,int> >::const_iterator oit = olpProcesses().begin(); oit != olpProcesses().end(); ++oit ) { olps[oit->first] = oit->second; } for ( map::tptr,map,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::getSplittingChannels(tStdXCombPtr xcptr) const { if ( xcptr->lastProjector() ) xcptr = xcptr->lastProjector(); const StandardXComb& xc = *xcptr; cPDVector proc = xc.mePartonData(); map::ptr> >::const_iterator splitEntries = splittingDipoles().find(proc); list res; if ( splitEntries == splittingDipoles().end() ) return res; const set::ptr>& splitDipoles = splitEntries->second; SplittingChannel channel; if ( !splitDipoles.empty() ) { Ptr::tptr bornME = const_ptr_cast::tptr>((**splitDipoles.begin()).underlyingBornME()); channel.bornXComb = bornME->makeXComb(xc.maxEnergy(),xc.particles(),xc.eventHandlerPtr(), const_ptr_cast(xc.subProcessHandler()), xc.pExtractor(),xc.CKKWHandler(), xc.partonBins(),xc.cuts(),xc.diagrams(),xc.mirror(), PartonPairVec()); } for ( set::ptr>::const_iterator sd = splitDipoles.begin(); sd != splitDipoles.end(); ++sd ) { channel.dipole = *sd; vector realXCombs = (**sd).makeRealXCombs(channel.bornXComb); for ( vector::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::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::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>::const_iterator m = bornMEs().begin(); m != bornMEs().end(); ++m ) { (**m).print(os); } os << flush; os << " generated real emission matrix elements:\n"; for ( vector::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>::const_iterator bv = bornVirtualMEs().begin(); bv != bornVirtualMEs().end(); ++bv ) { (**bv).print(os); } os << " generated subtracted matrix elements:\n"; for ( vector::ptr>::const_iterator sub = subtractedMEs().begin(); sub != subtractedMEs().end(); ++sub ) { os << " '" << (**sub).name() << "'\n"; } os << "---------------------------------------------------\n"; os << flush; } void MatchboxFactory::summary(ostream& os) const { os << "\n\n================================================================================\n" << " Matchbox hard process summary\n" << "================================================================================\n\n"; os << " Electro-weak parameter summary:\n" << "---------------------------------------------------\n\n"; os << " Electro-weak scheme : "; switch ( SM().ewScheme() ) { case 0: os << "Default"; break; case 1: os << "GMuScheme"; break; case 2: os << "alphaMZScheme"; break; case 3: os << "NoMass"; break; case 4: os << "mW"; break; case 5: os << "mZ"; break; case 6: os << "Independent"; break; case 7: os << "FeynRulesUFO"; break; default: assert(false); } os << "\n"; os << " alphaEM is " << (SM().ewScheme() == 0 && !theFixedQEDCouplings ? "running" : "fixed at alphaEM(m(Z))") << "\n"; if ( SM().ewScheme() == 0 && !theFixedQEDCouplings ) os << " alphaEM is running at " << SM().alphaEMPtr()->nloops() << " loops\n\n"; else os << "\n"; os << (SM().ewScheme() != 0 ? " Tree level relations " : " Best values ") << "yield:\n\n" << " m(Z)/GeV = " << getParticleData(ParticleID::Z0)->hardProcessMass()/GeV << "\n" << " g(Z)/GeV = " << getParticleData(ParticleID::Z0)->hardProcessWidth()/GeV << "\n" << " m(W)/GeV = " << getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV << "\n" << " g(W)/GeV = " << getParticleData(ParticleID::Wplus)->hardProcessWidth()/GeV << "\n" << " m(H)/GeV = " << getParticleData(ParticleID::h0)->hardProcessMass()/GeV << "\n" << " g(H)/GeV = " << getParticleData(ParticleID::h0)->hardProcessWidth()/GeV << "\n" << " alphaEM(m(Z)) = " << SM().alphaEMME(sqr(getParticleData(ParticleID::Z0)->hardProcessMass())) << "\n" << " sin^2(theta) = " << SM().sin2ThetaW() << "\n" << " GeV^2 GF = " << GeV2*SM().fermiConstant() << "\n\n"; os << " Quark masses and widths are:\n" << "---------------------------------------------------\n\n" << " m(u)/GeV = " << getParticleData(ParticleID::u)->hardProcessMass()/GeV << "\n" << " m(d)/GeV = " << getParticleData(ParticleID::d)->hardProcessMass()/GeV << "\n" << " m(c)/GeV = " << getParticleData(ParticleID::c)->hardProcessMass()/GeV << "\n" << " m(s)/GeV = " << getParticleData(ParticleID::s)->hardProcessMass()/GeV << "\n" << " m(t)/GeV = " << getParticleData(ParticleID::t)->hardProcessMass()/GeV << "\n" << " g(t)/GeV = " << getParticleData(ParticleID::t)->hardProcessWidth()/GeV << "\n" << " m(b)/GeV = " << getParticleData(ParticleID::b)->hardProcessMass()/GeV << "\n\n"; os << " Lepton masses and widths are:\n" << "---------------------------------------------------\n\n" << " m(n_e)/GeV = " << getParticleData(ParticleID::nu_e)->hardProcessMass()/GeV << "\n" << " m(e)/GeV = " << getParticleData(ParticleID::eminus)->hardProcessMass()/GeV << "\n" << " m(n_mu)/GeV = " << getParticleData(ParticleID::nu_mu)->hardProcessMass()/GeV << "\n" << " m(mu)/GeV = " << getParticleData(ParticleID::muminus)->hardProcessMass()/GeV << "\n" << " m(nu_tau)/GeV = " << getParticleData(ParticleID::nu_tau)->hardProcessMass()/GeV << "\n" << " m(tau)/GeV = " << getParticleData(ParticleID::tauminus)->hardProcessMass()/GeV << "\n\n"; os << " Strong coupling summary:\n" << "---------------------------------------------------\n\n"; os << " alphaS is"; if ( !theFixedCouplings ) { os << " running at " << SM().alphaSPtr()->nloops() << " loops with\n" << " alphaS(m(Z)) = " << SM().alphaSPtr()->value(sqr(getParticleData(ParticleID::Z0)->mass())) << "\n\n"; } else { os << " fixed at " << SM().alphaS() << "\n\n"; } if ( !theFixedCouplings ) { os << " flavour thresholds are matched at\n"; for ( long id = 1; id <= 6; ++id ) { os << " m(" << id << ")/GeV = " << (SM().alphaSPtr()->quarkMasses().empty() ? getParticleData(id)->mass()/GeV : SM().alphaSPtr()->quarkMasses()[id-1]/GeV) << "\n"; } } os << "\n\n" << flush; } void MatchboxFactory::doinit() { theIsMatchboxRun() = true; theCurrentFactory = Ptr::tptr(this); if ( RunDirectories::empty() ) RunDirectories::pushRunId(generator()->runName()); setup(); if ( theShowerApproximation ) theShowerApproximation->init(); if ( initVerbose() && !ranSetup ) print(Repository::clog()); Ptr::tptr eh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); assert(eh); if ( initVerbose() && !ranSetup ) { assert(standardModel()); standardModel()->init(); summary(Repository::clog()); } SubProcessHandler::doinit(); } void MatchboxFactory::doinitrun() { theIsMatchboxRun() = true; theCurrentFactory = Ptr::tptr(this); if ( theShowerApproximation ) theShowerApproximation->initrun(); Ptr::tptr eh = dynamic_ptr_cast::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 << thePhasespace << theScaleChoice << theFactorizationScaleFactor << theRenormalizationScaleFactor << theFixedCouplings << theFixedQEDCouplings << theVetoScales << theAmplitudes << theBornMEs << theVirtuals << theRealEmissionMEs << theLoopInducedMEs << theBornVirtualMEs << theSubtractedMEs << theFiniteRealMEs << theVerbose << theInitVerbose << theSubtractionData << theSubtractionPlotType << theSubtractionScatterPlot << thePoleData << theParticleGroups << processes << loopInducedProcesses << realEmissionProcesses << theShowerApproximation << theSplittingDipoles << theRealEmissionScales << theAllProcesses << theOLPProcesses << theExternalAmplitudes << theSelectedAmplitudes << theDeselectedAmplitudes << theDipoleSet << theReweighters << thePreweighters << theMECorrectionsOnly<< theLoopSimCorrections<> theDiagramGenerator >> theProcessData >> theNLight >> theNLightJetVec >> theNHeavyJetVec >> theNLightProtonVec >> theOrderInAlphaS >> theOrderInAlphaEW >> theBornContributions >> theVirtualContributions >> theRealContributions >> theIndependentVirtuals >> theIndependentPKs >> thePhasespace >> theScaleChoice >> theFactorizationScaleFactor >> theRenormalizationScaleFactor >> theFixedCouplings >> theFixedQEDCouplings >> theVetoScales >> theAmplitudes >> theBornMEs >> theVirtuals >> theRealEmissionMEs >> theLoopInducedMEs >> theBornVirtualMEs >> theSubtractedMEs >> theFiniteRealMEs >> theVerbose >> 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 MatchboxFactory::parseProcess(string in) { vector process = StringUtils::split(in); if ( process.size() < 3 ) throw Exception() << "MatchboxFactory: Invalid process." << Exception::runerror; for ( vector::iterator p = process.begin(); p != process.end(); ++p ) { *p = StringUtils::stripws(*p); } vector pprocess; for ( vector::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 MatchboxFactory:: makeSubProcesses(const vector& proc) const { if ( proc.empty() ) throw Exception() << "MatchboxFactory: No process specified." << Exception::runerror; vector groups; typedef map::const_iterator GroupIterator; for ( vector::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 counts(groups.size(),0); PDVector proto(groups.size()); set 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); 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::reverse_iterator c = counts.rbegin(); vector::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 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 interfaceDiagramGenerator ("DiagramGenerator", "Set the diagram generator.", &MatchboxFactory::theDiagramGenerator, false, false, true, true, false); interfaceDiagramGenerator.rank(-1); static Reference interfaceProcessData ("ProcessData", "Set the process data object to be used.", &MatchboxFactory::theProcessData, false, false, true, true, false); interfaceProcessData.rank(-1); static Parameter interfaceOrderInAlphaS ("OrderInAlphaS", "The order in alpha_s to consider.", &MatchboxFactory::theOrderInAlphaS, 0, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceOrderInAlphaEW ("OrderInAlphaEW", "The order in alpha_EW to consider.", &MatchboxFactory::theOrderInAlphaEW, 2, 0, 0, false, false, Interface::lowerlim); static Switch interfaceBornContributions ("BornContributions", "Switch on or off the Born contributions.", &MatchboxFactory::theBornContributions, true, false, false); static SwitchOption interfaceBornContributionsYes (interfaceBornContributions, "Yes", "Switch on Born contributions.", true); static SwitchOption interfaceBornContributionsNo (interfaceBornContributions, "No", "Switch off Born contributions.", false); static Switch interfaceVirtualContributions ("VirtualContributions", "Switch on or off the virtual contributions.", &MatchboxFactory::theVirtualContributions, true, false, false); static SwitchOption interfaceVirtualContributionsYes (interfaceVirtualContributions, "Yes", "Switch on virtual contributions.", true); static SwitchOption interfaceVirtualContributionsNo (interfaceVirtualContributions, "No", "Switch off virtual contributions.", false); static Switch interfaceRealContributions ("RealContributions", "Switch on or off the real contributions.", &MatchboxFactory::theRealContributions, true, false, false); static SwitchOption interfaceRealContributionsYes (interfaceRealContributions, "Yes", "Switch on real contributions.", true); static SwitchOption interfaceRealContributionsNo (interfaceRealContributions, "No", "Switch off real contributions.", false); static Switch interfaceIndependentVirtuals ("IndependentVirtuals", "Switch on or off virtual contributions as separate subprocesses.", &MatchboxFactory::theIndependentVirtuals, true, false, false); static SwitchOption interfaceIndependentVirtualsYes (interfaceIndependentVirtuals, "Yes", "Switch on virtual contributions as separate subprocesses.", true); static SwitchOption interfaceIndependentVirtualsNo (interfaceIndependentVirtuals, "No", "Switch off virtual contributions as separate subprocesses.", false); static Switch interfaceIndependentPKs ("IndependentPKOperators", "Switch on or off PK oeprators as separate subprocesses.", &MatchboxFactory::theIndependentPKs, true, false, false); static SwitchOption interfaceIndependentPKsYes (interfaceIndependentPKs, "Yes", "Switch on PK operators as separate subprocesses.", true); static SwitchOption interfaceIndependentPKsNo (interfaceIndependentPKs, "No", "Switch off PK operators as separate subprocesses.", false); static Reference interfacePhasespace ("Phasespace", "Set the phasespace generator.", &MatchboxFactory::thePhasespace, false, false, true, true, false); static Reference interfaceScaleChoice ("ScaleChoice", "Set the scale choice object.", &MatchboxFactory::theScaleChoice, false, false, true, true, false); static Parameter interfaceFactorizationScaleFactor ("FactorizationScaleFactor", "The factorization scale factor.", &MatchboxFactory::theFactorizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceRenormalizationScaleFactor ("RenormalizationScaleFactor", "The renormalization scale factor.", &MatchboxFactory::theRenormalizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Switch interfaceFixedCouplings ("FixedCouplings", "Switch on or off fixed couplings.", &MatchboxFactory::theFixedCouplings, true, false, false); static SwitchOption interfaceFixedCouplingsYes (interfaceFixedCouplings, "Yes", "Yes", true); static SwitchOption interfaceFixedCouplingsNo (interfaceFixedCouplings, "No", "No", false); interfaceFixedCouplings.rank(-1); static Switch interfaceFixedQEDCouplings ("FixedQEDCouplings", "Switch on or off fixed QED couplings.", &MatchboxFactory::theFixedQEDCouplings, true, false, false); static SwitchOption interfaceFixedQEDCouplingsYes (interfaceFixedQEDCouplings, "Yes", "Yes", true); static SwitchOption interfaceFixedQEDCouplingsNo (interfaceFixedQEDCouplings, "No", "No", false); interfaceFixedQEDCouplings.rank(-1); // @TDOO SP to remove this in the code as well /* static Switch interfaceVetoScales ("VetoScales", "Switch on or setting veto scales.", &MatchboxFactory::theVetoScales, false, false, false); static SwitchOption interfaceVetoScalesYes (interfaceVetoScales, "Yes", "Yes", true); static SwitchOption interfaceVetoScalesNo (interfaceVetoScales, "No", "No", false); */ static RefVector interfaceAmplitudes ("Amplitudes", "The amplitude objects.", &MatchboxFactory::theAmplitudes, -1, false, false, true, true, false); static Switch interfaceVerbose ("Verbose", "Print full infomation on each evaluated phase space point.", &MatchboxFactory::theVerbose, false, false, false); static SwitchOption interfaceVerboseYes (interfaceVerbose, "Yes", "Yes", true); static SwitchOption interfaceVerboseNo (interfaceVerbose, "No", "No", false); interfaceVerbose.rank(-1); static Switch interfaceInitVerbose ("InitVerbose", "Print setup information.", &MatchboxFactory::theInitVerbose, false, false, false); static SwitchOption interfaceInitVerboseYes (interfaceInitVerbose, "Yes", "Yes", true); static SwitchOption interfaceInitVerboseNo (interfaceInitVerbose, "No", "No", false); interfaceInitVerbose.rank(-1); static Parameter interfaceSubtractionData ("SubtractionData", "Prefix for subtraction check data.", &MatchboxFactory::theSubtractionData, "", false, false); static Switch 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 interfaceSubtractionScatterPlot ("SubtractionScatterPlot", "Switch for controlling whether subtraction data should be plotted for each phase space point individually", &MatchboxFactory::theSubtractionScatterPlot, false, false, false); static SwitchOption interfaceSubtractionScatterPlotNo (interfaceSubtractionScatterPlot, "No", "Switch off the scatter plot", false); static SwitchOption interfaceSubtractionScatterPlotYes (interfaceSubtractionScatterPlot, "Yes", "Switch on the scatter plot", true); static Parameter interfacePoleData ("PoleData", "Prefix for subtraction check data.", &MatchboxFactory::thePoleData, "", false, false); static RefVector interfaceParticleGroup ("ParticleGroup", "The particle group just started.", &MatchboxFactory::particleGroup, -1, false, false, true, false, false); static Command interfaceStartParticleGroup ("StartParticleGroup", "Start a particle group.", &MatchboxFactory::startParticleGroup, false); static Command interfaceEndParticleGroup ("EndParticleGroup", "End a particle group.", &MatchboxFactory::endParticleGroup, false); static Command interfaceProcess ("Process", "Set the process(es) to consider.", &MatchboxFactory::doProcess, false); static Command interfaceLoopInducedProcess ("LoopInducedProcess", "Set the loop induced process(es) to consider.", &MatchboxFactory::doLoopInducedProcess, false); static Command interfaceSingleRealProcess ("SingleRealProcess", "Set the real emission process(es) to consider.", &MatchboxFactory::doSingleRealProcess, false); static Reference interfaceShowerApproximation ("ShowerApproximation", "Set the shower approximation to be considered.", &MatchboxFactory::theShowerApproximation, false, false, true, true, false); static Switch interfaceRealEmissionScales ("RealEmissionScales", "Switch on or off calculation of subtraction scales from real emission kinematics.", &MatchboxFactory::theRealEmissionScales, false, false, false); static SwitchOption interfaceRealEmissionScalesYes (interfaceRealEmissionScales, "Yes", "Yes", true); static SwitchOption interfaceRealEmissionScalesNo (interfaceRealEmissionScales, "No", "No", false); interfaceRealEmissionScales.rank(-1); static Switch 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); interfaceAllProcesses.rank(-1); static RefVector interfaceSelectAmplitudes ("SelectAmplitudes", "The amplitude objects to be favoured in clashing responsibilities.", &MatchboxFactory::theSelectedAmplitudes, -1, false, false, true, true, false); static RefVector interfaceDeselectAmplitudes ("DeselectAmplitudes", "The amplitude objects to be disfavoured in clashing responsibilities.", &MatchboxFactory::theDeselectedAmplitudes, -1, false, false, true, true, false); static Switch 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); interfaceDipoleSet.rank(-1); static RefVector interfaceReweighters ("Reweighters", "Reweight objects for matrix elements.", &MatchboxFactory::theReweighters, -1, false, false, true, false, false); static RefVector interfacePreweighters ("Preweighters", "Preweight objects for matrix elements.", &MatchboxFactory::thePreweighters, -1, false, false, true, false, false); static Switch 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 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 interfaceFirstPerturbativePDF ("FirstPerturbativePDF", "", &MatchboxFactory::theFirstPerturbativePDF, true, false, false); static SwitchOption interfaceFirstPerturbativePDFYes (interfaceFirstPerturbativePDF, "Yes", "", true); static SwitchOption interfaceFirstPerturbativePDFNo (interfaceFirstPerturbativePDF, "No", "", false); interfaceFirstPerturbativePDF.rank(-1); static Switch interfaceSecondPerturbativePDF ("SecondPerturbativePDF", "", &MatchboxFactory::theSecondPerturbativePDF, true, false, false); static SwitchOption interfaceSecondPerturbativePDFYes (interfaceSecondPerturbativePDF, "Yes", "", true); static SwitchOption interfaceSecondPerturbativePDFNo (interfaceSecondPerturbativePDF, "No", "", false); interfaceSecondPerturbativePDF.rank(-1); static Command interfaceProductionMode ("ProductionMode", "Switch this factory to production mode.", &MatchboxFactory::doProductionMode, false); static Switch 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 interfaceAlphaParameter ("AlphaParameter", "Nagy-AlphaParameter.", &MatchboxFactory::theAlphaParameter, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Switch 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); interfaceEnforceChargeConservation.rank(-1); static Switch interfaceEnforceColourConservation ("EnforceColourConservation", "Enforce colour conservation while generating the hard process.", &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); interfaceEnforceColourConservation.rank(-1); static Switch interfaceEnforceLeptonNumberConservation ("EnforceLeptonNumberConservation", "Enforce lepton number conservation while generating the hard process.", &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); interfaceEnforceLeptonNumberConservation.rank(-1); static Switch interfaceEnforceQuarkNumberConservation ("EnforceQuarkNumberConservation", "Enforce quark number conservation while generating the hard process.", &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); interfaceEnforceQuarkNumberConservation.rank(-1); static Switch interfaceLeptonFlavourDiagonal ("LeptonFlavourDiagonal", "Assume that lepton interactions are flavour diagonal while generating the hard process.", &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); interfaceLeptonFlavourDiagonal.rank(-1); static Switch interfaceQuarkFlavourDiagonal ("QuarkFlavourDiagonal", "Assume that quark interactions are flavour diagonal while generating the hard process.", &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); interfaceQuarkFlavourDiagonal.rank(-1); } // *** 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 describeHerwigMatchboxFactory("Herwig::MatchboxFactory", "Herwig.so"); diff --git a/MatrixElement/Matchbox/MatchboxFactory.h b/MatrixElement/Matchbox/MatchboxFactory.h --- a/MatrixElement/Matchbox/MatchboxFactory.h +++ b/MatrixElement/Matchbox/MatchboxFactory.h @@ -1,1305 +1,1297 @@ // -*- C++ -*- // // MatchboxFactory.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MatchboxFactory_H #define HERWIG_MatchboxFactory_H // // This is the declaration of the MatchboxFactory class. // #include "ThePEG/Handlers/SubProcessHandler.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h" #include "Herwig/MatrixElement/Matchbox/Utility/ProcessData.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.fh" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxFactory automatically sets up a NLO * QCD calculation carried out in dipole subtraction. * * @see \ref MatchboxFactoryInterfaces "The interfaces" * defined for MatchboxFactory. */ class MatchboxFactory: public SubProcessHandler { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxFactory(); - /** - * The destructor. - */ - virtual ~MatchboxFactory(); - //@} - public: /** * Pointer to the current factory object */ static const Ptr::tptr currentFactory() { assert(theCurrentFactory); return theCurrentFactory; } private: /** * Pointer to the current factory object */ static Ptr::tptr theCurrentFactory; public: /** * Flag to indicate that at least one MatchboxFactory object is in action */ static bool isMatchboxRun() { return theIsMatchboxRun(); } /** @name Process and diagram information */ //@{ /** * Return the diagram generator. */ Ptr::tptr diagramGenerator() const { return theDiagramGenerator; } /** * Set the diagram generator. */ void diagramGenerator(Ptr::ptr dg) { theDiagramGenerator = dg; } /** * Return the process data. */ Ptr::tptr processData() const { return theProcessData; } /** * Set the process data. */ void processData(Ptr::ptr pd) { theProcessData = pd; } /** * Return the number of light flavours, this matrix * element is calculated for. */ unsigned int nLight() const { return theNLight; } /** * Set the number of light flavours, this matrix * element is calculated for. */ void nLight(unsigned int n) { theNLight = n; } /** * Return the vector that contains the PDG ids of * the light flavours, which are contained in the * jet particle group. */ vector nLightJetVec() const { return theNLightJetVec; } /** * Set the elements of the vector that contains the PDG * ids of the light flavours, which are contained in the * jet particle group. */ void nLightJetVec(long n) { theNLightJetVec.push_back(n); } /** * Return the vector that contains the PDG ids of * the heavy flavours, which are contained in the * jet particle group. */ vector nHeavyJetVec() const { return theNHeavyJetVec; } /** * Set the elements of the vector that contains the PDG * ids of the heavy flavours, which are contained in the * jet particle group. */ void nHeavyJetVec(long n) { theNHeavyJetVec.push_back(n); } /** * Return the vector that contains the PDG ids of * the light flavours, which are contained in the * proton particle group. */ vector nLightProtonVec() const { return theNLightProtonVec; } /** * Set the elements of the vector that contains the PDG * ids of the light flavours, which are contained in the * proton particle group. */ void nLightProtonVec(long n) { theNLightProtonVec.push_back(n); } /** * Return the order in \f$\alpha_S\f$. */ unsigned int orderInAlphaS() const { return theOrderInAlphaS; } /** * Set the order in \f$\alpha_S\f$. */ void orderInAlphaS(unsigned int o) { theOrderInAlphaS = o; } /** * Return the order in \f$\alpha_{EM}\f$. */ unsigned int orderInAlphaEW() const { return theOrderInAlphaEW; } /** * Set the order in \f$\alpha_{EM}\f$. */ void orderInAlphaEW(unsigned int o) { theOrderInAlphaEW = o; } /** * The multiplicity of legs with virtual contributions. */ size_t highestVirt() const {return theHighestVirtualSize;} /** * Set the highest **/ void setHighestVirt(size_t n){theHighestVirtualSize=n;} /** * Access the processes vector. */ const vector > getProcesses() const {return processes;} /** * Return true, if all processes up to a maximum order are considered */ bool allProcesses() const { return theAllProcesses; } /** * Switch on/off inclusino off all processes up to a maximum order */ void setAllProcesses(bool on = true) { theAllProcesses = on; } /** * Return true, if Born contributions should be included. */ bool bornContributions() const { return theBornContributions; } /** * Switch on or off Born contributions */ void setBornContributions(bool on = true) { theBornContributions = on; } /** * Return true, if virtual contributions should be included. */ bool virtualContributions() const { return theVirtualContributions; } /** * Switch on or off virtual contributions */ void setVirtualContributions(bool on = true) { theVirtualContributions = on; } /** * Produce matrix element corrections, but no NLO */ bool meCorrectionsOnly() const { return theMECorrectionsOnly; } /** * Switch to produce matrix element corrections, but no NLO */ void setMECorrectionsOnly(bool on = true) { theMECorrectionsOnly = on; } /** * Produce matrix element corrections, with LoopSim NLO */ bool loopSimCorrections() const { return theLoopSimCorrections; } /** * Switch to produce matrix element corrections, with LoopSim NLO */ void setLoopSimCorrections(bool on = true) { theLoopSimCorrections = on; } /** * Return true, if subtracted real emission contributions should be included. */ bool realContributions() const { return theRealContributions; } /** * Switch on or off subtracted real emission contributions */ void setRealContributions(bool on = true) { theRealContributions = on; } /** * Return true, if virtual contributions should be treated as independent subprocesses */ bool independentVirtuals() const { return theIndependentVirtuals; } /** * Switch on/off virtual contributions should be treated as independent subprocesses */ void setIndependentVirtuals(bool on = true) { theIndependentVirtuals = on; } /** * Return true, if PK operator contributions should be treated as independent subprocesses */ bool independentPKs() const { return theIndependentPKs; } /** * Switch on/off PK operator contributions should be treated as independent subprocesses */ void setIndependentPKs(bool on = true) { theIndependentPKs = on; } /** * Return true, if SubProcessGroups should be * setup from this MEGroup. If not, a single SubProcess * is constructed from the data provided by the * head matrix element. */ virtual bool subProcessGroups() const { return !showerApproximation(); } /** * Return true, if subtraction scales should be caluclated from real emission kinematics */ bool realEmissionScales() const { return theRealEmissionScales; } /** * Switch on/off that subtraction scales should be caluclated from real emission kinematics */ void setRealEmissionScales(bool on = true) { theRealEmissionScales = on; } /** * Set the shower approximation. */ void showerApproximation(Ptr::tptr app) { theShowerApproximation = app; } /** * Return the shower approximation. */ Ptr::tptr showerApproximation() const { return theShowerApproximation; } //@} /** @name Phasespace generation and scale choice */ //@{ /** * Return the phase space generator to be used. */ Ptr::tptr phasespace() const { return thePhasespace; } /** * Set the phase space generator to be used. */ void phasespace(Ptr::ptr ps) { thePhasespace = ps; } /** * Set the scale choice object */ void scaleChoice(Ptr::ptr sc) { theScaleChoice = sc; } /** * Return the scale choice object */ Ptr::tptr scaleChoice() const { return theScaleChoice; } /** * 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; } /** * Return true, if fixed couplings are used. */ bool fixedCouplings() const { return theFixedCouplings; } /** * Switch on fixed couplings. */ void setFixedCouplings(bool on = true) { theFixedCouplings = on; } /** * Return true, if fixed couplings are used. */ bool fixedQEDCouplings() const { return theFixedQEDCouplings; } /** * Switch on fixed couplings. */ void setFixedQEDCouplings(bool on = true) { theFixedQEDCouplings = on; } /** * Return true, if veto scales should be set * for the real emission */ bool vetoScales() const { return theVetoScales; } /** * Switch on setting veto scales */ void doVetoScales() { theVetoScales = true; } /** * Switch off setting veto scales */ void noVetoScales() { theVetoScales = true; } //@} /** @name Amplitudes and caching */ //@{ /** * Return the amplitudes to be considered */ const vector::ptr>& amplitudes() const { return theAmplitudes; } /** * Access the amplitudes to be considered */ vector::ptr>& amplitudes() { return theAmplitudes; } //@} /** @name Matrix element objects. */ //@{ /** * Return the Born matrix elements to be considered */ const vector::ptr>& bornMEs() const { return theBornMEs; } /** * Access the Born matrix elements to be considered */ vector::ptr>& bornMEs() { return theBornMEs; } /** * Return the loop induced matrix elements to be considered */ const vector::ptr>& loopInducedMEs() const { return theLoopInducedMEs; } /** * Access the loop induced matrix elements to be considered */ vector::ptr>& loopInducedMEs() { return theLoopInducedMEs; } /** * Return the processes to be ordered from an OLP */ const map::tptr, map,int> >& olpProcesses() const { return theOLPProcesses; } /** * Access the processes to be ordered from an OLP */ map::tptr, map,int> >& olpProcesses() { return theOLPProcesses; } /** * Order an OLP process and return its id */ int orderOLPProcess(const Process& p, Ptr::tptr amp, int type); /** * Return the amplitudes which need external initialization */ const set::tptr>& externalAmplitudes() const { return theExternalAmplitudes; } /** * Access the amplitudes which need external initialization */ set::tptr>& externalAmplitudes() { return theExternalAmplitudes; } /** * Return the virtual corrections to be considered */ const vector::ptr>& virtuals() const { return theVirtuals; } /** * Access the virtual corrections to be considered */ vector::ptr>& virtuals() { return theVirtuals; } /** * Return the produced NLO matrix elements */ const vector::ptr>& bornVirtualMEs() const { return theBornVirtualMEs; } /** * Access the produced NLO matrix elements */ vector::ptr>& bornVirtualMEs() { return theBornVirtualMEs; } /** * Return the real emission matrix elements to be considered */ const vector::ptr>& realEmissionMEs() const { return theRealEmissionMEs; } /** * Access the real emission matrix elements to be considered */ vector::ptr>& realEmissionMEs() { return theRealEmissionMEs; } /** * Return, which set of dipoles should be considered */ int dipoleSet() const { return theDipoleSet; } /** * Return, which set of dipoles should be considered */ void dipoleSet(int s) { theDipoleSet = s; } /** * Return the produced subtracted matrix elements */ const vector::ptr>& subtractedMEs() const { return theSubtractedMEs; } /** * Access the produced subtracted matrix elements */ vector::ptr>& subtractedMEs() { return theSubtractedMEs; } /** * Return the produced finite real emission matrix elements */ const vector::ptr>& finiteRealMEs() const { return theFiniteRealMEs; } /** * Access the produced finite real emission elements */ vector::ptr>& finiteRealMEs() { return theFiniteRealMEs; } /** * Return the map of Born processes to splitting dipoles */ const map::ptr> >& splittingDipoles() const { return theSplittingDipoles; } /** * Identify a splitting channel */ struct SplittingChannel { /** * The Born XComb */ StdXCombPtr bornXComb; /** * The real XComb */ StdXCombPtr realXComb; /** * The set of tilde XCombs to consider for the real xcomb */ vector tildeXCombs; /** * The dipole in charge of the splitting */ Ptr::ptr dipole; /** * Dump the setup */ void print(ostream&) const; }; /** * Generate all splitting channels for the Born process handled by * the given XComb */ list getSplittingChannels(tStdXCombPtr xc) const; /** * Return the reweight objects for matrix elements */ const vector& reweighters() const { return theReweighters; } /** * Access the reweight objects for matrix elements */ vector& reweighters() { return theReweighters; } /** * Return the preweight objects for matrix elements */ const vector& preweighters() const { return thePreweighters; } /** * Access the preweight objects for matrix elements */ vector& preweighters() { return thePreweighters; } //@} /** @name Setup the matrix elements */ //@{ /** * Return true if this object needs to be initialized before all * other objects (except those for which this function also returns * true). This default version always returns false, but subclasses * may override it to return true. */ virtual bool preInitialize() const { return true; } /** * Prepare a matrix element. */ void prepareME(Ptr::ptr); /** * Check consistency and switch to porduction mode. */ virtual void productionMode(); /** * Setup everything */ virtual void setup(); /** * The highest multiplicity of legs having virtual contributions.(needed for madgraph) */ size_t highestVirt(){return theHighestVirtualsize;} //@} /** @name Diagnostic information */ //@{ /** * Return true, if verbose */ bool verbose() const { return theVerbose; } /** * Switch on diagnostic information. */ void setVerbose(bool on = true) { theVerbose = on; } /** * Return true, if verbose while initializing */ bool initVerbose() const { return theInitVerbose || verbose(); } /** * Switch on diagnostic information while initializing */ void setInitVerbose(bool on = true) { theInitVerbose = on; } /** * Dump the setup */ void print(ostream&) const; /** * Return the subtraction data prefix. */ const string& subtractionData() const { return theSubtractionData; } /** * Set the subtraction data prefix. */ void subtractionData(const string& s) { theSubtractionData = s; } /** * Return the subtraction plot type. */ const int& subtractionPlotType() const { return theSubtractionPlotType; } /** * Set the subtraction plot type. */ void subtractionPlotType(const int& t) { theSubtractionPlotType = t; } /** * Return whether subtraction data should be plotted for all phase space points individually */ const bool& subtractionScatterPlot() const { return theSubtractionScatterPlot; } /** * Set whether subtraction data should be plotted for all phase space points individually */ void subtractionScatterPlot(const bool& s) { theSubtractionScatterPlot = s; } /** * Return the pole data prefix. */ const string& poleData() const { return thePoleData; } /** * Set the pole data prefix. */ void poleData(const string& s) { thePoleData = s; } /** * Return true, if cancellationn of epsilon poles should be checked. */ bool checkPoles() const { return poleData() != ""; } //@} /** @name Process generation */ //@{ /** * Return the particle groups. */ const map& particleGroups() const { return theParticleGroups; } /** * Access the particle groups. */ map& particleGroups() { return theParticleGroups; } /** * Return true, if the given particle is incoming */ bool isIncoming(cPDPtr p) const { return theIncoming.find(p->id()) != theIncoming.end(); } /** * Return true, if spin correlation information should be provided, if possible. */ bool spinCorrelations() const { return theSpinCorrelations; } /** * Indicate that spin correlation information should be provided, if possible. */ void setSpinCorrelations(bool yes) { theSpinCorrelations = yes; } //@} /** @name Truncated qtilde shower information */ //@{ /** * Return the subprocess of the real emission */ tSubProPtr hardTreeSubprocess() { return theHardtreeSubprocess; } /** * Set the subprocess of the real emission for use in calculating the shower hardtree */ void setHardTreeSubprocess(tSubProPtr hardTree) { theHardtreeSubprocess = hardTree; } /** * Return the born emitter */ int hardTreeEmitter() { return theHardtreeEmitter; } /** * Set the born emitter for use in calculating the shower hardtree */ void setHardTreeEmitter(int emitter) { theHardtreeEmitter = emitter; } /** * Return the born spectator */ int hardTreeSpectator() { return theHardtreeSpectator; } /** * Set the born spectator for use in calculating the shower hardtree */ void setHardTreeSpectator(int spectator) { theHardtreeSpectator = spectator; } //@} /** @name Data handling */ //@{ /** * Return (and possibly create) a directory to contain amplitude * information. */ const string& buildStorage(); /** * Return (and possibly create) a directory to contain integration grid * information. */ const string& runStorage(); /** * alpha of http://arxiv.org/pdf/hep-ph/0307268v2.pdf to restrict * dipole phase space */ double alphaParameter() const { return theAlphaParameter; } /** * set the alpha parameter (needed for massive PK-Operator) */ void setAlphaParameter(double a)const { theAlphaParameter = a; } //@} public: /** * Print a summary of the parameters used */ void summary(ostream&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * Flag to indicate that at least one MatchboxFactory object is in action */ static bool& theIsMatchboxRun(); /** * The diagram generator. */ Ptr::ptr theDiagramGenerator; /** * The process data object to be used */ Ptr::ptr theProcessData; /** * The number of light flavours, this matrix * element is calculated for. */ unsigned int theNLight; /** * Vector with the PDG ids of the light quark flavours, * which are contained in the jet particle group. */ vector theNLightJetVec; /** * Vector with the PDG ids of the heavy quark flavours, * which are contained in the jet particle group. */ vector theNHeavyJetVec; /** * Vector with the PDG ids of the light quark flavours, * which are contained in the proton particle group. */ vector theNLightProtonVec; /** * The order in \f$\alpha_S\f$. */ unsigned int theOrderInAlphaS; /** * The order in \f$\alpha_{EM}\f$. */ unsigned int theOrderInAlphaEW; /** * The maximum number of legs with virtual corrections. **/ unsigned int theHighestVirtualSize; /** * Switch on or off Born contributions */ bool theBornContributions; /** * Switch on or off virtual contributions */ bool theVirtualContributions; /** * Switch on or off subtracted real emission contributions should be included. */ bool theRealContributions; /** * True if virtual contributions should be treated as independent subprocesses */ bool theIndependentVirtuals; /** * True if PK operator contributions should be treated as independent subprocesses */ bool theIndependentPKs; /** * The phase space generator to be used. */ Ptr::ptr thePhasespace; /** * The scale choice object */ Ptr::ptr theScaleChoice; /** * The factorization scale factor. */ double theFactorizationScaleFactor; /** * The renormalization scale factor. */ double theRenormalizationScaleFactor; /** * Use non-running couplings. */ bool theFixedCouplings; /** * Use non-running couplings. */ bool theFixedQEDCouplings; /** * True, if veto scales should be set * for the real emission */ bool theVetoScales; /** * The amplitudes to be considered */ vector::ptr> theAmplitudes; /** * The Born matrix elements to be considered */ vector::ptr> theBornMEs; /** * The loop induced matrix elements to be considered */ vector::ptr> theLoopInducedMEs; /** * The virtual corrections to be considered */ vector::ptr> theVirtuals; /** * The real emission matrix elements to be considered */ vector::ptr> theRealEmissionMEs; /** * The produced NLO matrix elements */ vector::ptr> theBornVirtualMEs; /** * The produced subtracted matrix elements */ vector::ptr> theSubtractedMEs; /** * The produced finite real emission matrix elements */ vector::ptr> theFiniteRealMEs; /** * Which set of dipoles should be considered */ int theDipoleSet; /** * Switch on or off verbosity */ bool theVerbose; /** * True, if verbose while initializing */ bool theInitVerbose; /** * Prefix for subtraction data */ string theSubtractionData; /** * Set the type of plot that is to be generated for subtraction checking */ int theSubtractionPlotType; /** * Set whether subtraction data should be plotted for all phase space points individually */ bool theSubtractionScatterPlot; /** * Prefix for pole data. */ string thePoleData; /** * Command to limit the real emission process to be considered. */ string doSingleRealProcess(string); /** * The real emission process to be included; if empty, all possible * ones will be considered. */ vector > realEmissionProcesses; /** * Particle groups. */ map theParticleGroups; /** * Command to start a particle group. */ string startParticleGroup(string); /** * The name of the particle group currently edited. */ string particleGroupName; /** * The particle group currently edited. */ PDVector particleGroup; /** * Command to end a particle group. */ string endParticleGroup(string); protected: /** * Parse a process description */ virtual vector parseProcess(string); private: /** * Command to set the process. */ string doProcess(string); /** * Command to set the process. */ string doLoopInducedProcess(string); /** * The process to consider in terms of particle groups. */ vector > processes; /** * The loop induced process to consider in terms of particle groups. */ vector > loopInducedProcesses; /** * Generate subprocesses. */ set makeSubProcesses(const vector&) const; public: /** * Generate matrix element objects for the given process. */ vector::ptr> makeMEs(const vector&, unsigned int orderas, bool virt); private: /** * The shower approximation. */ Ptr::ptr theShowerApproximation; /** * The map of Born processes to splitting dipoles */ map::ptr> > theSplittingDipoles; /** * True, if subtraction scales should be caluclated from real emission kinematics */ bool theRealEmissionScales; /** * Consider all processes with order in couplings specifying the * maximum order. */ bool theAllProcesses; /** * The processes to be ordered from an OLP */ map::tptr,map,int> > theOLPProcesses; /** * Amplitudes which need external initialization */ set::tptr> theExternalAmplitudes; /** * Amplitudes to be selected on clashing responsibilities. */ vector::ptr> theSelectedAmplitudes; /** * Amplitudes to be deselected on clashing responsibilities. */ vector::ptr> theDeselectedAmplitudes; /** * Reweight objects for matrix elements */ vector theReweighters; /** * Preweight objects for matrix elements */ vector thePreweighters; /** * Produce matrix element corrections, but no NLO */ bool theMECorrectionsOnly; /** * The highest multiplicity of legs having virtual contributions.(needed for madgraph) */ int theHighestVirtualsize; /** * Produce matrix element corrections, with LoopSim NLO */ bool theLoopSimCorrections; /** * True, if the setup has already been run. */ bool ranSetup; /** * PDG ids of incoming particles */ set theIncoming; /** * True, if first incoming partons originate from perturbative PDF */ bool theFirstPerturbativePDF; /** * True, if second incoming partons originate from perturbative PDF */ bool theSecondPerturbativePDF; /** * True, if this Factory is in production mode. */ bool inProductionMode; /** * The real emission subprocess used when calculating the hardtree * in the truncated qtilde shower */ tSubProPtr theHardtreeSubprocess; /** * The born emitter used when calculating the hardtree in * the truncated shower */ int theHardtreeEmitter; /** * The born spectator used when calculating the hardtree in * the truncated shower */ int theHardtreeSpectator; /** * True, if spin correlation information should be provided, if possible. */ bool theSpinCorrelations; /** * The alpha parameter to be used for the dipole subtraction * JB: The parameter is muatble, since we need to be able to change it * while calculating the difference of IPK with and without alpha. */ mutable double theAlphaParameter; /** * Wether or not charge conservation should be enforced for the processes * constructed. */ bool theEnforceChargeConservation; /** * Wether or not colour conservation should be enforced for the processes * constructed. */ bool theEnforceColourConservation; /** * Wether or not lepton number conservation should be enforced for the processes * constructed. */ bool theEnforceLeptonNumberConservation; /** * Wether or not quark number conservation should be enforced for the processes * constructed. */ bool theEnforceQuarkNumberConservation; /** * Assume flavour diagonal lepton interactions */ bool theLeptonFlavourDiagonal; /** * Assume flavour diagonal quark interactions */ bool theQuarkFlavourDiagonal; /** * Command for production mode */ string doProductionMode(string) { productionMode(); return ""; } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxFactory & operator=(const MatchboxFactory &) = delete; }; } #endif /* HERWIG_MatchboxFactory_H */ diff --git a/MatrixElement/Matchbox/Matching/DipoleMatching.cc b/MatrixElement/Matchbox/Matching/DipoleMatching.cc --- a/MatrixElement/Matchbox/Matching/DipoleMatching.cc +++ b/MatrixElement/Matchbox/Matching/DipoleMatching.cc @@ -1,147 +1,141 @@ // -*- C++ -*- // // DipoleMatching.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleMatching class. // #include "DipoleMatching.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" - - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" using namespace Herwig; -DipoleMatching::DipoleMatching() {} - -DipoleMatching::~DipoleMatching() {} - IBPtr DipoleMatching::clone() const { return new_ptr(*this); } IBPtr DipoleMatching::fullclone() const { return new_ptr(*this); } CrossSection DipoleMatching::dSigHatDR() const { double xme2 = 0.; pair ij(dipole()->bornEmitter(), dipole()->bornSpectator()); double ccme2 = dipole()->underlyingBornME()->largeNColourCorrelatedME2(ij,theLargeNBasis); if(ccme2==0.)return 0.*nanobarn; double lnme2=dipole()->underlyingBornME()->largeNME2(theLargeNBasis); if(lnme2==0){ generator()->log() <<"\nDipoleMatching: "; generator()->log() <<"\n LargeNME2 is ZERO, while largeNColourCorrelatedME2 is not ZERO." ; generator()->log() <<"\n This is too seriuos.\n" ; generator()->log() << Exception::runerror; } ccme2 *= dipole()->underlyingBornME()->me2() /lnme2; xme2 = dipole()->me2Avg(ccme2); xme2 /= dipole()->underlyingBornME()->lastXComb().lastAlphaS(); double bornPDF = bornPDFWeight(dipole()->underlyingBornME()->lastScale()); if ( bornPDF == 0.0 ) return ZERO; xme2 *= bornPDF; if ( profileScales() ) xme2 *= profileScales()->hardScaleProfile(dipole()->showerHardScale(),dipole()->lastPt()); CrossSection res = sqr(hbarc) * realXComb()->jacobian() * subtractionScaleWeight() * xme2 / (2. * realXComb()->lastSHat()); return res; } double DipoleMatching::me2() const { throw Exception() << "DipoleMatching::me2(): Not intented to use. Disable the ShowerApproximationGenerator." << Exception::runerror; return 0.; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleMatching::persistentOutput(PersistentOStream & os) const { os << theShowerHandler; } void DipoleMatching::persistentInput(PersistentIStream & is, int) { is >> theShowerHandler; } void DipoleMatching::doinit() { if ( theShowerHandler ) { theShowerHandler->init(); hardScaleFactor(theShowerHandler->hardScaleFactor()); factorizationScaleFactor(theShowerHandler->factorizationScaleFactor()); renormalizationScaleFactor(theShowerHandler->renormalizationScaleFactor()); profileScales(theShowerHandler->profileScales()); restrictPhasespace(theShowerHandler->restrictPhasespace()); hardScaleIsMuF(theShowerHandler->hardScaleIsMuF()); if ( theShowerHandler->showerPhaseSpaceOption() == 0 ) { useOpenZ(false); } else if ( theShowerHandler->showerPhaseSpaceOption() == 1 ) { useOpenZ(true); } else { throw InitException() << "DipoleMatching::doinit(): Choice of shower phase space cannot be handled by the matching"; } } // need to fo this after for consistency checks ShowerApproximation::doinit(); } // *** 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 describeHerwigDipoleMatching("Herwig::DipoleMatching", "HwDipoleMatching.so HwShower.so"); void DipoleMatching::Init() { static ClassDocumentation documentation ("DipoleMatching implements NLO matching with the dipole shower."); static Reference interfaceShowerHandler ("ShowerHandler", "The dipole shower handler object to use.", &DipoleMatching::theShowerHandler, false, false, true, true, false); interfaceShowerHandler.rank(-1); } diff --git a/MatrixElement/Matchbox/Matching/DipoleMatching.h b/MatrixElement/Matchbox/Matching/DipoleMatching.h --- a/MatrixElement/Matchbox/Matching/DipoleMatching.h +++ b/MatrixElement/Matchbox/Matching/DipoleMatching.h @@ -1,140 +1,125 @@ // -*- C++ -*- // // DipoleMatching.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_DipoleMatching_H #define Herwig_DipoleMatching_H // // This is the declaration of the DipoleMatching class. // #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief DipoleMatching implements NLO matching with the dipole shower. * */ class DipoleMatching: public Herwig::ShowerApproximation { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - DipoleMatching(); - - /** - * The destructor. - */ - virtual ~DipoleMatching(); - //@} - -public: - /** * Return the shower approximation to the real emission cross * section for the given pair of Born and real emission * configurations. */ virtual CrossSection dSigHatDR() const; /** * Return the shower approximation splitting kernel for the given * pair of Born and real emission configurations in units of the * Born center of mass energy squared, and including a weight to * project onto the splitting given by the dipole used. */ virtual double me2() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The shower handler to be used */ Ptr::ptr theShowerHandler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleMatching & operator=(const DipoleMatching &) = delete; }; } #endif /* Herwig_DipoleMatching_H */ diff --git a/MatrixElement/Matchbox/Matching/HardScaleProfile.cc b/MatrixElement/Matchbox/Matching/HardScaleProfile.cc --- a/MatrixElement/Matchbox/Matching/HardScaleProfile.cc +++ b/MatrixElement/Matchbox/Matching/HardScaleProfile.cc @@ -1,134 +1,132 @@ // -*- C++ -*- // // HardScaleProfile.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HardScaleProfile class. // #include "HardScaleProfile.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 "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; HardScaleProfile::HardScaleProfile() : theFixedHardScale(ZERO), theProfileRho(0.3), theProfileType(resummation) {} -HardScaleProfile::~HardScaleProfile() {} - IBPtr HardScaleProfile::clone() const { return new_ptr(*this); } IBPtr HardScaleProfile::fullclone() const { return new_ptr(*this); } double HardScaleProfile::hardScaleProfile(Energy hard, Energy soft) const { if ( theFixedHardScale > ZERO ) hard = theFixedHardScale; double x = soft/hard; if ( theProfileType == theta ) { return x <= 1. ? 1.0 : 0.0; } if ( theProfileType == resummation ) { if ( x > 1. ) { return 0.; } else if ( x <= 1. && x > 1. - theProfileRho ) { return sqr(1.-x)/(2.*sqr(theProfileRho)); } else if ( x <= 1. - theProfileRho && x > 1. - 2.*theProfileRho ) { return 1. - sqr(1.-2.*theProfileRho-x)/(2.*sqr(theProfileRho)); } else { return 1.; } } if ( theProfileType == hfact ) { return 1./(1.+x); } return 1.; } bool HardScaleProfile::unrestrictedPhasespace() const { if ( theProfileType == theta || theProfileType == resummation ) { return false; } return true; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void HardScaleProfile::persistentOutput(PersistentOStream & os) const { os << ounit(theFixedHardScale,GeV) << theProfileRho << theProfileType; } void HardScaleProfile::persistentInput(PersistentIStream & is, int) { is >> iunit(theFixedHardScale,GeV) >> theProfileRho >> theProfileType; } // *** 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 describeHerwigHardScaleProfile("Herwig::HardScaleProfile", "Herwig.so"); void HardScaleProfile::Init() { static ClassDocumentation documentation ("HardScaleProfile implements profile scales."); static Parameter interfaceFixedHardScale ("FixedHardScale", "A fixed hard scale to be used instead of the process specific choice.", &HardScaleProfile::theFixedHardScale, GeV, ZERO, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceProfileRho ("ProfileRho", "The profile width parameter", &HardScaleProfile::theProfileRho, 0.3, 0.0, 1.0, false, false, Interface::limited); static Switch interfaceProfileType ("ProfileType", "The type of profile to use.", &HardScaleProfile::theProfileType, resummation, false, false); static SwitchOption interfaceProfileTypeTheta (interfaceProfileType, "Theta", "Use a hard cutoff.", theta); static SwitchOption interfaceProfileTypeResummation (interfaceProfileType, "Resummation", "Use the resummation profile with quadratic interpolation.", resummation); static SwitchOption interfaceProfileTypeHFact (interfaceProfileType, "HFact", "Use the hfact profile.", hfact); } diff --git a/MatrixElement/Matchbox/Matching/HardScaleProfile.h b/MatrixElement/Matchbox/Matching/HardScaleProfile.h --- a/MatrixElement/Matchbox/Matching/HardScaleProfile.h +++ b/MatrixElement/Matchbox/Matching/HardScaleProfile.h @@ -1,150 +1,142 @@ // -*- C++ -*- // // HardScaleProfile.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_HardScaleProfile_H #define Herwig_HardScaleProfile_H // // This is the declaration of the HardScaleProfile class. // #include "ThePEG/Interface/Interfaced.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief HardScaleProfile is the base class for profile scales. A few * standard choices are provided by this implementation. * */ class HardScaleProfile: public Interfaced { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ HardScaleProfile(); - /** - * The destructor. - */ - virtual ~HardScaleProfile(); - //@} - public: /** * Return a scale profile towards the hard scale */ virtual double hardScaleProfile(Energy hard, Energy soft) const; /** * Return true, if this hard scale profile requires an unrestricted * radiation phase space. */ virtual bool unrestrictedPhasespace() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** * Enumerate the possible profiles */ enum ProfileTypes { theta = 0, /** hard theta cut */ resummation = 1, /** `resummation' profile with quadratic interpolation */ hfact = 2 /** hfact profile */ }; /** * A fixed hard scale to be used instead of the hard scale decided * for the process in question. */ Energy theFixedHardScale; /** * A dimensionless width parameter setting the smearing size * relative to the hard scale; this may have different * interpretations depending on the profile type chosen. */ double theProfileRho; /** * The profile type to be used */ int theProfileType; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HardScaleProfile & operator=(const HardScaleProfile &) = delete; }; } #endif /* Herwig_HardScaleProfile_H */ diff --git a/MatrixElement/Matchbox/Matching/MEMatching.cc b/MatrixElement/Matchbox/Matching/MEMatching.cc --- a/MatrixElement/Matchbox/Matching/MEMatching.cc +++ b/MatrixElement/Matchbox/Matching/MEMatching.cc @@ -1,152 +1,150 @@ // -*- C++ -*- // // MEMatching.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEMatching class. // #include "MEMatching.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Handlers/StdXCombGroup.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" using namespace Herwig; MEMatching::MEMatching() : theTruncatedShower(false) {} -MEMatching::~MEMatching() {} - IBPtr MEMatching::clone() const { return new_ptr(*this); } IBPtr MEMatching::fullclone() const { return new_ptr(*this); } CrossSection MEMatching::dSigHatDR() const { // need to ensure the partner dipoles all got their xcombs set // for a safe evaluation of channelweight Ptr::tcptr grp = dynamic_ptr_cast::tcptr>(realCXComb()); assert(grp); for ( vector::const_iterator dep = grp->dependent().begin(); dep != grp->dependent().end(); ++dep ) { (**dep).matrixElement()->setXComb(*dep); } double xme2 = dipole()->realEmissionME()->me2(); xme2 *= channelWeight(); xme2 /= pow(dipole()->realEmissionME()->lastXComb().lastAlphaS(), (double)(dipole()->realEmissionME()->orderInAlphaS())); xme2 *= pow(dipole()->underlyingBornME()->lastXComb().lastAlphaS(), (double)(dipole()->underlyingBornME()->orderInAlphaS())); double bornPDF = bornPDFWeight(dipole()->underlyingBornME()->lastScale()); if ( bornPDF == 0.0 ) return ZERO; xme2 *= bornPDF; if ( profileScales() ) xme2 *= profileScales()->hardScaleProfile(dipole()->showerHardScale(),dipole()->lastPt()); return sqr(hbarc) * realXComb()->jacobian() * subtractionScaleWeight() * xme2 / (2. * realXComb()->lastSHat()); } double MEMatching::me2() const { double bme2 = bornXComb()->matrixElement()->me2(); bme2 /= pow(dipole()->underlyingBornME()->lastXComb().lastAlphaS(), (double)(dipole()->underlyingBornME()->orderInAlphaS())); double rme2 = dipole()->realEmissionME()->me2(); rme2 /= pow(dipole()->realEmissionME()->lastXComb().lastAlphaS(), (double)(dipole()->realEmissionME()->orderInAlphaS())); rme2 *= pow(bornXComb()->lastSHat()/realXComb()->lastSHat(), realCXComb()->mePartonData().size()-4.); if ( profileScales() ) rme2 *= profileScales()->hardScaleProfile(dipole()->showerHardScale(),dipole()->lastPt()); return channelWeight() * (rme2/bme2) * (bornXComb()->lastSHat()/realXComb()->lastSHat()) * splittingScaleWeight(); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MEMatching::persistentOutput(PersistentOStream & os) const { os << theTruncatedShower; } void MEMatching::persistentInput(PersistentIStream & is, int) { is >> theTruncatedShower; } // *** 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 describeHerwigMEMatching("Herwig::MEMatching", "Herwig.so"); void MEMatching::Init() { static ClassDocumentation documentation ("MEMatching implements NLO matching with matrix element correction (aka Powheg)."); static Switch interfaceTruncatedShower ("TruncatedShower", "Include a truncated qtilde shower", &MEMatching::theTruncatedShower, false, false, false); static SwitchOption interfaceTruncatedShowerYes (interfaceTruncatedShower, "Yes", "", true); static SwitchOption interfaceTruncatedShowerNo (interfaceTruncatedShower, "No", "", false); } diff --git a/MatrixElement/Matchbox/Matching/MEMatching.h b/MatrixElement/Matchbox/Matching/MEMatching.h --- a/MatrixElement/Matchbox/Matching/MEMatching.h +++ b/MatrixElement/Matchbox/Matching/MEMatching.h @@ -1,147 +1,139 @@ // -*- C++ -*- // // MEMatching.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MEMatching_H #define Herwig_MEMatching_H // // This is the declaration of the MEMatching class. // #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MEMatching implements NLO matching with matrix element correction (aka Powheg). * */ class MEMatching: public Herwig::ShowerApproximation { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MEMatching(); - /** - * The destructor. - */ - virtual ~MEMatching(); - //@} - public: /** * Return true, if this shower approximation will require a * splitting generator */ virtual bool needsSplittingGenerator() const { return true; } /** * Return true, if this shower approximation will require * H events */ virtual bool hasHEvents() const { return restrictPhasespace() || profileScales(); } /** * Return true, if this shower approximation will require * a truncated parton shower */ virtual bool needsTruncatedShower() const { return theTruncatedShower; } public: /** * Return the shower approximation to the real emission cross * section for the given pair of Born and real emission * configurations. */ virtual CrossSection dSigHatDR() const; /** * Return the shower approximation splitting kernel for the given * pair of Born and real emission configurations in units of the * Born center of mass energy squared, and including a weight to * project onto the splitting given by the dipole used. */ virtual double me2() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEMatching & operator=(const MEMatching &) = delete; /** * True, if a truncated parton shower should be generated */ bool theTruncatedShower; }; } #endif /* Herwig_MEMatching_H */ diff --git a/MatrixElement/Matchbox/Matching/QTildeMatching.cc b/MatrixElement/Matchbox/Matching/QTildeMatching.cc --- a/MatrixElement/Matchbox/Matching/QTildeMatching.cc +++ b/MatrixElement/Matchbox/Matching/QTildeMatching.cc @@ -1,538 +1,536 @@ // -*- C++ -*- // // QTildeMatching.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the QTildeMatching class. // #include "QTildeMatching.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" #include "Herwig/Shower/QTilde/Kinematics/KinematicHelpers.h" using namespace Herwig; QTildeMatching::QTildeMatching() : theCorrectForXZMismatch(true) {} -QTildeMatching::~QTildeMatching() {} - IBPtr QTildeMatching::clone() const { return new_ptr(*this); } IBPtr QTildeMatching::fullclone() const { return new_ptr(*this); } void QTildeMatching::checkCutoff() { if ( showerTildeKinematics() ) { showerTildeKinematics()-> prepare(realCXComb(),bornCXComb()); showerTildeKinematics()->dipole(dipole()); showerTildeKinematics()->getShowerVariables(); } } void QTildeMatching::getShowerVariables() { // already filled from checkCutoff in this case if ( showerTildeKinematics() ) return; // get the shower variables calculateShowerVariables(); // check for the cutoff dipole()->isAboveCutoff(isAboveCutoff()); // get the hard scale dipole()->showerHardScale(hardScale()); // check for phase space dipole()->isInShowerPhasespace(isInShowerPhasespace()); } bool QTildeMatching::isInShowerPhasespace() const { Energy qtildeHard = ZERO; Energy qtilde = dipole()->showerScale(); assert(!dipole()->showerParameters().empty()); double z = dipole()->showerParameters()[0]; // FF if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() > 1 ) { qtildeHard = theQTildeFinder-> calculateFinalFinalScales(bornCXComb()->meMomenta()[dipole()->bornEmitter()], bornCXComb()->meMomenta()[dipole()->bornSpectator()]).first; } // FI if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() < 2 ) { qtildeHard = theQTildeFinder-> calculateInitialFinalScales(bornCXComb()->meMomenta()[dipole()->bornSpectator()], bornCXComb()->meMomenta()[dipole()->bornEmitter()],false).second; } // IF if ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() > 1 ) { qtildeHard = theQTildeFinder-> calculateInitialFinalScales(bornCXComb()->meMomenta()[dipole()->bornEmitter()], bornCXComb()->meMomenta()[dipole()->bornSpectator()],false).first; if ( z < (dipole()->bornEmitter() == 0 ? bornCXComb()->lastX1() : bornCXComb()->lastX2()) ) return false; } // II if ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() < 2 ) { qtildeHard = theQTildeFinder-> calculateInitialInitialScales(bornCXComb()->meMomenta()[dipole()->bornEmitter()], bornCXComb()->meMomenta()[dipole()->bornSpectator()]).first; if ( z < (dipole()->bornEmitter() == 0 ? bornCXComb()->lastX1() : bornCXComb()->lastX2()) ) return false; } Energy2 pt2 = ZERO; const vector & masses = theQTildeSudakov->virtualMasses({{ bornCXComb()->mePartonData()[dipole()->bornEmitter() ], realCXComb()->mePartonData()[dipole()->realEmitter() ], realCXComb()->mePartonData()[dipole()->realEmission()] }}); const Energy2 m22 = sqr(masses[2]); if ( dipole()->bornEmitter() > 1 ) { const Energy2 m02 = sqr(masses[0]); const Energy2 m12 = sqr(masses[1]); pt2 = QTildeKinematics::pT2_FSR(sqr(qtilde),z,m02,m12,m22,m12,m22); } else { pt2 = QTildeKinematics::pT2_ISR(sqr(qtilde),z,m22); } if ( pt2 < max(theQTildeSudakov->pT2min(),sqr(safeCut()) )) return false; bool hardVeto = restrictPhasespace() && sqrt(pt2) >= dipole()->showerHardScale(); return qtilde <= qtildeHard && !hardVeto; } bool QTildeMatching::isAboveCutoff() const { Energy qtilde = dipole()->showerScale(); assert(!dipole()->showerParameters().empty()); double z = dipole()->showerParameters()[0]; const vector & masses = theQTildeSudakov->virtualMasses({{ bornCXComb()->mePartonData()[dipole()->bornEmitter() ], realCXComb()->mePartonData()[dipole()->realEmitter() ], realCXComb()->mePartonData()[dipole()->realEmission()] }}); const Energy2 m22 = sqr(masses[2]); if ( dipole()->bornEmitter() > 1 ) { const Energy2 m02 = sqr(masses[0]); const Energy2 m12 = sqr(masses[1]); const Energy2 pt2 = QTildeKinematics::pT2_FSR(sqr(qtilde),z,m02,m12,m22,m12,m22); return pt2 >= max(theQTildeSudakov->pT2min(),sqr(safeCut())); } else { const Energy2 pt2 = QTildeKinematics::pT2_ISR(sqr(qtilde),z,m22); return pt2 >= max(theQTildeSudakov->pT2min(),sqr(safeCut())); } return false; } CrossSection QTildeMatching::dSigHatDR() const { assert(!dipole()->showerParameters().empty()); pair vars = make_pair(sqr(dipole()->showerScale()), dipole()->showerParameters()[0]); pair ij(dipole()->bornEmitter(), dipole()->bornSpectator()); double ccme2 = dipole()->underlyingBornME()->largeNColourCorrelatedME2(ij,theLargeNBasis); if(ccme2==0.)return 0.*nanobarn; double lnme2=dipole()->underlyingBornME()->largeNME2(theLargeNBasis); if(lnme2==0){ generator()->log() <<"\nQTildeMatching: "; generator()->log() <<"\n largeNME2 is ZERO, while largeNColourCorrelatedME2 is not ZERO." ; generator()->log() <<"\n This is too seriuos.\n" ; generator()->log() << Exception::runerror; } ccme2 *= dipole()->underlyingBornME()->me2() /lnme2; Energy2 prop = ZERO; if ( dipole()->bornEmitter() > 1 ) { prop = (realCXComb()->meMomenta()[dipole()->realEmitter()] + realCXComb()->meMomenta()[dipole()->realEmission()]).m2() - bornCXComb()->meMomenta()[dipole()->bornEmitter()].m2(); } else { prop = 2.*vars.second*(realCXComb()->meMomenta()[dipole()->realEmitter()]* realCXComb()->meMomenta()[dipole()->realEmission()]); } // note alphas included downstream from subtractionScaleWeight() double xme2 = -8.*Constants::pi*ccme2*splitFn(vars)*realXComb()->lastSHat()/prop; xme2 *= pow(realCXComb()->lastSHat() / bornCXComb()->lastSHat(), bornCXComb()->mePartonData().size()-4.); double bornPDF = bornPDFWeight(dipole()->underlyingBornME()->lastScale()); if ( bornPDF == 0.0 ) return ZERO; xme2 *= bornPDF; xme2 *= dipole()->realEmissionME()->finalStateSymmetry() / dipole()->underlyingBornME()->finalStateSymmetry(); // take care of mismatch between z and x as we are approaching the // hard phase space boundary // TODO get rid of this useless scale option business and simplify PDF handling in here if ( dipole()->bornEmitter() < 2 && theCorrectForXZMismatch ) { Energy2 emissionScale = ZERO; if ( emissionScaleInSubtraction() == showerScale ) { emissionScale = showerFactorizationScale(); } else if ( emissionScaleInSubtraction() == realScale ) { emissionScale = dipole()->realEmissionME()->lastScale(); } else if ( emissionScaleInSubtraction() == bornScale ) { emissionScale = dipole()->underlyingBornME()->lastScale(); } double xzMismatch = dipole()->subtractionParameters()[0] / dipole()->showerParameters()[0]; double realCorrectedPDF = dipole()->bornEmitter() == 0 ? dipole()->realEmissionME()->pdf1(emissionScale,theExtrapolationX, xzMismatch) : dipole()->realEmissionME()->pdf2(emissionScale,theExtrapolationX, xzMismatch); double realPDF = dipole()->bornEmitter() == 0 ? dipole()->realEmissionME()->pdf1(emissionScale,theExtrapolationX,1.0) : dipole()->realEmissionME()->pdf2(emissionScale,theExtrapolationX,1.0); if ( realPDF == 0.0 || realCorrectedPDF == 0.0 ) return ZERO; xme2 *= realCorrectedPDF / realPDF; } Energy qtilde = sqrt(vars.first); double z = vars.second; Energy2 pt2 = ZERO; const vector & masses = theQTildeSudakov->virtualMasses({{ bornCXComb()->mePartonData()[dipole()->bornEmitter() ], realCXComb()->mePartonData()[dipole()->realEmitter() ], realCXComb()->mePartonData()[dipole()->realEmission()] }}); const Energy2 m22 = sqr(masses[2]); if ( dipole()->bornEmitter() > 1 ) { const Energy2 m02 = sqr(masses[0]); const Energy2 m12 = sqr(masses[1]); pt2 = QTildeKinematics::pT2_FSR(sqr(qtilde),z,m02,m12,m22,m12,m22); } else { pt2 = QTildeKinematics::pT2_ISR(sqr(qtilde),z,m22); } assert(pt2 >= ZERO); if ( profileScales() ) xme2 *= profileScales()->hardScaleProfile(dipole()->showerHardScale(),sqrt(pt2)); CrossSection res = sqr(hbarc) * realXComb()->jacobian() * subtractionScaleWeight() * xme2 / (2. * realXComb()->lastSHat()); return res; } double QTildeMatching::me2() const { throw Exception() << "QTildeMatching::me2(): Not intented to use. Disable the ShowerApproximationGenerator." << Exception::runerror; return 0.; } void QTildeMatching::calculateShowerVariables() const { Lorentz5Momentum n; Energy2 Q2 = ZERO; const Lorentz5Momentum& pb = bornCXComb()->meMomenta()[dipole()->bornEmitter()]; const Lorentz5Momentum& pc = bornCXComb()->meMomenta()[dipole()->bornSpectator()]; if ( dipole()->bornEmitter() > 1 ) { Q2 = (pb+pc).m2(); } else { Q2 = -(pb-pc).m2(); } if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() > 1 ) { double b = sqr(bornCXComb()->meMomenta()[dipole()->bornEmitter()].m())/Q2; double c = sqr(bornCXComb()->meMomenta()[dipole()->bornSpectator()].m())/Q2; double lambda = sqrt(1.+sqr(b)+sqr(c)-2.*b-2.*c-2.*b*c); n = (1.-0.5*(1.-b+c-lambda))*pc - 0.5*(1.-b+c-lambda)*pb; } if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() < 2 ) { n = bornCXComb()->meMomenta()[dipole()->bornSpectator()]; } if ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() > 1 ) { double c = sqr(bornCXComb()->meMomenta()[dipole()->bornSpectator()].m())/Q2; n = (1.+c)*pc - c*pb; } if ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() < 2 ) { n = bornCXComb()->meMomenta()[dipole()->bornSpectator()]; } // the light-cone condition is numerically not very stable, so we // explicitly push it on the light-cone here n.setMass(ZERO); n.rescaleEnergy(); double z = 0.0; if ( dipole()->bornEmitter() > 1 ) { z = 1. - (n*realCXComb()->meMomenta()[dipole()->realEmission()])/ (n*bornCXComb()->meMomenta()[dipole()->bornEmitter()]); } else { z = 1. - (n*realCXComb()->meMomenta()[dipole()->realEmission()])/ (n*realCXComb()->meMomenta()[dipole()->realEmitter()]); } // allow small violations (numerical inaccuracies) if ( z <= 0 && z >= -1e-6 ) { z = std::numeric_limits::epsilon(); } else if ( z >= 1 && z <= 1+1e-6 ) { z = 1-std::numeric_limits::epsilon(); } Energy2 qtilde2 = ZERO; Energy2 q2 = ZERO; if ( dipole()->bornEmitter() > 1 ) { q2 = (realCXComb()->meMomenta()[dipole()->realEmitter()] + realCXComb()->meMomenta()[dipole()->realEmission()]).m2(); qtilde2 = (q2 - bornCXComb()->meMomenta()[dipole()->bornEmitter()].m2())/(z*(1.-z)); } else { q2 = -(realCXComb()->meMomenta()[dipole()->realEmitter()] - realCXComb()->meMomenta()[dipole()->realEmission()]).m2(); qtilde2 = (q2 + bornCXComb()->meMomenta()[dipole()->bornEmitter()].m2())/(1.-z); } if ( qtilde2 < ZERO ) { qtilde2 = ZERO; } assert(qtilde2 >= ZERO && z > 0.0 && z < 1.0); dipole()->showerScale(sqrt(qtilde2)); dipole()->showerParameters().resize(1); dipole()->showerParameters()[0] = z; } double QTildeMatching::splitFn(const pair& vars) const { const Energy2& qtilde2 = vars.first; const double z = vars.second; double Nc = SM().Nc(); // final state branching if ( dipole()->bornEmitter() > 1 ) { // final state quark quark branching if ( abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 7 ) { Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(z)-2.*sqr(m)/(z*qtilde2))/(1.-z); } // final state gluon branching if ( bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == ParticleID::g ) { if ( realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { // ATTENTION the factor 2 here is intentional as it cancels to the 1/2 // stemming from the large-N colour correlator return 2.*Nc*(z/(1.-z)+(1.-z)/z+z*(1.-z)); } if ( abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { Energy m = realCXComb()->mePartonData()[dipole()->realEmission()]->hardProcessMass(); return (1./2.)*(1.-2.*z*(1.-z)+2.*sqr(m)/(z*(1.-z)*qtilde2)); } } // final state squark branching if ((abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) > 1000000 && abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 1000007) || (abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) > 2000000 && abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 2000007)){ Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return ((sqr(Nc)-1.)/Nc)*(z-sqr(m)/(z*qtilde2))/(1.-z); } // final state gluino branching if (bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == 1000021){ Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return Nc*(1.+sqr(z)-2.*sqr(m)/(z*qtilde2))/(1.-z); } } // initial state branching if ( dipole()->bornEmitter() < 2 ) { // g/g if ( realCXComb()->mePartonData()[dipole()->realEmitter()]->id() == ParticleID::g && realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { // see above for factor of 2 return 2.*Nc*(z/(1.-z)+(1.-z)/z+z*(1.-z)); } // q/q if ( abs(realCXComb()->mePartonData()[dipole()->realEmitter()]->id()) < 7 && realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(z))/(1.-z); } // g/q if ( realCXComb()->mePartonData()[dipole()->realEmitter()]->id() == ParticleID::g && abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { return (1./2.)*(1.-2.*z*(1.-z)); } // q/g if ( abs(realCXComb()->mePartonData()[dipole()->realEmitter()]->id()) < 7 && abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(1.-z))/z; } } return 0.0; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void QTildeMatching::doinit() { assert(theShowerHandler && theQTildeFinder && theQTildeSudakov); theShowerHandler->init(); theQTildeFinder->init(); theQTildeSudakov->init(); hardScaleFactor(theShowerHandler->hardScaleFactor()); factorizationScaleFactor(theShowerHandler->factorizationScaleFactor()); renormalizationScaleFactor(theShowerHandler->renormalizationScaleFactor()); profileScales(theShowerHandler->profileScales()); restrictPhasespace(theShowerHandler->restrictPhasespace()); hardScaleIsMuF(theShowerHandler->hardScaleIsMuF()); ShowerApproximation::doinit(); } void QTildeMatching::doinitrun() { assert(theShowerHandler && theQTildeFinder && theQTildeSudakov); theShowerHandler->initrun(); theQTildeFinder->initrun(); theQTildeSudakov->initrun(); ShowerApproximation::doinitrun(); } void QTildeMatching::persistentOutput(PersistentOStream & os) const { os << theQTildeFinder << theQTildeSudakov << theShowerHandler << theCorrectForXZMismatch; } void QTildeMatching::persistentInput(PersistentIStream & is, int) { is >> theQTildeFinder >> theQTildeSudakov >> theShowerHandler >> theCorrectForXZMismatch; } // *** 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 describeHerwigQTildeMatching("Herwig::QTildeMatching", "HwShower.so HwQTildeMatching.so"); void QTildeMatching::Init() { static ClassDocumentation documentation ("QTildeMatching implements NLO matching with the default shower."); static Reference interfaceQTildeFinder ("QTildeFinder", "Set the partner finder to calculate hard scales.", &QTildeMatching::theQTildeFinder, false, false, true, false, false); interfaceQTildeFinder.rank(-1); static Reference interfaceQTildeSudakov ("QTildeSudakov", "Set the partner finder to calculate hard scales.", &QTildeMatching::theQTildeSudakov, false, false, true, false, false); interfaceQTildeSudakov.rank(-1); static Reference interfaceShowerHandler ("ShowerHandler", "The QTilde shower handler to use.", &QTildeMatching::theShowerHandler, false, false, true, true, false); interfaceShowerHandler.rank(-1); static Switch interfaceCorrectForXZMismatch ("CorrectForXZMismatch", "Correct for x/z mismatch near hard phase space boundary.", &QTildeMatching::theCorrectForXZMismatch, true, false, false); static SwitchOption interfaceCorrectForXZMismatchYes (interfaceCorrectForXZMismatch, "Yes", "Include the correction factor.", true); static SwitchOption interfaceCorrectForXZMismatchNo (interfaceCorrectForXZMismatch, "No", "Do not include the correction factor.", false); interfaceCorrectForXZMismatch.rank(-1); } diff --git a/MatrixElement/Matchbox/Matching/QTildeMatching.h b/MatrixElement/Matchbox/Matching/QTildeMatching.h --- a/MatrixElement/Matchbox/Matching/QTildeMatching.h +++ b/MatrixElement/Matchbox/Matching/QTildeMatching.h @@ -1,201 +1,193 @@ // -*- C++ -*- // // QTildeMatching.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_QTildeMatching_H #define Herwig_QTildeMatching_H // // This is the declaration of the QTildeMatching class. // #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief QTildeMatching implements NLO matching with the default shower. * */ class QTildeMatching: public Herwig::ShowerApproximation { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ QTildeMatching(); - /** - * The destructor. - */ - virtual ~QTildeMatching(); - //@} - public: /** * Return the shower approximation to the real emission cross * section for the given pair of Born and real emission * configurations. */ virtual CrossSection dSigHatDR() const; /** * Return the shower approximation splitting kernel for the given * pair of Born and real emission configurations in units of the * Born center of mass energy squared, and including a weight to * project onto the splitting given by the dipole used. */ virtual double me2() const; /** * Determine if the configuration is below or above the cutoff. */ virtual void checkCutoff(); /** * Determine all kinematic variables which are not provided by the * dipole kinematics; store all shower variables in the respective * dipole object for later use. */ virtual void getShowerVariables(); protected: /** * Return true, if the shower was able to generate an emission * leading from the given Born to the given real emission process. */ virtual bool isInShowerPhasespace() const; /** * Return true, if the shower emission leading from the given Born * to the given real emission process would have been generated * above the shower's infrared cutoff. */ virtual bool isAboveCutoff() const; /** * Calculate qtilde^2 and z for the splitting considered */ void calculateShowerVariables() const; /** * Return the splitting function as a function of the kinematic * variables */ double splitFn(const pair&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeMatching & operator=(const QTildeMatching &) = delete; /** * The shower handler to be used */ Ptr::ptr theShowerHandler; /** * The qtilde partner finder for calculating the hard scales */ Ptr::ptr theQTildeFinder; /** * The qtilde Sudakov to access the cutoff */ Ptr::ptr theQTildeSudakov; /** * True, if PDF weight should be corrected for z/x mismatch at the * hard phase space boundary */ bool theCorrectForXZMismatch; }; } #endif /* Herwig_QTildeMatching_H */ diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximation.cc b/MatrixElement/Matchbox/Matching/ShowerApproximation.cc --- a/MatrixElement/Matchbox/Matching/ShowerApproximation.cc +++ b/MatrixElement/Matchbox/Matching/ShowerApproximation.cc @@ -1,718 +1,716 @@ // -*- C++ -*- // // ShowerApproximation.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerApproximation class. // #include "ShowerApproximation.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" using namespace Herwig; ShowerApproximation::ShowerApproximation() : HandlerBase(), theExtrapolationX(1.0), theBelowCutoff(false), theFFPtCut(1.0*GeV), theFFScreeningScale(ZERO), theFIPtCut(1.0*GeV), theFIScreeningScale(ZERO), theIIPtCut(1.0*GeV), theIIScreeningScale(ZERO), theSafeCut(0.0*GeV), theRestrictPhasespace(true), theHardScaleFactor(1.0), theRenormalizationScaleFactor(1.0), theFactorizationScaleFactor(1.0), theRealEmissionScaleInSubtraction(showerScale), theBornScaleInSubtraction(showerScale), theEmissionScaleInSubtraction(showerScale), theRealEmissionScaleInSplitting(showerScale), theBornScaleInSplitting(showerScale), theEmissionScaleInSplitting(showerScale), theRenormalizationScaleFreeze(1.*GeV), theFactorizationScaleFreeze(1.*GeV), maxPtIsMuF(false), theOpenZ(true) {} -ShowerApproximation::~ShowerApproximation() {} - void ShowerApproximation::setLargeNBasis() { assert(dipole()->realEmissionME()->matchboxAmplitude()); if ( !dipole()->realEmissionME()->matchboxAmplitude()->treeAmplitudes() ) return; if ( !theLargeNBasis ) { if ( !dipole()->realEmissionME()->matchboxAmplitude()->colourBasis() ) throw Exception() << "ShowerApproximation::setLargeNBasis(): Expecting a colour basis object." << Exception::runerror; theLargeNBasis = dipole()->realEmissionME()->matchboxAmplitude()->colourBasis()->cloneMe(); theLargeNBasis->clear(); theLargeNBasis->doLargeN(); } } void ShowerApproximation::setDipole(Ptr::tptr dip) { theDipole = dip; setLargeNBasis(); } Ptr::tptr ShowerApproximation::dipole() const { return theDipole; } Ptr::tptr ShowerApproximation::showerTildeKinematics() const { return Ptr::tptr(); } Ptr::tptr ShowerApproximation::showerInvertedTildeKinematics() const { return Ptr::tptr(); } void ShowerApproximation::checkCutoff() { assert(!showerTildeKinematics()); } void ShowerApproximation::getShowerVariables() { // check for the cutoff dipole()->isAboveCutoff(isAboveCutoff()); // get the hard scale dipole()->showerHardScale(hardScale()); // set the shower scale and variables for completeness dipole()->showerScale(dipole()->lastPt()); dipole()->showerParameters().resize(1); dipole()->showerParameters()[0] = dipole()->lastZ(); // check for phase space dipole()->isInShowerPhasespace(isInShowerPhasespace()); } bool ShowerApproximation::isAboveCutoff() const { if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() > 1 ) { return dipole()->lastPt() >= max(ffPtCut(),safeCut()); } else if ( ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() < 2 ) || ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() > 1 ) ) { return dipole()->lastPt() >= max(fiPtCut(),safeCut()); } else { assert(dipole()->bornEmitter() < 2 && dipole()->bornSpectator() < 2); return dipole()->lastPt() >= max(iiPtCut(),safeCut()); } return true; } Energy ShowerApproximation::hardScale() const { if ( !maxPtIsMuF ) { if ( !bornCXComb()->mePartonData()[0]->coloured() && !bornCXComb()->mePartonData()[1]->coloured() ) { Energy maxPt = (bornCXComb()->meMomenta()[0] + bornCXComb()->meMomenta()[1]).m(); maxPt *= hardScaleFactor(); return maxPt; } Energy maxPt = generator()->maximumCMEnergy(); vector::const_iterator p = bornCXComb()->meMomenta().begin() + 2; cPDVector::const_iterator pp = bornCXComb()->mePartonData().begin() + 2; for ( ; p != bornCXComb()->meMomenta().end(); ++p, ++pp ) if ( (**pp).coloured() ) maxPt = min(maxPt,p->mt()); if ( maxPt == generator()->maximumCMEnergy() ) maxPt = (bornCXComb()->meMomenta()[0] + bornCXComb()->meMomenta()[1]).m(); maxPt *= hardScaleFactor(); return maxPt; } else { return hardScaleFactor()*sqrt(bornCXComb()->lastShowerScale()); } } bool ShowerApproximation::isInShowerPhasespace() const { if ( !dipole()->isAboveCutoff() ) return false; if ( !restrictPhasespace() ) return true; InvertedTildeKinematics& kinematics = const_cast(*dipole()->invertedTildeKinematics()); tcStdXCombPtr tmpreal = kinematics.realXComb(); tcStdXCombPtr tmpborn = kinematics.bornXComb(); Ptr::tptr tmpdip = kinematics.dipole(); Energy hard = dipole()->showerHardScale(); Energy pt = dipole()->lastPt(); double z = dipole()->lastZ(); pair zbounds(0.,1.); kinematics.dipole(const_ptr_cast::tptr>(theDipole)); kinematics.prepare(realCXComb(),bornCXComb()); if ( pt > hard ) { kinematics.dipole(tmpdip); kinematics.prepare(tmpreal,tmpborn); return false; } try { zbounds = kinematics.zBounds(pt,openZ() ? kinematics.ptMax() : hard); } catch(...) { kinematics.dipole(tmpdip); kinematics.prepare(tmpreal,tmpborn); throw; } kinematics.dipole(tmpdip); kinematics.prepare(tmpreal,tmpborn); return z > zbounds.first && z < zbounds.second; } Energy2 ShowerApproximation::showerEmissionScale() const { Energy2 mur = sqr(dipole()->lastPt()); if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() > 1 ) { return mur + sqr(ffScreeningScale()); } else if ( ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() < 2 ) || ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() > 1 ) ) { return mur + sqr(fiScreeningScale()); } else { assert(dipole()->bornEmitter() < 2 && dipole()->bornSpectator() < 2); return mur + sqr(iiScreeningScale()); } return mur; } Energy2 ShowerApproximation::bornRenormalizationScale() const { return sqr(dipole()->underlyingBornME()->renormalizationScaleFactor()) * dipole()->underlyingBornME()->renormalizationScale(); } Energy2 ShowerApproximation::bornFactorizationScale() const { return sqr(dipole()->underlyingBornME()->factorizationScaleFactor()) * dipole()->underlyingBornME()->factorizationScale(); } Energy2 ShowerApproximation::realRenormalizationScale() const { return sqr(dipole()->realEmissionME()->renormalizationScaleFactor()) * dipole()->realEmissionME()->renormalizationScale(); } Energy2 ShowerApproximation::realFactorizationScale() const { return sqr(dipole()->realEmissionME()->factorizationScaleFactor()) * dipole()->realEmissionME()->factorizationScale(); } double ShowerApproximation::bornPDFWeight(Energy2 muf) const { if ( !bornCXComb()->mePartonData()[0]->coloured() && !bornCXComb()->mePartonData()[1]->coloured() ) return 1.; if ( muf < sqr(theFactorizationScaleFreeze) ) muf = sqr(theFactorizationScaleFreeze); double pdfweight = 1.; if ( bornCXComb()->mePartonData()[0]->coloured() && dipole()->underlyingBornME()->havePDFWeight1() ) pdfweight *= dipole()->underlyingBornME()->pdf1(muf,theExtrapolationX); if ( bornCXComb()->mePartonData()[1]->coloured() && dipole()->underlyingBornME()->havePDFWeight2() ) pdfweight *= dipole()->underlyingBornME()->pdf2(muf,theExtrapolationX); return pdfweight; } double ShowerApproximation::realPDFWeight(Energy2 muf) const { if ( !realCXComb()->mePartonData()[0]->coloured() && !realCXComb()->mePartonData()[1]->coloured() ) return 1.; if ( muf < sqr(theFactorizationScaleFreeze) ) muf = sqr(theFactorizationScaleFreeze); double pdfweight = 1.; if ( realCXComb()->mePartonData()[0]->coloured() && dipole()->realEmissionME()->havePDFWeight1() ) pdfweight *= dipole()->realEmissionME()->pdf1(muf,theExtrapolationX); if ( realCXComb()->mePartonData()[1]->coloured() && dipole()->realEmissionME()->havePDFWeight2() ) pdfweight *= dipole()->realEmissionME()->pdf2(muf,theExtrapolationX); return pdfweight; } double ShowerApproximation::scaleWeight(int rScale, int bScale, int eScale) const { double emissionAlpha = 1.; Energy2 emissionScale = ZERO; Energy2 showerscale = ZERO; if ( eScale == showerScale || bScale == showerScale || eScale == showerScale ) { showerscale = showerRenormalizationScale(); if ( showerscale < sqr(theRenormalizationScaleFreeze) ) showerscale = sqr(theFactorizationScaleFreeze); } if ( eScale == showerScale ) { emissionAlpha = SM().alphaS(showerscale); emissionScale = showerFactorizationScale(); } else if ( eScale == realScale ) { emissionAlpha = dipole()->realEmissionME()->lastXComb().lastAlphaS(); emissionScale = dipole()->realEmissionME()->lastScale(); } else if ( eScale == bornScale ) { emissionAlpha = dipole()->underlyingBornME()->lastXComb().lastAlphaS(); emissionScale = dipole()->underlyingBornME()->lastScale(); } double emissionPDF = realPDFWeight(emissionScale); double couplingFactor = 1.; if ( bScale != rScale ) { double bornAlpha = 1.; if ( bScale == showerScale ) { bornAlpha = SM().alphaS(showerscale); } else if ( bScale == realScale ) { bornAlpha = dipole()->realEmissionME()->lastXComb().lastAlphaS(); } else if ( bScale == bornScale ) { bornAlpha = dipole()->underlyingBornME()->lastXComb().lastAlphaS(); } double realAlpha = 1.; if ( rScale == showerScale ) { realAlpha = SM().alphaS(showerscale); } else if ( rScale == realScale ) { realAlpha = dipole()->realEmissionME()->lastXComb().lastAlphaS(); } else if ( rScale == bornScale ) { realAlpha = dipole()->underlyingBornME()->lastXComb().lastAlphaS(); } couplingFactor *= pow(realAlpha/bornAlpha,(double)(dipole()->underlyingBornME()->orderInAlphaS())); } Energy2 hardScale = ZERO; if ( bScale == showerScale ) { hardScale = showerFactorizationScale(); } else if ( bScale == realScale ) { hardScale = dipole()->realEmissionME()->lastScale(); } else if ( bScale == bornScale ) { hardScale = dipole()->underlyingBornME()->lastScale(); } double bornPDF = bornPDFWeight(hardScale); if ( abs(bornPDF) < 1e-8 ) bornPDF = 0.0; if ( abs(emissionPDF) < 1e-8 ) emissionPDF = 0.0; if ( emissionPDF == 0.0 || bornPDF == 0.0 ) return 0.0; double pdfRatio = emissionPDF/bornPDF; pdfRatio = min(abs(pdfRatio),100000.); return emissionAlpha * pdfRatio * couplingFactor; } double ShowerApproximation::channelWeight(int emitter, int emission, int spectator, int) const { double cfac = 1.; double Nc = generator()->standardModel()->Nc(); if (realCXComb()->mePartonData()[emitter]->iColour() == PDT::Colour8){ if (realCXComb()->mePartonData()[emission]->iColour() == PDT::Colour8) cfac = Nc; else if ( realCXComb()->mePartonData()[emission]->iColour() == PDT::Colour3 || realCXComb()->mePartonData()[emission]->iColour() == PDT::Colour3bar) cfac = 0.5; else assert(false); } else if ((realCXComb()->mePartonData()[emitter] ->iColour() == PDT::Colour3 || realCXComb()->mePartonData()[emitter] ->iColour() == PDT::Colour3bar)) cfac = (sqr(Nc)-1.)/(2.*Nc); else assert(false); // do the most simple thing for the time being; needs fixing later if ( realCXComb()->mePartonData()[emission]->id() == ParticleID::g ) { Energy2 pipk = realCXComb()->meMomenta()[emitter] * realCXComb()->meMomenta()[spectator]; Energy2 pipj = realCXComb()->meMomenta()[emitter] * realCXComb()->meMomenta()[emission]; Energy2 pjpk = realCXComb()->meMomenta()[emission] * realCXComb()->meMomenta()[spectator]; return cfac *GeV2 * pipk / ( pipj * ( pipj + pjpk ) ); } return cfac * GeV2 / (realCXComb()->meMomenta()[emitter] * realCXComb()->meMomenta()[emission]); } double ShowerApproximation::channelWeight() const { double currentChannel = channelWeight(dipole()->realEmitter(), dipole()->realEmission(), dipole()->realSpectator(), dipole()->bornEmitter()); if ( currentChannel == 0. ) return 0.; double sum = 0.; for ( vector::tptr>::const_iterator dip = dipole()->partnerDipoles().begin(); dip != dipole()->partnerDipoles().end(); ++dip ) sum += channelWeight((**dip).realEmitter(), (**dip).realEmission(), (**dip).realSpectator(), (**dip).bornEmitter()); assert(sum > 0.0); return currentChannel / sum; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ShowerApproximation::doinit() { if ( profileScales() ) { if ( profileScales()->unrestrictedPhasespace() && restrictPhasespace() ) { generator()->log() << "ShowerApproximation warning: The scale profile chosen requires an unrestricted phase space,\n" << "however, the phase space was set to be restricted. Will switch to unrestricted phase space.\n" << flush; restrictPhasespace(false); } } HandlerBase::doinit(); } void ShowerApproximation::persistentOutput(PersistentOStream & os) const { os << theLargeNBasis << theBornXComb << theRealXComb << theTildeXCombs << theDipole << theBelowCutoff << ounit(theFFPtCut,GeV) << ounit(theFFScreeningScale,GeV) << ounit(theFIPtCut,GeV) << ounit(theFIScreeningScale,GeV) << ounit(theIIPtCut,GeV) << ounit(theIIScreeningScale,GeV) << ounit(theSafeCut,GeV) << theRestrictPhasespace << theHardScaleFactor << theRenormalizationScaleFactor << theFactorizationScaleFactor << theExtrapolationX << theRealEmissionScaleInSubtraction << theBornScaleInSubtraction << theEmissionScaleInSubtraction << theRealEmissionScaleInSplitting << theBornScaleInSplitting << theEmissionScaleInSplitting << ounit(theRenormalizationScaleFreeze,GeV) << ounit(theFactorizationScaleFreeze,GeV) << maxPtIsMuF << theHardScaleProfile << theOpenZ; } void ShowerApproximation::persistentInput(PersistentIStream & is, int) { is >> theLargeNBasis >> theBornXComb >> theRealXComb >> theTildeXCombs >> theDipole >> theBelowCutoff >> iunit(theFFPtCut,GeV) >> iunit(theFFScreeningScale,GeV) >> iunit(theFIPtCut,GeV) >> iunit(theFIScreeningScale,GeV) >> iunit(theIIPtCut,GeV) >> iunit(theIIScreeningScale,GeV) >> iunit(theSafeCut,GeV) >> theRestrictPhasespace >> theHardScaleFactor >> theRenormalizationScaleFactor >> theFactorizationScaleFactor >> theExtrapolationX >> theRealEmissionScaleInSubtraction >> theBornScaleInSubtraction >> theEmissionScaleInSubtraction >> theRealEmissionScaleInSplitting >> theBornScaleInSplitting >> theEmissionScaleInSplitting >> iunit(theRenormalizationScaleFreeze,GeV) >> iunit(theFactorizationScaleFreeze,GeV) >> maxPtIsMuF >> theHardScaleProfile >> theOpenZ; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeHerwigShowerApproximation("Herwig::ShowerApproximation", "Herwig.so"); void ShowerApproximation::Init() { static ClassDocumentation documentation ("ShowerApproximation describes the shower emission to be used " "in NLO matching."); static Parameter interfaceFFPtCut ("FFPtCut", "Set the pt infrared cutoff", &ShowerApproximation::theFFPtCut, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFIPtCut ("FIPtCut", "Set the pt infrared cutoff", &ShowerApproximation::theFIPtCut, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceIIPtCut ("IIPtCut", "Set the pt infrared cutoff", &ShowerApproximation::theIIPtCut, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceSafeCut ("SafeCut", "Set the enhanced infrared cutoff for the Matching.", &ShowerApproximation::theSafeCut, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFFScreeningScale ("FFScreeningScale", "Set the screening scale", &ShowerApproximation::theFFScreeningScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFIScreeningScale ("FIScreeningScale", "Set the screening scale", &ShowerApproximation::theFIScreeningScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceIIScreeningScale ("IIScreeningScale", "Set the screening scale", &ShowerApproximation::theIIScreeningScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Switch interfaceRestrictPhasespace ("RestrictPhasespace", "Switch on or off phasespace restrictions", &ShowerApproximation::theRestrictPhasespace, true, false, false); static SwitchOption interfaceRestrictPhasespaceYes (interfaceRestrictPhasespace, "Yes", "Perform phasespace restrictions", true); static SwitchOption interfaceRestrictPhasespaceNo (interfaceRestrictPhasespace, "No", "Do not perform phasespace restrictions", false); static Parameter interfaceHardScaleFactor ("HardScaleFactor", "The hard scale factor.", &ShowerApproximation::theHardScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceRenormalizationScaleFactor ("RenormalizationScaleFactor", "The hard scale factor.", &ShowerApproximation::theRenormalizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceFactorizationScaleFactor ("FactorizationScaleFactor", "The hard scale factor.", &ShowerApproximation::theFactorizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceExtrapolationX ("ExtrapolationX", "The x from which on extrapolation should be performed.", &ShowerApproximation::theExtrapolationX, 1.0, 0.0, 1.0, false, false, Interface::limited); static Switch interfaceRealEmissionScaleInSubtraction ("RealEmissionScaleInSubtraction", "Set the scale choice for the real emission cross section in the matching subtraction.", &ShowerApproximation::theRealEmissionScaleInSubtraction, showerScale, false, false); static SwitchOption interfaceRealEmissionScaleInSubtractionRealScale (interfaceRealEmissionScaleInSubtraction, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceRealEmissionScaleInSubtractionBornScale (interfaceRealEmissionScaleInSubtraction, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceRealEmissionScaleInSubtractionShowerScale (interfaceRealEmissionScaleInSubtraction, "ShowerScale", "Use the shower scale", showerScale); interfaceRealEmissionScaleInSubtraction.rank(-1); static Switch interfaceBornScaleInSubtraction ("BornScaleInSubtraction", "Set the scale choice for the Born cross section in the matching subtraction.", &ShowerApproximation::theBornScaleInSubtraction, showerScale, false, false); static SwitchOption interfaceBornScaleInSubtractionRealScale (interfaceBornScaleInSubtraction, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceBornScaleInSubtractionBornScale (interfaceBornScaleInSubtraction, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceBornScaleInSubtractionShowerScale (interfaceBornScaleInSubtraction, "ShowerScale", "Use the shower scale", showerScale); interfaceBornScaleInSubtraction.rank(-1); static Switch interfaceEmissionScaleInSubtraction ("EmissionScaleInSubtraction", "Set the scale choice for the emission in the matching subtraction.", &ShowerApproximation::theEmissionScaleInSubtraction, showerScale, false, false); static SwitchOption interfaceEmissionScaleInSubtractionRealScale (interfaceEmissionScaleInSubtraction, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceEmissionScaleInSubtractionEmissionScale (interfaceEmissionScaleInSubtraction, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceEmissionScaleInSubtractionShowerScale (interfaceEmissionScaleInSubtraction, "ShowerScale", "Use the shower scale", showerScale); interfaceEmissionScaleInSubtraction.rank(-1); static Switch interfaceRealEmissionScaleInSplitting ("RealEmissionScaleInSplitting", "Set the scale choice for the real emission cross section in the splitting.", &ShowerApproximation::theRealEmissionScaleInSplitting, showerScale, false, false); static SwitchOption interfaceRealEmissionScaleInSplittingRealScale (interfaceRealEmissionScaleInSplitting, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceRealEmissionScaleInSplittingBornScale (interfaceRealEmissionScaleInSplitting, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceRealEmissionScaleInSplittingShowerScale (interfaceRealEmissionScaleInSplitting, "ShowerScale", "Use the shower scale", showerScale); interfaceRealEmissionScaleInSplitting.rank(-1); static Switch interfaceBornScaleInSplitting ("BornScaleInSplitting", "Set the scale choice for the Born cross section in the splitting.", &ShowerApproximation::theBornScaleInSplitting, showerScale, false, false); static SwitchOption interfaceBornScaleInSplittingRealScale (interfaceBornScaleInSplitting, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceBornScaleInSplittingBornScale (interfaceBornScaleInSplitting, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceBornScaleInSplittingShowerScale (interfaceBornScaleInSplitting, "ShowerScale", "Use the shower scale", showerScale); interfaceBornScaleInSplitting.rank(-1); static Switch interfaceEmissionScaleInSplitting ("EmissionScaleInSplitting", "Set the scale choice for the emission in the splitting.", &ShowerApproximation::theEmissionScaleInSplitting, showerScale, false, false); static SwitchOption interfaceEmissionScaleInSplittingRealScale (interfaceEmissionScaleInSplitting, "RealScale", "Use the real emission scale.", realScale); static SwitchOption interfaceEmissionScaleInSplittingEmissionScale (interfaceEmissionScaleInSplitting, "BornScale", "Use the Born scale.", bornScale); static SwitchOption interfaceEmissionScaleInSplittingShowerScale (interfaceEmissionScaleInSplitting, "ShowerScale", "Use the shower scale", showerScale); interfaceEmissionScaleInSplitting.rank(-1); static Parameter interfaceRenormalizationScaleFreeze ("RenormalizationScaleFreeze", "The freezing scale for the renormalization scale.", &ShowerApproximation::theRenormalizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); interfaceRenormalizationScaleFreeze.rank(-1); static Parameter interfaceFactorizationScaleFreeze ("FactorizationScaleFreeze", "The freezing scale for the factorization scale.", &ShowerApproximation::theFactorizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); interfaceFactorizationScaleFreeze.rank(-1); static Reference interfaceHardScaleProfile ("HardScaleProfile", "The hard scale profile to use.", &ShowerApproximation::theHardScaleProfile, false, false, true, true, false); static Reference interfaceLargeNBasis ("LargeNBasis", "Set the large-N colour basis implementation.", &ShowerApproximation::theLargeNBasis, false, false, true, true, false); interfaceLargeNBasis.rank(-1); static Switch interfaceMaxPtIsMuF ("MaxPtIsMuF", "", &ShowerApproximation::maxPtIsMuF, false, false, false); static SwitchOption interfaceMaxPtIsMuFYes (interfaceMaxPtIsMuF, "Yes", "", true); static SwitchOption interfaceMaxPtIsMuFNo (interfaceMaxPtIsMuF, "No", "", false); } diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximation.h b/MatrixElement/Matchbox/Matching/ShowerApproximation.h --- a/MatrixElement/Matchbox/Matching/ShowerApproximation.h +++ b/MatrixElement/Matchbox/Matching/ShowerApproximation.h @@ -1,691 +1,683 @@ // -*- C++ -*- // // ShowerApproximation.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_ShowerApproximation_H #define Herwig_ShowerApproximation_H // // This is the declaration of the ShowerApproximation class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh" #include "Herwig/MatrixElement/Matchbox/Utility/ColourBasis.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.fh" #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.fh" #include "HardScaleProfile.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief ShowerApproximation describes the shower emission to be used * in NLO matching. * */ class ShowerApproximation: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ ShowerApproximation(); - /** - * The destructor. - */ - virtual ~ShowerApproximation(); - //@} - public: /** * Return true, if this shower approximation will require a * splitting generator */ virtual bool needsSplittingGenerator() const { return false; } /** * Return true, if this shower approximation will require * H events */ virtual bool hasHEvents() const { return true; } /** * Return true, if this shower approximation will require tilde * XCombs for the real phase space point generated */ virtual bool needsTildeXCombs() const { return false; } /** * Return true, if this shower approximation will require * a truncated parton shower */ virtual bool needsTruncatedShower() const { return false; } /** * Return the tilde kinematics object returning the shower * kinematics parametrization if different from the nominal dipole * mappings. */ virtual Ptr::tptr showerTildeKinematics() const; /** * Return the tilde kinematics object returning the shower * kinematics parametrization if different from the nominal dipole * mappings. */ virtual Ptr::tptr showerInvertedTildeKinematics() const; public: /** * Set the XComb object describing the Born process */ void setBornXComb(tStdXCombPtr xc) { theBornXComb = xc; } /** * Return the XComb object describing the Born process */ tStdXCombPtr bornXComb() const { return theBornXComb; } /** * Return the XComb object describing the Born process */ tcStdXCombPtr bornCXComb() const { return theBornXComb; } /** * Set the XComb object describing the real emission process */ void setRealXComb(tStdXCombPtr xc) { theRealXComb = xc; } /** * Return the XComb object describing the real emission process */ tStdXCombPtr realXComb() const { return theRealXComb; } /** * Return the XComb object describing the real emission process */ tcStdXCombPtr realCXComb() const { return theRealXComb; } /** * Set the tilde xcomb objects associated to the real xcomb */ void setTildeXCombs(const vector& xc) { theTildeXCombs = xc; } /** * Return the tilde xcomb objects associated to the real xcomb */ const vector& tildeXCombs() const { return theTildeXCombs; } /** * Set the dipole in charge for the emission */ void setDipole(Ptr::tptr); /** * Return the dipole in charge for the emission */ Ptr::tptr dipole() const; /** * Return true, if this matching is capable of spin correlations. */ virtual bool hasSpinCorrelations() const { return false; } public: /** * Return true if one of the recently encountered configutations was * below the infrared cutoff. */ bool belowCutoff() const { return theBelowCutoff; } /** * Indicate that one of the recently encountered configutations was * below the infrared cutoff. */ void wasBelowCutoff() { theBelowCutoff = true; } /** * Reset the below cutoff flag. */ void resetBelowCutoff() { theBelowCutoff = false; } /** * Return the pt cut to be applied for final-final dipoles. */ Energy ffPtCut() const { return theFFPtCut; } /** * Return the pt cut to be applied for final-initial dipoles. */ Energy fiPtCut() const { return theFIPtCut; } /** * Return the pt cut to be applied for initial-initial dipoles. */ Energy iiPtCut() const { return theIIPtCut; } /** * Return the pt cut to be applied for initial-initial dipoles. */ Energy safeCut() const { return theSafeCut;} /** * Return the screening scale to be applied for final-final dipoles. */ Energy ffScreeningScale() const { return theFFScreeningScale; } /** * Return the screening scale to be applied for final-initial dipoles. */ Energy fiScreeningScale() const { return theFIScreeningScale; } /** * Return the screening scale to be applied for initial-initial dipoles. */ Energy iiScreeningScale() const { return theIIScreeningScale; } /** * Return the shower renormalization scale */ virtual Energy2 showerEmissionScale() const; /** * Return the shower renormalization scale */ Energy2 showerRenormalizationScale() const { return sqr(renormalizationScaleFactor())*showerEmissionScale(); } /** * Return the shower factorization scale */ Energy2 showerFactorizationScale() const { return sqr(factorizationScaleFactor())*showerEmissionScale(); } /** * Return the Born renormalization scale */ Energy2 bornRenormalizationScale() const; /** * Return the Born factorization scale */ Energy2 bornFactorizationScale() const; /** * Return the real emission renormalization scale */ Energy2 realRenormalizationScale() const; /** * Return the real emission factorization scale */ Energy2 realFactorizationScale() const; /** * Enumerate possible scale choices */ enum ScaleChoices { bornScale = 0, /** Use the born scales */ realScale = 1, /** Use the real scales */ showerScale = 2 /** Use the shower scales */ }; /** * Return the scale choice in the real emission cross section to be * used in the matching subtraction. */ int realEmissionScaleInSubtraction() const { return theRealEmissionScaleInSubtraction; } /** * Return the scale choice in the born cross section to be * used in the matching subtraction. */ int bornScaleInSubtraction() const { return theBornScaleInSubtraction; } /** * Return the scale choice in the emission contribution to be * used in the matching subtraction. */ int emissionScaleInSubtraction() const { return theEmissionScaleInSubtraction; } /** * Return the scale choice in the real emission cross section to be * used in the splitting. */ int realEmissionScaleInSplitting() const { return theRealEmissionScaleInSplitting; } /** * Return the scale choice in the born cross section to be * used in the splitting. */ int bornScaleInSplitting() const { return theBornScaleInSplitting; } /** * Return the scale choice in the emission contribution to be * used in the splitting. */ int emissionScaleInSplitting() const { return theEmissionScaleInSplitting; } /** * Return the scale weight */ double scaleWeight(int rScale, int bScale, int eScale) const; /** * Return the scale weight for the matching subtraction */ double subtractionScaleWeight() const { return scaleWeight(realEmissionScaleInSubtraction(), bornScaleInSubtraction(), emissionScaleInSubtraction()); } /** * Return the scale weight for the splitting */ double splittingScaleWeight() const { return scaleWeight(realEmissionScaleInSplitting(), bornScaleInSplitting(), emissionScaleInSplitting()); } public: /** * Return true, if the phase space restrictions of the dipole shower should * be applied. */ bool restrictPhasespace() const { return theRestrictPhasespace; } /** * Indicate that the phase space restrictions of the dipole shower should * be applied. */ void restrictPhasespace(bool yes) { theRestrictPhasespace = yes; } /** * Return profile scales */ Ptr::tptr profileScales() const { return theHardScaleProfile; } /** * Set profile scales */ void profileScales(Ptr::ptr prof) { theHardScaleProfile = prof; } /** * Return true if maximum pt should be deduced from the factorization scale */ bool hardScaleIsMuF() const { return maxPtIsMuF; } /** * Indicate that maximum pt should be deduced from the factorization scale */ void hardScaleIsMuF(bool yes) { maxPtIsMuF = yes; } /** * Return the scale factor for the hard scale */ double hardScaleFactor() const { return theHardScaleFactor; } /** * Set the scale factor for the hard scale */ void hardScaleFactor(double f) { theHardScaleFactor = f; } /** * Get the factorization scale factor */ double factorizationScaleFactor() const { return theFactorizationScaleFactor; } /** * Get the renormalization scale factor */ double renormalizationScaleFactor() const { return theRenormalizationScaleFactor; } /** * Set the factorization scale factor */ void factorizationScaleFactor(double f) { theFactorizationScaleFactor = f; } /** * Set the renormalization scale factor */ void renormalizationScaleFactor(double f) { theRenormalizationScaleFactor = f; } /** * Determine if the configuration is below or above the cutoff. */ virtual void checkCutoff(); /** * Determine all kinematic variables which are not provided by the * dipole kinematics; store all shower variables in the respective * dipole object for later use. */ virtual void getShowerVariables(); /** * Return the shower approximation to the real emission cross * section for the given pair of Born and real emission * configurations. */ virtual CrossSection dSigHatDR() const = 0; /** * Return the shower approximation splitting kernel for the given * pair of Born and real emission configurations in units of the * Born center of mass energy squared, and including a weight to * project onto the splitting given by the dipole used. */ virtual double me2() const = 0; /** * Return the Born PDF weight */ double bornPDFWeight(Energy2 muF) const; /** * Return the real emission PDF weight */ double realPDFWeight(Energy2 muF) const; protected: /** * Return true, if the shower was able to generate an emission * leading from the given Born to the given real emission process. */ virtual bool isInShowerPhasespace() const; /** * Return true, if the shower emission leading from the given Born * to the given real emission process would have been generated * above the shower's infrared cutoff. */ virtual bool isAboveCutoff() const; /** * Return the relevant hard scale */ virtual Energy hardScale() const; /** * Use the maximum available phase space for the momentum fraction */ void useOpenZ(bool yes) { theOpenZ = yes; } /** * Return true if the maximum available phase space should be used * for the momentum fraction */ bool openZ() const { return theOpenZ; } public: /** * Generate a weight for the given dipole channel */ virtual double channelWeight(int emitter, int emission, int spectator, int bemitter) const; /** * Generate a normalized weight taking into account all channels */ virtual double channelWeight() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name 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(); //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). public: /** * A large-N colour basis to be used when reproducing the shower * kernels. */ Ptr::tptr largeNBasis() const { return theLargeNBasis; } protected: /** * A large-N colour basis to be used when reproducing the shower * kernels. */ Ptr::ptr theLargeNBasis; /** * Set the large-N basis */ void setLargeNBasis(); /** * The x value from which on we extrapolate PDFs for numerically stable ratios. */ double theExtrapolationX; private: /** * The XComb object describing the Born process */ tStdXCombPtr theBornXComb; /** * The XComb object describing the real emission process */ tStdXCombPtr theRealXComb; /** * The tilde xcomb objects associated to the real xcomb */ vector theTildeXCombs; /** * The dipole in charge for the emission */ Ptr::tptr theDipole; /** * True if one of the recently encountered configutations was below * the infrared cutoff. */ bool theBelowCutoff; /** * The pt cut to be applied for final-final dipoles. */ Energy theFFPtCut; /** * An optional screening scale for final-final dipoles; see * DipoleSplittingKernel */ Energy theFFScreeningScale; /** * The pt cut to be applied for final-initial dipoles. */ Energy theFIPtCut; /** * An optional screening scale for final-initial dipoles; see * DipoleSplittingKernel */ Energy theFIScreeningScale; /** * The pt cut to be applied for initial-initial dipoles. */ Energy theIIPtCut; /** * An optional screening scale for initial-initial dipoles; see * DipoleSplittingKernel */ Energy theIIScreeningScale; /** * The cut to be applied as an enhanced shower cutoff. */ Energy theSafeCut; /** * True, if the phase space restrictions of the dipole shower should * be applied. */ bool theRestrictPhasespace; /** * The scale factor for the hard scale */ double theHardScaleFactor; /** * The scale factor for the renormalization scale */ double theRenormalizationScaleFactor; /** * The scale factor for the factorization scale */ double theFactorizationScaleFactor; /** * The scale choice in the real emission cross section to be * used in the matching subtraction. */ int theRealEmissionScaleInSubtraction; /** * The scale choice in the born cross section to be * used in the matching subtraction. */ int theBornScaleInSubtraction; /** * The scale choice in the emission contribution to be * used in the matching subtraction. */ int theEmissionScaleInSubtraction; /** * The scale choice in the real emission cross section to be * used in the splitting. */ int theRealEmissionScaleInSplitting; /** * The scale choice in the born cross section to be * used in the splitting. */ int theBornScaleInSplitting; /** * The scale choice in the emission contribution to be * used in the splitting. */ int theEmissionScaleInSplitting; /** * A freezing value for the renormalization scale */ Energy theRenormalizationScaleFreeze; /** * A freezing value for the factorization scale */ Energy theFactorizationScaleFreeze; /** * True if maximum pt should be deduced from the factorization scale */ bool maxPtIsMuF; /** * The profile scales */ Ptr::ptr theHardScaleProfile; /** * Use the maximum available phase space for the momentum fraction */ bool theOpenZ; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerApproximation & operator=(const ShowerApproximation &) = delete; }; } #endif /* Herwig_ShowerApproximation_H */ diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.cc b/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.cc --- a/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.cc +++ b/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.cc @@ -1,527 +1,525 @@ // -*- C++ -*- // // ShowerApproximationGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerApproximationGenerator class. // #include #include "ShowerApproximationGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; ShowerApproximationGenerator::ShowerApproximationGenerator() : thePresamplingPoints(2000), theMaxTry(100000), theFreezeGrid(500000), theDoCompensate(false) {} -ShowerApproximationGenerator::~ShowerApproximationGenerator() {} - double ShowerApproximationGenerator::generateFraction(tcPDPtr pd, double r, double xmin) const { if ( pd->coloured() || pd->id() == ParticleID::gamma ) { return pow(xmin,r); } double x0 = 1.e-5; return 1. + x0 - x0*pow((1.+x0)/x0,r); } double ShowerApproximationGenerator::invertFraction(tcPDPtr pd, double x, double xmin) const { if ( pd->coloured() || pd->id() == ParticleID::gamma ) { return log(x)/log(xmin); } double x0 = 1.e-5; return log((1.-x+x0)/x0)/log((1.+x0)/x0); } bool ShowerApproximationGenerator::prepare(bool didproject) { tSubProPtr oldSub = lastIncomingXComb->subProcess(); tcStdXCombPtr cIncomingXC = lastIncomingXComb; bool hasFractions = thePhasespace->haveX1X2() || cIncomingXC->mePartonData().size() == 3; theLastMomenta.resize(cIncomingXC->mePartonData().size()); if ( !hasFractions ) theLastRandomNumbers.resize(thePhasespace->nDim(cIncomingXC->mePartonData()) + 2); else theLastRandomNumbers.resize(thePhasespace->nDim(cIncomingXC->mePartonData())); if ( !hasFractions ) { double x1 = oldSub->incoming().first->momentum().plus() / lastIncomingXComb->lastParticles().first->momentum().plus(); theLastRandomNumbers[0] = invertFraction(oldSub->incoming().first->dataPtr(),x1, lastIncomingXComb->cuts()->x1Min()); double x2 = oldSub->incoming().second->momentum().minus() / lastIncomingXComb->lastParticles().second->momentum().minus(); theLastRandomNumbers[1] = invertFraction(oldSub->incoming().second->dataPtr(),x2, lastIncomingXComb->cuts()->x2Min()); } theLastMomenta = cIncomingXC->meMomenta(); theLastPartons.first = oldSub->incoming().first->data().produceParticle(oldSub->incoming().first->momentum()); theLastPartons.second = oldSub->incoming().second->data().produceParticle(oldSub->incoming().second->momentum()); thePhasespace->setXComb(lastIncomingXComb); // this is a brute force fix for private ticket #241 ; only done to get fixed // for the release but will need to be looked at in more detail later on by // cleaning up the XCombs for these cases if ( theLastMomenta.size() == 3 && didproject ) { // boost them where they belong so invertKinematics is doing something sensible Boost toLab = (lastIncomingXComb->lastPartons().first->momentum() + lastIncomingXComb->lastPartons().second->momentum()).boostVector(); for ( int i = 0; i < 3; ++i ) theLastMomenta[i].boost(toLab); } thePhasespace->invertKinematics(theLastMomenta, !hasFractions ? &theLastRandomNumbers[2] : &theLastRandomNumbers[0]); theLastBornXComb->clean(); theLastBornXComb->fill(lastIncomingXComb->lastParticles(),theLastPartons, theLastMomenta,theLastRandomNumbers); if ( !theLastBornXComb->cuts()->initSubProcess(theLastBornXComb->lastSHat(), theLastBornXComb->lastY(), theLastBornXComb->mirror()) ) return false; theLastBornME->setXComb(theLastBornXComb); if ( !theLastBornME->generateKinematics(!hasFractions ? &theLastRandomNumbers[2] : &theLastRandomNumbers[0]) ) return false; CrossSection bornXS = theLastBornME->dSigHatDR(); if ( bornXS == ZERO ) return false; return true; } bool ShowerApproximationGenerator::generate(const vector& r) { theLastBornXComb->clean(); bool hasFractions = thePhasespace->haveX1X2() || theLastBornXComb->mePartonData().size() == 3; if ( !hasFractions ) { double x = generateFraction(theLastPartons.first->dataPtr(),r[0], lastIncomingXComb->cuts()->x1Min()); Energy Q = lastIncomingXComb->lastParticles().first->momentum().plus(); Energy mass = theLastPartons.first->dataPtr()->mass(); double xi = (sqr(x*Q) - sqr(mass))/(sqr(Q)*x); Lorentz5Momentum p1(ZERO,ZERO,xi*Q/2.); p1.setMass(mass); p1.rescaleEnergy(); theLastPartons.first->set5Momentum(p1); x = generateFraction(theLastPartons.second->dataPtr(),r[1], lastIncomingXComb->cuts()->x2Min()); Q = lastIncomingXComb->lastParticles().second->momentum().minus(); mass = theLastPartons.second->dataPtr()->mass(); xi = (sqr(x*Q) - sqr(mass))/(sqr(Q)*x); Lorentz5Momentum p2(ZERO,ZERO,-xi*Q/2.); p2.setMass(mass); p2.rescaleEnergy(); theLastPartons.second->set5Momentum(p2); } else { theLastBornME->setXComb(theLastBornXComb); theLastBornXComb->lastParticles(lastIncomingXComb->lastParticles()); theLastBornXComb->lastP1P2(make_pair(0.0, 0.0)); theLastBornXComb->lastS(lastIncomingXComb->lastS()); if ( !theLastBornME->generateKinematics(&r[0]) ) return false; theLastPartons.first->set5Momentum(theLastBornME->lastMEMomenta()[0]); theLastPartons.second->set5Momentum(theLastBornME->lastMEMomenta()[1]); } theLastPresamplingMomenta.resize(theLastMomenta.size()); Boost toCMS = (theLastPartons.first->momentum() + theLastPartons.second->momentum()).findBoostToCM(); theLastPresamplingMomenta[0] = theLastPartons.first->momentum(); if ( !hasFractions ) theLastPresamplingMomenta[0].boost(toCMS); theLastPresamplingMomenta[1] = theLastPartons.second->momentum(); if ( !hasFractions ) theLastPresamplingMomenta[1].boost(toCMS); if ( hasFractions ) { for ( size_t k = 2; k < theLastBornME->lastMEMomenta().size(); ++k ) theLastPresamplingMomenta[k] = theLastBornME->lastMEMomenta()[k]; } theLastBornXComb->fill(lastIncomingXComb->lastParticles(),theLastPartons, theLastPresamplingMomenta,r); if ( !theLastBornXComb->cuts()->initSubProcess(theLastBornXComb->lastSHat(), theLastBornXComb->lastY(), theLastBornXComb->mirror()) ) return false; if ( !hasFractions ) { theLastBornME->setXComb(theLastBornXComb); if ( !theLastBornME->generateKinematics(&r[2]) ) return false; } CrossSection bornXS = theLastBornME->dSigHatDR(); if ( bornXS == ZERO ) return false; return true; } void ShowerApproximationGenerator::restore() { theLastBornXComb->clean(); bool hasFractions = thePhasespace->haveX1X2() || theLastBornXComb->mePartonData().size() == 3; if ( !hasFractions ) { tSubProPtr oldSub = lastIncomingXComb->subProcess(); theLastPartons.first->set5Momentum(oldSub->incoming().first->momentum()); theLastPartons.second->set5Momentum(oldSub->incoming().second->momentum()); } else { theLastBornME->setXComb(theLastBornXComb); theLastBornXComb->lastParticles(lastIncomingXComb->lastParticles()); theLastBornXComb->lastP1P2(make_pair(0.0, 0.0)); theLastBornXComb->lastS(lastIncomingXComb->lastS()); theLastBornME->generateKinematics(&theLastRandomNumbers[0]); theLastPartons.first->set5Momentum(theLastBornME->lastMEMomenta()[0]); theLastPartons.second->set5Momentum(theLastBornME->lastMEMomenta()[1]); } theLastBornXComb->fill(lastIncomingXComb->lastParticles(),theLastPartons, theLastMomenta,theLastRandomNumbers); if ( !hasFractions ) { theLastBornME->setXComb(theLastBornXComb); theLastBornME->generateKinematics(&theLastRandomNumbers[2]); } theLastBornME->dSigHatDR(); } void ShowerApproximationGenerator:: handle(EventHandler & eh, const tPVector &, const Hint &) { MatchboxFactory::currentFactory()->setHardTreeEmitter(-1); MatchboxFactory::currentFactory()->setHardTreeSpectator(-1); MatchboxFactory::currentFactory()->setHardTreeSubprocess(SubProPtr()); lastIncomingXComb = dynamic_ptr_cast(eh.lastXCombPtr()); if ( !lastIncomingXComb ) throw Exception() << "ShowerApproximationGenerator::handle(): Expecting a standard event handler." << Exception::runerror; bool didproject = false; if ( lastIncomingXComb->lastProjector() ) { lastIncomingXComb = lastIncomingXComb->lastProjector(); didproject = true; } const StandardXComb& xc = *lastIncomingXComb; map::ptr> >::const_iterator kernelit = theKernelMap.find(xc.mePartonData()); if ( kernelit == theKernelMap.end() ) { list channels = MatchboxFactory::currentFactory()->getSplittingChannels(lastIncomingXComb); set::ptr> newKernels; for ( list::const_iterator c = channels.begin(); c != channels.end(); ++c ) { Ptr::ptr kernel = new_ptr(ShowerApproximationKernel()); kernel->setBornXComb(c->bornXComb); kernel->setRealXComb(c->realXComb); kernel->setTildeXCombs(c->tildeXCombs); kernel->setDipole(c->dipole); kernel->showerApproximation(theShowerApproximation); kernel->presamplingPoints(thePresamplingPoints); kernel->maxtry(theMaxTry); kernel->freezeGrid(theFreezeGrid); kernel->showerApproximationGenerator(this); kernel->doCompensate(theDoCompensate); if ( kernel->dipole()->bornEmitter() > 1 && kernel->dipole()->bornSpectator() > 1 ) { kernel->ptCut(ffPtCut()); } else if ( ( kernel->dipole()->bornEmitter() > 1 && kernel->dipole()->bornSpectator() < 2 ) || ( kernel->dipole()->bornEmitter() < 2 && kernel->dipole()->bornSpectator() > 1 ) ) { kernel->ptCut(fiPtCut()); } else { assert(kernel->dipole()->bornEmitter() < 2 && kernel->dipole()->bornSpectator() < 2); kernel->ptCut(iiPtCut()); } newKernels.insert(kernel); } theKernelMap[xc.mePartonData()] = newKernels; kernelit = theKernelMap.find(xc.mePartonData()); } if ( kernelit->second.empty() ) return; const set::ptr>& kernels = kernelit->second; theLastBornME = (**kernels.begin()).dipole()->underlyingBornME(); if ( theLastBornME->phasespace()->wantCMS() != thePhasespace->wantCMS() ) { throw Exception() << "Mismatch in centre-of-mass-system requirements of hard matrix element phasespace (" << (theLastBornME->phasespace()->wantCMS()?"Yes":"No") << ") and shower approximation phasespace (" << (thePhasespace->wantCMS()?"Yes":"No") << ")" << Exception::abortnow; } theLastBornME->phasespace(thePhasespace); theLastBornXComb = (**kernels.begin()).bornXComb(); if ( !prepare(didproject) ) return; Energy winnerPt = ZERO; Ptr::ptr winnerKernel; try { for ( set::ptr>::const_iterator k = kernels.begin(); k != kernels.end(); ++k ) { if ( (**k).generate() != 0. && (*k)->dipole()->lastPt() > winnerPt){ winnerKernel = *k; winnerPt = winnerKernel->dipole()->lastPt(); } } } catch(ShowerApproximationKernel::MaxTryException&) { throw Exception() << "Too many tries needed to generate the matrix element correction in '" << name() << "'" << Exception::eventerror; } if ( !winnerKernel || winnerPt == ZERO ) return; //Hardest emission should be this one. winnerKernel->realXComb()->lastShowerScale(sqr(winnerPt)); winnerKernel->bornXComb()->lastShowerScale(sqr(winnerPt)); lastIncomingXComb->lastShowerScale(sqr(winnerPt)); SubProPtr oldSub = lastIncomingXComb->subProcess(); SubProPtr newSub; try { tcDiagPtr bornDiag = lastIncomingXComb->lastDiagram(); tcDiagPtr realDiag = winnerKernel->dipole()->realEmissionDiagram(bornDiag); winnerKernel->realXComb()->externalDiagram(realDiag); newSub = winnerKernel->realXComb()->construct(); } catch(Veto&) { return; } if ( !theShowerApproximation->needsTruncatedShower() ){ tParticleSet firstS = oldSub->incoming().first->siblings(); assert(firstS.empty() || firstS.size() == 1); if ( !firstS.empty() ) { eh.currentStep()->removeParticle(*firstS.begin()); } tParticleSet secondS = oldSub->incoming().second->siblings(); assert(secondS.empty() || secondS.size() == 1); if ( !secondS.empty() ) { eh.currentStep()->removeParticle(*secondS.begin()); } // prevent the colliding particles from disappearing // in the initial state and appearing // in the final state when we've cut off all their // (physical) children; only applies to the case // where we have a parton extractor not build from // noPDF, so check wether the incoming particle // doesnt equal the incoming parton -- this needs fixing in ThePEG PPtr dummy = new_ptr(Particle(getParticleData(ParticleID::gamma))); bool usedDummy = false; if ( eh.currentStep()->incoming().first != oldSub->incoming().first ) { eh.currentStep()->addDecayProduct(eh.currentStep()->incoming().first,dummy); usedDummy = true; } if ( eh.currentStep()->incoming().second != oldSub->incoming().second ) { eh.currentStep()->addDecayProduct(eh.currentStep()->incoming().second,dummy); usedDummy = true; } eh.currentStep()->removeSubProcess(oldSub); eh.currentStep()->addSubProcess(newSub); // get rid of the dummy if ( usedDummy ) { eh.currentStep()->removeParticle(dummy); } eh.select(winnerKernel->realXComb()); winnerKernel->realXComb()->recreatePartonBinInstances(winnerKernel->realXComb()->lastScale()); winnerKernel->realXComb()->refillPartonBinInstances(&(xc.lastRandomNumbers()[0])); winnerKernel->realXComb()->pExtractor()->constructRemnants(winnerKernel->realXComb()->partonBinInstances(), newSub, eh.currentStep()); } else{ MatchboxFactory::currentFactory()->setHardTreeSubprocess(newSub); MatchboxFactory::currentFactory()->setHardTreeEmitter(winnerKernel->dipole()->bornEmitter()); MatchboxFactory::currentFactory()->setHardTreeSpectator(winnerKernel->dipole()->bornSpectator()); } } IBPtr ShowerApproximationGenerator::clone() const { return new_ptr(*this); } IBPtr ShowerApproximationGenerator::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ShowerApproximationGenerator::persistentOutput(PersistentOStream & os) const { os << theShowerApproximation << thePhasespace << theKernelMap << thePresamplingPoints << theMaxTry << theFreezeGrid << lastIncomingXComb << theLastBornME << ounit(theLastMomenta,GeV) << ounit(theLastPresamplingMomenta,GeV) << theLastRandomNumbers << theLastBornXComb << theLastPartons << theDoCompensate; } void ShowerApproximationGenerator::persistentInput(PersistentIStream & is, int) { is >> theShowerApproximation >> thePhasespace >> theKernelMap >> thePresamplingPoints >> theMaxTry >> theFreezeGrid >> lastIncomingXComb >> theLastBornME >> iunit(theLastMomenta,GeV) >> iunit(theLastPresamplingMomenta,GeV) >> theLastRandomNumbers >> theLastBornXComb >> theLastPartons >> theDoCompensate; } // *** 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 describeHerwigShowerApproximationGenerator("Herwig::ShowerApproximationGenerator", "Herwig.so"); void ShowerApproximationGenerator::Init() { static ClassDocumentation documentation ("ShowerApproximationGenerator generates emissions according to a " "shower approximation entering a NLO matching."); static Reference interfaceShowerApproximation ("ShowerApproximation", "Set the shower approximation to sample.", &ShowerApproximationGenerator::theShowerApproximation, false, false, true, false, false); interfaceShowerApproximation.rank(-1); static Reference interfacePhasespace ("Phasespace", "The phase space generator to use.", &ShowerApproximationGenerator::thePhasespace, false, false, true, false, false); interfacePhasespace.rank(-1); static Parameter interfacePresamplingPoints ("PresamplingPoints", "Set the number of presampling points.", &ShowerApproximationGenerator::thePresamplingPoints, 2000, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceMaxTry ("MaxTry", "Set the number of maximum attempts.", &ShowerApproximationGenerator::theMaxTry, 100000, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceFreezeGrid ("FreezeGrid", "", &ShowerApproximationGenerator::theFreezeGrid, 500000, 1, 0, false, false, Interface::lowerlim); static Switch interfaceDoCompensate ("DoCompensate", "", &ShowerApproximationGenerator::theDoCompensate, false, false, false); static SwitchOption interfaceDoCompensateYes (interfaceDoCompensate, "Yes", "", true); static SwitchOption interfaceDoCompensateNo (interfaceDoCompensate, "No", "", false); } diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.h b/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.h --- a/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.h +++ b/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.h @@ -1,251 +1,243 @@ // -*- C++ -*- // // ShowerApproximationGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_ShowerApproximationGenerator_H #define Herwig_ShowerApproximationGenerator_H // // This is the declaration of the ShowerApproximationGenerator class. // #include "ThePEG/Handlers/StepHandler.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief ShowerApproximationGenerator generates emissions according to a * shower approximation entering a NLO matching. * */ class ShowerApproximationGenerator: public StepHandler { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ ShowerApproximationGenerator(); - /** - * The destructor. - */ - virtual ~ShowerApproximationGenerator(); - //@} - public: /** @name Virtual functions required by the StepHandler class. */ //@{ /** * The main function called by the EventHandler class to * perform a step. Given the current state of an Event, this function * performs the event generation step and includes the result in a new * Step object int the Event record. * @param eh the EventHandler in charge of the Event generation. * @param tagged if not empty these are the only particles which should * be considered by the StepHandler. * @param hint a Hint object with possible information from previously * performed steps. * @throws Veto if the StepHandler requires the current step to be discarded. * @throws Stop if the generation of the current Event should be stopped * after this call. * @throws Exception if something goes wrong. */ virtual void handle(EventHandler & eh, const tPVector & tagged, const Hint & hint); //@} public: /** * Fill information on the Born process */ bool prepare(bool didproject); /** * Generate a Born phase space point while kernels are being * presampled */ bool generate(const vector&); /** * Restore information on the Born process */ void restore(); protected: /** * Generate a momentum fraction for the given parton species */ double generateFraction(tcPDPtr, double, double) const; /** * Invert the momentum fraction for the given parton species */ double invertFraction(tcPDPtr, double, double) const; /** * Return the pt cut to be applied for final-final dipoles. */ Energy ffPtCut() const { return theShowerApproximation->ffPtCut(); } /** * Return the pt cut to be applied for final-initial dipoles. */ Energy fiPtCut() const { return theShowerApproximation->fiPtCut(); } /** * Return the pt cut to be applied for initial-initial dipoles. */ Energy iiPtCut() const { return theShowerApproximation->iiPtCut(); } 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: /** * The shower approximation to consider */ Ptr::ptr theShowerApproximation; /** * The (invertible) phase space generator to use */ Ptr::ptr thePhasespace; /** * Map hard processes to the respective kernels. */ map::ptr> > theKernelMap; /** * The number of points to presample this splitting generator. */ unsigned long thePresamplingPoints; /** * The maximum number of trials to generate a splitting. */ unsigned long theMaxTry; /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long theFreezeGrid; /** * The last external Born XComb dealt with */ tStdXCombPtr lastIncomingXComb; // the next three are filled from the incoming xcomb in the prepare method /** * The last internal Born matrix element dealt with */ Ptr::ptr theLastBornME; /** * The last Born phase space point */ vector theLastMomenta; /** * The last Born phase space point used while presampling */ vector theLastPresamplingMomenta; /** * The random numbers which have produced the last Born phase space * point. */ vector theLastRandomNumbers; /** * The last internal Born XComb dealt with */ tStdXCombPtr theLastBornXComb; /** * The last internal incoming partons dealt with */ PPair theLastPartons; /** * True, if sampler should apply compensation */ bool theDoCompensate; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerApproximationGenerator & operator=(const ShowerApproximationGenerator &) = delete; }; } #endif /* Herwig_ShowerApproximationGenerator_H */ diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.cc b/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.cc --- a/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.cc +++ b/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.cc @@ -1,210 +1,208 @@ // -*- C++ -*- // // ShowerApproximationKernel.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerApproximationKernel class. // #include #include "ShowerApproximationKernel.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ShowerApproximationGenerator.h" using namespace Herwig; ShowerApproximationKernel::ShowerApproximationKernel() : thePresampling(false), thePresamplingPoints(10000), theMaxTry(100000), theFreezeGrid(500000), sampler(0), theDoCompensate(false) {} -ShowerApproximationKernel::~ShowerApproximationKernel() {} - IBPtr ShowerApproximationKernel::clone() const { return new_ptr(*this); } IBPtr ShowerApproximationKernel::fullclone() const { return new_ptr(*this); } void ShowerApproximationKernel::showerApproximationGenerator(Ptr::tptr gen) { theShowerApproximationGenerator = gen; } Ptr::tptr ShowerApproximationKernel::showerApproximationGenerator() const { return theShowerApproximationGenerator; } const vector& ShowerApproximationKernel::sampleFlags() { if ( !theFlags.empty() ) return theFlags; theFlags.resize(nDim(),false); for ( int k = nDimBorn(); k < nDimBorn() + dipole()->nDimRadiation(); ++k ) theFlags[k] = true; return theFlags; } const pair,vector >& ShowerApproximationKernel::support() { if ( !theSupport.first.empty() ) return theSupport; vector l(nDim(),0.0); vector u(nDim(),1.0); theSupport.first = l; theSupport.second = u; return theSupport; } const vector& ShowerApproximationKernel::parameterPoint() { theLastParameterPoint.resize(nDim()); copy(bornCXComb()->lastRandomNumbers().begin(), bornCXComb()->lastRandomNumbers().end(), theLastParameterPoint.begin()); theLastParameterPoint[evolutionVariable()] = 1.; return theLastParameterPoint; } void ShowerApproximationKernel::startPresampling() { thePresampling = true; } void ShowerApproximationKernel::stopPresampling() { showerApproximationGenerator()->restore(); thePresampling = false; } double ShowerApproximationKernel::evaluate(const vector& r) { if ( presampling() ) { theLastBornPoint.resize(nDimBorn()); copy(r.begin(),r.begin()+nDimBorn(),theLastBornPoint.begin()); if ( !showerApproximationGenerator()->generate(theLastBornPoint) ) return 0.; } assert(dipole()->splitting()); realXComb()->clean(); dipole()->setXComb(realXComb()); for ( vector::const_iterator t = tildeXCombs().begin(); t != tildeXCombs().end(); ++t ) { (**t).clean(); (**t).matrixElement()->setXComb(*t); } if ( !dipole()->generateKinematics(&r[nDimBorn()]) ) return 0.; double jac = showerApproximation()->showerInvertedTildeKinematics() ? showerApproximation()->showerInvertedTildeKinematics()->jacobian() : dipole()->invertedTildeKinematics()->jacobian(); showerApproximation()->setBornXComb(bornXComb()); showerApproximation()->setRealXComb(realXComb()); showerApproximation()->setTildeXCombs(tildeXCombs()); showerApproximation()->setDipole(dipole()); showerApproximation()->checkCutoff(); showerApproximation()->getShowerVariables(); if ( !dipole()->isInShowerPhasespace() ) return 0.; return showerApproximation()->me2() * jac; } double ShowerApproximationKernel::generate() { if ( !sampler ) { sampler = new ExponentialGenerator(); sampler->sampling_parameters().maxtry = maxtry(); sampler->sampling_parameters().presampling_points = presamplingPoints(); sampler->sampling_parameters().freeze_grid = freezeGrid(); sampler->docompensate(theDoCompensate); sampler->function(this); sampler->initialize(); } double res = 0.; while (true) { try { res = sampler->generate(); } catch (exsample::exponential_regenerate&) { continue; } catch (exsample::hit_and_miss_maxtry&) { throw MaxTryException(); } catch (exsample::selection_maxtry&) { throw MaxTryException(); } break; } return res; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ShowerApproximationKernel::persistentOutput(PersistentOStream & os) const { os << theDipole << theShowerApproximation << theBornXComb << theRealXComb << theTildeXCombs << thePresampling << thePresamplingPoints << theMaxTry << theFreezeGrid << theFlags << theSupport << theShowerApproximationGenerator << theLastParameterPoint << theLastBornPoint << (sampler ? true : false) << theDoCompensate; if ( sampler ) sampler->put(os); } void ShowerApproximationKernel::persistentInput(PersistentIStream & is, int) { bool haveSampler; is >> theDipole >> theShowerApproximation >> theBornXComb >> theRealXComb >> theTildeXCombs >> thePresampling >> thePresamplingPoints >> theMaxTry >> theFreezeGrid >> theFlags >> theSupport >> theShowerApproximationGenerator >> theLastParameterPoint >> theLastBornPoint >> haveSampler >> theDoCompensate; if ( haveSampler ) { sampler = new ExponentialGenerator(); sampler->get(is); sampler->function(this); sampler->initialize(); } } // *** 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 describeHerwigShowerApproximationKernel("Herwig::ShowerApproximationKernel", "Herwig.so"); void ShowerApproximationKernel::Init() { static ClassDocumentation documentation ("ShowerApproximationKernel generates emissions according to a " "shower approximation entering a NLO matching."); } diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h b/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h --- a/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h +++ b/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h @@ -1,478 +1,470 @@ // -*- C++ -*- // // ShowerApproximationKernel.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_ShowerApproximationKernel_H #define Herwig_ShowerApproximationKernel_H // // This is the declaration of the ShowerApproximationKernel class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/Sampling/exsample/exponential_generator.h" namespace Herwig { using namespace ThePEG; class ShowerApproximationGenerator; /** * \ingroup Matchbox * \author Simon Platzer * * \brief ShowerApproximationKernel generates emissions according to a * shower approximation entering a NLO matching. * */ class ShowerApproximationKernel: public HandlerBase { public: /** * Exception to communicate sampler maxtry events. */ struct MaxTryException {}; public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ ShowerApproximationKernel(); - /** - * The destructor. - */ - virtual ~ShowerApproximationKernel(); - //@} - public: /** * Set the XComb object describing the Born process */ void setBornXComb(tStdXCombPtr xc) { theBornXComb = xc; } /** * Return the XComb object describing the Born process */ tcStdXCombPtr bornCXComb() const { return theBornXComb; } /** * Return the XComb object describing the Born process */ tStdXCombPtr bornXComb() const { return theBornXComb; } /** * Set the XComb object describing the real emission process */ void setRealXComb(tStdXCombPtr xc) { theRealXComb = xc; } /** * Return the XComb object describing the real emission process */ tcStdXCombPtr realCXComb() const { return theRealXComb; } /** * Return the XComb object describing the real emission process */ tStdXCombPtr realXComb() const { return theRealXComb; } /** * Set the tilde xcomb objects associated to the real xcomb */ void setTildeXCombs(const vector& xc) { theTildeXCombs = xc; } /** * Return the tilde xcomb objects associated to the real xcomb */ const vector& tildeXCombs() const { return theTildeXCombs; } /** * Set the dipole in charge for the emission */ void setDipole(Ptr::tptr dip) { theDipole = dip; } /** * Return the dipole in charge for the emission */ Ptr::tptr dipole() const { return theDipole; } /** * Set the shower approximation. */ void showerApproximation(Ptr::tptr app) { theShowerApproximation = app; } /** * Return the shower approximation. */ Ptr::tptr showerApproximation() const { return theShowerApproximation; } /** * Set the shower approximation generator. */ void showerApproximationGenerator(Ptr::tptr); /** * Return the shower approximation generator. */ Ptr::tptr showerApproximationGenerator() const; /** * Generate the next emission */ double generate(); public: /** * Set a pt cut on the dipole to generate the radiation */ void ptCut(Energy pt) { dipole()->ptCut(pt); } /** * Return the number of random numbers * needed to sample this kernel. */ int nDim() const { return nDimBorn() + dipole()->nDimRadiation(); } /** * Return the number of random numbers * needed to sample the Born process. */ int nDimBorn() const { return bornCXComb()->lastRandomNumbers().size(); } /** * Flag, which variables are free variables. */ const vector& 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 >& support(); /** * Return the parameter point associated to the splitting * previously supplied through fixParameters. */ const vector& parameterPoint(); /** * 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(); /** * Indicate that a veto with the given kernel value and overestimate has occured. */ void veto(const vector&, double, double) { /** use born and real xcombs in here to figure out what we need to reweight; it should have its kinematic variables completed at this step */ } /** * Indicate that an accept with the given kernel value and overestimate has occured. */ void accept(const vector&, double, double) { /** use born and real xcombs in here to figure out what we need to reweight; it should have its kinematic variables completed at this step */ } /** * Return true, if currently being presampled */ bool presampling() const { return thePresampling; } /** * Return the number of points to presample this * splitting generator. */ unsigned long presamplingPoints() const { return thePresamplingPoints; } /** * Return the maximum number of trials * to generate a splitting. */ unsigned long maxtry() const { return theMaxTry; } /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long freezeGrid() const { return theFreezeGrid; } /** * Set the number of points to presample this * splitting generator. */ void presamplingPoints(unsigned long p) { thePresamplingPoints = p; } /** * Set the maximum number of trials * to generate a splitting. */ void maxtry(unsigned long p) { theMaxTry = p; } /** * Set the number of accepted points after which the grid should * be frozen */ void freezeGrid(unsigned long n) { theFreezeGrid = n; } /** * Evalute the splitting kernel. */ double evaluate(const vector&); /** * Return the index of the random number corresponding * to the evolution variable. */ int evolutionVariable() const { return nDimBorn() + (showerApproximation()->showerInvertedTildeKinematics() ? showerApproximation()->showerInvertedTildeKinematics()->evolutionVariable() : dipole()->invertedTildeKinematics()->evolutionVariable()); } /** * Return the cutoff on the evolution * random number corresponding to the pt cut. */ double evolutionCutoff() const { return showerApproximation()->showerInvertedTildeKinematics() ? showerApproximation()->showerInvertedTildeKinematics()->evolutionCutoff() : dipole()->invertedTildeKinematics()->evolutionCutoff(); } /** * 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& variable_flags () { return sampleFlags(); } inline size_t evolution_variable () const { return evolutionVariable(); } inline double evolution_cutoff () const { return evolutionCutoff(); } inline const vector& parameter_point () { 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: /** * The dipole in charge of the emission */ Ptr::ptr theDipole; /** * The shower approximation to consider */ Ptr::ptr theShowerApproximation; /** * The XComb off which radiation will be generated */ StdXCombPtr theBornXComb; /** * The XComb describing the process after radiation */ StdXCombPtr theRealXComb; /** * The tilde xcomb objects associated to the real xcomb */ vector theTildeXCombs; /** * True, if currently being presampled */ bool thePresampling; /** * The number of points to presample this * splitting generator. */ unsigned long thePresamplingPoints; /** * The maximum number of trials * to generate a splitting. */ unsigned long theMaxTry; /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long theFreezeGrid; /** * The sampling flags */ vector theFlags; /** * The support. */ pair,vector > theSupport; /** * The shower approximation generator. */ Ptr::tptr theShowerApproximationGenerator; /** * The last parameter point */ vector theLastParameterPoint; /** * The last random numbers used for Born sampling */ vector theLastBornPoint; /** * Define the Sudakov sampler */ typedef exsample::exponential_generator ExponentialGenerator; /** * Define a pointer to the Sudakov sampler */ typedef exsample::exponential_generator* ExponentialGeneratorPtr; /** * The Sudakov sampler */ ExponentialGeneratorPtr sampler; /** * True, if sampler should apply compensation */ bool theDoCompensate; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerApproximationKernel & operator=(const ShowerApproximationKernel &) = delete; }; } #endif /* Herwig_ShowerApproximationKernel_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.cc @@ -1,137 +1,133 @@ // -*- C++ -*- // // FFLightInvertedTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFLightInvertedTildeKinematics class. // #include "FFLightInvertedTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -FFLightInvertedTildeKinematics::FFLightInvertedTildeKinematics() {} - -FFLightInvertedTildeKinematics::~FFLightInvertedTildeKinematics() {} - IBPtr FFLightInvertedTildeKinematics::clone() const { return new_ptr(*this); } IBPtr FFLightInvertedTildeKinematics::fullclone() const { return new_ptr(*this); } bool FFLightInvertedTildeKinematics::doMap(const double * r) { if ( ptMax() < ptCut() ) { jacobian(0.0); return false; } Lorentz5Momentum emitter = bornEmitterMomentum(); Lorentz5Momentum spectator = bornSpectatorMomentum(); double mapping = 1.0; pair ptz = generatePtZ(mapping,r); if ( mapping == 0.0 ) { jacobian(0.0); return false; } Energy pt = ptz.first; double z = ptz.second; double y = sqr(pt/lastScale())/(z*(1.-z)); if ( y < 0. || y > 1. || z < 0. || z > 1. ) { jacobian(0.0); return false; } mapping *= (1.-y)/(z*(1.-z)); jacobian(mapping*(sqr(lastScale())/sHat())/(16.*sqr(Constants::pi))); double phi = 2.*Constants::pi*r[2]; Lorentz5Momentum kt = getKt(emitter,spectator,pt,phi); subtractionParameters().resize(2); subtractionParameters()[0] = y; subtractionParameters()[1] = z; realEmitterMomentum() = z*emitter + y*(1.-z)*spectator + kt; realEmissionMomentum() = (1.-z)*emitter + y*z*spectator - kt; realSpectatorMomentum() = (1.-y)*spectator; realEmitterMomentum().setMass(ZERO); realEmitterMomentum().rescaleEnergy(); realEmissionMomentum().setMass(ZERO); realEmissionMomentum().rescaleEnergy(); realSpectatorMomentum().setMass(ZERO); realSpectatorMomentum().rescaleEnergy(); return true; } Energy FFLightInvertedTildeKinematics::lastPt() const { Energy scale = sqrt(2.*(bornEmitterMomentum()*bornSpectatorMomentum())); double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; return scale * sqrt(y*z*(1.-z)); } double FFLightInvertedTildeKinematics::lastZ() const { return subtractionParameters()[1]; } Energy FFLightInvertedTildeKinematics::ptMax() const { return lastScale()/2.; } pair FFLightInvertedTildeKinematics::zBounds(Energy pt, Energy hardPt) const { hardPt = hardPt == ZERO ? ptMax() : min(hardPt,ptMax()); if(pt>hardPt) return make_pair(0.5,0.5); double s = sqrt(1.-sqr(pt/hardPt)); return make_pair(0.5*(1.-s),0.5*(1.+s)); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFLightInvertedTildeKinematics::persistentOutput(PersistentOStream &) const { } void FFLightInvertedTildeKinematics::persistentInput(PersistentIStream &, int) { } void FFLightInvertedTildeKinematics::Init() { static ClassDocumentation documentation ("FFLightInvertedTildeKinematics inverts the final-final tilde " "kinematics."); } // *** 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 describeHerwigFFLightInvertedTildeKinematics("Herwig::FFLightInvertedTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FFLightInvertedTildeKinematics.h @@ -1,138 +1,123 @@ // -*- C++ -*- // // FFLightInvertedTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFLightInvertedTildeKinematics_H #define HERWIG_FFLightInvertedTildeKinematics_H // // This is the declaration of the FFLightInvertedTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FFLightInvertedTildeKinematics inverts the final-final tilde * kinematics. * */ class FFLightInvertedTildeKinematics: public Herwig::InvertedTildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FFLightInvertedTildeKinematics(); - - /** - * The destructor. - */ - virtual ~FFLightInvertedTildeKinematics(); - //@} - -public: - /** * Perform the mapping of the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the real * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(const double *); /** * Return the pt associated to the last generated splitting. */ virtual Energy lastPt() const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Return the upper bound on pt */ virtual Energy ptMax() const; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt = ZERO) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFLightInvertedTildeKinematics & operator=(const FFLightInvertedTildeKinematics &) = delete; }; } #endif /* HERWIG_FFLightInvertedTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.cc @@ -1,114 +1,109 @@ // -*- C++ -*- // // FFLightTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFLightTildeKinematics class. // #include "FFLightTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -FFLightTildeKinematics::FFLightTildeKinematics() {} - -FFLightTildeKinematics::~FFLightTildeKinematics() {} - IBPtr FFLightTildeKinematics::clone() const { return new_ptr(*this); } IBPtr FFLightTildeKinematics::fullclone() const { return new_ptr(*this); } bool FFLightTildeKinematics::doMap() { Lorentz5Momentum emitter = realEmitterMomentum(); Lorentz5Momentum emission = realEmissionMomentum(); Lorentz5Momentum spectator = realSpectatorMomentum(); double y = emission*emitter / (emission*emitter + emission*spectator + emitter*spectator); double z = emitter*spectator / (emitter*spectator + emission*spectator); subtractionParameters().resize(2); subtractionParameters()[0] = y; subtractionParameters()[1] = z; bornEmitterMomentum() = emitter+emission-(y/(1.-y))*spectator; bornSpectatorMomentum() = spectator/(1.-y); bornEmitterMomentum().setMass(ZERO); bornEmitterMomentum().rescaleEnergy(); bornSpectatorMomentum().setMass(ZERO); bornSpectatorMomentum().rescaleEnergy(); return true; } Energy FFLightTildeKinematics::lastPt() const { Energy scale = sqrt(2.*(bornEmitterMomentum()*bornSpectatorMomentum())); double y = subtractionParameters()[0]; double z = subtractionParameters()[1]; return scale * sqrt(y*z*(1.-z)); } Energy FFLightTildeKinematics::lastPt(Lorentz5Momentum emitter,Lorentz5Momentum emission,Lorentz5Momentum spectator)const { Energy scale = (emitter+emission+spectator).m(); double y = emission*emitter/(emission*emitter + emission*spectator + emitter*spectator); double z = emitter*spectator / (emitter*spectator + emission*spectator); Energy ret = scale * sqrt( y * z*(1.-z) ); return ret; } pair FFLightTildeKinematics::zBounds(Energy pt, Energy hardPt) const { if(pt>hardPt) return make_pair(0.5,0.5); double s = sqrt(1.-sqr(pt/hardPt)); return make_pair(0.5*(1.-s),0.5*(1.+s)); } double FFLightTildeKinematics::lastZ() const { return subtractionParameters()[1]; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFLightTildeKinematics::persistentOutput(PersistentOStream &) const { } void FFLightTildeKinematics::persistentInput(PersistentIStream &, int) { } void FFLightTildeKinematics::Init() { static ClassDocumentation documentation ("FFLightTildeKinematics implements the 'tilde' kinematics for " "a final-final subtraction dipole."); } // *** 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 describeHerwigFFLightTildeKinematics("Herwig::FFLightTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FFLightTildeKinematics.h @@ -1,144 +1,129 @@ // -*- C++ -*- // // FFLightTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFLightTildeKinematics_H #define HERWIG_FFLightTildeKinematics_H // // This is the declaration of the FFLightTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FFLightTildeKinematics implements the 'tilde' kinematics for * a final-final subtraction dipole. * */ class FFLightTildeKinematics: public TildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FFLightTildeKinematics(); - - /** - * The destructor. - */ - virtual ~FFLightTildeKinematics(); - //@} - -public: - /** * Perform the mapping to the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the tilde * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(); /** * Return the pt associated to the last merged splitting. */ virtual Energy lastPt() const; /** * Return the pt associated to emitter emission and sppectator momentum. */ virtual Energy lastPt(Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum) const ; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt ) const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /* * True if phase space point is above the alpha cut for this dipole. */ bool aboveAlpha() const {return dipole()->alpha() values(6); pair ptz = generatePtZ(mapping, r, &values); if ( mapping == 0.0 ) { jacobian(0.0); return false; } Energy pt = ptz.first; Energy2 pt2 = sqr(pt); double z = ptz.second; // masses double mui2 = sqr( realEmitterData()->hardProcessMass() / lastScale() ); double muj2 = sqr( realEmissionData()->hardProcessMass() / lastScale() ); double muk2 = sqr( realSpectatorData()->hardProcessMass() / lastScale() ); double Muij2 = sqr( bornEmitterData()->hardProcessMass() / lastScale() ); double Muk2 = sqr( bornSpectatorData()->hardProcessMass() / lastScale() ); // Define the scale Energy2 Qijk = sqr(lastScale()); // Most of the required values have been calculated in ptzAllowed double y = values[0]; double zi = values[1]; double xk = values[2]; double xij = values[3]; double QijN2 = values[4]; double sijkN = values[5]; double sijkN2 = sqr(sijkN); // Construct reference momenta nk, nij Lorentz5Momentum nij = ( sijkN2 / (sijkN2-Muij2*Muk2) ) * (emitter - (Muij2/sijkN)*spectator); Lorentz5Momentum nk = ( sijkN2 / (sijkN2-Muij2*Muk2) ) * (spectator - (Muk2/sijkN)*emitter); // Construct qt double phi = 2.*Constants::pi*r[2]; Lorentz5Momentum qt = getKt(emitter,spectator,pt,phi); // Construct qij, qk, qi and qj Lorentz5Momentum qij = xij*nij + (Muij2/(xij*sijkN))*nk; Lorentz5Momentum spe = xk*nk + (Muk2/(xk*sijkN))*nij; Lorentz5Momentum em = z*qij + ((pt2/Qijk + mui2 - z*z*Muij2)/(xij*sijkN*z))*nk + qt; Lorentz5Momentum emm = (1.-z)*qij + ((pt2/Qijk + muj2 - sqr(1.-z)*Muij2)/(xij*sijkN*(1.-z)))*nk - qt; em.setMass(realEmitterData()->hardProcessMass()); em.rescaleEnergy(); emm.setMass(realEmissionData()->hardProcessMass()); emm.rescaleEnergy(); spe.setMass(realSpectatorData()->hardProcessMass()); spe.rescaleEnergy(); // book realEmitterMomentum() = em; realEmissionMomentum() = emm; realSpectatorMomentum() = spe; // Calculate the jacobian double bar = 1.-mui2-muj2-muk2; // mapFactor defined as dy dz = mapFactor * dpt2/sqr(lastScale()) dz double mapFactor = 0.0; mapFactor = y*(sqr(lastScale()) / (pt2 + sqr(1.-z)*mui2*Qijk + sqr(z)*muj2*Qijk)) * abs(1. - 2.*Muk2*QijN2 / (bar*(1.-y)*xij*xk*sijkN)); // Mapping includes only the variable changes/jacobians mapping *= mapFactor; jacobian( (Qijk*sqr(bar)/rootOfKallen(1.,Muij2,Muk2)) * mapping * (1.-y)/(16.*sqr(Constants::pi)) / sHat() ); // Store the parameters subtractionParameters().resize(3); subtractionParameters()[0] = y; subtractionParameters()[1] = zi; subtractionParameters()[2] = z; return true; } Energy FFMassiveInvertedTildeKinematics::lastPt() const { Energy scale = (bornEmitterMomentum()+bornSpectatorMomentum()).m(); // masses double mui2 = sqr( realEmitterData()->hardProcessMass() / scale ); double muj2 = sqr( realEmissionData()->hardProcessMass() / scale ); double muk2 = sqr( realSpectatorData()->hardProcessMass() / scale ); double y = subtractionParameters()[0]; double z = subtractionParameters()[2]; Energy ret = scale * sqrt( y * (1.-mui2-muj2-muk2) * z*(1.-z) - sqr(1.-z)*mui2 - sqr(z)*muj2 ); return ret; } double FFMassiveInvertedTildeKinematics::lastZ() const { return subtractionParameters()[2]; } Energy FFMassiveInvertedTildeKinematics::ptMax() const { Energy scale = (bornEmitterMomentum()+bornSpectatorMomentum()).m(); // masses double mui2 = sqr( realEmitterData()->hardProcessMass() / scale ); double muj2 = sqr( realEmissionData()->hardProcessMass() / scale ); double muk2 = sqr( realSpectatorData()->hardProcessMass() / scale ); Energy ptmax = rootOfKallen( mui2, muj2, sqr(1.-sqrt(muk2)) ) / ( 2.-2.*sqrt(muk2) ) * scale; return ptmax > 0.*GeV ? ptmax : 0.*GeV; } // NOTE: bounds calculated at this step may be too loose pair FFMassiveInvertedTildeKinematics::zBounds(Energy pt, Energy hardPt) const { hardPt = hardPt == ZERO ? ptMax() : min(hardPt,ptMax()); if(pt>hardPt) return make_pair(0.5,0.5); Energy scale = (bornEmitterMomentum()+bornSpectatorMomentum()).m(); // masses double mui2 = sqr( realEmitterData()->hardProcessMass() / scale ); double muj2 = sqr( realEmissionData()->hardProcessMass() / scale ); double muk2 = sqr( realSpectatorData()->hardProcessMass() / scale ); double zp = ( 1.+mui2-muj2+muk2-2.*sqrt(muk2) + rootOfKallen(mui2,muj2,sqr(1.-sqrt(muk2))) * sqrt( 1.-sqr(pt/hardPt) ) ) / ( 2.*sqr(1.-sqrt(muk2)) ); double zm = ( 1.+mui2-muj2+muk2-2.*sqrt(muk2) - rootOfKallen(mui2,muj2,sqr(1.-sqrt(muk2))) * sqrt( 1.-sqr(pt/hardPt) ) ) / ( 2.*sqr(1.-sqrt(muk2)) ); return make_pair(zm,zp); } // Matches Stephen Webster's thesis bool FFMassiveInvertedTildeKinematics::ptzAllowed(pair ptz, vector* values) const { Energy pt = ptz.first; Energy2 pt2 = sqr(pt); double z = ptz.second; // masses double mui2 = sqr( realEmitterData()->hardProcessMass() / lastScale() ); double muj2 = sqr( realEmissionData()->hardProcessMass() / lastScale() ); double muk2 = sqr( realSpectatorData()->hardProcessMass() / lastScale() ); double Muij2 = sqr( bornEmitterData()->hardProcessMass() / lastScale() ); double Muk2 = sqr( bornSpectatorData()->hardProcessMass() / lastScale() ); // Calculate the scales that we need Energy2 Qijk = sqr(lastScale()); double QijN2 = (pt2/Qijk + (1.-z)*mui2 + z*muj2) / z / (1.-z); double sijkN = 0.5*( 1. - Muij2 - Muk2 + sqrt( sqr(1.-Muij2-Muk2) - 4.*Muij2*Muk2 ) ); double bar = 1.-mui2-muj2-muk2; double y = ( pt2/Qijk + sqr(1.-z)*mui2 + z*z*muj2 ) / (z*(1.-z)*bar); // Calculate the scaling factors, xk and xij double lambdaK = 1. + (Muk2/sijkN); double lambdaIJ = 1. + (Muij2/sijkN); double fac1 = lambdaIJ*lambdaK + (muk2 - QijN2)/sijkN; double xk = ( fac1 + sqrt( sqr(fac1) - 4.*lambdaIJ*lambdaK*muk2/sijkN ) ) / 2. / lambdaK ; double xij = 1. - muk2*(1.-xk) / xk / sijkN; // Calculate zi double zi = ( z*xij*xk*sijkN + muk2*(pt2/Qijk + mui2) / (z*xij*xk*sijkN) ) / (1.-y) / bar; // Limits on zi double facA = (2.*mui2+bar*y)/2./(mui2 + muj2 + bar*y); double facB = sqrt( (sqr(2.*muk2 + bar*(1.-y)) - 4.*muk2) * (sqr(bar)*sqr(y) - 4.*mui2*muj2)) / bar / (1.-y) / (bar*y + 2.*mui2); double zim = facA * (1. - facB); double zip = facA * (1. + facB); // check (y,z) phase space boundary double ym = 2.*sqrt(mui2)*sqrt(muj2)/bar; double yp = 1. - 2.*sqrt(muk2)*(1.-sqrt(muk2))/bar; if ( yyp || zizip ) return false; assert( (*values).size() == 6); (*values)[0] = y; (*values)[1] = zi; (*values)[2] = xk; (*values)[3] = xij; (*values)[4] = QijN2; (*values)[5] = sijkN; return true; } // This is used to generate pt and z pair FFMassiveInvertedTildeKinematics::generatePtZ(double& jac, const double * r, vector * values) const { double kappaMin = ptCut() != ZERO ? sqr(ptCut()/ptMax()) : sqr(0.1*GeV/GeV); double kappa; using namespace RandomHelpers; if ( ptCut() > ZERO ) { pair kw = generate(inverse(0.,kappaMin,1.),r[0]); kappa = kw.first; jac *= kw.second; } else { pair kw = generate((piecewise(), flat(1e-4,kappaMin), match(inverse(0.,kappaMin,1.))),r[0]); kappa = kw.first; jac *= kw.second; } Energy pt = sqrt(kappa)*ptMax(); pair zLims = zBounds(pt); pair zw = generate(inverse(0.,zLims.first,zLims.second)+ inverse(1.,zLims.first,zLims.second),r[1]); double z = zw.first; jac *= zw.second; jac *= sqr(ptMax()/lastScale()); if( !ptzAllowed(make_pair(pt,z), values )) jac = 0.; return make_pair(pt,z); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFMassiveInvertedTildeKinematics::persistentOutput(PersistentOStream &) const { } void FFMassiveInvertedTildeKinematics::persistentInput(PersistentIStream &, int) { } void FFMassiveInvertedTildeKinematics::Init() { static ClassDocumentation documentation ("FFMassiveInvertedTildeKinematics inverts the final-final tilde " "kinematics involving a massive particle."); } // *** 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 describeHerwigFFMassiveInvertedTildeKinematics("Herwig::FFMassiveInvertedTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h @@ -1,179 +1,164 @@ // -*- C++ -*- // // FFMassiveInvertedTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFMassiveInvertedTildeKinematics_H #define HERWIG_FFMassiveInvertedTildeKinematics_H // // This is the declaration of the FFMassiveInvertedTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Stephen Webster * * \brief FFMassiveInvertedTildeKinematics inverts the final-final tilde * kinematics. * */ class FFMassiveInvertedTildeKinematics: public Herwig::InvertedTildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FFMassiveInvertedTildeKinematics(); - - /** - * The destructor. - */ - virtual ~FFMassiveInvertedTildeKinematics(); - //@} - -public: - /** * Perform the mapping of the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the real * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(const double *); /** * Return the pt associated to the last generated splitting. */ virtual Energy lastPt() const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Return the upper bound on pt */ virtual Energy ptMax() const; /** * Given a pt, return the boundaries on z * Note that allowing parton masses these bounds may be too loose */ virtual pair zBounds(Energy pt, Energy hardPt = ZERO) const; /** * For generated pt and z, check if this point is * kinematically allowed */ /*virtual*/ bool ptzAllowed(pair ptz, vector* values ) const; /** * Generate pt and z */ virtual pair generatePtZ(double& jac, const double * r, vector* values) const; public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { return sqrt( a*a + b*b + c*c - 2.*( a*b+a*c+b*c ) ); } // TODO: remove in both /** * stolen from FFMassiveKinematics.h * Perform a rotation on both momenta such that the first one will * point along the (positive) z axis. Rotate back to the original * reference frame by applying rotateUz(returnedVector) to each momentum. */ ThreeVector rotateToZ (Lorentz5Momentum& pTarget, Lorentz5Momentum& p1) { ThreeVector oldAxis = pTarget.vect().unit(); double ct = oldAxis.z(); double st = sqrt( 1.-sqr(ct) ); // cos,sin(theta) double cp = oldAxis.x()/st; double sp = oldAxis.y()/st; // cos,sin(phi) pTarget.setZ( pTarget.vect().mag() ); pTarget.setX( 0.*GeV ); pTarget.setY( 0.*GeV ); Lorentz5Momentum p1old = p1; p1.setX( sp*p1old.x() - cp*p1old.y() ); p1.setY( ct*cp*p1old.x() + ct*sp*p1old.y() - st*p1old.z() ); p1.setZ( st*cp*p1old.x() + st*sp*p1old.y() + ct*p1old.z() ); return oldAxis; } 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMassiveInvertedTildeKinematics & operator=(const FFMassiveInvertedTildeKinematics &) = delete; }; } #endif /* HERWIG_FFMassiveInvertedTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.cc @@ -1,232 +1,227 @@ // -*- C++ -*- // // FFMassiveTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFMassiveTildeKinematics class. // #include "FFMassiveTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -FFMassiveTildeKinematics::FFMassiveTildeKinematics() {} - -FFMassiveTildeKinematics::~FFMassiveTildeKinematics() {} - IBPtr FFMassiveTildeKinematics::clone() const { return new_ptr(*this); } IBPtr FFMassiveTildeKinematics::fullclone() const { return new_ptr(*this); } // Matches Stephen Webster's thesis bool FFMassiveTildeKinematics::doMap() { Lorentz5Momentum emitter = realEmitterMomentum(); Lorentz5Momentum emission = realEmissionMomentum(); Lorentz5Momentum spectator = realSpectatorMomentum(); // Compute y double y = emission*emitter / (emission*emitter + emission*spectator + emitter*spectator); // Calculate the scale Lorentz5Momentum pTot = emitter+emission+spectator; Energy scale = pTot.m(); // masses double mui2 = sqr( realEmitterData()->hardProcessMass() / scale ); double muj2 = sqr( realEmissionData()->hardProcessMass() / scale ); double muk2 = sqr( realSpectatorData()->hardProcessMass() / scale ); double Muij2 = sqr( bornEmitterData()->hardProcessMass() / scale ); double Muk2 = sqr( bornSpectatorData()->hardProcessMass() / scale ); // Calculate the invariants Energy2 Qijk = sqr(scale); double sijkN = 0.5*( 1. - Muij2 - Muk2 + sqrt( sqr(1.-Muij2-Muk2) - 4.*Muij2*Muk2 ) ); double bar = 1. - mui2 - muj2 - muk2; // Calculate Qij2 double QijN2 = sqr(emitter + emission)/Qijk; // Calculate the scale factors, xk and xij double lambdaK = 1. + (Muk2/sijkN); double lambdaIJ = 1. + (Muij2/sijkN); double fac1 = lambdaIJ*lambdaK + (muk2 - QijN2)/sijkN; double xk = ( fac1 + sqrt( sqr(fac1) - 4.*lambdaIJ*lambdaK*muk2/sijkN ) ) / 2. / lambdaK ; double xij = 1. - muk2*(1.-xk) / xk / sijkN; // Calculate z = qi.nk / (qi+qj).nk from qi.qk and y double l = Muk2 / (2.*xk*xij*sijkN); double a = (xij*xk*sijkN/2.) - l*(bar*y + mui2 + muj2); double b = (-emitter*spectator)/Qijk + l*(bar*y + 2.*mui2); double z = -b/a; // Calculate zi double zi = emitter*spectator / ((emitter + emission)*spectator); // Store the variables subtractionParameters().resize(3); subtractionParameters()[0] = y; subtractionParameters()[1] = zi; subtractionParameters()[2] = z; // Calculate nij and nk from qi, q, qj double L = QijN2/xij/xk/sijkN; Lorentz5Momentum nij = (emitter + emission - L*spectator)/(xij - L*Muk2/xk/sijkN); Lorentz5Momentum nk = (1./xk)*(spectator - Muk2*nij/(xk*sijkN)); // Calculate the born momenta from nij and nk bornSpectatorMomentum() = nk + (Muk2/sijkN)*nij; bornEmitterMomentum() = pTot - bornSpectatorMomentum(); bornEmitterMomentum().setMass( bornEmitterData()->hardProcessMass() ); bornEmitterMomentum().rescaleEnergy(); bornSpectatorMomentum().setMass( bornSpectatorData()->hardProcessMass() ); bornSpectatorMomentum().rescaleEnergy(); return true; } Energy FFMassiveTildeKinematics::lastPt() const { Energy scale = (bornEmitterMomentum()+bornSpectatorMomentum()).m(); double y = subtractionParameters()[0]; double z = subtractionParameters()[2]; // masses double mui2 = sqr( realEmitterData()->hardProcessMass() / scale ); double muj2 = sqr( realEmissionData()->hardProcessMass() / scale ); double muk2 = sqr( realSpectatorData()->hardProcessMass() / scale ); Energy ret = scale * sqrt( y * (1.-mui2-muj2-muk2) * z*(1.-z) - sqr(1.-z)*mui2 - sqr(z)*muj2 ); return ret; } // Matches Stephen Webster's thesis Energy FFMassiveTildeKinematics::lastPt(Lorentz5Momentum emitter, Lorentz5Momentum emission, Lorentz5Momentum spectator)const { // Compute y double y = emission*emitter / (emission*emitter + emission*spectator + emitter*spectator); // Calculate the scale Lorentz5Momentum pTot = emitter+emission+spectator; Energy scale = pTot.m(); // masses double mui2 = sqr( emitter.mass() / scale ); double muj2 = sqr( emission.mass() / scale ); double muk2 = sqr( spectator.mass() / scale ); // TODO: here we assume a gluon bool isgluon= emitter.mass()==emission.mass(); double Muij2 = sqr(( isgluon?ZERO:max(emission.mass(),emitter.mass()) )/ scale ); double Muk2 = sqr( spectator.mass() / scale ); // Calculate the invariants Energy2 Qijk = sqr(scale); double sijkN = 0.5*( 1. - Muij2 - Muk2 + sqrt( sqr(1.-Muij2-Muk2) - 4.*Muij2*Muk2 ) ); double bar = 1. - mui2 - muj2 - muk2; // Calculate Qij2 double QijN2 = sqr(emitter + emission)/Qijk; // Calculate the scale factors, xk and xij double lambdaK = 1. + (Muk2/sijkN); double lambdaIJ = 1. + (Muij2/sijkN); double fac1 = lambdaIJ*lambdaK + (muk2 - QijN2)/sijkN; double xk = ( fac1 + sqrt( sqr(fac1) - 4.*lambdaIJ*lambdaK*muk2/sijkN ) ) / 2. / lambdaK ; double xij = 1. - muk2*(1.-xk) / xk / sijkN; // Calculate z = qi.nk / (qi+qj).nk from qi.qk and y double l = Muk2 / (2.*xk*xij*sijkN); double a = (xij*xk*sijkN/2.) - l*(bar*y + mui2 + muj2); double b = (-emitter*spectator)/Qijk + l*(bar*y + 2.*mui2); double z = -b/a; Energy ret = scale * sqrt( z*(1.-z)*QijN2 - (1.-z)*mui2 - z*muj2 ); return ret; } // NOTE: bounds calculated at this step may be too loose pair FFMassiveTildeKinematics::zBounds(Energy pt, Energy hardPt) const { if(pt>hardPt) return make_pair(0.5,0.5); Energy scale = (bornEmitterMomentum()+bornSpectatorMomentum()).m(); // masses double mui2 = sqr( realEmitterData()->hardProcessMass() / scale ); double muj2 = sqr( realEmissionData()->hardProcessMass() / scale ); double muk2 = sqr( realSpectatorData()->hardProcessMass() / scale ); double zp = ( 1.+mui2-muj2+muk2-2.*sqrt(muk2) + rootOfKallen(mui2,muj2,sqr(1.-sqrt(muk2))) * sqrt( 1.-sqr(pt/hardPt) ) ) / ( 2.*sqr(1.-sqrt(muk2)) ); double zm = ( 1.+mui2-muj2+muk2-2.*sqrt(muk2) - rootOfKallen(mui2,muj2,sqr(1.-sqrt(muk2))) * sqrt( 1.-sqr(pt/hardPt) ) ) / ( 2.*sqr(1.-sqrt(muk2)) ); return make_pair(zm,zp); } double FFMassiveTildeKinematics::lastZ() const { return subtractionParameters()[2]; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFMassiveTildeKinematics::persistentOutput(PersistentOStream &) const { } void FFMassiveTildeKinematics::persistentInput(PersistentIStream &, int) { } void FFMassiveTildeKinematics::Init() { static ClassDocumentation documentation ("FFMassiveTildeKinematics implements the 'tilde' kinematics for " "a final-final subtraction dipole involving a massive particle."); } // *** 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 describeHerwigFFMassiveTildeKinematics("Herwig::FFMassiveTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FFMassiveTildeKinematics.h @@ -1,148 +1,133 @@ // -*- C++ -*- // // FFMassiveTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFMassiveTildeKinematics_H #define HERWIG_FFMassiveTildeKinematics_H // // This is the declaration of the FFMassiveTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Stephen Webster * * \brief FFMassiveTildeKinematics implements the 'tilde' kinematics for * a final-final subtraction dipole. * */ class FFMassiveTildeKinematics: public TildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FFMassiveTildeKinematics(); - - /** - * The destructor. - */ - virtual ~FFMassiveTildeKinematics(); - //@} - -public: - /** * Perform the mapping to the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the tilde * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(); /** * Return the pt associated to the last merged splitting. */ virtual Energy lastPt() const; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt ) const; /** * Return the pt associated to emitter emission and sppectator momentum. */ virtual Energy lastPt(Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum) const ; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { return sqrt( a*a + b*b + c*c - 2.*( a*b+a*c+b*c ) ); } 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMassiveTildeKinematics & operator=(const FFMassiveTildeKinematics &) = delete; }; } #endif /* HERWIG_FFMassiveTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.cc @@ -1,136 +1,132 @@ // -*- C++ -*- // // FILightInvertedTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FILightInvertedTildeKinematics class. // #include "FILightInvertedTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -FILightInvertedTildeKinematics::FILightInvertedTildeKinematics() {} - -FILightInvertedTildeKinematics::~FILightInvertedTildeKinematics() {} - IBPtr FILightInvertedTildeKinematics::clone() const { return new_ptr(*this); } IBPtr FILightInvertedTildeKinematics::fullclone() const { return new_ptr(*this); } bool FILightInvertedTildeKinematics::doMap(const double * r) { if ( ptMax() < ptCut() ) { jacobian(0.0); return false; } Lorentz5Momentum emitter = bornEmitterMomentum(); Lorentz5Momentum spectator = bornSpectatorMomentum(); double mapping = 1.0; pair ptz = generatePtZ(mapping,r); if ( mapping == 0.0 ) { jacobian(0.0); return false; } Energy pt = ptz.first; double z = ptz.second; double y = sqr(pt/lastScale())/(z*(1.-z)); double x = 1./(1.+y); if ( x < spectatorX() || x > 1. || z < 0. || z > 1. ) { jacobian(0.0); return false; } // This should (and does) have a factor of 1/x relative to // the dipole shower jacobian. mapping /= z*(1.-z); jacobian(mapping*(sqr(lastScale())/sHat())/(16.*sqr(Constants::pi))); double phi = 2.*Constants::pi*r[2]; Lorentz5Momentum kt = getKt(spectator,emitter,pt,phi,true); subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = z; realEmitterMomentum() = z*emitter + (1.-z)*((1.-x)/x)*spectator + kt; realEmissionMomentum() = (1.-z)*emitter + z*((1.-x)/x)*spectator - kt; realSpectatorMomentum() = (1./x)*spectator; realEmitterMomentum().setMass(ZERO); realEmitterMomentum().rescaleEnergy(); realEmissionMomentum().setMass(ZERO); realEmissionMomentum().rescaleEnergy(); realSpectatorMomentum().setMass(ZERO); realSpectatorMomentum().rescaleEnergy(); return true; } Energy FILightInvertedTildeKinematics::lastPt() const { Energy scale = sqrt(2.*(bornEmitterMomentum()*bornSpectatorMomentum())); double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; return scale * sqrt(z*(1.-z)*(1.-x)/x); } double FILightInvertedTildeKinematics::lastZ() const { return subtractionParameters()[1]; } Energy FILightInvertedTildeKinematics::ptMax() const { double x = spectatorX(); return sqrt((1.-x)/x)*lastScale()/2.; } pair FILightInvertedTildeKinematics::zBounds(Energy pt, Energy hardPt) const { hardPt = hardPt == ZERO ? ptMax() : min(hardPt,ptMax()); if(pt>hardPt) return make_pair(0.5,0.5); double s = sqrt(1.-sqr(pt/hardPt)); return make_pair(0.5*(1.-s),0.5*(1.+s)); } void FILightInvertedTildeKinematics::persistentOutput(PersistentOStream &) const { } void FILightInvertedTildeKinematics::persistentInput(PersistentIStream &, int) { } void FILightInvertedTildeKinematics::Init() { static ClassDocumentation documentation ("FILightInvertedTildeKinematics inverts the final-initial tilde " "kinematics."); } // *** 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 describeHerwigFILightInvertedTildeKinematics("Herwig::FILightInvertedTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FILightInvertedTildeKinematics.h @@ -1,138 +1,123 @@ // -*- C++ -*- // // FILightInvertedTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FILightInvertedTildeKinematics_H #define HERWIG_FILightInvertedTildeKinematics_H // // This is the declaration of the FILightInvertedTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FILightInvertedTildeKinematics inverts the final-final tilde * kinematics. * */ class FILightInvertedTildeKinematics: public Herwig::InvertedTildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FILightInvertedTildeKinematics(); - - /** - * The destructor. - */ - virtual ~FILightInvertedTildeKinematics(); - //@} - -public: - /** * Perform the mapping of the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the real * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(const double *); /** * Return the pt associated to the last generated splitting. */ virtual Energy lastPt() const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Return the upper bound on pt */ virtual Energy ptMax() const; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt = ZERO) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FILightInvertedTildeKinematics & operator=(const FILightInvertedTildeKinematics &) = delete; }; } #endif /* HERWIG_FILightInvertedTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.cc @@ -1,121 +1,116 @@ // -*- C++ -*- // // FILightTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FILightTildeKinematics class. // #include "FILightTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -FILightTildeKinematics::FILightTildeKinematics() {} - -FILightTildeKinematics::~FILightTildeKinematics() {} - IBPtr FILightTildeKinematics::clone() const { return new_ptr(*this); } IBPtr FILightTildeKinematics::fullclone() const { return new_ptr(*this); } bool FILightTildeKinematics::doMap() { Lorentz5Momentum emitter = realEmitterMomentum(); Lorentz5Momentum emission = realEmissionMomentum(); Lorentz5Momentum spectator = realSpectatorMomentum(); double x = (- emission*emitter + emission*spectator + emitter*spectator) / (emitter*spectator + emission*spectator); double z = emitter*spectator / (emitter*spectator + emission*spectator); subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = z; bornEmitterMomentum() = emitter+emission-(1.-x)*spectator; bornSpectatorMomentum() = x*spectator; bornEmitterMomentum().setMass(ZERO); bornEmitterMomentum().rescaleEnergy(); bornSpectatorMomentum().setMass(ZERO); bornSpectatorMomentum().rescaleEnergy(); return true; } Energy FILightTildeKinematics::lastPt() const { Energy scale = sqrt(2.*(bornEmitterMomentum()*bornSpectatorMomentum())); double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; return scale * sqrt(z*(1.-z)*(1.-x)/x); } Energy FILightTildeKinematics::lastPt(Lorentz5Momentum emitter,Lorentz5Momentum emission,Lorentz5Momentum spectator)const { Energy2 scale = - (emitter+emission-spectator).m2(); double x = (- emission*emitter + emission*spectator + emitter*spectator) / (emitter*spectator + emission*spectator); double z = emitter*spectator / (emitter*spectator + emission*spectator); return sqrt( z*(1.-z)*(1.-x)/x*scale ) ; } pair FILightTildeKinematics::zBounds(Energy pt, Energy hardPt) const { if(pt>hardPt) return make_pair(0.5,0.5); double s = sqrt(1.-sqr(pt/hardPt)); return make_pair(0.5*(1.-s),0.5*(1.+s)); } double FILightTildeKinematics::lastZ() const { return subtractionParameters()[1]; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FILightTildeKinematics::persistentOutput(PersistentOStream &) const { } void FILightTildeKinematics::persistentInput(PersistentIStream &, int) { } void FILightTildeKinematics::Init() { static ClassDocumentation documentation ("FILightTildeKinematics implements the 'tilde' kinematics for " "a final-initial subtraction dipole."); } // *** 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 describeHerwigFILightTildeKinematics("Herwig::FILightTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FILightTildeKinematics.h @@ -1,144 +1,129 @@ // -*- C++ -*- // // FILightTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FILightTildeKinematics_H #define HERWIG_FILightTildeKinematics_H // // This is the declaration of the FILightTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FILightTildeKinematics implements the 'tilde' kinematics for * a final-initial subtraction dipole. * */ class FILightTildeKinematics: public TildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FILightTildeKinematics(); - - /** - * The destructor. - */ - virtual ~FILightTildeKinematics(); - //@} - -public: - /** * Perform the mapping to the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the tilde * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(); /** * Return the pt associated to the last merged splitting. */ virtual Energy lastPt() const; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt ) const; /** * Return the pt associated to emitter emission and sppectator momentum. */ virtual Energy lastPt(Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum) const ; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /* * True if phase space point is above the alpha cut for this dipole. */ bool aboveAlpha() const {return dipole()->alpha()<1.-subtractionParameters()[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 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FILightTildeKinematics & operator=(const FILightTildeKinematics &) = delete; }; } #endif /* HERWIG_FILightTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.cc @@ -1,182 +1,178 @@ // -*- C++ -*- // // FIMassiveInvertedTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIMassiveInvertedTildeKinematics class. // #include "FIMassiveInvertedTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -FIMassiveInvertedTildeKinematics::FIMassiveInvertedTildeKinematics() {} - -FIMassiveInvertedTildeKinematics::~FIMassiveInvertedTildeKinematics() {} - IBPtr FIMassiveInvertedTildeKinematics::clone() const { return new_ptr(*this); } IBPtr FIMassiveInvertedTildeKinematics::fullclone() const { return new_ptr(*this); } bool FIMassiveInvertedTildeKinematics::doMap(const double * r) { if ( ptMax() < ptCut() ) { jacobian(0.0); return false; } Lorentz5Momentum emitter = bornEmitterMomentum(); Lorentz5Momentum spectator = bornSpectatorMomentum(); double mapping = 1.0; pair ptz = generatePtZ(mapping,r); if ( mapping == 0.0 ) { jacobian(0.0); return false; } Energy pt = ptz.first; double z = ptz.second; Energy2 mi2 = sqr(realEmitterData()->hardProcessMass()); Energy2 m2 = sqr(realEmissionData()->hardProcessMass()); Energy2 Mi2 = sqr(bornEmitterData()->hardProcessMass()); Energy2 scale=2.*emitter*spectator; double y = (pt*pt+(1.-z)*mi2+z*m2-z*(1.-z)*Mi2) / (z*(1.-z)*scale); double x = 1./(1.+y); if ( x < spectatorX() ) { jacobian(0.0); return false; } // SW 05/12/2016: Checked this is correct // This should appear to have a factor of 1/x relative // to the dipole shower jacobian. It is cancelled by ratios of // real and born cross sections in the units. mapping /= z*(1.-z); jacobian(mapping*(sqr(lastScale())/sHat())/(16.*sqr(Constants::pi))); double phi = 2.*Constants::pi*r[2]; Lorentz5Momentum kt = getKt(spectator,emitter,pt,phi,true); subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = z; realEmitterMomentum() = z*emitter + (sqr(pt)+mi2-z*z*Mi2)/(z*scale)*spectator + kt; realEmissionMomentum() = (1.-z)*emitter + (pt*pt+m2-sqr(1.-z)*Mi2)/((1.-z)*scale)*spectator - kt; realSpectatorMomentum() = (1.+y)*spectator; double mui2 = x*mi2/scale; double mu2 = x*m2/scale; double Mui2 = x*Mi2/scale; double xp = 1. + Mui2 - sqr(sqrt(mui2)+sqrt(mu2)); double zm = .5*( 1.-x+Mui2+mui2-mu2 - sqrt( sqr(1.-x+Mui2-mui2-mu2)-4.*mui2*mu2 ) ) / (1.-x+Mui2); double zp = .5*( 1.-x+Mui2+mui2-mu2 + sqrt( sqr(1.-x+Mui2-mui2-mu2)-4.*mui2*mu2 ) ) / (1.-x+Mui2); if ( x > xp || z < zm || z > zp ) { jacobian(0.0); return false; } realEmitterMomentum().setMass(sqrt(mi2)); realEmitterMomentum().rescaleEnergy(); realEmissionMomentum().setMass(sqrt(m2)); realEmissionMomentum().rescaleEnergy(); realSpectatorMomentum().setMass(ZERO); realSpectatorMomentum().rescaleEnergy(); return true; } Energy FIMassiveInvertedTildeKinematics::lastPt() const { Energy2 mi2 = sqr(realEmitterData()->hardProcessMass()); Energy2 m2 = sqr(realEmissionData()->hardProcessMass()); Energy2 Mi2 = sqr(bornEmitterData()->hardProcessMass()); Energy2 scale = Mi2 - (realEmitterMomentum()+realEmissionMomentum()-realSpectatorMomentum()).m2(); double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; return sqrt( z*(1.-z)*(1.-x)/x*scale - ((1.-z)*mi2+z*m2-z*(1.-z)*Mi2) ); } double FIMassiveInvertedTildeKinematics::lastZ() const { return subtractionParameters()[1]; } Energy FIMassiveInvertedTildeKinematics::ptMax() const { Energy2 mi2 = sqr(realEmitterData()->hardProcessMass()); Energy2 m2 = sqr(realEmissionData()->hardProcessMass()); Energy2 Mi2 = sqr(bornEmitterData()->hardProcessMass()); double x = spectatorX(); // s^star/x Energy2 scale=2.*bornEmitterMomentum()*bornSpectatorMomentum(); Energy2 s = scale * (1.-x)/x + Mi2; Energy ptmax = .5 * sqrt(s) * rootOfKallen( s/s, mi2/s, m2/s ); return ptmax > 0.*GeV ? ptmax : 0.*GeV; } pair FIMassiveInvertedTildeKinematics::zBounds(Energy pt, Energy hardPt) const { hardPt = hardPt == ZERO ? ptMax() : min(hardPt,ptMax()); if(pt>hardPt) return make_pair(0.5,0.5); Energy2 mi2 = sqr(realEmitterData()->hardProcessMass()); Energy2 m2 = sqr(realEmissionData()->hardProcessMass()); Energy2 Mi2 = sqr(bornEmitterData()->hardProcessMass()); // s^star/x Energy2 scale=2.*bornEmitterMomentum()*bornSpectatorMomentum(); Energy2 s = scale * (1.-spectatorX())/spectatorX() + Mi2; double zm = .5*( 1.+(mi2-m2)/s - rootOfKallen(s/s,mi2/s,m2/s) * sqrt( 1.-sqr(pt/hardPt) ) ); double zp = .5*( 1.+(mi2-m2)/s + rootOfKallen(s/s,mi2/s,m2/s) * sqrt( 1.-sqr(pt/hardPt) ) ); return make_pair(zm, zp); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMassiveInvertedTildeKinematics::persistentOutput(PersistentOStream &) const { } void FIMassiveInvertedTildeKinematics::persistentInput(PersistentIStream &, int) { } void FIMassiveInvertedTildeKinematics::Init() { static ClassDocumentation documentation ("FIMassiveInvertedTildeKinematics inverts the final-initial tilde " "kinematics involving a massive particle."); } // *** 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 describeHerwigFIMassiveInvertedTildeKinematics("Herwig::FIMassiveInvertedTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FIMassiveInvertedTildeKinematics.h @@ -1,147 +1,132 @@ // -*- C++ -*- // // FIMassiveInvertedTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIMassiveInvertedTildeKinematics_H #define HERWIG_FIMassiveInvertedTildeKinematics_H // // This is the declaration of the FIMassiveInvertedTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Martin Stoll * * \brief FIMassiveInvertedTildeKinematics inverts the final-final tilde * kinematics. * */ class FIMassiveInvertedTildeKinematics: public Herwig::InvertedTildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FIMassiveInvertedTildeKinematics(); - - /** - * The destructor. - */ - virtual ~FIMassiveInvertedTildeKinematics(); - //@} - -public: - /** * Perform the mapping of the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the real * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(const double *); /** * Return the pt associated to the last generated splitting. */ virtual Energy lastPt() const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Return the upper bound on pt */ virtual Energy ptMax() const; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt = ZERO) const; public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { return sqrt( a*a + b*b + c*c - 2.*( a*b+a*c+b*c ) ); } 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMassiveInvertedTildeKinematics & operator=(const FIMassiveInvertedTildeKinematics &) = delete; }; } #endif /* HERWIG_FIMassiveInvertedTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.cc @@ -1,149 +1,144 @@ // -*- C++ -*- // // FIMassiveTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIMassiveTildeKinematics class. // #include "FIMassiveTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -FIMassiveTildeKinematics::FIMassiveTildeKinematics() {} - -FIMassiveTildeKinematics::~FIMassiveTildeKinematics() {} - IBPtr FIMassiveTildeKinematics::clone() const { return new_ptr(*this); } IBPtr FIMassiveTildeKinematics::fullclone() const { return new_ptr(*this); } bool FIMassiveTildeKinematics::doMap() { Lorentz5Momentum emitter = realEmitterMomentum(); Lorentz5Momentum emission = realEmissionMomentum(); Lorentz5Momentum spectator = realSpectatorMomentum(); Energy2 mi2 = sqr(realEmitterData()->hardProcessMass()); Energy2 m2 = sqr(realEmissionData()->hardProcessMass()); Energy2 Mi2 = sqr(bornEmitterData()->hardProcessMass()); double x = (- emission*emitter + emission*spectator + emitter*spectator + 0.5*(Mi2-mi2-m2)) / (emitter*spectator + emission*spectator); double z = emitter*spectator / (emitter*spectator + emission*spectator); subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = z; bornEmitterMomentum() = emitter+emission-(1.-x)*spectator; bornSpectatorMomentum() = x*spectator; bornEmitterMomentum().setMass(bornEmitterData()->hardProcessMass()); bornEmitterMomentum().rescaleEnergy(); bornSpectatorMomentum().setMass(bornSpectatorData()->hardProcessMass()); bornSpectatorMomentum().rescaleEnergy(); return true; } Energy FIMassiveTildeKinematics::lastPt() const { Energy2 Mi2 = sqr(bornEmitterData()->hardProcessMass()); Energy2 mi2 = sqr(realEmitterData()->hardProcessMass()); Energy2 m2 = sqr(realEmissionData()->hardProcessMass()); Energy2 scale = Mi2 - (realEmitterMomentum()+realEmissionMomentum()-realSpectatorMomentum()).m2(); double x = subtractionParameters()[0]; double z = subtractionParameters()[1]; return sqrt( z*(1.-z)*(1.-x)/x*scale - ((1.-z)*mi2+z*m2-z*(1.-z)*Mi2) ); } Energy FIMassiveTildeKinematics::lastPt(Lorentz5Momentum emitter,Lorentz5Momentum emission,Lorentz5Momentum spectator)const { // g->QQ or Q -> Qg Energy2 Mi2 = emitter.m()==emission.m()?0.*GeV2:max(emitter.m2(),emission.m2()); Energy2 mi2 = emitter.m2(); Energy2 m2 = emission.m2(); Energy2 scale = Mi2 - (emitter+emission-spectator).m2(); double x = (- emission*emitter + emission*spectator + emitter*spectator + 0.5*(Mi2-mi2-m2)) / (emitter*spectator + emission*spectator); double z = emitter*spectator / (emitter*spectator + emission*spectator); return sqrt( z*(1.-z)*(1.-x)/x*scale - ((1.-z)*mi2+z*m2-z*(1.-z)*Mi2) ); } pair FIMassiveTildeKinematics::zBounds(Energy pt, Energy hardPt) const { if(pt>hardPt) return make_pair(0.5,0.5); Energy2 mi2 = sqr(realEmitterData()->hardProcessMass()); Energy2 m2 = sqr(realEmissionData()->hardProcessMass()); Energy2 Mi2 = sqr(bornEmitterData()->hardProcessMass()); // s^star/x Energy2 scale=2.*bornEmitterMomentum()*bornSpectatorMomentum(); Energy2 s = scale * (1.-spectatorX())/spectatorX() + Mi2; double zm = .5*( 1.+(mi2-m2)/s - rootOfKallen(s/s,mi2/s,m2/s) * sqrt( 1.-sqr(pt/hardPt) ) ); double zp = .5*( 1.+(mi2-m2)/s + rootOfKallen(s/s,mi2/s,m2/s) * sqrt( 1.-sqr(pt/hardPt) ) ); return make_pair(zm, zp); } double FIMassiveTildeKinematics::lastZ() const { return subtractionParameters()[1]; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMassiveTildeKinematics::persistentOutput(PersistentOStream &) const { } void FIMassiveTildeKinematics::persistentInput(PersistentIStream &, int) { } void FIMassiveTildeKinematics::Init() { static ClassDocumentation documentation ("FIMassiveTildeKinematics implements the 'tilde' kinematics for " "a final-initial subtraction dipole involving a massive particle."); } // *** 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 describeHerwigFIMassiveTildeKinematics("Herwig::FIMassiveTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FIMassiveTildeKinematics.h @@ -1,144 +1,129 @@ // -*- C++ -*- // // FIMassiveTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIMassiveTildeKinematics_H #define HERWIG_FIMassiveTildeKinematics_H // // This is the declaration of the FIMassiveTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Martin Stoll * * \brief FIMassiveTildeKinematics implements the 'tilde' kinematics for * a final-initial subtraction dipole. * */ class FIMassiveTildeKinematics: public TildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FIMassiveTildeKinematics(); - - /** - * The destructor. - */ - virtual ~FIMassiveTildeKinematics(); - //@} - -public: - /** * Perform the mapping to the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the tilde * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(); /** * Return the pt associated to the last merged splitting. */ virtual Energy lastPt() const; /** * Return the pt associated to emitter emission and sppectator momentum. */ virtual Energy lastPt(Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum) const ; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt ) const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { return sqrt( a*a + b*b + c*c - 2.*( a*b+a*c+b*c ) ); } /** @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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMassiveTildeKinematics & operator=(const FIMassiveTildeKinematics &) = delete; }; } #endif /* HERWIG_FIMassiveTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FlatInvertibleLabframePhasespace.cc b/MatrixElement/Matchbox/Phasespace/FlatInvertibleLabframePhasespace.cc --- a/MatrixElement/Matchbox/Phasespace/FlatInvertibleLabframePhasespace.cc +++ b/MatrixElement/Matchbox/Phasespace/FlatInvertibleLabframePhasespace.cc @@ -1,171 +1,169 @@ // -*- C++ -*- // // FlatInvertiblePhasespace.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FlatInvertibleLabframePhasespace class. // #include "FlatInvertibleLabframePhasespace.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Utilities/GSLBisection.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FlatInvertibleLabframePhasespace::FlatInvertibleLabframePhasespace() : theLogSHat(false) {} -FlatInvertibleLabframePhasespace::~FlatInvertibleLabframePhasespace() {} - IBPtr FlatInvertibleLabframePhasespace::clone() const { return new_ptr(*this); } IBPtr FlatInvertibleLabframePhasespace::fullclone() const { return new_ptr(*this); } double FlatInvertibleLabframePhasespace::invertTwoToNKinematics(const vector& momenta, double* r) const { double weight = 1.; Energy finalstatemass = 0*GeV; for ( vector::const_iterator p = momenta.begin()+2; p != momenta.end(); ++p ) finalstatemass += p->mass(); Lorentz5Momentum pinitial = momenta[0]+momenta[1]; Energy2 sh = pinitial.m2(); double tau = sh/lastS(); Energy2 shmax = lastCuts().sHatMax(); Energy2 shmin = max(lastCuts().sHatMin(),sqr(finalstatemass)); if (theLogSHat) { r[0] = log(sh/shmin)/log(shmax/shmin); weight *= tau*log(shmax/shmin); } else { r[0] = (sh-shmin)/(shmax-shmin); weight *= (shmax-shmin)/lastS(); } double ltau = log(tau); r[1] = 0.5 - pinitial.rapidity()/ltau; weight *= -ltau; vector Pcms = momenta; Boost toCMS = pinitial.findBoostToCM(); for ( vector::iterator pit = Pcms.begin(); pit != Pcms.end(); ++pit ) pit->boost(toCMS); weight *= FlatInvertiblePhasespace::invertTwoToNKinematics(Pcms, r+2); return weight; } double FlatInvertibleLabframePhasespace::generateTwoToNKinematics(const double* r, vector& momenta) { double weight = 1.; Energy finalstatemass = 0*GeV; for ( vector::const_iterator p = momenta.begin()+2; p != momenta.end(); ++p ) finalstatemass += p->mass(); Energy beamenergy = sqrt(lastS())/2.; Energy2 shmax = lastCuts().sHatMax(); Energy2 shmin = max(lastCuts().sHatMin(),sqr(finalstatemass)); Energy2 sh; double tau; if (theLogSHat) { sh = shmin*pow(shmax/shmin, r[0]); tau = sh/lastS(); weight *= tau*log(shmax/shmin); } else { sh = r[0]*(shmax-shmin)+shmin; tau = sh/lastS(); weight *= (shmax-shmin)/lastS(); } double ltau = log(tau); double y = ltau*(0.5 - r[1]); weight *= -ltau; double x1 = sqrt(tau)*exp(y); double x2 = sqrt(tau)*exp(-y); momenta[0] = Lorentz5Momentum(0*GeV,0*GeV,+x1*beamenergy,x1*beamenergy); momenta[1] = Lorentz5Momentum(0*GeV,0*GeV,-x2*beamenergy,x2*beamenergy); lastXCombPtr()->lastX1X2(make_pair(x1,x2)); lastXCombPtr()->lastSHat(sh); weight *= FlatInvertiblePhasespace::generateTwoToNKinematics(r+2, momenta); // find boost to the relevant partonic frame note final state kinematics are // always generated in the CMS for this phase space algorithm Boost boostinitial = (momenta[0]+momenta[1]).findBoostToCM(); for ( vector::iterator pit = momenta.begin()+2; pit != momenta.end(); ++pit ) pit->boost(-boostinitial); return weight; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FlatInvertibleLabframePhasespace::persistentOutput(PersistentOStream & os) const { os << theLogSHat; } void FlatInvertibleLabframePhasespace::persistentInput(PersistentIStream & is, int) { is >> theLogSHat; } // *** 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 describeHerwigFlatInvertibleLabframePhasespace("Herwig::FlatInvertibleLabframePhasespace", "Herwig.so"); void FlatInvertibleLabframePhasespace::Init() { static ClassDocumentation documentation ("FlatInvertibleLabframePhasespace implements flat, invertible phase space generation in the lab frame."); static Switch interfaceLogSHat ("LogSHat", "Generate a flat distribution in \\f$\\log(\\hat{s})\\f$.", &FlatInvertibleLabframePhasespace::theLogSHat, false, false, false); static SwitchOption interfaceLogSHatYes (interfaceLogSHat, "Yes", "Generate flat in \\f$\\log(\\hat{s})\\f$", true); static SwitchOption interfaceLogSHatNo (interfaceLogSHat, "No", "Generate flat in \\f$\\hat{s}\\f$", false); interfaceLogSHat.rank(-1); } diff --git a/MatrixElement/Matchbox/Phasespace/FlatInvertibleLabframePhasespace.h b/MatrixElement/Matchbox/Phasespace/FlatInvertibleLabframePhasespace.h --- a/MatrixElement/Matchbox/Phasespace/FlatInvertibleLabframePhasespace.h +++ b/MatrixElement/Matchbox/Phasespace/FlatInvertibleLabframePhasespace.h @@ -1,152 +1,144 @@ // -*- C++ -*- // // FlatInvertiblePhasespaceLabFrame.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_FlatInvertibleLabframePhasespace_H #define Herwig_FlatInvertibleLabframePhasespace_H // // This is the declaration of the FlatInvertibleLabframePhasespace class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Michael Rauch * * \brief FlatInvertibleLabframePhasespace implements flat, invertible phase space generation in the lab frame * */ class FlatInvertibleLabframePhasespace: public FlatInvertiblePhasespace { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FlatInvertibleLabframePhasespace(); - /** - * The destructor. - */ - virtual ~FlatInvertibleLabframePhasespace(); - //@} - public: /** * Generate a phase space point and return its weight. */ virtual double generateTwoToNKinematics(const double*, vector& momenta); /** * Return the number of random numbers required to produce a given * multiplicity final state. */ virtual int nDimPhasespace(int nFinal) const { if ( nFinal == 1 ) return 3; return 3*nFinal - 2; } public: /** * Return true, if this phasespace generator will generate incoming * partons itself. */ virtual bool haveX1X2() const { return true; } /** * Return true, if this phase space generator expects * the incoming partons in their center-of-mass system */ virtual bool wantCMS() const { return false; } /** * Invert the given phase space point to the random numbers which * would have generated it. */ virtual double invertTwoToNKinematics(const vector& momenta, double* r) const; private: /** * True if SHat should be generated flat in log(SHat/S), * false if SHat should be generated flat in SHat. */ bool theLogSHat; 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FlatInvertibleLabframePhasespace & operator=(const FlatInvertibleLabframePhasespace &) = delete; }; } #endif /* Herwig_FlatInvertiblePhasespace_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.cc b/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.cc --- a/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.cc +++ b/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.cc @@ -1,304 +1,299 @@ // -*- C++ -*- // // FlatInvertiblePhasespace.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FlatInvertiblePhasespace class. // #include "FlatInvertiblePhasespace.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Utilities/GSLBisection.h" #include "ThePEG/Cuts/Cuts.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -FlatInvertiblePhasespace::FlatInvertiblePhasespace() {} - -FlatInvertiblePhasespace::~FlatInvertiblePhasespace() {} - IBPtr FlatInvertiblePhasespace::clone() const { return new_ptr(*this); } IBPtr FlatInvertiblePhasespace::fullclone() const { return new_ptr(*this); } double FlatInvertiblePhasespace::bisect(double v, double n, double target, double maxLevel) const { if ( v != 0.0 && v != 1.0 ) { double level = 0; double left = 0; double right = 1; double checkV = -1.; double u = -1; while ( level < maxLevel ) { u = (left+right)*pow(0.5,level+1.); checkV = pow(u,n+1.)*(n+2.-(n+1.)*u); if ( log10(abs(1.-checkV/v)) <= target ) break; left *= 2.; right *= 2.; if ( v <= checkV ) { right -= 1.; ++level; } if ( v > checkV ) { left += 1.; ++level; } } return u; } return v; } double FlatInvertiblePhasespace::generateIntermediates(vector& K, const double* r) const { size_t n = K.size() + 1; for ( size_t i = 2; i <= n-1; ++i ) { double u = bisect(r[i-2],n-1-i); K[i-1] = sqrt(u*sqr(K[i-2])); } int kap = K.size() + 1; return flatWeights(kap); } double FlatInvertiblePhasespace::invertIntermediates(const vector& K, double* r) const { size_t n = K.size() + 1; for ( size_t i = 2; i <= n-1; ++i ) { double u = sqr(K[i-1]/K[i-2]); r[i-2] = (n+1-i)*pow(u,(double)(n-i)) - (n-i)*pow(u,(double)(n+1-i)); } int kap = K.size() + 1; return flatWeights(kap); } double FlatInvertiblePhasespace::generateIntermediates(vector& M, const vector& m, const double* r) const { size_t n = M.size() + 1; vector K = M; for ( size_t i = 1; i <= n; ++i ) K[0] -= m[i-1]; double w0 = generateIntermediates(K,r); M = K; for ( size_t i = 1; i <= n-1; ++i ) { for ( size_t k = i; k <= n; ++k ) M[i-1] += m[k-1]; } double weight = 8.*w0*rho(M[n-2],m[n-1],m[n-2]); for ( size_t i = 2; i <= n-1; ++i ) { weight *= (rho(M[i-2],M[i-1],m[i-2])/rho(K[i-2],K[i-1],ZERO)) * (M[i-1]/K[i-1]); } weight *= pow(K[0]/M[0],2.*n-4.); return weight; } double FlatInvertiblePhasespace::invertIntermediates(const vector& M, const vector& m, double* r) const { size_t n = M.size() + 1; vector K = M; for ( size_t i = 1; i <= n-1; ++i ) { for ( size_t k = i; k <= n; ++k ) K[i-1] -= m[k-1]; } double w0 = invertIntermediates(K,r); double weight = 8.*w0*rho(M[n-2],m[n-1],m[n-2]); for ( size_t i = 2; i <= n-1; ++i ) { weight *= (rho(M[i-2],M[i-1],m[i-2])/rho(K[i-2],K[i-1],ZERO)) * (M[i-1]/K[i-1]); } weight *= pow(K[0]/M[0],2.*n-4.); return weight; } double FlatInvertiblePhasespace::generateKinematics(vector& P, Energy Ecm, const double* r) const { vector m; for ( vector::const_iterator p = P.begin() + 2; p != P.end(); ++p ) m.push_back(p->mass()); size_t n = P.size() - 2; vector M(n-1); M[0] = Ecm; double weight = generateIntermediates(M,m,r); M.push_back(m.back()); Lorentz5Momentum Q(M[0]); Lorentz5Momentum nextQ; for ( size_t i = 2; i <= n; ++i ) { Energy q = 4.*M[i-2]*rho(M[i-2],M[i-1],m[i-2]); double c = 2.*r[n-6+2*i]-1.; double s = sqrt(1.-sqr(c)); double phi = 2.*Constants::pi*r[n-5+2*i]; double cphi = cos(phi); double sphi = sqrt(1.-sqr(cphi)); if ( phi > Constants::pi ) sphi = -sphi; P[i].setX(q*cphi*s); P[i].setY(q*sphi*s); P[i].setZ(q*c); P[i].rescaleEnergy(); P[i].boost(Q.boostVector()); P[i].rescaleEnergy(); nextQ = Q - P[i]; nextQ.setMass(M[i-1]); nextQ.rescaleEnergy(); Q = nextQ; } P.back() = Q; return weight; } double FlatInvertiblePhasespace::invertKinematics(const vector& P, Energy Ecm, double* r) const { vector m; for ( vector::const_iterator p = P.begin() + 2; p != P.end(); ++p ) m.push_back(p->mass()); size_t n = P.size() - 2; vector M(n-1); M[0] = Ecm; vector Q(n-1); Q[0] = Lorentz5Momentum(M[0]); for ( size_t i = 2; i <= n-1; ++i ) { for ( size_t k = i; k <= n; ++k ) Q[i-1] += P[k+1]; M[i-1] = Q[i-1].m(); } double weight = invertIntermediates(M,m,r); for ( size_t i = 2; i <= n; ++i ) { Lorentz5Momentum p = P[i]; p.boost(-Q[i-2].boostVector()); r[n-6+2*i] = (p.cosTheta()+1.)/2.; double phi = p.phi(); if ( phi < 0. ) phi = 2.*Constants::pi + phi; r[n-5+2*i] = phi/(2.*Constants::pi); } return weight; } double FlatInvertiblePhasespace::generateTwoToNKinematics(const double* r, vector& momenta) { double weight = generateKinematics(momenta,sqrt(lastXCombPtr()->lastSHat()),r); return weight; } long double FlatInvertiblePhasespace::flatWeights(int k) const{ using Constants::pi; if(k<2) { return -1; } else return pow((pi/2),(k-1)) * pow((2*pi),(4-3*k))/factorial(k-1)/factorial(k-2); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FlatInvertiblePhasespace::persistentOutput(PersistentOStream &) const {} void FlatInvertiblePhasespace::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigFlatInvertiblePhasespace("Herwig::FlatInvertiblePhasespace", "Herwig.so"); void FlatInvertiblePhasespace::Init() { static ClassDocumentation documentation ("FlatInvertiblePhasespace implements flat, invertible phase space generation."); } diff --git a/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h b/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h --- a/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h +++ b/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h @@ -1,204 +1,189 @@ // -*- C++ -*- // // FlatInvertiblePhasespace.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_FlatInvertiblePhasespace_H #define Herwig_FlatInvertiblePhasespace_H // // This is the declaration of the FlatInvertiblePhasespace class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief FlatInvertiblePhasespace implements flat, invertible phase space generation. * */ class FlatInvertiblePhasespace: public MatchboxPhasespace { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - FlatInvertiblePhasespace(); - - /** - * The destructor. - */ - virtual ~FlatInvertiblePhasespace(); - //@} - -public: - /** * Generate a phase space point and return its weight. */ virtual double generateTwoToNKinematics(const double*, vector& momenta); /** * Return the number of random numbers required to produce a given * multiplicity final state. */ virtual int nDimPhasespace(int nFinal) const { if ( nFinal == 1 ) return 1; return 3*nFinal - 4; } public: /** * Return true, if this phase space generator is invertible */ virtual bool isInvertible() const { return true; } /** * Invert the given phase space point to the random numbers which * would have generated it. */ virtual double invertTwoToNKinematics(const vector& momenta, double* r) const { return invertKinematics(momenta,(momenta[0]+momenta[1]).m(),r); } private: /** * Solve v = (n+2) * u^(n+1) - (n+1) * u^(n+2) for u */ double bisect(double v, double n, double target = -16., double maxLevel = 80.) const; /** * Return rho */ double rho(Energy M, Energy N, Energy m) const { return sqrt((sqr(M)-sqr(N+m))*(sqr(M)-sqr(N-m)))/(8.*sqr(M)); } /** * Generate intermediate masses for a massless final state */ double generateIntermediates(vector& K, const double* r) const; /** * Invert intermediate masses for a massless final state */ double invertIntermediates(const vector& K, double* r) const; /** * Generate intermediate masses for a massive final state */ double generateIntermediates(vector& M, const vector& m, const double* r) const; /** * Invert intermediate masses for a massive final state */ double invertIntermediates(const vector& M, const vector& m, double* r) const; /** * Generate momenta in the CMS */ double generateKinematics(vector& P, Energy Ecm, const double* r) const; /** * Invert momenta in the CMS */ double invertKinematics(const vector& P, Energy Ecm, double* r) const; /** * Return the appropriate phase space weight, * Eq. 11 in 1308.2922 * with the factor (2 pi)^4/(2 pi)^(3n) included * and the SHat of the process divided out to have everything expressed in the units of the ThePEG conventions, i.e. * without the Q^2 factor */ long double flatWeights(int n) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FlatInvertiblePhasespace & operator=(const FlatInvertiblePhasespace &) = delete; }; } #endif /* Herwig_FlatInvertiblePhasespace_H */ diff --git a/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.cc @@ -1,150 +1,145 @@ // -*- C++ -*- // // IFLightInvertedTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFLightInvertedTildeKinematics class. // #include "IFLightInvertedTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/EventGenerator.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -IFLightInvertedTildeKinematics::IFLightInvertedTildeKinematics() {} - -IFLightInvertedTildeKinematics::~IFLightInvertedTildeKinematics() {} - IBPtr IFLightInvertedTildeKinematics::clone() const { return new_ptr(*this); } IBPtr IFLightInvertedTildeKinematics::fullclone() const { return new_ptr(*this); } bool IFLightInvertedTildeKinematics::doMap(const double * r) { if ( ptMax() < ptCut() ) { jacobian(0.0); return false; } Lorentz5Momentum emitter = bornEmitterMomentum(); Lorentz5Momentum spectator = bornSpectatorMomentum(); double mapping = 1.0; pair ptz = generatePtZ(mapping,r); if ( mapping == 0.0 ) { jacobian(0.0); return false; } Energy pt = ptz.first; double z = ptz.second; double ratio = sqr(pt/lastScale()); double rho = 1. - 4.*ratio*z*(1.-z) / sqr(1. - z + ratio); if ( rho < 0. ) { jacobian(0.0); return false; } double x = 0.5*(1./ratio)*(1.-z+ratio)*(1.-sqrt(rho)); double u = 0.5*(1./(1.-z))*(1.-z+ratio)*(1.-sqrt(rho)); if ( x < emitterX() || x > 1. || u < 0. || u > 1. ) { jacobian(0.0); return false; } // This jacobian is (1/x^2)*dx*du mapping *= (1.-x)/((1.-z)*(z*(1.-z)+sqr(x-z))); jacobian(mapping*(sqr(lastScale())/sHat())/(16.*sqr(Constants::pi))); double phi = 2.*Constants::pi*r[2]; Lorentz5Momentum kt = getKt(emitter,spectator,pt,phi,true); subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = u; realEmitterMomentum() = (1./x)*emitter; realEmissionMomentum() = ((1.-x)*(1.-u)/x)*emitter + u*spectator + kt; realSpectatorMomentum() = ((1.-x)*u/x)*emitter + (1.-u)*spectator - kt; realEmitterMomentum().setMass(ZERO); realEmitterMomentum().rescaleEnergy(); realEmissionMomentum().setMass(ZERO); realEmissionMomentum().rescaleEnergy(); realSpectatorMomentum().setMass(ZERO); realSpectatorMomentum().rescaleEnergy(); return true; } Energy IFLightInvertedTildeKinematics::lastPt() const { Energy scale = sqrt(2.*(bornEmitterMomentum()*bornSpectatorMomentum())); double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; return scale * sqrt(u*(1.-u)*(1.-x)/x); } Energy IFLightInvertedTildeKinematics::ptMax() const { double x = emitterX(); return sqrt((1.-x)/x)*lastScale()/2.; } pair IFLightInvertedTildeKinematics::zBounds(Energy pt, Energy hardPt) const { hardPt = hardPt == ZERO ? ptMax() : min(hardPt,ptMax()); if(pt>hardPt) return make_pair(0.5,0.5); double s = sqrt(1.-sqr(pt/hardPt)); double x = emitterX(); return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); } double IFLightInvertedTildeKinematics::lastZ() const { double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; return 1. - (1.-x)*(1.-u); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFLightInvertedTildeKinematics::persistentOutput(PersistentOStream &) const { } void IFLightInvertedTildeKinematics::persistentInput(PersistentIStream &, int) { } void IFLightInvertedTildeKinematics::Init() { static ClassDocumentation documentation ("IFLightInvertedTildeKinematics inverts the initial-final tilde " "kinematics."); } // *** 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 describeHerwigIFLightInvertedTildeKinematics("Herwig::IFLightInvertedTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/IFLightInvertedTildeKinematics.h @@ -1,138 +1,123 @@ // -*- C++ -*- // // IFLightInvertedTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFLightInvertedTildeKinematics_H #define HERWIG_IFLightInvertedTildeKinematics_H // // This is the declaration of the IFLightInvertedTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFLightInvertedTildeKinematics inverts the final-final tilde * kinematics. * */ class IFLightInvertedTildeKinematics: public Herwig::InvertedTildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - IFLightInvertedTildeKinematics(); - - /** - * The destructor. - */ - virtual ~IFLightInvertedTildeKinematics(); - //@} - -public: - /** * Perform the mapping of the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the real * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(const double *); /** * Return the pt associated to the last generated splitting. */ virtual Energy lastPt() const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Return the upper bound on pt */ virtual Energy ptMax() const; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt = ZERO) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFLightInvertedTildeKinematics & operator=(const IFLightInvertedTildeKinematics &) = delete; }; } #endif /* HERWIG_IFLightInvertedTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.cc @@ -1,123 +1,118 @@ // -*- C++ -*- // // IFLightTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFLightTildeKinematics class. // #include "IFLightTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -IFLightTildeKinematics::IFLightTildeKinematics() {} - -IFLightTildeKinematics::~IFLightTildeKinematics() {} - IBPtr IFLightTildeKinematics::clone() const { return new_ptr(*this); } IBPtr IFLightTildeKinematics::fullclone() const { return new_ptr(*this); } bool IFLightTildeKinematics::doMap() { Lorentz5Momentum emitter = realEmitterMomentum(); Lorentz5Momentum emission = realEmissionMomentum(); Lorentz5Momentum spectator = realSpectatorMomentum(); double x = (- emission*spectator + emitter*spectator + emitter*emission) / (emitter*emission + emitter*spectator); double u = emitter*emission / (emitter*emission + emitter*spectator); subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = u; bornEmitterMomentum() = x*emitter; bornSpectatorMomentum() = spectator + emission - (1.-x)*emitter; bornEmitterMomentum().setMass(ZERO); bornEmitterMomentum().rescaleEnergy(); bornSpectatorMomentum().setMass(ZERO); bornSpectatorMomentum().rescaleEnergy(); return true; } Energy IFLightTildeKinematics::lastPt() const { Energy scale = sqrt(2.*(bornEmitterMomentum()*bornSpectatorMomentum())); double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; return scale * sqrt(u*(1.-u)*(1.-x)/x); } Energy IFLightTildeKinematics::lastPt(Lorentz5Momentum emitter,Lorentz5Momentum emission,Lorentz5Momentum spectator)const { double x = (- emission*spectator + emitter*spectator + emitter*emission) / (emitter*emission + emitter*spectator); double u = emitter*emission / (emitter*emission + emitter*spectator); Energy scale = sqrt(2.*(emission*emitter-emission*spectator+emitter*spectator)); return scale * sqrt(u*(1.-u)*(1.-x)/x); } pair IFLightTildeKinematics::zBounds(Energy pt, Energy hardPt) const { if(pt>hardPt) return make_pair(0.5,0.5); double s = sqrt(1.-sqr(pt/hardPt)); double x = emitterX(); return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); } double IFLightTildeKinematics::lastZ() const { double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; return 1. - (1.-x)*(1.-u); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFLightTildeKinematics::persistentOutput(PersistentOStream &) const { } void IFLightTildeKinematics::persistentInput(PersistentIStream &, int) { } void IFLightTildeKinematics::Init() { static ClassDocumentation documentation ("IFLightTildeKinematics implements the 'tilde' kinematics for " "a initial-final subtraction dipole."); } // *** 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 describeHerwigIFLightTildeKinematics("Herwig::IFLightTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/IFLightTildeKinematics.h @@ -1,146 +1,131 @@ // -*- C++ -*- // // IFLightTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFLightTildeKinematics_H #define HERWIG_IFLightTildeKinematics_H // // This is the declaration of the IFLightTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief IFLightTildeKinematics implements the 'tilde' kinematics for * a initial-final subtraction dipole. * */ class IFLightTildeKinematics: public TildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - IFLightTildeKinematics(); - - /** - * The destructor. - */ - virtual ~IFLightTildeKinematics(); - //@} - -public: - /** * Perform the mapping to the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the tilde * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(); /** * Return the pt associated to the last merged splitting. */ virtual Energy lastPt() const; /** * Return the pt associated to emitter emission and sppectator momentum. */ virtual Energy lastPt(Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum) const ; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt ) const; /* * True if phase space point is above the alpha cut for this dipole. */ bool aboveAlpha() const {return dipole()->alpha() ptz = generatePtZ(mapping,r); if ( mapping == 0.0 ){ jacobian(0.0); return false; } Energy pt = ptz.first; double z = ptz.second; // Compute x and u double ratio = sqr(pt)/scale; double muk2 = sqr(bornSpectatorData()->hardProcessMass())/scale; double rho = 1. - 4.*ratio*(1.-muk2)*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/(ratio*(1.-muk2))) * (1. - sqrt(rho)); double u = x*ratio / (1.-z); // Following Catani-Seymour paper double muk2CS = x*muk2; double up = (1.-x) / ( 1.-x + muk2CS ); if ( x < emitterX() || x > 1. || u < 0. || u > up ) { jacobian(0.0); return false; } // Store x and u subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = u; // jac = sajk*(1./x^2)*dx*du // Note - lastScale() is not equal to scale!!!!!!! double jac = u/x/(u + x - 2.*u*x*(1.-muk2))*scale/sqr(pt); mapping *= jac; jacobian( mapping*(sqr(lastScale())/sHat()) / (16.*sqr(Constants::pi)) ); // Compute the new momenta double phi = 2.*Constants::pi*r[2]; Lorentz5Momentum kt = getKt(emitter,spectator,pt,phi,true); realEmitterMomentum() = (1./x)*emitter; realEmissionMomentum() = ((1.-x)*(1.-u)/x - 2.*u*muk2)*emitter + u*spectator + kt; realSpectatorMomentum() = ((1.-x)*u/x + 2.*u*muk2)*emitter + (1.-u)*spectator - kt; realEmitterMomentum().setMass(ZERO); realEmitterMomentum().rescaleEnergy(); realEmissionMomentum().setMass(ZERO); realEmissionMomentum().rescaleEnergy(); realSpectatorMomentum().setMass(bornSpectatorData()->hardProcessMass()); realSpectatorMomentum().rescaleEnergy(); return true; } Energy IFMassiveInvertedTildeKinematics::lastPt() const { Energy2 scale = 2.*(bornEmitterMomentum()*bornSpectatorMomentum()); double muk2 = sqr(bornSpectatorData()->hardProcessMass())/scale; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; return sqrt(scale * ( u*(1.-u)*(1.-x)/x - u*u*muk2 )); } double IFMassiveInvertedTildeKinematics::lastZ() const { Energy2 scale = 2.*(bornEmitterMomentum()*bornSpectatorMomentum()); double muk2 = sqr(bornSpectatorData()->hardProcessMass())/scale; double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; return u + x + u*x*(muk2-1.); } Energy IFMassiveInvertedTildeKinematics::ptMax() const { double xe = emitterX(); Energy2 scale = 2.*(bornEmitterMomentum()*bornSpectatorMomentum()); Energy2 A = scale*(1.-xe)/xe; Energy2 mk2 = sqr(bornSpectatorData()->hardProcessMass()); return 0.5*A/sqrt(mk2+A); } pair IFMassiveInvertedTildeKinematics::zBounds(Energy pt, Energy hardPt) const { hardPt = hardPt == ZERO ? ptMax() : min(hardPt,ptMax()); if(pt>hardPt) return make_pair(0.5,0.5); double s = sqrt(1.-sqr(pt/hardPt)); double xe = emitterX(); return make_pair(0.5*(1.+xe-(1.-xe)*s),0.5*(1.+xe+(1.-xe)*s)); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFMassiveInvertedTildeKinematics::persistentOutput(PersistentOStream &) const { } void IFMassiveInvertedTildeKinematics::persistentInput(PersistentIStream &, int) { } void IFMassiveInvertedTildeKinematics::Init() { static ClassDocumentation documentation ("IFMassiveInvertedTildeKinematics inverts the initial-final tilde " "kinematics involving a massive particle."); } // *** 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 describeHerwigIFMassiveInvertedTildeKinematics("Herwig::IFMassiveInvertedTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/IFMassiveInvertedTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/IFMassiveInvertedTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/IFMassiveInvertedTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/IFMassiveInvertedTildeKinematics.h @@ -1,138 +1,123 @@ // -*- C++ -*- // // IFMassiveInvertedTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFMassiveInvertedTildeKinematics_H #define HERWIG_IFMassiveInvertedTildeKinematics_H // // This is the declaration of the IFMassiveInvertedTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Martin Stoll * * \brief IFMassiveInvertedTildeKinematics inverts the final-final tilde * kinematics. * */ class IFMassiveInvertedTildeKinematics: public Herwig::InvertedTildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - IFMassiveInvertedTildeKinematics(); - - /** - * The destructor. - */ - virtual ~IFMassiveInvertedTildeKinematics(); - //@} - -public: - /** * Perform the mapping of the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the real * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(const double *); /** * Return the pt associated to the last generated splitting. */ virtual Energy lastPt() const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Return the upper bound on pt */ virtual Energy ptMax() const; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt = ZERO) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMassiveInvertedTildeKinematics & operator=(const IFMassiveInvertedTildeKinematics &) = delete; }; } #endif /* HERWIG_IFMassiveInvertedTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.cc @@ -1,124 +1,119 @@ // -*- C++ -*- // // IFMassiveTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFMassiveTildeKinematics class. // #include "IFMassiveTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -IFMassiveTildeKinematics::IFMassiveTildeKinematics() {} - -IFMassiveTildeKinematics::~IFMassiveTildeKinematics() {} - IBPtr IFMassiveTildeKinematics::clone() const { return new_ptr(*this); } IBPtr IFMassiveTildeKinematics::fullclone() const { return new_ptr(*this); } bool IFMassiveTildeKinematics::doMap() { Lorentz5Momentum emitter = realEmitterMomentum(); Lorentz5Momentum emission = realEmissionMomentum(); Lorentz5Momentum spectator = realSpectatorMomentum(); double x = (- emission*spectator + emitter*spectator + emitter*emission) / (emitter*emission + emitter*spectator); double u = emitter*emission / (emitter*emission + emitter*spectator); subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = u; bornEmitterMomentum() = x*emitter; bornSpectatorMomentum() = spectator + emission - (1.-x)*emitter; bornEmitterMomentum().setMass(ZERO); bornEmitterMomentum().rescaleEnergy(); bornSpectatorMomentum().setMass(bornSpectatorData()->hardProcessMass()); bornSpectatorMomentum().rescaleEnergy(); return true; } Energy IFMassiveTildeKinematics::lastPt() const { Energy2 scale = 2.*(realEmissionMomentum()*realEmitterMomentum() -realEmissionMomentum()*realSpectatorMomentum() +realEmitterMomentum()*realSpectatorMomentum()); double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; double muk2 = sqr(bornSpectatorData()->hardProcessMass())/scale; return sqrt(scale * ( u*(1.-u)*(1.-x)/x - u*u*muk2 )); } Energy IFMassiveTildeKinematics::lastPt(Lorentz5Momentum emitter,Lorentz5Momentum emission,Lorentz5Momentum spectator)const { Energy2 scale = 2.*(emission*emitter-emission*spectator+emitter*spectator); double x = 0.5*scale / (emitter*emission + emitter*spectator); double u = emitter*emission / (emitter*emission + emitter*spectator); double muk2 = sqr(spectator.mass())/scale; return sqrt(scale * ( u*(1.-u)*(1.-x)/x - u*u*muk2 )); } pair IFMassiveTildeKinematics::zBounds(Energy pt, Energy hardPt) const { if(pt>hardPt) return make_pair(0.5,0.5); double s = sqrt(1.-sqr(pt/hardPt)); double xe = emitterX(); return make_pair(0.5*(1.+xe-(1.-xe)*s),0.5*(1.+xe+(1.-xe)*s)); } double IFMassiveTildeKinematics::lastZ() const { Energy2 scale = 2.*(realEmissionMomentum()*realEmitterMomentum() -realEmissionMomentum()*realSpectatorMomentum() +realEmitterMomentum()*realSpectatorMomentum()); double x = subtractionParameters()[0]; double u = subtractionParameters()[1]; double muk2 = sqr(bornSpectatorData()->hardProcessMass())/scale; return u + x - u*x*(1.-muk2); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFMassiveTildeKinematics::persistentOutput(PersistentOStream &) const { } void IFMassiveTildeKinematics::persistentInput(PersistentIStream &, int) { } void IFMassiveTildeKinematics::Init() { static ClassDocumentation documentation ("IFMassiveTildeKinematics implements the 'tilde' kinematics for " "a initial-final subtraction dipole involving a massive particle."); } // *** 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 describeHerwigIFMassiveTildeKinematics("Herwig::IFMassiveTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/IFMassiveTildeKinematics.h @@ -1,138 +1,123 @@ // -*- C++ -*- // // IFMassiveTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFMassiveTildeKinematics_H #define HERWIG_IFMassiveTildeKinematics_H // // This is the declaration of the IFMassiveTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Martin Stoll * * \brief IFMassiveTildeKinematics implements the 'tilde' kinematics for * a initial-final subtraction dipole. * */ class IFMassiveTildeKinematics: public TildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - IFMassiveTildeKinematics(); - - /** - * The destructor. - */ - virtual ~IFMassiveTildeKinematics(); - //@} - -public: - /** * Perform the mapping to the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the tilde * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(); /** * Return the pt associated to the last merged splitting. */ virtual Energy lastPt() const; /** * Return the pt associated to emitter emission and sppectator momentum. */ virtual Energy lastPt(Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum) const ; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt ) const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMassiveTildeKinematics & operator=(const IFMassiveTildeKinematics &) = delete; }; } #endif /* HERWIG_IFMassiveTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.cc @@ -1,125 +1,120 @@ // -*- C++ -*- // // IILightTildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IILightTildeKinematics class. // #include "IILightTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -IILightTildeKinematics::IILightTildeKinematics() {} - -IILightTildeKinematics::~IILightTildeKinematics() {} - IBPtr IILightTildeKinematics::clone() const { return new_ptr(*this); } IBPtr IILightTildeKinematics::fullclone() const { return new_ptr(*this); } Lorentz5Momentum IILightTildeKinematics::transform(const Lorentz5Momentum& k) const { LorentzMomentum res = k - 2.*((k*(K+Ktilde)/(K+Ktilde).m2())*(K+Ktilde)-((k*K)/(K.m2()))*Ktilde); return res; } bool IILightTildeKinematics::doMap() { Lorentz5Momentum emitter = realEmitterMomentum(); Lorentz5Momentum emission = realEmissionMomentum(); Lorentz5Momentum spectator = realSpectatorMomentum(); double x = (emitter*spectator - emitter*emission - spectator*emission)/(emitter*spectator); double v = (emitter*emission)/(emitter*spectator); subtractionParameters().resize(2); subtractionParameters()[0] = x; subtractionParameters()[1] = v; bornEmitterMomentum() = x * emitter; bornSpectatorMomentum() = spectator; bornEmitterMomentum().setMass(ZERO); bornEmitterMomentum().rescaleEnergy(); bornSpectatorMomentum().setMass(ZERO); bornSpectatorMomentum().rescaleEnergy(); K = emitter + spectator - emission; Ktilde = x * emitter + spectator; return true; } Energy IILightTildeKinematics::lastPt() const { Energy scale = sqrt(2.*(bornEmitterMomentum()*bornSpectatorMomentum())); double x = subtractionParameters()[0]; double v = subtractionParameters()[1]; return scale * sqrt(v*(1.-x-v)/x); } Energy IILightTildeKinematics::lastPt(Lorentz5Momentum ,Lorentz5Momentum emission,Lorentz5Momentum )const { return emission.perp(); } pair IILightTildeKinematics::zBounds(Energy pt, Energy hardPt) const { if(pt>hardPt) return make_pair(0.5,0.5); double root = (1.-emitterX())*sqrt(1.-sqr(pt/hardPt)); return make_pair(0.5*( 1.+emitterX() - root),0.5*( 1.+emitterX() + root)); } double IILightTildeKinematics::lastZ() const { double x = subtractionParameters()[0]; double v = subtractionParameters()[1]; return x + v; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IILightTildeKinematics::persistentOutput(PersistentOStream & os) const { os << ounit(K,GeV) << ounit(Ktilde,GeV); } void IILightTildeKinematics::persistentInput(PersistentIStream & is, int) { is >> iunit(K,GeV) >> iunit(Ktilde,GeV); } void IILightTildeKinematics::Init() { static ClassDocumentation documentation ("IILightTildeKinematics implements the 'tilde' kinematics for " "a initial-initial subtraction dipole."); } // *** 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 describeHerwigIILightTildeKinematics("Herwig::IILightTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/IILightTildeKinematics.h @@ -1,171 +1,156 @@ // -*- C++ -*- // // IILightTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IILightTildeKinematics_H #define HERWIG_IILightTildeKinematics_H // // This is the declaration of the IILightTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \breif IILightTildeKinematics implements the 'tilde' kinematics for * a initial-initial subtraction dipole. * */ class IILightTildeKinematics: public TildeKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - IILightTildeKinematics(); - - /** - * The destructor. - */ - virtual ~IILightTildeKinematics(); - //@} - -public: - /** * Perform the mapping to the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the tilde * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(); /** * Return the pt associated to the last merged splitting. */ virtual Energy lastPt() const; /** * Return the pt associated to emitter emission and sppectator momentum. */ //TODO: make this static? virtual Energy lastPt(Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum) const ; /** * Given a pt, return the boundaries on z */ virtual pair zBounds(Energy pt, Energy hardPt ) const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Return true, if this TildeKinematics object needs to transform * all other particles in the process except the emitter and spectator */ virtual bool doesTransform() const { return true; } /** * If this TildeKinematics object needs to transform all other particles * in the process except the emitter and spectator, return the transformed * momentum. */ virtual Lorentz5Momentum transform(const Lorentz5Momentum& p) const; /* * True if phase space point is above the alpha cut for this dipole. */ bool aboveAlpha() const {return dipole()->alpha() #include "InvertedTildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Utilities/Rebinder.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" - #include "Herwig/MatrixElement/Matchbox/Phasespace/RandomHelpers.h" using namespace Herwig; InvertedTildeKinematics::InvertedTildeKinematics() : HandlerBase(), theJacobian(0.0), thePtCut(0.0*GeV) {} -InvertedTildeKinematics::~InvertedTildeKinematics() {} - // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). Lorentz5Momentum InvertedTildeKinematics::getKt(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2, Energy pt, double phi, bool spacelike) const { Lorentz5Momentum P; if ( !spacelike ) P = p1 + p2; else P = p1 - p2; Energy2 Q2 = abs(P.m2()); Lorentz5Momentum Q = !spacelike ? Lorentz5Momentum(ZERO,ZERO,ZERO,sqrt(Q2),sqrt(Q2)) : Lorentz5Momentum(ZERO,ZERO,sqrt(Q2),ZERO,-sqrt(Q2)); if ( spacelike && Q.z() < P.z() ) Q.setZ(-Q.z()); bool boost = abs((P-Q).vect().mag2()/GeV2) > 1e-10 || abs((P-Q).t()/GeV) > 1e-5; boost &= (P*Q-Q.mass2())/GeV2 > 1e-8; Lorentz5Momentum inFrame1; if ( boost ) inFrame1 = p1 + ((P*p1-Q*p1)/(P*Q-Q.mass2()))*(P-Q); else inFrame1 = p1; Energy ptx = inFrame1.x(); Energy pty = inFrame1.y(); Energy q = 2.*inFrame1.z(); Energy Qp = sqrt(4.*(sqr(ptx)+sqr(pty))+sqr(q)); Energy Qy = sqrt(4.*sqr(pty)+sqr(q)); double cPhi = cos(phi); double sPhi = sqrt(1.-sqr(cPhi)); if ( phi > Constants::pi ) sPhi = -sPhi; Lorentz5Momentum kt; if ( !spacelike ) { kt.setT(ZERO); kt.setX(pt*Qy*cPhi/Qp); kt.setY(-pt*(4*ptx*pty*cPhi/Qp+q*sPhi)/Qy); kt.setZ(2.*pt*(-ptx*q*cPhi/Qp + pty*sPhi)/Qy); } else { kt.setT(2.*pt*(ptx*q*cPhi+pty*Qp*sPhi)/(q*Qy)); kt.setX(pt*(Qp*q*cPhi+4.*ptx*pty*sPhi)/(q*Qy)); kt.setY(pt*Qy*sPhi/q); kt.setZ(ZERO); } if ( boost ) kt = kt + ((P*kt-Q*kt)/(P*Q-Q.mass2()))*(P-Q); kt.setMass(-pt); kt.rescaleRho(); return kt; } Energy InvertedTildeKinematics::lastScale() const { if ( ( theDipole->bornEmitter() < 2 && theDipole->bornSpectator() > 1 ) || ( theDipole->bornEmitter() > 1 && theDipole->bornSpectator() < 2 ) ) { return -(bornEmitterMomentum()-bornSpectatorMomentum()).m(); } return (bornEmitterMomentum()+bornSpectatorMomentum()).m(); } pair InvertedTildeKinematics::generatePtZ(double& jac, const double * r, double pow, vector* ) const { double kappaMin = ptCut() != ZERO ? sqr(ptCut()/ptMax()) : sqr(0.1*GeV/GeV); double kappa; using namespace RandomHelpers; if ( ptCut() > ZERO ) { pair kw = pow==1. ? generate(inverse(0.,kappaMin,1.),r[0]) : generate(power(0.,-pow,kappaMin,1.),r[0]); kappa = kw.first; jac *= kw.second; } else { pair kw = generate((piecewise(), flat(1e-4,kappaMin), match(inverse(0.,kappaMin,1.))),r[0]); kappa = kw.first; jac *= kw.second; } Energy pt = sqrt(kappa)*ptMax(); pair zLims = zBounds(pt); pair zw(0,0);// = // generate(inverse(0.,zLims.first,zLims.second)+ // inverse(1.,zLims.first,zLims.second),r[1]); // FlatZ = 1 if ( theDipole->samplingZ() == 1 ) { zw = generate(flat(zLims.first,zLims.second),r[1]); } // OneOverZ = 2 if ( theDipole->samplingZ() == 2 ) { zw = generate(inverse(0.0,zLims.first,zLims.second),r[1]); } // OneOverOneMinusZ = 3 if ( theDipole->samplingZ() == 3 ) { zw = generate(inverse(1.0,zLims.first,zLims.second),r[1]); } // OneOverZOneMinusZ = 4 if ( theDipole->samplingZ() == 4 ) { zw = generate(inverse(0.0,zLims.first,zLims.second) + inverse(1.0,zLims.first,zLims.second),r[1]); } double z = zw.first; jac *= zw.second; jac *= sqr(ptMax()/lastScale()); return make_pair(pt,z); } void InvertedTildeKinematics::rebind(const TranslationMap & trans) { theDipole = trans.translate(theDipole); HandlerBase::rebind(trans); } IVector InvertedTildeKinematics::getReferences() { IVector ret = HandlerBase::getReferences(); ret.push_back(theDipole); return ret; } void InvertedTildeKinematics::persistentOutput(PersistentOStream & os) const { os << theDipole << theRealXComb << theBornXComb << ounit(theRealEmitterMomentum,GeV) << ounit(theRealEmissionMomentum,GeV) << ounit(theRealSpectatorMomentum,GeV) << theJacobian << ounit(thePtCut,GeV); } void InvertedTildeKinematics::persistentInput(PersistentIStream & is, int) { is >> theDipole >> theRealXComb >> theBornXComb >> iunit(theRealEmitterMomentum,GeV) >> iunit(theRealEmissionMomentum,GeV) >> iunit(theRealSpectatorMomentum,GeV) >> theJacobian >> iunit(thePtCut,GeV); } void InvertedTildeKinematics::Init() { static ClassDocumentation documentation ("InvertedTildeKinematics is the base class for the inverted 'tilde' " "kinematics being used for subtraction terms in the " "formalism of Catani and Seymour."); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeInvertedTildeKinematics("Herwig::InvertedTildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h @@ -1,450 +1,442 @@ // -*- C++ -*- // // InvertedTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_InvertedTildeKinematics_H #define HERWIG_InvertedTildeKinematics_H // // This is the declaration of the InvertedTildeKinematics class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief InvertedTildeKinematics is the base class for the inverted 'tilde' * kinematics being used for subtraction terms in the * formalism of Catani and Seymour. * */ class InvertedTildeKinematics: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ InvertedTildeKinematics(); - /** - * The destructor. - */ - virtual ~InvertedTildeKinematics(); - //@} - public: /** @name Access to kinematic quantities. */ //@{ /** * Return the momentum of the emitter in the real emission process */ const Lorentz5Momentum& realEmitterMomentum() const { return theRealEmitterMomentum; } /** * Return the momentum of the emission in the real emission process */ const Lorentz5Momentum& realEmissionMomentum() const { return theRealEmissionMomentum; } /** * Return the momentum of the spectator in the real emission process */ const Lorentz5Momentum& realSpectatorMomentum() const { return theRealSpectatorMomentum; } /** * Return the momentum of the emitter in the underlying Born process */ const Lorentz5Momentum& bornEmitterMomentum() const { return theBornXComb->meMomenta()[theDipole->bornEmitter()]; } /** * Return the momentum of the spectator in the underlying Born process */ const Lorentz5Momentum& bornSpectatorMomentum() const { return theBornXComb->meMomenta()[theDipole->bornSpectator()]; } /** * Return the momentum fraction of the emitter */ double emitterX() const { return theDipole->bornEmitter() == 0 ? theBornXComb->lastX1() : theBornXComb->lastX2(); } /** * Return the momentum fraction of the spectator */ double spectatorX() const { return theDipole->bornSpectator() == 0 ? theBornXComb->lastX1() : theBornXComb->lastX2(); } /** * Return the vector of dimensionless variables calculated */ const vector& subtractionParameters() const { return theDipole->subtractionParameters(); } /** * Return true, if this InvertedTildeKinematics object needs to transform * all other particles in the process except the emitter, emission and spectator */ virtual bool doesTransform() const { return false; } /** * If this InvertedTildeKinematics object needs to transform all other particles * in the process except the emitter, emission and spectator, return the transformed * momentum. */ virtual Lorentz5Momentum transform(const Lorentz5Momentum& p) const { return p; } /** * Return the centre of mass energy for the underlying Born configuration */ Energy2 sHat() const { return theBornXComb->lastSHat(); } //@} public: /** * Clone this object */ Ptr::ptr cloneMe() const { return dynamic_ptr_cast::ptr>(clone()); } /** @name Access to process data. */ //@{ /** * Prepare given a dipole, and XCombs describing the real emission * and underlying Born processes, respectively. */ void prepare(tcStdXCombPtr newRealXComb, tcStdXCombPtr newBornXComb) { theRealXComb = newRealXComb; theBornXComb = newBornXComb; } /** * Return the real xcomb */ tcStdXCombPtr realXComb() const { return theRealXComb; } /** * Return the Born xcomb */ tcStdXCombPtr bornXComb() const { return theBornXComb; } /** * Set the current dipole */ void dipole(Ptr::tptr dip) { theDipole = dip; } /** * Return the current dipole */ Ptr::tptr dipole() { return theDipole; } /** * Return the current dipole */ Ptr::tcptr dipole() const { return theDipole; } /** * Return the number of random numbers needed to generate * a real emission configuration off the underlying Born * configuration. */ virtual int nDimRadiation() const { return 3; } /** * Perform the mapping of the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the real * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(const double *) = 0; /** * Set an optional cutoff on the emission's * transverse momentum. */ void ptCut(Energy pt) { thePtCut = pt; } /** * Return the optional cutoff on the emission's * transverse momentum. */ Energy ptCut() const { return thePtCut; } /** * Return the random number index * corresponding to the evolution variable. */ virtual int evolutionVariable() const { return 0; } /** * Return the cutoff on the evolution * random number corresponding to the pt cut. */ virtual double evolutionCutoff() const { return 0.0; } /** * Return the pt associated to the last generated splitting. */ virtual Energy lastPt() const = 0; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const = 0; /** * Return the relevant dipole scale */ virtual Energy lastScale() const; /** * Return the upper bound on pt */ virtual Energy ptMax() const = 0; /** * Given a pt and a hard pt, return the boundaries on z; if the hard * pt is zero, ptMax() will be used. */ virtual pair zBounds(Energy pt, Energy hardPt = ZERO) const = 0; /** * Generate pt and z */ virtual pair generatePtZ(double& jac, const double * r, double power=1., vector* values = NULL) const; /** * Return the single particle phase space weight in units * of sHat() for the last selected configuration. */ double jacobian() const { return theJacobian; } /** * Return the particle type of the emitter in the real emission process */ cPDPtr realEmitterData() const { return (theDipole && theRealXComb) ? theRealXComb->mePartonData()[theDipole->realEmitter()] : cPDPtr(); } /** * Return the particle type of the emission in the real emission process */ cPDPtr realEmissionData() const { return (theDipole && theRealXComb) ? theRealXComb->mePartonData()[theDipole->realEmission()] : cPDPtr(); } /** * Return the particle type of the spectator in the real emission process */ cPDPtr realSpectatorData() const { return (theDipole && theRealXComb) ? theRealXComb->mePartonData()[theDipole->realSpectator()] : cPDPtr(); } /** * Return the particle type of the emitter in the underlying Born process */ cPDPtr bornEmitterData() const { return (theDipole && theBornXComb) ? theBornXComb->mePartonData()[theDipole->bornEmitter()] : cPDPtr(); } /** * Return the particle type of the spectator in the underlying Born process */ cPDPtr bornSpectatorData() const { return (theDipole && theBornXComb) ? theBornXComb->mePartonData()[theDipole->bornSpectator()] : cPDPtr(); } //@} protected: /** * Access the momentum of the emitter in the real emission process */ Lorentz5Momentum& realEmitterMomentum() { return theRealEmitterMomentum; } /** * Access the momentum of the emission in the real emission process */ Lorentz5Momentum& realEmissionMomentum() { return theRealEmissionMomentum; } /** * Access the momentum of the spectator in the real emission process */ Lorentz5Momentum& realSpectatorMomentum() { return theRealSpectatorMomentum; } /** * Access the vector of dimensionless variables calculated */ vector& subtractionParameters() { return theDipole->subtractionParameters(); } /** * Set the single particle phase space weight in units * of sHat() for the last selected configuration. */ void jacobian(double w) { theJacobian = w; } /** * Calculate a transverse momentum for the given momenta, * invariant pt and azimuth. */ Lorentz5Momentum getKt(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2, Energy pt, double phi, bool spacelike = false) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). 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: /** * The last dipole this InvertedTildeKinematics has been selected for */ Ptr::tptr theDipole; /** * The XComb object describing the real emission process */ tcStdXCombPtr theRealXComb; /** * The XComb object describing the underlying Born process */ tcStdXCombPtr theBornXComb; /** * The momentum of the emitter in the real emission process */ Lorentz5Momentum theRealEmitterMomentum; /** * The momentum of the emission in the real emission process */ Lorentz5Momentum theRealEmissionMomentum; /** * The momentum of the spectator in the real emission process */ Lorentz5Momentum theRealSpectatorMomentum; /** * Return the single particle phase space weight in units * of sHat() for the last selected configuration. */ double theJacobian; /** * The optional cutoff on the emission's * transverse momentum. */ Energy thePtCut; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ InvertedTildeKinematics & operator=(const InvertedTildeKinematics &) = delete; }; } #endif /* HERWIG_InvertedTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc --- a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc +++ b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc @@ -1,565 +1,563 @@ // -*- C++ -*- // // MatchboxPhasespace.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxPhasespace class. // #include "MatchboxPhasespace.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Reference.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/Utility/ProcessData.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" using namespace Herwig; MatchboxPhasespace::MatchboxPhasespace() : singularCutoff(10*GeV), theUseMassGenerators(false), theLoopParticleIdMin(200001), theLoopParticleIdMax(200100) {} -MatchboxPhasespace::~MatchboxPhasespace() {} - void MatchboxPhasespace::cloneDependencies(const std::string&) {} Ptr::tcptr MatchboxPhasespace::factory() const { return MatchboxFactory::currentFactory(); } Ptr::tptr MatchboxPhasespace::processData() const { return factory()->processData(); } double MatchboxPhasespace::generateKinematics(const double* r, vector& momenta) { diagramWeights().clear(); cPDVector::const_iterator pd = mePartonData().begin() + 2; vector::iterator p = momenta.begin() + 2; double massJacobian = 1.; Energy summ = ZERO; if ( useMassGenerators() ) { Energy gmass = ZERO; tGenericMassGeneratorPtr mgen; Energy maxMass = (!haveX1X2() && momenta.size() > 3) ? sqrt(lastSHat()) : sqrt(lastS()); for ( ; pd != mePartonData().end(); ++pd, ++p ) { mgen = processData()->massGenerator(*pd); if ( mgen && !isInvertible() ) { Energy massMax = min((**pd).massMax(),maxMass); Energy massMin = (**pd).massMin(); if ( massMin > massMax ) return 0.0; gmass = mgen->mass(massJacobian,**pd,massMin,massMax,r[0]); ++r; } else if ( (**pd).hardProcessWidth() != ZERO ) { Energy massMax = min((**pd).massMax(),maxMass); Energy massMin = (**pd).massMin(); if ( massMin > massMax ) return 0.0; // use a standard Breit Wigner here which we can invert // see invertKinematics as well double bwILow = atan((sqr(massMin)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth())); double bwIUp = atan((sqr(massMax)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth())); gmass = sqrt(sqr((**pd).hardProcessMass()) + (**pd).hardProcessMass()*(**pd).hardProcessWidth()*tan(bwILow+r[0]*(bwIUp-bwILow))); ++r; } else { gmass = (**pd).hardProcessMass(); } maxMass -= gmass; p->setMass(gmass); summ += gmass; } } else { for ( ; pd != mePartonData().end(); ++pd, ++p ) { summ += (**pd).hardProcessMass(); p->setMass((**pd).hardProcessMass()); } } if ( momenta.size() > 3 && !haveX1X2() ) { if ( summ > (momenta[0]+momenta[1]).m() ) return 0.0; } double weight = momenta.size() > 3 ? generateTwoToNKinematics(r,momenta) : generateTwoToOneKinematics(r,momenta); fillDiagramWeights(); return weight*massJacobian; } double MatchboxPhasespace::generateTwoToOneKinematics(const double* r, vector& momenta) { double tau = momenta[2].mass2()/lastXCombPtr()->lastS(); double ltau = log(tau)/2.; //old: y = ltau - 2.*r[0]*ltau; x1 = sqrt(tau)*exp(y); x2 = sqrt(tau)*exp(-y); double x1=pow(tau,1.-r[0]); double x2=pow(tau,r[0]); // Due to the proton mass and P1.e() + P2.e() == lastS() we multiply here // with the correction factor abs(P1.e()/P1.z()) to produce incoming // p1/2 = (e1/2,0,0,+/- e1/2) Lorentz5Momentum P1 = lastXCombPtr()->lastParticles().first->momentum(); ThreeVector p1 = x1 * (P1.vect()) * abs(P1.e()/P1.z()); Lorentz5Momentum P2 = lastXCombPtr()->lastParticles().second->momentum(); ThreeVector p2 = x2 * (P2.vect()) * abs(P2.e()/P2.z()); ThreeVector q = p1 + p2; momenta[0] = Lorentz5Momentum(momenta[0].mass(),p1); momenta[1] = Lorentz5Momentum(momenta[1].mass(),p2); momenta[2] = Lorentz5Momentum(momenta[2].mass(),q); // check for energy conservation: if ((momenta[0]+momenta[1]-momenta[2]).e()>pow(10,-9)*GeV) generator()->log() << "Warning: Momentum conservation in generateTwoToOneKinematics not precise.\n" << flush; lastXCombPtr()->lastX1X2({x1,x2}); lastXCombPtr()->lastSHat((momenta[0]+momenta[1]).m2()); return -4.*Constants::pi*ltau; } double MatchboxPhasespace::invertKinematics(const vector& momenta, double* r) const { if ( useMassGenerators() ) { Energy gmass = ZERO; Energy maxMass = (!haveX1X2() && momenta.size() > 3) ? sqrt((momenta[0]+momenta[1]).m2()) : sqrt(lastS()); cPDVector::const_iterator pd = mePartonData().begin() + 2; vector::const_iterator p = momenta.begin() + 2; for ( ; pd != mePartonData().end(); ++pd, ++p ) { if ( (**pd).hardProcessWidth() != ZERO ) { Energy massMax = min((**pd).massMax(),maxMass); Energy massMin = (**pd).massMin(); if ( massMin > massMax ) return 0.0; double bwILow = atan((sqr(massMin)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth())); double bwIUp = atan((sqr(massMax)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth())); gmass = p->mass(); double bw = atan((sqr(gmass)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth())); r[0] = (bw-bwILow)/(bwIUp-bwILow); ++r; } else { gmass = (**pd).hardProcessMass(); } maxMass -= gmass; } } return momenta.size() > 3 ? invertTwoToNKinematics(momenta,r) : invertTwoToOneKinematics(momenta,r); } double MatchboxPhasespace::invertTwoToOneKinematics(const vector& momenta, double* r) const { double tau = momenta[2].mass2()/lastXCombPtr()->lastS(); double ltau = log(tau)/2.; r[0] = (ltau - (momenta[0]+momenta[1]).rapidity())/(2.*ltau); return -4.*Constants::pi*ltau; } void MatchboxPhasespace::setCoupling(long a, long b, long c, double coupling, bool includeCrossings) { cPDPtr A = getParticleData(a); cPDPtr B = getParticleData(b); cPDPtr C = getParticleData(c); if ( !A || !B || !C ) { generator()->log() << "Warning: could not determine particle data for ids " << a << " " << b << " " << c << " when setting coupling in MatchboxPhasespace.\n" << flush; return; } if ( !includeCrossings ) { theCouplings->couplings()[LTriple(a,b,c)] = coupling; return; } if ( A->CC() ) { theCouplings->couplings()[LTriple(-a,b,c)] = coupling; theCouplings->couplings()[LTriple(-a,c,b)] = coupling; } else { theCouplings->couplings()[LTriple(a,b,c)] = coupling; theCouplings->couplings()[LTriple(a,c,b)] = coupling; } if ( B->CC() ) { theCouplings->couplings()[LTriple(-b,a,c)] = coupling; theCouplings->couplings()[LTriple(-b,c,a)] = coupling; } else { theCouplings->couplings()[LTriple(b,a,c)] = coupling; theCouplings->couplings()[LTriple(b,c,a)] = coupling; } if ( C->CC() ) { theCouplings->couplings()[LTriple(-c,a,b)] = coupling; theCouplings->couplings()[LTriple(-c,b,a)] = coupling; } else { theCouplings->couplings()[LTriple(c,a,b)] = coupling; theCouplings->couplings()[LTriple(c,b,a)] = coupling; } } string MatchboxPhasespace::doSetCoupling(string in) { istringstream is(in); long a,b,c; double coupling; is >> a >> b >> c >> coupling; if ( !is ) return "MatchboxPhasespace: error in setting coupling."; setCoupling(a,b,c,coupling,true); return ""; } string MatchboxPhasespace::doSetPhysicalCoupling(string in) { istringstream is(in); long a,b,c; double coupling; is >> a >> b >> c >> coupling; if ( !is ) return "MatchboxPhasespace: error in setting coupling."; setCoupling(a,b,c,coupling,false); return ""; } pair MatchboxPhasespace::timeLikeWeight(const Tree2toNDiagram& diag, int branch, double flatCut) const { pair children = diag.children(branch); if ( children.first == -1 ) { return make_pair(1.,meMomenta()[diag.externalId(branch)]); } pair res = timeLikeWeight(diag,children.first,flatCut); pair other = timeLikeWeight(diag,children.second,flatCut); res.first *= other.first; res.second += other.second; LTriple vertexKey(diag.allPartons()[branch]->id(), diag.allPartons()[children.first]->id(), diag.allPartons()[children.second]->id()); map::const_iterator cit = theCouplings->couplings().find(vertexKey); if ( cit != theCouplings->couplings().end() ){ res.first *= cit->second; } Energy2 mass2 = sqr(diag.allPartons()[branch]->hardProcessMass()); Energy2 width2 = sqr(diag.allPartons()[branch]->hardProcessWidth()); if ( abs(diag.allPartons()[branch]->id()) >= theLoopParticleIdMin && abs(diag.allPartons()[branch]->id()) <= theLoopParticleIdMax ) { // "loop particle" if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut ) { res.first /= abs((res.second.m2()-mass2)/GeV2); res.first *= log(abs((res.second.m2()-mass2)/GeV2)); // normal. of the argument in the log? } } else { if ( width2 == ZERO ) { if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut ) res.first /= abs((res.second.m2()-mass2)/GeV2); } else { res.first /= (sqr((res.second.m2()-mass2)/GeV2) + mass2*width2/sqr(GeV2))/(abs(res.second.m2()/GeV2)); } } return res; } double MatchboxPhasespace::spaceLikeWeight(const Tree2toNDiagram& diag, const Lorentz5Momentum& incoming, int branch, double flatCut) const { if ( branch == -1 ) return 1.; pair children = diag.children(branch); pair res = timeLikeWeight(diag,children.second,flatCut); LTriple vertexKey(diag.allPartons()[branch]->id(), diag.allPartons()[children.first]->id(), diag.allPartons()[children.second]->id()); if ( children.first == diag.nSpace() - 1 ) { if ( diag.allPartons()[children.first]->CC() ) vertexKey = LTriple(diag.allPartons()[branch]->id(), diag.allPartons()[children.second]->id(), diag.allPartons()[children.first]->CC()->id()); else vertexKey = LTriple(diag.allPartons()[branch]->id(), diag.allPartons()[children.second]->id(), diag.allPartons()[children.first]->id()); } map::const_iterator cit = theCouplings->couplings().find(vertexKey); if ( cit != theCouplings->couplings().end() ){ res.first *= cit->second; } if ( children.first == diag.nSpace() - 1 ) { return res.first; } res.second = incoming - res.second; Energy2 mass2 = sqr(diag.allPartons()[children.first]->hardProcessMass()); Energy2 width2 = sqr(diag.allPartons()[children.first]->hardProcessWidth()); if ( abs(diag.allPartons()[children.first]->id()) >= theLoopParticleIdMin && (diag.allPartons()[children.first]->id()) <= theLoopParticleIdMax ) { // "loop particle" if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut ) { res.first /= abs((res.second.m2()-mass2)/GeV2); res.first *= log(abs((res.second.m2()-mass2)/GeV2)); // normal. of the argument in the log? } } else { if ( width2 == ZERO ) { if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut ) res.first /= abs((res.second.m2()-mass2)/GeV2); } else { res.first /= (sqr((res.second.m2()-mass2)/GeV2) + mass2*width2/sqr(GeV2))/(abs(res.second.m2()/GeV2)); } } return res.first * spaceLikeWeight(diag,res.second,children.first,flatCut); } void MatchboxPhasespace::fillDiagramWeights(double flatCut) { if ( !diagramWeights().empty() ) return; for ( auto & d : lastXComb().diagrams() ) { diagramWeights()[d->id()] = spaceLikeWeight(dynamic_cast(*d),meMomenta()[0],0,flatCut); } } Selector MatchboxPhasespace::selectDiagrams(const MEBase::DiagramVector& diags) const { Selector ret; for ( MEBase::DiagramIndex d = 0; d < diags.size(); ++d ) { ret.insert(diagramWeight(dynamic_cast(*diags[d])),d); } return ret; } bool MatchboxPhasespace::matchConstraints(const vector& momenta) { if ( singularLimits().empty() ) return true; lastSingularLimit() = singularLimits().begin(); for ( ; lastSingularLimit() != singularLimits().end(); ++lastSingularLimit() ) { if ( lastSingularLimit()->first == lastSingularLimit()->second && momenta[lastSingularLimit()->first].t() < singularCutoff ) break; if ( lastSingularLimit()->first != lastSingularLimit()->second && sqrt(momenta[lastSingularLimit()->first]* momenta[lastSingularLimit()->second]) < singularCutoff ) { bool match = true; for ( set >::const_iterator other = singularLimits().begin(); other != singularLimits().end(); ++other ) { if ( other == lastSingularLimit() ) continue; if ( other->first == other->second && momenta[other->first].t() < singularCutoff ) { match = false; break; } if ( other->first != other->second && sqrt(momenta[other->first]* momenta[other->second]) < singularCutoff ) { match = false; break; } } if ( match ) break; } } return lastSingularLimit() != singularLimits().end(); } int MatchboxPhasespace::nDim(const cPDVector& data) const { int ndimps = nDimPhasespace(data.size()-2); if ( useMassGenerators() ) { for ( cPDVector::const_iterator pd = data.begin(); pd != data.end(); ++pd ) { if ( (**pd).massGenerator() || (**pd).hardProcessWidth() != ZERO ) { ++ndimps; } } } return ndimps; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxPhasespace::persistentOutput(PersistentOStream & os) const { os << theLastXComb << ounit(singularCutoff,GeV) << theUseMassGenerators << theLoopParticleIdMin << theLoopParticleIdMax << theCouplings; } void MatchboxPhasespace::persistentInput(PersistentIStream & is, int) { is >> theLastXComb >> iunit(singularCutoff,GeV) >> theUseMassGenerators >> theLoopParticleIdMin >> theLoopParticleIdMax >> theCouplings; lastMatchboxXComb(theLastXComb); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeMatchboxPhasespace("Herwig::MatchboxPhasespace", "Herwig.so"); void MatchboxPhasespace::Init() { static ClassDocumentation documentation ("MatchboxPhasespace defines an abstract interface to a phase " "space generator."); static Parameter interfaceSingularCutoff ("SingularCutoff", "[debug] Cutoff below which a region is considered singular.", &MatchboxPhasespace::singularCutoff, GeV, 10.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); interfaceSingularCutoff.rank(-1); /* static Switch interfaceUseMassGenerators ("UseMassGenerators", "Use mass generators instead of fixed masses.", &MatchboxPhasespace::theUseMassGenerators, false, false, false); static SwitchOption interfaceUseMassGeneratorsYes (interfaceUseMassGenerators, "Yes", "Use mass generators.", true); static SwitchOption interfaceUseMassGeneratorsNo (interfaceUseMassGenerators, "No", "Do not use mass generators.", false); */ static Command interfaceSetCoupling ("SetCoupling", "", &MatchboxPhasespace::doSetCoupling, false); static Command interfaceSetPhysicalCoupling ("SetPhysicalCoupling", "", &MatchboxPhasespace::doSetPhysicalCoupling, false); static Parameter interfaceLoopParticleIdMin ("LoopParticleIdMin", "First id in a range of id's meant to denote fictitious " "'ghost' particles to be used by the diagram generator " "in loop induced processes.", &MatchboxPhasespace::theLoopParticleIdMin, 200001, 0, 0, false, false, Interface::lowerlim); interfaceLoopParticleIdMin.rank(-1); static Parameter interfaceLoopParticleIdMax ("LoopParticleIdMax", "Last id in a range of id's meant to denote fictitious " "'ghost' particles to be used by the diagram generator " "in loop induced processes.", &MatchboxPhasespace::theLoopParticleIdMax, 200100, 0, 0, false, false, Interface::lowerlim); interfaceLoopParticleIdMax.rank(-1); static Reference interfaceCouplingData ("CouplingData", "Set the storage for the couplings.", &MatchboxPhasespace::theCouplings, false, false, true, false, false); interfaceCouplingData.rank(-1); } diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h --- a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h +++ b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h @@ -1,366 +1,358 @@ // -*- C++ -*- // // MatchboxPhasespace.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MatchboxPhasespace_H #define HERWIG_MatchboxPhasespace_H // // This is the declaration of the MatchboxPhasespace class. // #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h" #include "Herwig/MatrixElement/Matchbox/Utility/ProcessData.fh" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.fh" #include "Herwig/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief Wrap around a vector of random numbers to behave as a stream * of those. */ struct StreamingRnd { /** * The random numbers */ const double* numbers; /** * The number of random numbers available. */ size_t nRnd; /** * Default constructor. */ StreamingRnd() : numbers(0), nRnd(0) {} /** * Construct from random numbers. */ explicit StreamingRnd(const double* newNumbers, size_t n) : numbers(newNumbers), nRnd(n) {} /** * Return next random number */ inline double operator()() { assert(numbers && nRnd > 0); const double ret = numbers[0]; ++numbers; --nRnd; return ret; } }; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxPhasespace defines an abstract interface to a phase * space generator. * */ class MatchboxPhasespace: public HandlerBase, public LastXCombInfo, public LastMatchboxXCombInfo { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxPhasespace(); - /** - * The destructor. - */ - virtual ~MatchboxPhasespace(); - //@} - public: /** * Set the XComb object steering the Born matrix * element this class represents virtual corrections to. */ virtual void setXComb(tStdXCombPtr xc) { theLastXComb = xc; lastMatchboxXComb(xc); } /** * Return the factory object */ Ptr::tcptr factory() const; /** * Return the process data object */ Ptr::tptr processData() const; /** * Generate a phase space point and return its weight. */ virtual double generateKinematics(const double* r, vector& momenta); /** * Generate a phase space point and return its weight. */ virtual double generateTwoToNKinematics(const double*, vector& momenta) = 0; /** * Generate a 2 -> 1 phase space point and return its weight. */ virtual double generateTwoToOneKinematics(const double*, vector& momenta); /** * Return the number of random numbers required to produce a given * multiplicity final state. */ virtual int nDim(const cPDVector&) const; /** * Return the number of random numbers required to produce a given * multiplicity final state. */ virtual int nDimPhasespace(int nFinal) const = 0; /** * Return true, if this phasespace generator will generate incoming * partons itself. */ virtual bool haveX1X2() const { return false; } /** * Return true, if this phase space generator expects * the incoming partons in their center-of-mass system */ virtual bool wantCMS() const { return true; } /** * True, if mass generators should be used instead of fixed masses */ bool useMassGenerators() const { return theUseMassGenerators; } /** * Fill a diagram selector for the last phase space point. */ virtual Selector selectDiagrams(const MEBase::DiagramVector&) const; /** * Return the momentum and weight appropriate to the given timelike * branch of the diagram. */ pair timeLikeWeight(const Tree2toNDiagram& diag, int branch, double flatCut) const; /** * Return the weight appropriate to the given spacelike branch of * the diagram. */ double spaceLikeWeight(const Tree2toNDiagram& diag, const Lorentz5Momentum& incoming, int branch, double flatCut) const; /** * Return the weight appropriate to the given diagram. */ double diagramWeight(const Tree2toNDiagram& diag) const { assert( !diagramWeights().empty() ); return diagramWeights().find(diag.id())->second; } /** * Fill the diagram weights. */ void fillDiagramWeights(double flatCut = 0.0); /** * Clear the diagram weights. */ void clearDiagramWeights() { diagramWeights().clear(); } /** * Clone this phase space generator. */ Ptr::ptr cloneMe() const { return dynamic_ptr_cast::ptr>(clone()); } /** * Clone the dependencies, using a given prefix. */ virtual void cloneDependencies(const std::string& prefix = ""); public: /** * Return true, if this phase space generator is invertible */ virtual bool isInvertible() const { return false; } /** * Invert the given phase space point to the random numbers which * would have generated it. */ virtual double invertKinematics(const vector& momenta, double* r) const; /** * Invert the given phase space point to the random numbers which * would have generated it. */ virtual double invertTwoToNKinematics(const vector&, double*) const { return 0.; } /** * Invert the given 2 -> 1 phase space point to the random numbers which * would have generated it. */ virtual double invertTwoToOneKinematics(const vector&, double*) const; public: /** * Limit phasespace generation to a given collinear or soft limit. */ void singularLimit(size_t i, size_t j) { if ( i > j ) swap(i,j); singularLimits().insert(make_pair(i,j)); } /** * Return the last matched singular limit. */ const pair& lastSingularIndices() const { assert(lastSingularLimit() != singularLimits().end()); return *lastSingularLimit(); } /** * Return true, if constraints on phasespace generation have been met. */ bool matchConstraints(const vector& momenta); protected: /** * Set a coupling for the given vertex; the convention is that all * legs are outgoing, and all possible crossings will be taken care * of. If not set, coupling weights default to one. */ void setCoupling(long a, long b, long c, double coupling, bool includeCrossings = true); 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); //@} public: /** * 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: /** * A cutoff below which a region is considered singular. */ Energy singularCutoff; /** * True, if mass generators should be used instead of fixed masses */ bool theUseMassGenerators; /** * Couplings to be used in diagram weighting */ Ptr::ptr theCouplings; /** * Interface function to setcoupling */ string doSetCoupling(string); /** * Interface function to setcoupling */ string doSetPhysicalCoupling(string); /** * The first id in a range of id's meant to denote fictitious * 'ghost' particles to be used by the diagram generator * in loop induced processes. */ int theLoopParticleIdMin; /** * The last id in a range of id's meant to denote fictitious * 'ghost' particles to be used by the diagram generator * in loop induced processes. */ int theLoopParticleIdMax; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxPhasespace & operator=(const MatchboxPhasespace &) = delete; }; } #endif /* HERWIG_MatchboxPhasespace_H */ diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxRambo.cc b/MatrixElement/Matchbox/Phasespace/MatchboxRambo.cc --- a/MatrixElement/Matchbox/Phasespace/MatchboxRambo.cc +++ b/MatrixElement/Matchbox/Phasespace/MatchboxRambo.cc @@ -1,263 +1,261 @@ // -*- C++ -*- // // MatchboxRambo.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxRambo class. // #include "MatchboxRambo.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Utilities/GSLBisection.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MatchboxRambo::MatchboxRambo() : needToReshuffle(false), theMakeReferenceSample(false), referenceSample(0) {} -MatchboxRambo::~MatchboxRambo() {} - IBPtr MatchboxRambo::clone() const { return new_ptr(*this); } IBPtr MatchboxRambo::fullclone() const { return new_ptr(*this); } static double weights[7] = { -1.,-1., 0.039788735772973833942, 0.00012598255637968550463, 1.3296564302788840628E-7, 7.0167897579949011130E-11, 2.2217170114046130768E-14 }; void MatchboxRambo::setXComb(tStdXCombPtr xc) { MatchboxPhasespace::setXComb(xc); needToReshuffle = false; if ( xc ) { for ( cPDVector::const_iterator d = mePartonData().begin(); d != mePartonData().end(); ++d ) { if ( (**d).hardProcessMass() != ZERO ) { needToReshuffle = true; break; } } } } void MatchboxRambo::dumpReference(const vector& momenta, double weight) const { *referenceSample << lastX1() << " " << lastX2() << " "; Boost toLab = (lastPartons().first->momentum() + lastPartons().second->momentum()).boostVector(); for ( vector::const_iterator p = momenta.begin(); p != momenta.end(); ++p ) { Lorentz5Momentum pl = *p; if ( toLab.mag2() > Constants::epsilon ) pl.boost(toLab); *referenceSample << (pl.x()/GeV) << " " << (pl.y()/GeV) << " " << (pl.z()/GeV) << " " << (pl.t()/GeV) << " " << (pl.mass()/GeV) << " "; } double ymax = lastCuts().yHatMax(); double ymin = lastCuts().yHatMin(); double km = log(lastCuts().sHatMax()/lastCuts().sHatMin()); ymax = min(ymax, log(lastCuts().x1Max()*sqrt(lastS()/lastSHat()))); ymin = max(ymin, -log(lastCuts().x2Max()*sqrt(lastS()/lastSHat()))); *referenceSample << weight*km*(ymax-ymin)/(lastX1()*lastX2()) << "\n" << flush; } double MatchboxRambo::generateTwoToNKinematics(const double* r, vector& momenta) { if ( theMakeReferenceSample ) { map::iterator ref = referenceSamples.find(mePartonData()); if ( ref == referenceSamples.end() ) { ostringstream refname; for ( cPDVector::const_iterator p = mePartonData().begin(); p != mePartonData().end(); ++p ) { refname << (**p).PDGName(); } refname << ".rambo"; referenceSamples[mePartonData()] = new ofstream(refname.str().c_str(),std::ios_base::app); ref = referenceSamples.find(mePartonData()); *(ref->second) << setprecision(26); } assert(ref != referenceSamples.end()); referenceSample = ref->second; } size_t offset = 2; if ( lastXCombPtr() ) offset = dynamic_cast(*lastXComb().diagrams().front()).nSpace() > 0 ? 2 : 1; Energy w = sqrt(lastSHat()); size_t count = 0; Lorentz5Momentum Q; for ( vector::iterator k = momenta.begin() + offset; k != momenta.end(); ++k ) { Energy q = -w*log(r[count]*r[count+1]); double ct = 2.*r[count+2]-1.; double st = sqrt(1.-sqr(ct)); double phi = 2.*Constants::pi*r[count+3]; double cphi = cos(phi); double sphi = sqrt(1.-sqr(cphi)); if ( phi > Constants::pi ) sphi = -sphi; (*k).setMass(ZERO); (*k).setT(q); (*k).setX(q*cphi*st); (*k).setY(q*sphi*st); (*k).setZ(q*ct); count += 4; Q += *k; } Energy M = sqrt(Q.m2()); double x = w/M; Boost beta = -(Q.vect() * (1./M)); double gamma = Q.t()/M; double a = 1./(1.+gamma); for ( vector::iterator k = momenta.begin() + offset; k != momenta.end(); ++k ) { Energy q = (*k).t(); Energy bq = beta*(*k).vect(); (*k).setT(x*(gamma*q+bq)); (*k).setVect(x*((*k).vect()+(q+a*bq)*beta)); } size_t n = momenta.size()-offset; double weight = weights[n]; if ( !needToReshuffle ) { if ( !matchConstraints(momenta) ) return 0.; if ( theMakeReferenceSample ) dumpReference(momenta, weight); return weight; } double xi; ReshuffleEquation solve(w,mePartonData().begin()+offset,mePartonData().end(), momenta.begin()+2,momenta.end()); GSLBisection solver(1e-10,1e-8,10000); try { xi = solver.value(solve,0.0,1.1); } catch (GSLBisection::GSLerror) { return 0.; } catch (GSLBisection::IntervalError) { return 0.; } weight *= pow(xi,3.*(n-1.)); Energy num = ZERO; Energy den = ZERO; cPDVector::const_iterator d = mePartonData().begin()+offset; for ( vector::iterator k = momenta.begin()+offset; k != momenta.end(); ++k, ++d ) { num += (*k).vect().mag2()/(*k).t(); Energy q = (*k).t(); (*k).setT(sqrt(sqr((**d).hardProcessMass())+xi*xi*sqr((*k).t()))); (*k).setVect(xi*(*k).vect()); weight *= q/(*k).t(); den += (*k).vect().mag2()/(*k).t(); (*k).setMass((**d).hardProcessMass()); } if ( !matchConstraints(momenta) ) return 0.; weight *= num/den; if ( theMakeReferenceSample ) dumpReference(momenta, weight); return weight; } Energy MatchboxRambo::ReshuffleEquation::operator() (double xi) const { cPDVector::const_iterator d = dataBegin; vector::const_iterator p = momentaBegin; Energy res = -w; for ( ; d != dataEnd; ++d, ++p ) { res += sqrt(sqr((**d).hardProcessMass()) + xi*xi*sqr(p->t())); } return res; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxRambo::persistentOutput(PersistentOStream & os) const { os << needToReshuffle << theMakeReferenceSample; } void MatchboxRambo::persistentInput(PersistentIStream & is, int) { is >> needToReshuffle >> theMakeReferenceSample; } // *** 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 describeHerwigMatchboxRambo("Herwig::MatchboxRambo", "Herwig.so"); void MatchboxRambo::Init() { static ClassDocumentation documentation ("MatchboxRambo implements RAMBO phase space generation."); static Switch interfaceMakeReferenceSample ("MakeReferenceSample", "Switch on generation of a reference sample of phase space points.", &MatchboxRambo::theMakeReferenceSample, false, false, false); static SwitchOption interfaceMakeReferenceSampleYes (interfaceMakeReferenceSample, "Yes", "Generate a reference sample.", true); static SwitchOption interfaceMakeReferenceSampleNo (interfaceMakeReferenceSample, "No", "Do not generate a reference sample.", false); interfaceMakeReferenceSample.rank(-1); } diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxRambo.h b/MatrixElement/Matchbox/Phasespace/MatchboxRambo.h --- a/MatrixElement/Matchbox/Phasespace/MatchboxRambo.h +++ b/MatrixElement/Matchbox/Phasespace/MatchboxRambo.h @@ -1,188 +1,180 @@ // -*- C++ -*- // // MatchboxRambo.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxRambo_H #define Herwig_MatchboxRambo_H // // This is the declaration of the MatchboxRambo class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxRambo implements RAMBO phase space generation. * */ class MatchboxRambo: public MatchboxPhasespace { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxRambo(); - /** - * The destructor. - */ - virtual ~MatchboxRambo(); - //@} - public: /** * Prepare a phase space generator for the given xcomb object. */ virtual void setXComb(tStdXCombPtr); /** * Generate a phase space point and return its weight. */ virtual double generateTwoToNKinematics(const double*, vector& momenta); /** * Return the number of random numbers required to produce a given * multiplicity final state. */ virtual int nDimPhasespace(int nFinal) const { if ( nFinal == 1 ) return 1; return 4*nFinal; } protected: /** * The function object defining the equation * to be solved. */ struct ReshuffleEquation { typedef double ArgType; typedef Energy ValType; static double aUnit() { return 1.; } static Energy vUnit() { return 1.*GeV; } Energy operator() (double xi) const; Energy w; cPDVector::const_iterator dataBegin; cPDVector::const_iterator dataEnd; vector::const_iterator momentaBegin; vector::const_iterator momentaEnd; ReshuffleEquation(Energy q, cPDVector::const_iterator dBegin, cPDVector::const_iterator dEnd, vector::const_iterator mBegin, vector::const_iterator mEnd) : w(q), dataBegin(dBegin), dataEnd(dEnd), momentaBegin(mBegin), momentaEnd(mEnd) {} }; 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxRambo & operator=(const MatchboxRambo &) = delete; /** * Whether or not we need to reshuffle. */ bool needToReshuffle; /** * True, if a reference sample of phasespace points should be * generated. */ bool theMakeReferenceSample; /** * Map processes to streams for reference samples */ map referenceSamples; /** * The stream to fill for the reference sample */ ofstream* referenceSample; /** * Write the generated point to the reference sample */ void dumpReference(const vector&, double) const; }; } #endif /* Herwig_MatchboxRambo_H */ diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxReference.cc b/MatrixElement/Matchbox/Phasespace/MatchboxReference.cc --- a/MatrixElement/Matchbox/Phasespace/MatchboxReference.cc +++ b/MatrixElement/Matchbox/Phasespace/MatchboxReference.cc @@ -1,105 +1,100 @@ // -*- C++ -*- // // MatchboxReference.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxReference class. // #include "MatchboxReference.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Utilities/GSLBisection.h" #include "ThePEG/Cuts/Cuts.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -MatchboxReference::MatchboxReference() {} - -MatchboxReference::~MatchboxReference() {} - IBPtr MatchboxReference::clone() const { return new_ptr(*this); } IBPtr MatchboxReference::fullclone() const { return new_ptr(*this); } double MatchboxReference::generateTwoToNKinematics(const double*, vector& momenta) { map::iterator ref = referenceSamples.find(mePartonData()); if ( ref == referenceSamples.end() ) { ostringstream refname; for ( cPDVector::const_iterator p = mePartonData().begin(); p != mePartonData().end(); ++p ) { refname << (**p).PDGName(); } refname << ".rambo"; referenceSamples[mePartonData()] = new ifstream(refname.str().c_str()); ref = referenceSamples.find(mePartonData()); } assert(ref != referenceSamples.end()); ifstream& in = *(ref->second); assert(in); double x1,x2; double x,y,z,t,m; double weight; in >> x1 >> x2; for ( vector::iterator p = momenta.begin(); p != momenta.end(); ++p ) { in >> x >> y >> z >> t >> m; *p = Lorentz5Momentum(x*GeV,y*GeV,z*GeV,t*GeV,m*GeV); } in >> weight; lastXCombPtr()->lastX1X2(make_pair(x1,x2)); lastXCombPtr()->lastSHat((momenta[0]+momenta[1]).m2()); return weight; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxReference::persistentOutput(PersistentOStream &) const {} void MatchboxReference::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigMatchboxReference("Herwig::MatchboxReference", "Herwig.so"); void MatchboxReference::Init() { static ClassDocumentation documentation ("MatchboxReference implements reference sample phase space generation."); } diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxReference.h b/MatrixElement/Matchbox/Phasespace/MatchboxReference.h --- a/MatrixElement/Matchbox/Phasespace/MatchboxReference.h +++ b/MatrixElement/Matchbox/Phasespace/MatchboxReference.h @@ -1,140 +1,125 @@ // -*- C++ -*- // // MatchboxReference.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxReference_H #define Herwig_MatchboxReference_H // // This is the declaration of the MatchboxReference class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxReference implements reference sample phase space generation. * */ class MatchboxReference: public MatchboxPhasespace { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - MatchboxReference(); - - /** - * The destructor. - */ - virtual ~MatchboxReference(); - //@} - -public: - /** * Generate a phase space point and return its weight. */ virtual double generateTwoToNKinematics(const double*, vector& momenta); /** * Return the number of random numbers required to produce a given * multiplicity final state. */ virtual int nDimPhasespace(int nFinal) const { if ( nFinal == 1 ) return 1; return 4*nFinal + 2; } /** * Return true, if this phase space generator will generate incoming * partons itself. */ virtual bool haveX1X2() const { return true; } /** * Return true, if this phase space generator expects * the incoming partons in their center-of-mass system */ virtual bool wantCMS() const { return false; } 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxReference & operator=(const MatchboxReference &) = delete; /** * Stream to read the reference samples. */ map referenceSamples; }; } #endif /* Herwig_MatchboxReference_H */ diff --git a/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.cc b/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.cc --- a/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.cc +++ b/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.cc @@ -1,77 +1,71 @@ // -*- C++ -*- // // PhasespaceCouplings.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PhasespaceCouplings class. // #include "PhasespaceCouplings.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -PhasespaceCouplings::PhasespaceCouplings() {} - -PhasespaceCouplings::~PhasespaceCouplings() {} - IBPtr PhasespaceCouplings::clone() const { return new_ptr(*this); } IBPtr PhasespaceCouplings::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void PhasespaceCouplings::persistentOutput(PersistentOStream & os) const { os << theCouplings.size(); for ( map::const_iterator cit = theCouplings.begin(); cit != theCouplings.end(); ++cit ) os << cit->first << cit->second; } void PhasespaceCouplings::persistentInput(PersistentIStream & is, int) { theCouplings.clear(); size_t size; LTriple k; is >> size; while ( size-- && is ) { is >> k; is >> theCouplings[k]; } } // *** 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 describeHerwigPhasespaceCouplings("Herwig::PhasespaceCouplings", "Herwig.so"); void PhasespaceCouplings::Init() { static ClassDocumentation documentation ("Store couplings for the phase space generator."); } diff --git a/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h b/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h --- a/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h +++ b/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h @@ -1,139 +1,124 @@ // -*- C++ -*- // // PhasespaceCouplings.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_PhasespaceCouplings_H #define Herwig_PhasespaceCouplings_H // // This is the declaration of the PhasespaceCouplings class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" namespace Herwig { using namespace ThePEG; typedef std::tuple LTriple; inline PersistentOStream& operator<<(PersistentOStream& os, const LTriple& t) { os << std::get<0>(t) << std::get<1>(t) << std::get<2>(t); return os; } inline PersistentIStream& operator>>(PersistentIStream& is, LTriple& t) { is >> std::get<0>(t) >> std::get<1>(t) >> std::get<2>(t); return is; } /** * * \ingroup Matchbox * \author Simon Platzer * * \brief Store couplings for the phase space generator. * * @see \ref PhasespaceCouplingsInterfaces "The interfaces" * defined for PhasespaceCouplings. */ class PhasespaceCouplings: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - PhasespaceCouplings(); - - /** - * The destructor. - */ - virtual ~PhasespaceCouplings(); - //@} - -public: - /** * Couplings to be used in diagram weighting */ map& couplings() { return theCouplings; } /** * Couplings to be used in diagram weighting */ const map& couplings() const { return theCouplings; } 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: /** * Couplings to be used in diagram weighting */ map theCouplings; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ PhasespaceCouplings & operator=(const PhasespaceCouplings &) = delete; }; } #endif /* Herwig_PhasespaceCouplings_H */ diff --git a/MatrixElement/Matchbox/Phasespace/TildeKinematics.cc b/MatrixElement/Matchbox/Phasespace/TildeKinematics.cc --- a/MatrixElement/Matchbox/Phasespace/TildeKinematics.cc +++ b/MatrixElement/Matchbox/Phasespace/TildeKinematics.cc @@ -1,78 +1,72 @@ // -*- C++ -*- // // TildeKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the TildeKinematics class. // #include "TildeKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Utilities/Rebinder.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -TildeKinematics::TildeKinematics() - : HandlerBase() {} - -TildeKinematics::~TildeKinematics() {} - Energy TildeKinematics::lastScale() const { if ( ( theDipole->bornEmitter() < 2 && theDipole->bornSpectator() > 1 ) || ( theDipole->bornEmitter() > 1 && theDipole->bornSpectator() < 2 ) ) { return -(bornEmitterMomentum()-bornSpectatorMomentum()).m(); } return (bornEmitterMomentum()+bornSpectatorMomentum()).m(); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void TildeKinematics::rebind(const TranslationMap & trans) { theDipole = trans.translate(theDipole); HandlerBase::rebind(trans); } IVector TildeKinematics::getReferences() { IVector ret = HandlerBase::getReferences(); ret.push_back(theDipole); return ret; } void TildeKinematics::persistentOutput(PersistentOStream & os) const { os << theDipole << theRealXComb << theBornXComb << ounit(theBornEmitterMomentum,GeV) << ounit(theBornSpectatorMomentum,GeV); } void TildeKinematics::persistentInput(PersistentIStream & is, int) { is >> theDipole >> theRealXComb >> theBornXComb >> iunit(theBornEmitterMomentum,GeV) >> iunit(theBornSpectatorMomentum,GeV); } void TildeKinematics::Init() { static ClassDocumentation documentation ("TildeKinematics is the base class for the 'tilde' " "kinematics being used for subtraction terms in the " "formalism of Catani and Seymour."); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeTildeKinematics("Herwig::TildeKinematics", "Herwig.so"); diff --git a/MatrixElement/Matchbox/Phasespace/TildeKinematics.h b/MatrixElement/Matchbox/Phasespace/TildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/TildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/TildeKinematics.h @@ -1,384 +1,369 @@ // -*- C++ -*- // // TildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_TildeKinematics_H #define HERWIG_TildeKinematics_H // // This is the declaration of the TildeKinematics class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief TildeKinematics is the base class for the 'tilde' * kinematics being used for subtraction terms in the * formalism of Catani and Seymour. * */ class TildeKinematics: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - TildeKinematics(); - - /** - * The destructor. - */ - virtual ~TildeKinematics(); - //@} - -public: - /** * Clone this object */ Ptr::ptr cloneMe() const { return dynamic_ptr_cast::ptr>(clone()); } /** @name Access to kinematic quantities. */ //@{ /** * Return the momentum of the emitter in the real emission process */ const Lorentz5Momentum& realEmitterMomentum() const { return theRealXComb->meMomenta()[theDipole->realEmitter()]; } /** * Return the momentum of the emission in the real emission process */ const Lorentz5Momentum& realEmissionMomentum() const { return theRealXComb->meMomenta()[theDipole->realEmission()]; } /** * Return the momentum of the spectator in the real emission process */ const Lorentz5Momentum& realSpectatorMomentum() const { return theRealXComb->meMomenta()[theDipole->realSpectator()]; } /** * Return the momentum of the emitter in the underlying Born process */ const Lorentz5Momentum& bornEmitterMomentum() const { return theBornEmitterMomentum; } /** * Return the momentum of the spectator in the underlying Born process */ const Lorentz5Momentum& bornSpectatorMomentum() const { return theBornSpectatorMomentum; } /** * Return the vector of dimensionless variables calculated */ const vector& subtractionParameters() const { return theDipole->subtractionParameters(); } /** * Return true, if this TildeKinematics object needs to transform * all other particles in the process except the emitter and spectator */ virtual bool doesTransform() const { return false; } /** * If this TildeKinematics object needs to transform all other particles * in the process except the emitter and spectator, return the transformed * momentum. */ virtual Lorentz5Momentum transform(const Lorentz5Momentum& p) const { return p; } //@} /** * If this tilde kinematics is implementing a mapping different from * the baseline dipole mapping, determine the relevant shower * parameters and check for phase space boundaries. Note that real * emission kinematics only are available at this stage. */ virtual void getShowerVariables() const {} /** * If this tilde kinematics is implementing a mapping different from * the baseline dipole mapping, return the ratio of phase space * factorization Jacobians for this and the nominal dipole * mapping. This is used for matching subtractions. */ virtual double jacobianRatio() const { return 1.; } public: /** @name Access to process data. */ //@{ /** * Prepare given a dipole, and XCombs describing the real emission * and underlying Born processes, respectively. */ void prepare(tcStdXCombPtr newRealXComb, tcStdXCombPtr newBornXComb) { theRealXComb = newRealXComb; theBornXComb = newBornXComb; } /** * Set the current dipole */ void dipole(Ptr::tptr dip) { theDipole = dip; } /** * Return the current dipole */ Ptr::tptr dipole() { return theDipole; } /** * Return the current dipole */ Ptr::tcptr dipole() const { return theDipole; } /** * Perform the mapping to the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the tilde * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap() = 0; /** * Return the pt associated to the last merged splitting. */ virtual Energy lastPt() const = 0; /** * Return the pt associated to emitter emission and sppectator momentum. */ virtual Energy lastPt(Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum) const =0 ; /** * Given a pt and a hard pt, return the boundaries on z; */ virtual pair zBounds(Energy pt, Energy hardPt ) const = 0; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const = 0; /** * Return the relevant dipole scale */ virtual Energy lastScale() const; virtual bool aboveAlpha() const { cerr<<"only implemented for light kinematics"; assert(false); return false; } /** * Return the particle type of the emitter in the real emission process */ cPDPtr realEmitterData() const { return (theDipole && theRealXComb) ? theRealXComb->mePartonData()[theDipole->realEmitter()] : cPDPtr(); } /** * Return the particle type of the emission in the real emission process */ cPDPtr realEmissionData() const { return (theDipole && theRealXComb) ? theRealXComb->mePartonData()[theDipole->realEmission()] : cPDPtr(); } /** * Return the particle type of the spectator in the real emission process */ cPDPtr realSpectatorData() const { return (theDipole && theRealXComb) ? theRealXComb->mePartonData()[theDipole->realSpectator()] : cPDPtr(); } /** * Return the particle type of the emitter in the underlying Born process */ cPDPtr bornEmitterData() const { return (theDipole && theBornXComb) ? theBornXComb->mePartonData()[theDipole->bornEmitter()] : cPDPtr(); } /** * Return the particle type of the spectator in the underlying Born process */ cPDPtr bornSpectatorData() const { return (theDipole && theBornXComb) ? theBornXComb->mePartonData()[theDipole->bornSpectator()] : cPDPtr(); } //@} protected: /** * Access the momentum of the emitter in the underlying Born process */ Lorentz5Momentum& bornEmitterMomentum() { return theBornEmitterMomentum; } /** * Access the momentum of the spectator in the underlying Born process */ Lorentz5Momentum& bornSpectatorMomentum() { return theBornSpectatorMomentum; } /** * Access the vector of dimensionless variables calculated */ vector& subtractionParameters() { return theDipole->subtractionParameters(); } public: /** * Return the momentum fraction of the emitter */ double emitterX() const { return theDipole->bornEmitter() == 0 ? theBornXComb->lastX1() : theBornXComb->lastX2(); } /** * Return the momentum fraction of the spectator */ double spectatorX() const { return theDipole->bornSpectator() == 0 ? theBornXComb->lastX1() : theBornXComb->lastX2(); } 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). 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: /** * The last dipole this TildeKinematics has been selected for */ Ptr::tptr theDipole; /** * The XComb object describing the real emission process */ tcStdXCombPtr theRealXComb; /** * The XComb object describing the underlying Born process */ tcStdXCombPtr theBornXComb; /** * The momentum of the emitter in the underlying Born process */ Lorentz5Momentum theBornEmitterMomentum; /** * The momentum of the spectator in the underlying Born process */ Lorentz5Momentum theBornSpectatorMomentum; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TildeKinematics & operator=(const TildeKinematics &) = delete; }; } #endif /* HERWIG_TildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Phasespace/TreePhasespace.cc b/MatrixElement/Matchbox/Phasespace/TreePhasespace.cc --- a/MatrixElement/Matchbox/Phasespace/TreePhasespace.cc +++ b/MatrixElement/Matchbox/Phasespace/TreePhasespace.cc @@ -1,234 +1,232 @@ // -*- C++ -*- // // TreePhasespace.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the TreePhasespace class. // #include #include #include "TreePhasespace.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/MatrixElement/Matchbox/Utility/DiagramDrawer.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace Herwig::PhasespaceHelpers; TreePhasespace::TreePhasespace() : x0(0.01), xc(1e-4), M0(ZERO), Mc(ZERO) { lastPhasespaceInfo.x0 = x0; lastPhasespaceInfo.xc = xc; lastPhasespaceInfo.M0 = M0; lastPhasespaceInfo.Mc = Mc; theIncludeMirrored = true; } -TreePhasespace::~TreePhasespace() {} - IBPtr TreePhasespace::clone() const { return new_ptr(*this); } IBPtr TreePhasespace::fullclone() const { return new_ptr(*this); } void TreePhasespace::setXComb(tStdXCombPtr xco) { MatchboxPhasespace::setXComb(xco); lastChannelsIterator = channelMap().find(lastXCombPtr()); if ( lastChannelsIterator == channelMap().end() ) { map::ptr,pair > channels; for ( auto const & d : lastXComb().diagrams()) { PhasespaceTree tree; Ptr::ptr diag = dynamic_ptr_cast::ptr>(d); tree.setup(*diag); PhasespaceTree treeMirror; treeMirror.setupMirrored(*diag, diag->nSpace() - 1); channels[diag] = make_pair(tree,treeMirror); } channelMap()[lastXCombPtr()] = channels; lastChannelsIterator = channelMap().find(lastXCombPtr()); } } double TreePhasespace::generateTwoToNKinematics(const double* random, vector& momenta) { lastPhasespaceInfo.sHat = lastXComb().lastSHat(); lastPhasespaceInfo.sqrtSHat = sqrt(lastXComb().lastSHat()); lastPhasespaceInfo.weight = 1.; size_t nchannels = lastXComb().diagrams().size(); bool doMirror = (UseRandom::rnd() < 0.5) && theIncludeMirrored; map::ptr, pair >::iterator ds = lastChannels().begin(); size_t i = (size_t)(random[0]*nchannels); advance(ds,i); Ptr::ptr channel = ds->first; ++random; lastPhasespaceInfo.rnd.numbers = random; lastPhasespaceInfo.rnd.nRnd = 3*momenta.size() - 10; try { if ( !doMirror ) lastChannels()[channel].first.generateKinematics(lastPhasespaceInfo,momenta); else lastChannels()[channel].second.generateKinematics(lastPhasespaceInfo,momenta); } catch (Veto) { return 0.; } if ( !matchConstraints(momenta) ) return 0.; double flatCut = x0; if ( M0 != ZERO ) flatCut = M0/sqrt(lastSHat()); fillDiagramWeights(flatCut); double sum = 0.; for ( auto const & d : lastChannels()) sum += diagramWeight(*(d.first)); double piWeight = pow(2.*Constants::pi,(double)(3*(momenta.size()-2)-4)); for ( auto & k : momenta ) k.rescaleRho(); return nchannels*lastPhasespaceInfo.weight*diagramWeight(*channel)/(sum*piWeight); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void TreePhasespace::doinit() { MatchboxPhasespace::doinit(); lastPhasespaceInfo.x0 = x0; lastPhasespaceInfo.xc = xc; lastPhasespaceInfo.M0 = M0; lastPhasespaceInfo.Mc = Mc; } void TreePhasespace::doinitrun() { MatchboxPhasespace::doinitrun(); lastPhasespaceInfo.x0 = x0; lastPhasespaceInfo.xc = xc; lastPhasespaceInfo.M0 = M0; lastPhasespaceInfo.Mc = Mc; } void TreePhasespace::persistentOutput(PersistentOStream & os) const { os << theChannelMap << x0 << xc << ounit(M0,GeV) << ounit(Mc,GeV) << theIncludeMirrored << theLastXComb; } void TreePhasespace::persistentInput(PersistentIStream & is, int) { is >> theChannelMap >> x0 >> xc >> iunit(M0,GeV) >> iunit(Mc,GeV) >> theIncludeMirrored >> theLastXComb; lastPhasespaceInfo.x0 = x0; lastPhasespaceInfo.xc = xc; lastPhasespaceInfo.M0 = M0; lastPhasespaceInfo.Mc = Mc; lastChannelsIterator = channelMap().find(lastXCombPtr()); } // *** 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 describeHerwigTreePhasespace("Herwig::TreePhasespace", "Herwig.so"); void TreePhasespace::Init() { static ClassDocumentation documentation ("TreePhasespace is a multi-channel phase space generator " "adapting to singularity structures as determined from the matrix " "elements diagrams."); static Reference interfaceChannelMap ("ChannelMap", "Set the object storing the channels.", &TreePhasespace::theChannelMap, false, false, true, false, false); interfaceChannelMap.rank(-1); static Parameter interfaceX0 ("X0", "Set the cut below which flat virtuality sampling is imposed.", &TreePhasespace::x0, 0.01, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceXC ("XC", "Set the cut below which no virtualities are generated.", &TreePhasespace::xc, 1e-4, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceM0 ("M0", "Set the cut below which flat virtuality sammpling is imposed.", &TreePhasespace::M0, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceMC ("MC", "Set the cut below which no virtualities are generated.", &TreePhasespace::Mc, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Switch interfaceIncludeMirrored ("IncludeMirrored", "Choose whether to include mirrored diagrams for PS generation", &TreePhasespace::theIncludeMirrored, true, true, false); static SwitchOption interfaceIncludeMirroredYes (interfaceIncludeMirrored, "Yes", "Use unmirrored and mirrored diagrams", true); static SwitchOption interfaceIncludeMirroredNo (interfaceIncludeMirrored, "No", "Use only unmirrored diagrams", false); interfaceIncludeMirrored.rank(-1); } diff --git a/MatrixElement/Matchbox/Phasespace/TreePhasespace.h b/MatrixElement/Matchbox/Phasespace/TreePhasespace.h --- a/MatrixElement/Matchbox/Phasespace/TreePhasespace.h +++ b/MatrixElement/Matchbox/Phasespace/TreePhasespace.h @@ -1,217 +1,209 @@ // -*- C++ -*- // // TreePhasespace.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_TreePhasespace_H #define Herwig_TreePhasespace_H // // This is the declaration of the TreePhasespace class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Ken Arnold * * \brief TreePhasespace is a multi-channel phase space generator * adapting to singularity structures as determined from the matrix * elements diagrams. * * @see \ref TreePhasespaceInterfaces "The interfaces" * defined for TreePhasespace. */ class TreePhasespace: public MatchboxPhasespace { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ TreePhasespace(); - /** - * The destructor. - */ - virtual ~TreePhasespace(); - //@} - public: /** * Prepare a phase space generator for the given xcomb object. */ virtual void setXComb(tStdXCombPtr); /** * Generate a phase space point and return its weight. */ virtual double generateTwoToNKinematics(const double*, vector& momenta); /** * Return the number of random numbers required to produce a given * multiplicity final state. */ virtual int nDimPhasespace(int nFinal) const { if ( nFinal == 1 ) return 1; return 3*(nFinal - 1); // one additional number needed for channel selection } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The object storing channel maps */ Ptr::ptr theChannelMap; /** * Map xcomb's to channel vectors indexed by diagram id. */ map::ptr, pair > >& channelMap() { return theChannelMap->channelMap(); } /** * The currently active channels. */ map::ptr, pair > >::iterator lastChannelsIterator; /** * The phase space info object to be used. */ PhasespaceHelpers::PhasespaceInfo lastPhasespaceInfo; /** * Parameter steering from which on propagator virtualities are * sampled flat. */ double x0; /** * Parameter steering at which virtuality singularities of * propagators are actually cut off. */ double xc; /** * Parameter steering from which on propagator virtualities are * sampled flat. */ Energy M0; /** * Parameter steering at which virtuality singularities of * propagators are actually cut off. */ Energy Mc; /** * Choose whether to also use mirrored phase space generation */ bool theIncludeMirrored; /** * Return the currently active channels. */ map::ptr, pair >& lastChannels() { return lastChannelsIterator->second; } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TreePhasespace & operator=(const TreePhasespace &) = delete; }; } #endif /* Herwig_TreePhasespace_H */ diff --git a/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.cc b/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.cc --- a/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.cc +++ b/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.cc @@ -1,89 +1,83 @@ // -*- C++ -*- // // TreePhasespaceChannels.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the TreePhasespaceChannels class. // #include "TreePhasespaceChannels.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace Herwig::PhasespaceHelpers; -TreePhasespaceChannels::TreePhasespaceChannels() {} - -TreePhasespaceChannels::~TreePhasespaceChannels() {} - IBPtr TreePhasespaceChannels::clone() const { return new_ptr(*this); } IBPtr TreePhasespaceChannels::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void TreePhasespaceChannels::persistentOutput(PersistentOStream & os) const { os << theChannelMap.size(); for ( map::ptr,pair > >::const_iterator k = theChannelMap.begin(); k != theChannelMap.end(); ++k ) { os << k->first << k->second.size(); for ( map::ptr,pair >::const_iterator l = k->second.begin(); l != k->second.end(); ++l ) { os << l->first; l->second.first.put(os); l->second.second.put(os); } } } void TreePhasespaceChannels::persistentInput(PersistentIStream & is, int) { size_t nk; is >> nk; for ( size_t k = 0; k < nk; ++k ) { tStdXCombPtr xc; is >> xc; size_t nl; is >> nl; map::ptr,pair > cm; for ( size_t l = 0; l < nl; ++l ) { Ptr::ptr ci; is >> ci; pair cp; cp.first.get(is); cp.second.get(is); cm[ci] = cp; } theChannelMap[xc] = cm; } } // *** 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 describeHerwigTreePhasespaceChannels("Herwig::TreePhasespaceChannels", "Herwig.so"); void TreePhasespaceChannels::Init() { static ClassDocumentation documentation ("Store channels for the tree phase space."); } diff --git a/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.h b/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.h --- a/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.h +++ b/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.h @@ -1,128 +1,113 @@ // -*- C++ -*- // // TreePhasespaceChannels.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_TreePhasespaceChannels_H #define Herwig_TreePhasespaceChannels_H // // This is the declaration of the TreePhasespaceChannels class. // #include "ThePEG/Handlers/HandlerBase.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/PhasespaceHelpers.h" namespace Herwig { using namespace ThePEG; /** * * \ingroup Matchbox * \author Simon Platzer, Ken Arnold * * \brief Store channels for the tree phasespace. * * @see \ref TreePhasespaceChannelsInterfaces "The interfaces" * defined for TreePhasespaceChannels. */ class TreePhasespaceChannels: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - TreePhasespaceChannels(); - - /** - * The destructor. - */ - virtual ~TreePhasespaceChannels(); - //@} - -public: - /** * Access the channel map */ map::ptr,pair > >& channelMap() { return theChannelMap; } /** * Return the channel map */ const map::ptr,pair > >& channelMap() const { return theChannelMap; } 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: /** * Map xcomb's to channel vectors indexed by diagram id. */ map::ptr,pair > > theChannelMap; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TreePhasespaceChannels & operator=(const TreePhasespaceChannels &) = delete; }; } #endif /* Herwig_TreePhasespaceChannels_H */ diff --git a/MatrixElement/Matchbox/Tests/HardProcessAnalysis.cc b/MatrixElement/Matchbox/Tests/HardProcessAnalysis.cc --- a/MatrixElement/Matchbox/Tests/HardProcessAnalysis.cc +++ b/MatrixElement/Matchbox/Tests/HardProcessAnalysis.cc @@ -1,433 +1,429 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the HardProcessAnalysis class. // #include "HardProcessAnalysis.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/EventRecord/SubProcessGroup.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; HardProcessAnalysis::HardProcessAnalysis() : sumWeights(0.0), theNBins(100), theUnitWeights(false), theSplitInitialStates(true), thePartonsAreJets(false) {} -HardProcessAnalysis::~HardProcessAnalysis() {} - - - #ifndef LWH_AIAnalysisFactory_H #ifndef LWH #define LWH ThePEGLWH #endif #include "ThePEG/Analysis/LWH/AnalysisFactory.h" #endif HardProcessAnalysis::Histograms::Histograms(Energy ECM, unsigned int theNBins) { vector logBins(theNBins+1); double logLow = 1.0; double logUp = ECM/GeV/4.; double cLog = log10(logUp/logLow)/theNBins; for ( size_t k = 0; k < theNBins+1; ++k ) logBins[k] = logLow*pow(10.0,cLog*k); transverse = new_ptr(Histogram(logBins)); rapidity = new_ptr(Histogram(-7.,7.,theNBins)); phi = new_ptr(Histogram(-Constants::pi,Constants::pi,theNBins)); } void HardProcessAnalysis::Histograms::fill(const Lorentz5Momentum& p, double weight) { transverse->addWeighted(p.perp()/GeV,weight); rapidity->addWeighted(p.rapidity(),weight); phi->addWeighted(p.phi(),weight); } void HardProcessAnalysis::Histograms::finalize(ostream& dat, ostream& plot, const string& subpro, size_t legid, double norm, bool theUnitWeights) { transverse->prefactor(norm); rapidity->prefactor(norm); phi->prefactor(norm); ostringstream prefix; prefix << subpro << "_" << legid; plot << "# BEGIN PLOT /HardProcessAnalysis" << (!theUnitWeights ? "" : "Flat") << "/" << prefix.str() << "_transverse\n" << "Title=Transverse momentum of " << prefix.str() << "\n" << "XLabel=" << "$p_\\perp$/GeV" << "\n" << "YLabel=" << "${\\rm d}\\sigma/{\\rm d}p_\\perp$/(nb/GeV)" << "\n" << "LogX=1\n" << "LogY=0\n" << "# END PLOT\n\n"; transverse->rivetOutput(dat,prefix.str() + "_transverse",!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat"); dat << "\n"; plot << "# BEGIN PLOT /HardProcessAnalysis" << (!theUnitWeights ? "" : "Flat") << "/" << prefix.str() << "_rapidity\n" << "Title=Rapidity of " << prefix.str() << "\n" << "XLabel=" << "$y$" << "\n" << "YLabel=" << "${\\rm d}\\sigma/{\\rm d}y$/nb" << "\n" << "LogX=0\n" << "LogY=0\n" << "# END PLOT\n\n"; rapidity->rivetOutput(dat,prefix.str() + "_rapidity",!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat"); dat << "\n"; plot << "# BEGIN PLOT /HardProcessAnalysis" << (!theUnitWeights ? "" : "Flat") << "/" << prefix.str() << "_phi\n" << "Title=Azimuthal angle of " << prefix.str() << "\n" << "XLabel=" << "$\\phi$" << "\n" << "YLabel=" << "${\\rm d}\\sigma/{\\rm d}\\phi$/nb" << "\n" << "LogX=0\n" << "LogY=0\n" << "# END PLOT\n\n"; phi->rivetOutput(dat,prefix.str() + "_phi",!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat"); dat << "\n"; } struct SortedInPt { bool partonsAreJets; explicit SortedInPt(bool newPartonsAreJets = false) : partonsAreJets(newPartonsAreJets) {} inline bool operator()(PPtr a, PPtr b) const { long aId = a->id(); if ( partonsAreJets && a->coloured() ) aId = 21; long bId = b->id(); if ( partonsAreJets && b->coloured() ) bId = 21; if ( aId != bId ) return ( aId < bId ); return a->momentum().perp() > b->momentum().perp(); } }; struct GetName { bool partonsAreJets; explicit GetName(bool newPartonsAreJets = false) : partonsAreJets(newPartonsAreJets) {} inline string operator()(PPtr p) const { if ( partonsAreJets && p->coloured() ) return "j"; string res = p->PDGName(); string::size_type pos = res.find("+"); while ( pos != string::npos ) { res.replace(pos,1,"plus"); pos = res.find("+"); } pos = res.find("-"); while ( pos != string::npos ) { res.replace(pos,1,"minus"); pos = res.find("-"); } return res; } }; void HardProcessAnalysis::fill(PPair in, ParticleVector out, double weight) { sort(out.begin(),out.end(),SortedInPt(thePartonsAreJets)); vector proc; if ( theSplitInitialStates ) { proc.push_back(GetName()(in.first)); proc.push_back(GetName()(in.second)); } std::transform(out.begin(),out.end(), back_inserter(proc),GetName(thePartonsAreJets)); AllHistograms& data = histogramData[proc]; if ( data.outgoing.empty() ) { for ( size_t k = 0; k < out.size(); ++k ) data.outgoing.push_back(Histograms(generator()->maximumCMEnergy(),theNBins)); vector logBins(theNBins+1); double logLow = 1.0e-6; double logUp = 1.0; double cLog = log10(logUp/logLow)/theNBins; for ( size_t k = 0; k < theNBins+1; ++k ) logBins[k] = logLow*pow(10.0,cLog*k); data.x1 = new_ptr(Histogram(logBins)); data.x2 = new_ptr(Histogram(logBins)); logUp = generator()->maximumCMEnergy()/GeV; logLow = 1.0; cLog = log10(logUp/logLow)/theNBins; for ( size_t k = 0; k < theNBins+1; ++k ) logBins[k] = logLow*pow(10.0,cLog*k); data.sshat = new_ptr(Histogram(logBins)); data.rapidity = new_ptr(Histogram(-7.,7.,theNBins)); data.sumWeights = 0.; } bool twoIdentical = false; if ( out.size() == 2 ) { if ( out[0]->id() == out[1]->id() || (out[0]->coloured() && out[1]->coloured() && thePartonsAreJets) ) twoIdentical = true; } if ( !twoIdentical ) { ParticleVector::const_iterator p = out.begin(); vector::iterator h = data.outgoing.begin(); for ( ; p != out.end(); ++p, ++h ) h->fill((**p).momentum(),weight); } else { data.outgoing[0].fill(out[0]->momentum(),weight/2.); data.outgoing[0].fill(out[1]->momentum(),weight/2.); data.outgoing[1].fill(out[0]->momentum(),weight/2.); data.outgoing[1].fill(out[1]->momentum(),weight/2.); } double y = (in.first->momentum() + in.second->momentum()).rapidity(); data.rapidity->addWeighted(y,weight); Energy2 shat = (in.first->momentum() + in.second->momentum()).m2(); data.sshat->addWeighted(sqrt(shat)/GeV,weight); double tau = shat/sqr(generator()->maximumCMEnergy()); double x1 = sqrt(tau)*exp(y); double x2 = sqrt(tau)*exp(-y); data.x1->addWeighted(x1,weight); data.x2->addWeighted(x2,weight); data.sumWeights += weight; } void HardProcessAnalysis::analyze(tEventPtr event, long ieve, int loop, int state) { AnalysisHandler::analyze(event, ieve, loop, state); tSubProPtr sub = event->primarySubProcess(); Ptr::tptr grp = dynamic_ptr_cast::tptr>(sub); double weight = !theUnitWeights ? event->weight()*sub->groupWeight() : 1.0; sumWeights += weight; fill(sub->incoming(),sub->outgoing(),weight); if ( grp ) { for ( SubProcessVector::const_iterator s = grp->dependent().begin(); s != grp->dependent().end(); ++s ) { weight = !theUnitWeights ? event->weight()*(**s).groupWeight() : 1.0; fill((**s).incoming(),(**s).outgoing(),weight); } } } void HardProcessAnalysis::dofinish() { AnalysisHandler::dofinish(); ofstream dat(!theUnitWeights ? "HardProcessAnalysis.dat" : "HardProcessAnalysisFlat.dat"); ofstream plot(!theUnitWeights ? "HardProcessAnalysis.plot" : "HardProcessAnalysisFlat.plot"); for ( map,AllHistograms>::iterator h = histogramData.begin(); h != histogramData.end(); ++h ) { string subpro; for ( vector::const_iterator p = h->first.begin(); p != h->first.end(); ++p ) { subpro += *p + (p != --(h->first.end()) ? "_" : ""); } double fraction = h->second.sumWeights / sumWeights; for ( size_t k = 0; k < h->second.outgoing.size(); ++k ) h->second.outgoing[k].finalize(dat,plot,subpro,k+2, generator()->eventHandler()->integratedXSec() * fraction/nanobarn, theUnitWeights); h->second.x1->prefactor(generator()->eventHandler()->integratedXSec() * fraction/nanobarn); plot << "# BEGIN PLOT /HardProcessAnalysis" << (!theUnitWeights ? "" : "Flat") << "/" << subpro << "_x1\n" << "Title=Momentum fraction of first parton in " << subpro << "\n" << "XLabel=" << "$x_1$" << "\n" << "YLabel=" << "${\\rm d}\\sigma/{\\rm d}x_1$/nb" << "\n" << "LogX=1\n" << "LogY=0\n" << "# END PLOT\n\n"; h->second.x1->rivetOutput(dat,subpro + "_x1",!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat"); dat << "\n"; h->second.x2->prefactor(generator()->eventHandler()->integratedXSec() * fraction/nanobarn); plot << "# BEGIN PLOT /HardProcessAnalysis" << (!theUnitWeights ? "" : "Flat") << "/" << subpro << "_x2\n" << "Title=Momentum fraction of second parton in " << subpro << "\n" << "XLabel=" << "$x_2$" << "\n" << "YLabel=" << "${\\rm d}\\sigma/{\\rm d}x_2$/nb" << "\n" << "LogX=1\n" << "LogY=0\n" << "# END PLOT\n\n"; h->second.x2->rivetOutput(dat,subpro + "_x2",!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat"); dat << "\n"; h->second.rapidity->prefactor(generator()->eventHandler()->integratedXSec() * fraction/nanobarn); plot << "# BEGIN PLOT /HardProcessAnalysis" << (!theUnitWeights ? "" : "Flat") << "/" << subpro << "_y\n" << "Title=Rapidity in " << subpro << "\n" << "XLabel=" << "$y$" << "\n" << "YLabel=" << "${\\rm d}\\sigma/{\\rm d}y$/nb" << "\n" << "LogX=0\n" << "LogY=0\n" << "# END PLOT\n\n"; h->second.rapidity->rivetOutput(dat,subpro + "_y",!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat"); dat << "\n"; h->second.sshat->prefactor(generator()->eventHandler()->integratedXSec() * fraction/nanobarn); plot << "# BEGIN PLOT /HardProcessAnalysis" << (!theUnitWeights ? "" : "Flat") << "/" << subpro << "_sshat\n" << "Title=Partonic centre of mass energy in " << subpro << "\n" << "XLabel=" << "$\\sqrt{\\hat{s}}$/GeV" << "\n" << "YLabel=" << "${\\rm d}\\sigma/{\\rm d}\\sqrt{\\hat{s}}$/(nb/GeV)" << "\n" << "LogX=1\n" << "LogY=0\n" << "# END PLOT\n\n"; h->second.sshat->rivetOutput(dat,subpro + "_sshat",!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat"); dat << "\n"; } Energy ECM = generator()->maximumCMEnergy(); CrossSection xsec = generator()->eventHandler()->integratedXSec(); CrossSection xsecErr = generator()->eventHandler()->integratedXSecErr(); dat << "# BEGIN HISTOGRAM /" << (!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat") << "/xsec\n" << "AidaPath=/" << (!theUnitWeights ? "HardProcessAnalysis" : "HardProcessAnalysisFlat") << "/xsec\n" << (ECM/GeV - 10.) << "\t" << (ECM/GeV + 10.) << "\t" << (xsec/nanobarn) << "\t" << (xsecErr/nanobarn) << "\n" << "# END HISTOGRAM\n"; plot << "# BEGIN PLOT /HardProcessAnalysis" << (!theUnitWeights ? "" : "Flat") << "/xsec\n" << "Title=Total cross section\n" << "XLabel=" << "$\\sqrt{S}$/GeV" << "\n" << "YLabel=" << "$\\sigma(\\sqrt(S))$/nb" << "\n" << "LogX=0\n" << "LogY=0\n" << "# END PLOT\n\n"; } void HardProcessAnalysis::doinitrun() { AnalysisHandler::doinitrun(); // *** ATTENTION *** histogramFactory().registerClient(this); // Initialize histograms. // *** ATTENTION *** histogramFactory().mkdirs("/SomeDir"); // Put histograms in specal directory. } IBPtr HardProcessAnalysis::clone() const { return new_ptr(*this); } IBPtr HardProcessAnalysis::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void HardProcessAnalysis::persistentOutput(PersistentOStream & os) const { os << theNBins << theUnitWeights << theSplitInitialStates << thePartonsAreJets; } void HardProcessAnalysis::persistentInput(PersistentIStream & is, int) { is >> theNBins >> theUnitWeights >> theSplitInitialStates >> thePartonsAreJets; } // *** 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 describeHerwigHardProcessAnalysis("Herwig::HardProcessAnalysis", "Herwig.so"); void HardProcessAnalysis::Init() { static ClassDocumentation documentation ("There is no documentation for the HardProcessAnalysis class"); static Parameter interfaceNBins ("NBins", "The number of bins to use", &HardProcessAnalysis::theNBins, 100, 1, 0, false, false, Interface::lowerlim); static Switch interfaceUnitWeights ("UnitWeights", "Use unit weights", &HardProcessAnalysis::theUnitWeights, false, false, false); static SwitchOption interfaceUnitWeightsYes (interfaceUnitWeights, "Yes", "Use unit weights", true); static SwitchOption interfaceUnitWeightsNo (interfaceUnitWeights, "No", "Do not use unit weights", false); static Switch interfaceSplitInitialStates ("SplitInitialStates", "Distinguish by initial state", &HardProcessAnalysis::theSplitInitialStates, true, false, false); static SwitchOption interfaceSplitInitialStatesYes (interfaceSplitInitialStates, "Yes", "", true); static SwitchOption interfaceSplitInitialStatesNo (interfaceSplitInitialStates, "No", "", false); static Switch interfacePartonsAreJets ("PartonsAreJets", "Treat each parton as a jet.", &HardProcessAnalysis::thePartonsAreJets, false, false, false); static SwitchOption interfacePartonsAreJetsYes (interfacePartonsAreJets, "Yes", "", true); static SwitchOption interfacePartonsAreJetsNo (interfacePartonsAreJets, "No", "", false); } diff --git a/MatrixElement/Matchbox/Tests/HardProcessAnalysis.h b/MatrixElement/Matchbox/Tests/HardProcessAnalysis.h --- a/MatrixElement/Matchbox/Tests/HardProcessAnalysis.h +++ b/MatrixElement/Matchbox/Tests/HardProcessAnalysis.h @@ -1,257 +1,249 @@ // -*- C++ -*- #ifndef Herwig_HardProcessAnalysis_H #define Herwig_HardProcessAnalysis_H // // This is the declaration of the HardProcessAnalysis class. // #include "ThePEG/Handlers/AnalysisHandler.h" #include "Herwig/Utilities/Histogram.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the HardProcessAnalysis class. * * @see \ref HardProcessAnalysisInterfaces "The interfaces" * defined for HardProcessAnalysis. */ class HardProcessAnalysis: public AnalysisHandler { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ HardProcessAnalysis(); - /** - * The destructor. - */ - virtual ~HardProcessAnalysis(); - //@} - 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: /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * 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). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HardProcessAnalysis & operator=(const HardProcessAnalysis &) = delete; /** * Differential information per outgoing parton */ struct Histograms { /** * The constructor */ Histograms() {} /** * The constructor */ explicit Histograms(Energy ECM, unsigned int theNBins); /** * Analyse given momentum */ void fill(const Lorentz5Momentum& p, double weight); /** * Finalize given process id and cross section. */ void finalize(ostream& dat, ostream& plot, const string& subpro, size_t legid, double norm, bool theUnitWeights); /** * Pt spectrum */ HistogramPtr transverse; /** * Rapidity distribution */ HistogramPtr rapidity; /** * Azimuthal angle distribution */ HistogramPtr phi; }; /** * Outgoing partons and x distributions */ struct AllHistograms { /** * Outgoing partons */ vector outgoing; /** * x1 distribution */ HistogramPtr x1; /** * x2 distribution */ HistogramPtr x2; /** * sqrt(shat) distribution */ HistogramPtr sshat; /** * y distribution */ HistogramPtr rapidity; /** * The sum of weights */ double sumWeights; }; /** * Histograms per subprocess */ map,AllHistograms> histogramData; /** * The total sum of weights */ double sumWeights; /** * Analyze a given final state */ void fill(PPair, ParticleVector, double); /** * The number of bins to use */ unsigned int theNBins; /** * True, if unit weights should be booked */ bool theUnitWeights; /** * True, if subprocesses should be distinguished by initial state */ bool theSplitInitialStates; /** * True, if partons should be handled as jets irrespective of flavour */ bool thePartonsAreJets; }; } #endif /* Herwig_HardProcessAnalysis_H */ diff --git a/MatrixElement/Matchbox/Tests/WeightAnalyzer.cc b/MatrixElement/Matchbox/Tests/WeightAnalyzer.cc --- a/MatrixElement/Matchbox/Tests/WeightAnalyzer.cc +++ b/MatrixElement/Matchbox/Tests/WeightAnalyzer.cc @@ -1,283 +1,279 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the WeightAnalyzer class. // #include "WeightAnalyzer.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 "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/EventRecord/SubProcessGroup.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; WeightAnalyzer::WeightAnalyzer() : sumWeights(0.0), sumPositiveWeights(0.0), sumNegativeWeights(0.0), sumGroupWeights(0.0), sumPositiveGroupWeights(0.0), sumNegativeGroupWeights(0.0), maxDeviationGroupWeight(0.0), maxDeviationEventWeight(0.0), nPositiveWeights(0.0), nNegativeWeights(0.0), maxPositiveWeight(0.0), maxNegativeWeight(0.0), gnuplot(true) {} -WeightAnalyzer::~WeightAnalyzer(){} - - - #ifndef LWH_AIAnalysisFactory_H #ifndef LWH #define LWH ThePEGLWH #endif #include "ThePEG/Analysis/LWH/AnalysisFactory.h" #endif void WeightAnalyzer::analyze(tEventPtr event, long ieve, int loop, int state) { AnalysisHandler::analyze(event, ieve, loop, state); double weight = event->weight(); sumWeights += weight; if ( weight > 0.0 ) { sumPositiveWeights += weight; maxPositiveWeight = max(maxPositiveWeight,weight); nPositiveWeights += 1; map::iterator b = positiveWeightDistribution.upper_bound(weight); if ( b != positiveWeightDistribution.end() ) b->second += 1; else (--positiveWeightDistribution.end())->second += 1; } if ( weight < 0.0 ) { sumNegativeWeights += weight; maxNegativeWeight = max(maxNegativeWeight,abs(weight)); nNegativeWeights += 1; map::iterator b = negativeWeightDistribution.upper_bound(abs(weight)); if ( b != negativeWeightDistribution.end() ) b->second += 1; else (--negativeWeightDistribution.end())->second += 1; } tSubProPtr sub = event->primarySubProcess(); Ptr::tptr grp = dynamic_ptr_cast::tptr>(sub); double sumEvents = 0.0; double sumGroups = 0.0; sumGroupWeights += weight*sub->groupWeight(); if ( weight*sub->groupWeight() > 0.0 ) sumPositiveGroupWeights += weight*sub->groupWeight(); if ( weight*sub->groupWeight() < 0.0 ) sumNegativeGroupWeights += weight*sub->groupWeight(); sumEvents += weight*sub->groupWeight(); sumGroups += sub->groupWeight(); if ( grp ) { for ( SubProcessVector::const_iterator s = grp->dependent().begin(); s != grp->dependent().end(); ++s ) { sumGroupWeights += weight*(**s).groupWeight(); if ( weight*(**s).groupWeight() > 0.0 ) sumPositiveGroupWeights += weight*(**s).groupWeight(); if ( weight*(**s).groupWeight() < 0.0 ) sumNegativeGroupWeights += weight*(**s).groupWeight(); sumEvents += weight*(**s).groupWeight(); sumGroups += (**s).groupWeight(); } } maxDeviationGroupWeight = max(maxDeviationGroupWeight,abs(sumGroups-1)); maxDeviationEventWeight = max(maxDeviationEventWeight,abs(sumEvents/weight-1)); } void WeightAnalyzer::dofinish() { AnalysisHandler::dofinish(); if ( nPositiveWeights != 0 ) for ( map::iterator b = positiveWeightDistribution.begin(); b != positiveWeightDistribution.end(); ++b ) { b->second /= nPositiveWeights; } if ( nNegativeWeights != 0 ) for ( map::iterator b = negativeWeightDistribution.begin(); b != negativeWeightDistribution.end(); ++b ) { b->second /= nNegativeWeights; } string dataName = generator()->filename() + "Weights."+(gnuplot?"gp":"dat"); ofstream data(dataName.c_str()); data << setprecision(17) << "# --------------------------------------------------------------------------------\n" << "# WeightAnalyzer information\n" << "# --------------------------------------------------------------------------------\n" << "# sum of weights : " << sumWeights << "\n" << "# sum of positive weights : " << sumPositiveWeights << "\n" << "# sum of negative weights : " << sumNegativeWeights << "\n" << "# sum of weights (from groups) : " << sumGroupWeights << "\n" << "# sum of positive weights (from groups) : " << sumPositiveGroupWeights << "\n" << "# sum of negative weights (from groups) : " << sumNegativeGroupWeights << "\n" << "# maximum devation group weights : " << maxDeviationGroupWeight << "\n" << "# maximum devation event weights : " << maxDeviationEventWeight << "\n" << "# number of positive weights : " << nPositiveWeights << "\n" << "# number of negative weights : " << nNegativeWeights << "\n" << "# maximum positive weight : " << maxPositiveWeight << "\n" << "# maximum negative weight : " << maxNegativeWeight << "\n" << "# --------------------------------------------------------------------------------\n" << flush; data << "\n\n"; if(gnuplot){ data << "set terminal pdf\n" << "set xlabel 'weights'\n" << "set ylabel '\n" << "set logscale \n" << "set output '" << generator()->filename()<<"Weights.pdf'\n" << "plot \"-\" using 2:3 with histeps lc rgbcolor \"#00AACC\" t \"positive weights\"\n" << "# low up val\n"; } for ( map::const_iterator b = positiveWeightDistribution.begin(); b != positiveWeightDistribution.end(); ++b ) { if ( b->second != 0 ) { double l,u; if ( b == positiveWeightDistribution.begin() ) { l = 0.; u = b->first; } else if ( b == --positiveWeightDistribution.end() ) { map::const_iterator bl = b; --bl; l = bl->first; u = Constants::MaxDouble; } else { map::const_iterator bl = b; --bl; l = bl->first; u = b->first; } data << l << " " << u << " " << b->second << "\n"; } } data << flush; if(gnuplot)data<< "e"; data << "\n\n"; if(gnuplot && sumNegativeGroupWeights>0.){ data<< "plot \"-\" using 2:3 with histeps lc rgbcolor \"#00AACC\" t \"negative weights\"\n" << "# low up val\n"; } for ( map::const_iterator b = negativeWeightDistribution.begin(); b != negativeWeightDistribution.end(); ++b ) { if ( b->second != 0 ) { double l,u; if ( b == negativeWeightDistribution.begin() ) { l = 0.; u = b->first; } else if ( b == --negativeWeightDistribution.end() ) { map::const_iterator bl = b; --bl; l = bl->first; u = Constants::MaxDouble; } else { map::const_iterator bl = b; --bl; l = bl->first; u = b->first; } data << l << " " << u << " " << b->second << "\n"; } } if(gnuplot&& sumNegativeGroupWeights>0.)data<< "e"; data << flush; } void WeightAnalyzer::doinitrun() { AnalysisHandler::doinitrun(); positiveWeightDistribution.clear(); negativeWeightDistribution.clear(); unsigned int nbins = 200; nbins += 1; double low = 1.e-8; double up = 1.e8; double c = log10(up/low) / (nbins-1.); for ( unsigned int k = 1; k < nbins + 1; ++k ) { // mind the overflow bin positiveWeightDistribution[low*pow(10.0,k*c)] = 0.; negativeWeightDistribution[low*pow(10.0,k*c)] = 0.; } } IBPtr WeightAnalyzer::clone() const { return new_ptr(*this); } IBPtr WeightAnalyzer::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void WeightAnalyzer::persistentOutput(PersistentOStream &) const {} void WeightAnalyzer::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigWeightAnalyzer("Herwig::WeightAnalyzer", "Herwig.so"); void WeightAnalyzer::Init() { static ClassDocumentation documentation ("There is no documentation for the WeightAnalyzer class"); static Switch interfacekeepinputtopmass ("Gnuplot output", "Switch On/Off gnuplot", &WeightAnalyzer::gnuplot, true, false, false); static SwitchOption interfacekeepinputtopmassYes (interfacekeepinputtopmass, "Yes", "Yes", true); static SwitchOption interfacekeepinputtopmassNo (interfacekeepinputtopmass, "No", "No", false); } diff --git a/MatrixElement/Matchbox/Tests/WeightAnalyzer.h b/MatrixElement/Matchbox/Tests/WeightAnalyzer.h --- a/MatrixElement/Matchbox/Tests/WeightAnalyzer.h +++ b/MatrixElement/Matchbox/Tests/WeightAnalyzer.h @@ -1,216 +1,208 @@ // -*- C++ -*- #ifndef Herwig_WeightAnalyzer_H #define Herwig_WeightAnalyzer_H // // This is the declaration of the WeightAnalyzer class. // #include "ThePEG/Handlers/AnalysisHandler.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the WeightAnalyzer class. * * @see \ref WeightAnalyzerInterfaces "The interfaces" * defined for WeightAnalyzer. */ class WeightAnalyzer: public AnalysisHandler { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ WeightAnalyzer(); - /** - * The destructor. - */ - virtual ~WeightAnalyzer(); - //@} - 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: /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * 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). private: /** * The sum of weights */ double sumWeights; /** * The sum of positive weights */ double sumPositiveWeights; /** * The sum of negative weights */ double sumNegativeWeights; /** * The sum of weights calculated by subprocess group weights */ double sumGroupWeights; /** * The sum of positive weights calculated by subprocess group weights */ double sumPositiveGroupWeights; /** * The sum of negative weights calculated by subprocess group weights */ double sumNegativeGroupWeights; /** * The maximum deviation of the group weight sum from one */ double maxDeviationGroupWeight; /** * The maximum deviation of the event weight sum from the overall * event weight */ double maxDeviationEventWeight; /** * Total number of positive weights */ double nPositiveWeights; /** * Total number of negative weights */ double nNegativeWeights; /** * The maximum postive weight */ double maxPositiveWeight; /** * The maximum absolute negative weight */ double maxNegativeWeight; /** * Histogram of positive weight occurences */ map positiveWeightDistribution; /** * Histogram of negative weight occurences */ map negativeWeightDistribution; /** * Gnuplot output */ bool gnuplot; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ WeightAnalyzer & operator=(const WeightAnalyzer &) = delete; }; } #endif /* Herwig_WeightAnalyzer_H */ diff --git a/MatrixElement/Matchbox/Utility/DensityOperator.cc b/MatrixElement/Matchbox/Utility/DensityOperator.cc --- a/MatrixElement/Matchbox/Utility/DensityOperator.cc +++ b/MatrixElement/Matchbox/Utility/DensityOperator.cc @@ -1,479 +1,477 @@ // -*- C++ -*- // // DensityOperator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 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 DensityOperator class. // #include "DensityOperator.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/Utility/MatchboxXCombData.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; DensityOperator::DensityOperator() : Nc(3.0), TR(0.5) { } -DensityOperator::~DensityOperator() {} - void DensityOperator::clear() { theCorrelatorMap.clear(); } // Prepare density operator if not done before void DensityOperator::prepare(const cPDVector& mePartonData) { // Take parton data and create key of type 33bar888 to use as key for basis vector mePartonDataColoured = theColourBasis->normalOrderMap(mePartonData); if( theDensityOperatorMap.count( mePartonDataColoured ) == 0 ){ // Get basis dimension size_t dim = theColourBasis->prepare( mePartonData, false ); // Allocate space for density matrix theDensityOperatorMap.insert(make_pair(mePartonDataColoured,matrix (dim,dim))); } } // Fill the density matrix for the first time void DensityOperator::fill(const Ptr::ptr MBXCombPtr, const cPDVector& partons, const vector& momenta){ // Map from helicity structure to amplitude vector in the color basis const map,CVector>& amplitudeMap = MBXCombPtr->lastAmplitudes(); const cPDVector& mePartonData = MBXCombPtr->mePartonData(); // Get the dimension of the basis for the indexChange method size_t dim = theColourBasis->prepare(mePartonData,false); // Normal order partons according to ColourBasis const vector mePartonDataColoured = theColourBasis->normalOrderMap(mePartonData); // Get the colour basis to colour basis map for this hard subprocess map >::iterator cb2cbit = theColourBasisToColourBasisMap.find(mePartonData); // Fill the map with this hard subprocess if it doesn't have it yet if ( cb2cbit == theColourBasisToColourBasisMap.end() ) { // Get the index map for the partons as they are ordered in the MatchboxXComb // object const map& mbIndexMap = theColourBasis->indexMap().at(mePartonData); // Get the index map for the partons as they are ordered // in the shower. // Use prepare, as it might not have been done for this order of the partons theColourBasis->prepare(partons,false); const map& showerIndexMap = theColourBasis->indexMap().at(partons); // ensure the maps are of the same size assert( mbIndexMap.size() == showerIndexMap.size() ); // Loop over both sets of partons to determine how the order between them // differs, then translate the index to the colour basis and put the // key-value pair into the map map cb2cbMap; // Get the momenta for comparison const vector& meMomenta = MBXCombPtr->matchboxME()->lastMEMomenta(); // Make sure there's the same number of momenta in both vectors assert( momenta.size() == meMomenta.size() ); bool done; // Boost the momenta to the same frame const vector momentaCM = boostToRestFrame(momenta); for ( size_t i = 0; i < momentaCM.size(); i++ ) { // The cb2cb map is intended to translate how the indices // are different in the colour basis due to the different // orderings of the partons, so it should only bother // with coloured particles. if ( partons[i]->coloured() ) { done = false; for ( size_t j = 0; j < meMomenta.size(); j++ ) { if ( !done ) { if ( compareMomentum(momentaCM[i],meMomenta[j]) ) { cb2cbMap[mbIndexMap.at(i)] = showerIndexMap.at(j); done = true; } } } } } // Make sure all momenta have been identified assert( cb2cbMap.size() == mePartonDataColoured.size() ); // Add the map to the cache theColourBasisToColourBasisMap[mePartonData] = cb2cbMap; // Get the iterator cb2cbit = theColourBasisToColourBasisMap.find(mePartonData); } // With the cb2cb index map we can create the basis vector index map const map vectorMap = theColourBasis->indexChange(mePartonDataColoured, dim,cb2cbit->second); // Prepare density operator (allocate) for set of particles prepare(mePartonData); // Check that density operator (place holder for) exist in density operator map map,matrix >::iterator dOit = theDensityOperatorMap.find(mePartonDataColoured); assert(dOit != theDensityOperatorMap.end()); // Initialize the density operator matrix& densOp = dOit->second; for(unsigned int i = 0; i < (amplitudeMap.begin()->second).size(); i++){ for(unsigned int j = 0; j < (amplitudeMap.begin()->second).size(); j++){ densOp (i,j) = 0; } } // Fill the density operator, ok to sum over helicities since the density operator // exist at the probability level CVector amplitude; for ( map,CVector>::const_iterator itHel = amplitudeMap.begin(); itHel != amplitudeMap.end(); itHel++ ) { amplitude = itHel->second; for ( unsigned int i = 0; i < amplitude.size(); i++ ) { for ( unsigned int j = 0; j < amplitude.size(); j++ ) { // vectorMap is used such that densOp is filled according to the // basis order defined by the input cPDVector partons. densOp (vectorMap.at(i),vectorMap.at(j)) += amplitude(i)*std::conj(amplitude(j)); } } } // Colour conservation check colourConservation(mePartonData); } // Update density matrix after emitting or splitting a gluon // The emissionsMap argument contains the relation of the indices in the smaller (before) // and larger basis (after). the first 3-tuple contains the indices // (emitter before, emitter after, emitted parton) // The map contains the old and new indices of all other partons (not involved) void DensityOperator::evolve(const map,Complex>& Vijk, const cPDVector& before, const cPDVector& after, const map,map >& emissionsMap, const bool splitAGluon, const bool initialGluonSplitting) { size_t dimBefore = theColourBasis->prepare( before, false ); size_t dimAfter = theColourBasis->prepare( after, false ); vector beforeColoured = theColourBasis->normalOrderMap(before); vector afterColoured = theColourBasis->normalOrderMap(after); const map,matrix >::iterator dOit = theDensityOperatorMap.find(beforeColoured); assert(dOit != theDensityOperatorMap.end()); const matrix& densOpBefore = dOit->second; prepare(after); matrix& densOpAfter = theDensityOperatorMap[afterColoured]; for(size_t i = 0; i < densOpAfter.size1(); i++){ for(size_t j = 0; j < densOpAfter.size2(); j++){ densOpAfter(i,j) = 0; } } compressed_matrix Tij; matrix TijMn (dimAfter,dimBefore); compressed_matrix Tk; matrix TijMnTkdagger (dimAfter,dimAfter); Complex V; // Compensate for sign from updated density matrix // TODO Check signs again double sign = -1.0; if ( splitAGluon ) sign = 1.0; // Loop over emitter legs ij and recoil legs k and add the contribution, // for Vijk is assumed to contain the factor 4*pi*\alpha_s/pi.pj typedef map,map > dictMap; int ij,k; // Loop over emitters for(dictMap::const_iterator ijit = emissionsMap.begin(); ijit != emissionsMap.end(); ijit++) { // get first element in 3-tuple, i.e., emitter before ij = std::get<0>(ijit->first); assert(before[ij]->coloured()); // Get rectangular matrices T_{ij} or S_{ij} taking us from the // smaller to the larger basis depending on // the involved particles before and after, the emitter index before ij, // the emitter after and the emitted parton index int i=std::get<1>(ijit->first); // emitter after int j=std::get<2>(ijit->first);// emitted parton Tij = theColourBasis->charge(before,after, ij,i,j,ijit->second).first; TijMn = prodSparseDense(Tij,densOpBefore); // Loop over spectators for(dictMap::const_iterator kit = emissionsMap.begin(); kit != emissionsMap.end(); kit++) { k = std::get<0>(kit->first); assert(before[k]->coloured()); // Standard case of gluon radiation if ( ijit != kit || splitAGluon || initialGluonSplitting ) { int k_after=std::get<1>(kit->first); // For color structure k now has role of emitter int k_emission= std::get<2>(kit->first); // Emitted parton index Tk = theColourBasis->charge(before,after, k, k_after, k_emission, kit->second).first; TijMnTkdagger = prodDenseSparse(TijMn,Tk); // sign == -1.0 if it isn't a gluon splitting into a qqbar pair V = sign*(1.0/colourNorm(before[ij]))* Vijk.at(make_pair(ij,k)); densOpAfter += V*TijMnTkdagger; } } } // Check that the density operator does not vanish assert( theColourBasis->me2(after,densOpAfter) != 0.0 ); colourConservation(after); } // The 3-tuple contains (emitter index, spectator index, emission pid) double DensityOperator::colourMatrixElementCorrection(const std::tuple& ikemission, const cPDVector& particles) { const int i = std::get<0>(ikemission); const int k = std::get<1>(ikemission); //const long emissionID = std::get<2>(ikemission); // Get the density operator // normal order particles as in ColourBasis vector particlesColoured = theColourBasis->normalOrderMap(particles); // ... and find corresponding density operator const map,matrix >::iterator particlesit = theDensityOperatorMap.find(particlesColoured); assert(particlesit != theDensityOperatorMap.end()); const matrix& densOp = particlesit->second; double Ti2 = colourNorm(particles[i]); // Emitter-spectator pair const pair ik = make_pair(i,k); // Create key for color matrix element correction map pair,pair > particlesAndLegs = make_pair(particlesColoured,ik); // Result double res = 0; // Check if it has already been calculated // TODO: move this check earlier (we only need particlesColoured to check if it has been // calculated). // Check for color matrix element associated with key, and calculate if not done const map,pair >,double >::const_iterator corrit = theCorrelatorMap.find(particlesAndLegs); if ( corrit == theCorrelatorMap.end() ) { double corrME2 = theColourBasis->colourCorrelatedME2(ik,particles,densOp); double me2 = theColourBasis->me2(particles,densOp); res = -(1/Ti2)*corrME2/me2; if ( particles[i]->id() == ParticleID::g ) res *= 2.; theCorrelatorMap.insert(make_pair(particlesAndLegs,res)); } else { res = corrit->second; } return res; } double DensityOperator::colourNorm(const cPDPtr particle) { if ( particle->id() == ParticleID::g ) { return Nc; //is 3.0 for Nc = 3, TR = 1/2 } else if ( particle->iColour() == PDT::Colour3 || particle->iColour() == PDT::Colour3bar ) { return TR*(Nc*Nc-1.)/Nc; // is 4.0/3.0 for Nc = 3, TR = 1/2 } else { throw Exception() << "Colour matrix element corrections only work " << "on quark and gluon legs. " << Exception::runerror; } } void DensityOperator::colourConservation(const cPDVector& particles) { // To contain (emitter, spectator, emission pid) std::tuple ikemission; // Normal order particles as defined in ColourBasis const vector particlesColoured = theColourBasis->normalOrderMap(particles); vector sum(particlesColoured.size(),0.0); size_t iterm = 0; // To compensate for the CMEC having a 1/(1+\delta(i is gluon)) factor // in the splitting kernel double gluonFactor = 1.0; // Loop over "emitters" to check color conservation for for ( size_t i = 0; i < particles.size(); i++ ) { if ( particles[i]->coloured() ) { for ( size_t k = 0; k < particles.size(); k++ ) { if ( particles[k]->coloured() && i != k ) { ikemission = std::make_tuple(i,k,ParticleID::g); if ( particles[i]->id() != ParticleID::g ) { gluonFactor = 1.0; } else { gluonFactor = 1./2.; } sum[iterm] += gluonFactor*colourMatrixElementCorrection(ikemission,particles); } } iterm++; } } for ( size_t i = 0; i < sum.size(); i++ ) assert( std::abs(sum[i]-1.0) < pow(10.0,-10.0)); } matrix DensityOperator::prodSparseDense(const compressed_matrix& Tij, const matrix& Mn){ // Dimension before emission size_t dimBefore = Tij.size2(); // Dimension after emission size_t dimAfter = Tij.size1(); //Check matrix dimensions assert( dimBefore == Mn.size1() ); // Allocate memory for the matrix matrix TijMn (dimAfter,dimBefore,0); // Use iterators for the compressed matrix to iterate only over the non-zero // elements. size_t ii; size_t jj; for ( compressed_matrix::const_iterator1 it1 = Tij.begin1(); it1 != Tij.end1(); it1++ ) { for ( compressed_matrix::const_iterator2 it2 = it1.begin(); it2 != it1.end(); it2++ ) { ii = it2.index1(); jj = it2.index2(); for ( size_t kk = 0; kk < dimBefore; kk++ ) { // *it2 is Tij(ii,jj) TijMn(ii,kk) += (*it2)*Mn(jj,kk); } } } return TijMn; } matrix DensityOperator::prodDenseSparse(const matrix& TijMn, const compressed_matrix& Tk){ // The compressed matrix comes from the charge method, do not transpose yet // Dimension after emission size_t dimAfter = Tk.size1();//Since this method returns TijMn*Tk^\dagger //Check matrix dimensions assert( TijMn.size2() == Tk.size2() ); // Allocate memory for the matrix matrix TijMnTkdagger (dimAfter,dimAfter,0); size_t jj; size_t kk; for ( compressed_matrix::const_iterator1 it1 = Tk.begin1(); it1 != Tk.end1(); it1++ ) { for ( compressed_matrix::const_iterator2 it2 = it1.begin(); it2 != it1.end(); it2++ ) { jj = it2.index2();//transposing Tk jj is index2(), not index1() kk = it2.index1();//transposing Tk for ( size_t ii = 0; ii < dimAfter; ii++ ) { // *it2 is Tk(kk,jj) = trans(Tk)(jj,kk) TijMnTkdagger(ii,kk) += TijMn(ii,jj)*(*it2); } } } return TijMnTkdagger; } vector DensityOperator::boostToRestFrame(const vector& momenta) { // We need 2 initial particles assert(momenta.size() >= 2); // The boosted vectors vector vboosted = momenta; // The boost should be to the rest frame of the initial particles Boost b = (momenta[0] + momenta[1]).findBoostToCM(); // Boost all of the vectors for ( size_t i = 0; i < momenta.size(); i++ ) { vboosted[i].boost(b); } return vboosted; } bool DensityOperator::compareMomentum(const Lorentz5Momentum& p, const Lorentz5Momentum& q) { bool equal = true; // Compares two momentum vectors p and q, if they are close enough (defined by the // double eps below) it returns true. This is sufficient to distinguish particles // in the matrix element as we are not interested in the matrix element for extremely // collinear radiation (better described by the parton shower). // Create the difference of the two vectors const Lorentz5Momentum l = p - q; // A relevant size that is guaranteed to be larger than 0 const Energy2 e2 = p.t()*p.t(); // Size of the difference that would be considered equal const double eps = pow(10.,-15.); if ( l.x()*l.x()/e2 > eps ) equal = false; if ( l.y()*l.y()/e2 > eps ) equal = false; if ( l.z()*l.z()/e2 > eps ) equal = false; if ( l.t()*l.t()/e2 > eps ) equal = false; return equal; } IBPtr DensityOperator::clone() const { return new_ptr(*this); } IBPtr DensityOperator::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DensityOperator::persistentOutput(PersistentOStream &) const { // *** ATTENTION *** os << ; // Add all member variable which should be written persistently here. } void DensityOperator::persistentInput(PersistentIStream &, int) { // *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here. } // *** 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 describeHerwigDensityOperator("Herwig::DensityOperator", "DensityOperator.so"); void DensityOperator::Init() { static ClassDocumentation documentation ("There is no documentation for the DensityOperator class"); } diff --git a/MatrixElement/Matchbox/Utility/DensityOperator.h b/MatrixElement/Matchbox/Utility/DensityOperator.h --- a/MatrixElement/Matchbox/Utility/DensityOperator.h +++ b/MatrixElement/Matchbox/Utility/DensityOperator.h @@ -1,248 +1,240 @@ // -*- C++ -*- // // DensityOperator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 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_DensityOperator_H #define Herwig_DensityOperator_H // // This is the declaration of the DensityOperator class. // #include "ThePEG/Handlers/HandlerBase.h" #include "Herwig/MatrixElement/Matchbox/Utility/ColourBasis.h" #include #include #include namespace Herwig { using namespace ThePEG; typedef boost::numeric::ublas::vector CVector; /** * Here is the documentation of the DensityOperator class. * * @see \ref DensityOperatorInterfaces "The interfaces" * defined for DensityOperator. */ class DensityOperator: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ DensityOperator(); - /** - * The destructor. - */ - virtual ~DensityOperator(); - //@} - public: /** * Clears theDensityOperatorMap. */ void clear(); /** * Prepare for the given sub process. */ void prepare(const cPDVector&); /** * Fill the density operator for the given hard subprocess, summing over all * helicity configurations. */ void fill(const Ptr::ptr, const cPDVector&, const vector& momenta); /** * Evolve the density operator, by * M_{n+1} = -\sum_{i,k}{-4*pi*alpha_s/Ti2*V_{ij,k} T_{i,n}M_nT_{k,n}^\dag}, * see arXiv:1206.0180 eq. (5), note that the pi*pj factor is assumed to be * included in V_{ij,k}. */ void evolve(const map,Complex>& Vijk, const cPDVector& before, const cPDVector& after, const map,map >& emissionsMap, const bool splitAGluon, const bool initialGluonSplitting); /** * Calculate the colour matrix element correction. * -(1+delta(i,gluon))/Ti^2 Tr(Sn+1 Ti Mn Tk^dagger)/Tr(Sn Mn) * where the bracket in front compensates for the gluon symmetry factor, * Ti^2 is C_f or C_a, Sn+1 is the matrix of scalar products, and * Ti is the radiation matrix. * The first arg contains (emitter index, spectator index, emission pid) * */ double colourMatrixElementCorrection(const std::tuple& ikemission, const cPDVector& particles); /** * Checking colour conservation for the colour matrix element corrections. */ void colourConservation(const cPDVector& particles); /** * Get the colour basis. */ Ptr::tptr colourBasis() { return theColourBasis; } /** * Get the colour basis. */ const Ptr::tptr colourBasis() const { return theColourBasis; } /** * Set the colour basis. */ void colourBasis(Ptr::ptr ptr) { theColourBasis = ptr; } /** * Get the correlator map. */ const map,pair >,double>& correlatorMap() const { return theCorrelatorMap; } /** @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: /** * Number of colours used in colourNorm. */ double Nc; /** * QCD vertex normalization. */ double TR; /** * Normalization of colour charges \mathbf{T}_{ij}^2. */ double colourNorm(const cPDPtr particle); /** * Fast evaluation of Tij*Mn, where a Tij is the matrix from ColourBasis::charge, * which is a sparse matrix, and Mn is the density operator, a dense matrix. * */ matrix prodSparseDense(const compressed_matrix&, const matrix&); /** * Fast evaluation of TijMn*Tkdagger, where a TijMn is the result from the method * prodSparseDense, a dense matrix, and Tkdagger is the transponse conjugate of * the matrix from ColourBasis::charge, a sparse matrix. * */ matrix prodDenseSparse(const matrix&, const compressed_matrix&); /** * Boosts a vector of momenta to the rest frame of the initial pair * of particles (the first 2 elements of the argument vector). Returns * the boosted vectors */ vector boostToRestFrame(const vector& momenta); /** * Boosts a vector of momenta to the rest frame of the initial pair */ bool compareMomentum(const Lorentz5Momentum& p, const Lorentz5Momentum& q); /** * Mapping of colour structures to density operator matrices. * */ map,matrix > theDensityOperatorMap; /** * Mapping of colour structures and legs to colour correlators. */ map,pair >,double> theCorrelatorMap; /** * A map from the hard subprocess particles to a map of amplitude colour * basis order to the normal ordered colour basis. */ map > theColourBasisToColourBasisMap; /** * Colour basis used. */ Ptr::ptr theColourBasis; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DensityOperator & operator=(const DensityOperator &) = delete; }; } #endif /* Herwig_DensityOperator_H */ diff --git a/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.cc b/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.cc --- a/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.cc +++ b/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.cc @@ -1,102 +1,100 @@ // -*- C++ -*- // // MatchboxFactoryMatcher.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxFactoryMatcher class. // #include "MatchboxFactoryMatcher.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MatchboxFactoryMatcher::MatchboxFactoryMatcher() : theGroup("") {} -MatchboxFactoryMatcher::~MatchboxFactoryMatcher() {} - IBPtr MatchboxFactoryMatcher::clone() const { return new_ptr(*this); } IBPtr MatchboxFactoryMatcher::fullclone() const { return new_ptr(*this); } PMPtr MatchboxFactoryMatcher::pmclone() const { return new_ptr(*this); } bool MatchboxFactoryMatcher::check(const ParticleData & data) const { return theIds.find(data.id()) != theIds.end(); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxFactoryMatcher::persistentOutput(PersistentOStream & os) const { os << theGroup << theIds; } void MatchboxFactoryMatcher::persistentInput(PersistentIStream & is, int) { is >> theGroup >> theIds; } void MatchboxFactoryMatcher::doinit() { if ( !MatchboxFactory::isMatchboxRun() ) return; if ( !MatchboxFactory::currentFactory() ) throw Exception() << "MatchboxFactoryMatcher::doinit(): No factory object is available in the matcher '" << name() << "'" << Exception::runerror; map::const_iterator grp = MatchboxFactory::currentFactory()->particleGroups().find(theGroup); if ( grp == MatchboxFactory::currentFactory()->particleGroups().end() ) throw Exception() << "MatchboxFactoryMatcher::doinit(): Particle group '" << theGroup << "' not defined in factory object '" << MatchboxFactory::currentFactory()->name() << "'" << Exception::runerror; theIds.clear(); for ( PDVector::const_iterator p = grp->second.begin(); p != grp->second.end(); ++p ) theIds.insert((**p).id()); MatcherBase::doinit(); } // *** 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 describeHerwigMatchboxFactoryMatcher("Herwig::MatchboxFactoryMatcher", "Herwig.so"); void MatchboxFactoryMatcher::Init() { static ClassDocumentation documentation ("MatchboxFactoryMatcher matches particles according to MatchboxFactory particle groups"); static Parameter interfaceGroup ("Group", "Set the group name to match.", &MatchboxFactoryMatcher::theGroup, "", false, false); } diff --git a/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.h b/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.h --- a/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.h +++ b/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.h @@ -1,147 +1,139 @@ // -*- C++ -*- // // MatchboxFactoryMatcher.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxFactoryMatcher_H #define Herwig_MatchboxFactoryMatcher_H // // This is the declaration of the MatchboxFactoryMatcher class. // #include "ThePEG/PDT/MatcherBase.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxFactoryMatcher matches particles according to * MatchboxFatory particle groups * * @see \ref MatchboxFactoryMatcherInterfaces "The interfaces" * defined for MatchboxFactoryMatcher. */ class MatchboxFactoryMatcher: public ThePEG::MatcherBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxFactoryMatcher(); - /** - * The destructor. - */ - virtual ~MatchboxFactoryMatcher(); - //@} - public: /** * Check if a particle type meets the criteria. */ virtual bool check(const ParticleData &) const; /** * Specialized clone method for MatcherBase used by the * Repository. A sub class must make sure that also the MatcherBase * object corresponding to the complex conjugate of this is cloned. */ virtual PMPtr pmclone() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The particle group to be matched */ string theGroup; /** * The set of particle ids to be matched */ set theIds; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxFactoryMatcher & operator=(const MatchboxFactoryMatcher &) = delete; }; } #endif /* Herwig_MatchboxFactoryMatcher_H */ diff --git a/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.cc b/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.cc --- a/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.cc +++ b/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.cc @@ -1,83 +1,81 @@ // -*- C++ -*- // // MatchboxScaleChoice.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxScaleChoice class. // #include "MatchboxScaleChoice.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MatchboxScaleChoice::MatchboxScaleChoice() : theFixedScale(ZERO), theFixedQEDScale(ZERO) {} -MatchboxScaleChoice::~MatchboxScaleChoice() {} - IBPtr MatchboxScaleChoice::clone() const { return new_ptr(*this); } IBPtr MatchboxScaleChoice::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MatchboxScaleChoice::persistentOutput(PersistentOStream & os) const { os << theLastXComb << ounit(theFixedScale,GeV) << ounit(theFixedQEDScale,GeV); } void MatchboxScaleChoice::persistentInput(PersistentIStream & is, int) { is >> theLastXComb >> iunit(theFixedScale,GeV) >> iunit(theFixedQEDScale,GeV); } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMatchboxScaleChoice("Herwig::MatchboxScaleChoice", "Herwig.so"); void MatchboxScaleChoice::Init() { static ClassDocumentation documentation ("MatchboxScaleChoice is the base class for scale choices " "within Matchbox."); static Parameter interfaceFixedScale ("FixedScale", "Set a fixed scale.", &MatchboxScaleChoice::theFixedScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFixedQEDScale ("FixedQEDScale", "Set a fixed QED scale.", &MatchboxScaleChoice::theFixedQEDScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); } diff --git a/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h b/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h --- a/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h +++ b/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h @@ -1,169 +1,161 @@ // -*- C++ -*- // // MatchboxScaleChoice.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxScaleChoice_H #define Herwig_MatchboxScaleChoice_H // // This is the declaration of the MatchboxScaleChoice class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Handlers/LastXCombInfo.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxScaleChoice is the base class for scale choices * within Matchbox. * */ class MatchboxScaleChoice: public HandlerBase, public LastXCombInfo { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MatchboxScaleChoice(); - /** - * The destructor. - */ - virtual ~MatchboxScaleChoice(); - //@} - public: /** * Clone this scale choice. */ Ptr::ptr cloneMe() const { return dynamic_ptr_cast::ptr>(clone()); } /** * Set the XComb object. */ virtual void setXComb(tStdXCombPtr xc) { theLastXComb = xc; } /** * Return the renormalization scale. This default version returns * shat. */ virtual Energy2 renormalizationScale() const { return theFixedScale == ZERO ? lastSHat() : sqr(theFixedScale); } /** * Return the factorization scale. This default version returns * shat. */ virtual Energy2 factorizationScale() const { return theFixedScale == ZERO ? lastSHat() : sqr(theFixedScale); } /** * Return the QED renormalization scale. This default version returns * the Z mass squared. */ virtual Energy2 renormalizationScaleQED() const { if ( theFixedQEDScale != ZERO ) return sqr(theFixedQEDScale); Energy mZ = getParticleData(ParticleID::Z0)->hardProcessMass(); return mZ*mZ; } /** * Return the shower hard scale. This default implementation returns the * factorization scale. */ virtual Energy2 showerScale() const { return factorizationScale(); } 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: /** * A fixed scale choice. If zero, shat will be used. */ Energy theFixedScale; /** * A fixed QED scale choice. If zero, shat will be used. */ Energy theFixedQEDScale; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxScaleChoice & operator=(const MatchboxScaleChoice &) = delete; }; } #endif /* Herwig_MatchboxScaleChoice_H */ diff --git a/MatrixElement/Matchbox/Utility/MatchboxXComb.cc b/MatrixElement/Matchbox/Utility/MatchboxXComb.cc --- a/MatrixElement/Matchbox/Utility/MatchboxXComb.cc +++ b/MatrixElement/Matchbox/Utility/MatchboxXComb.cc @@ -1,78 +1,76 @@ // -*- C++ -*- // // MatchboxXComb.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxXComb class. // #include "MatchboxXComb.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; MatchboxXComb::MatchboxXComb() : StandardXComb() { flushCaches(); } -MatchboxXComb::~MatchboxXComb() {} - MatchboxXComb::MatchboxXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, tMEPtr newME, const DiagramVector & newDiagrams, bool mir, tStdXCombPtr newHead) : StandardXComb(newMaxEnergy, inc, newEventHandler,newSubProcessHandler, newExtractor, newCKKW, newPartonBins, newCuts, newME, newDiagrams, mir, newHead), MatchboxXCombData(newME) { flushCaches(); } MatchboxXComb::MatchboxXComb(tStdXCombPtr newHead, const PBPair & newPartonBins, tMEPtr newME, const DiagramVector & newDiagrams) : StandardXComb(newHead, newPartonBins, newME, newDiagrams), MatchboxXCombData(newME) { flushCaches(); } void MatchboxXComb::clean() { StandardXComb::clean(); flushCaches(); } void MatchboxXComb::persistentOutput(PersistentOStream & os) const { MatchboxXCombData::persistentOutput(os); } void MatchboxXComb::persistentInput(PersistentIStream & is, int version) { MatchboxXCombData::persistentInput(is,version); } // *** 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 describeHerwigMatchboxXComb("Herwig::MatchboxXComb", "Herwig.so"); void MatchboxXComb::Init() { static ClassDocumentation documentation ("MatchboxXComb extents StandardXComb."); } diff --git a/MatrixElement/Matchbox/Utility/MatchboxXComb.h b/MatrixElement/Matchbox/Utility/MatchboxXComb.h --- a/MatrixElement/Matchbox/Utility/MatchboxXComb.h +++ b/MatrixElement/Matchbox/Utility/MatchboxXComb.h @@ -1,108 +1,102 @@ // -*- C++ -*- // // MatchboxXComb.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxXComb_H #define Herwig_MatchboxXComb_H // // This is the declaration of the MatchboxXComb class. // #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxXCombData.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief Matchbox extensions to StandardXComb */ class MatchboxXComb: public StandardXComb, public MatchboxXCombData { public: /** @name Standard constructors and destructors. */ //@{ /** * Standard constructor. */ MatchboxXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, tMEPtr newME, const DiagramVector & newDiagrams, bool mir, tStdXCombPtr newHead = tStdXCombPtr()); /** * Constructor given a head xcomb. */ MatchboxXComb(tStdXCombPtr newHead, const PBPair & newPartonBins, tMEPtr newME, const DiagramVector & newDiagrams); /** * Default constructor. */ MatchboxXComb(); - - /** - * Destructor. - */ - virtual ~MatchboxXComb(); - //@} public: /** * Reset all saved data about last generated phasespace point; */ virtual void clean(); 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(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxXComb & operator=(const MatchboxXComb &) = delete; }; } #endif /* Herwig_MatchboxXComb_H */ diff --git a/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.cc b/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.cc --- a/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.cc +++ b/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.cc @@ -1,70 +1,68 @@ // -*- C++ -*- // // MatchboxXCombGroup.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxXCombGroup class. // #include "MatchboxXCombGroup.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; MatchboxXCombGroup::MatchboxXCombGroup() : StdXCombGroup() { flushCaches(); } -MatchboxXCombGroup::~MatchboxXCombGroup() {} - MatchboxXCombGroup::MatchboxXCombGroup(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, tMEGroupPtr newME, const DiagramVector & newDiagrams, bool mir, tStdXCombPtr newHead) : StdXCombGroup(newMaxEnergy, inc, newEventHandler, newSubProcessHandler, newExtractor, newCKKW, newPartonBins, newCuts, newME, newDiagrams, mir, newHead), MatchboxXCombData(newME) { flushCaches(); } void MatchboxXCombGroup::clean() { StdXCombGroup::clean(); flushCaches(); } void MatchboxXCombGroup::persistentOutput(PersistentOStream & os) const { MatchboxXCombData::persistentOutput(os); } void MatchboxXCombGroup::persistentInput(PersistentIStream & is, int version) { MatchboxXCombData::persistentInput(is,version); } // *** 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 describeHerwigMatchboxXCombGroup("Herwig::MatchboxXCombGroup", "Herwig.so"); void MatchboxXCombGroup::Init() { static ClassDocumentation documentation ("MatchboxXCombGroup extents StdXCombGroup."); } diff --git a/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.h b/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.h --- a/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.h +++ b/MatrixElement/Matchbox/Utility/MatchboxXCombGroup.h @@ -1,102 +1,96 @@ // -*- C++ -*- // // MatchboxXCombGroup.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_MatchboxXCombGroup_H #define Herwig_MatchboxXCombGroup_H // // This is the declaration of the MatchboxXCombGroup class. // #include "ThePEG/Handlers/StdXCombGroup.h" #include "ThePEG/MatrixElement/MEGroup.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxXCombData.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief Matchbox extensions to StandardXComb */ class MatchboxXCombGroup: public StdXCombGroup, public MatchboxXCombData { public: /** @name Standard constructors and destructors. */ //@{ /** * Standard constructor. */ MatchboxXCombGroup(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, tMEGroupPtr newME, const DiagramVector & newDiagrams, bool mir, tStdXCombPtr newHead = tStdXCombPtr()); /** * Default constructor. */ MatchboxXCombGroup(); - - /** - * Destructor. - */ - virtual ~MatchboxXCombGroup(); - //@} public: /** * Reset all saved data about last generated phasespace point; */ virtual void clean(); 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(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxXCombGroup & operator=(const MatchboxXCombGroup &) = delete; }; } #endif /* Herwig_MatchboxXCombGroup_H */ diff --git a/MatrixElement/Matchbox/Utility/SimpleColourBasis.cc b/MatrixElement/Matchbox/Utility/SimpleColourBasis.cc --- a/MatrixElement/Matchbox/Utility/SimpleColourBasis.cc +++ b/MatrixElement/Matchbox/Utility/SimpleColourBasis.cc @@ -1,414 +1,409 @@ // -*- C++ -*- // // SimpleColourBasis.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SimpleColourBasis class. // #include "SimpleColourBasis.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 "ThePEG/StandardModel/StandardModelBase.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -SimpleColourBasis::SimpleColourBasis() {} - -SimpleColourBasis::~SimpleColourBasis() {} - IBPtr SimpleColourBasis::clone() const { return new_ptr(*this); } IBPtr SimpleColourBasis::fullclone() const { return new_ptr(*this); } size_t SimpleColourBasis::prepareBasis(const vector& basis) { if ( id33bar.empty() ) makeIds(); if ( basis == id88 || basis == id33bar || basis == id33bar8 ) return 1; if ( basis == id888 || basis == id33bar88 || basis == id33bar33bar ) return 2; if ( basis == id8888 ) return 6; throw Exception() << "SimpleColourBasis::prepareBasis(): Cannot handle colour configuration" << Exception::runerror; return 0; } double SimpleColourBasis::scalarProduct(size_t a, size_t b, const vector& abBasis) const { if ( id33bar.empty() ) makeIds(); double Nc = SM().Nc(); double Nc2 = sqr(Nc); double Nc3 = Nc*Nc2; double Nc4 = sqr(Nc2); double Nc6 = Nc2*Nc4; if ( a > b ) swap(a,b); if ( !largeN() ) { if ( abBasis == id88 ) { return ( Nc2 - 1. )/4.; } if ( abBasis == id33bar ) { return Nc; } if ( abBasis == id888 ) { if ( a == b ) return ( Nc4 - 3.*Nc2 + 2. )/(8.*Nc); return -( Nc2 - 1. )/(4.*Nc); } if ( abBasis == id33bar8 ) { return ( Nc2 - 1. )/2.; } if ( abBasis == id8888 ) { if ( a == b ) return ( Nc6 - 4.*Nc4 + 6.*Nc2 - 3. )/(16.*Nc2); if ( ( a == 0 && b == 1 ) || ( a == 2 && b == 3 ) || ( a == 4 && b == 5 ) ) return ( Nc4 + 2.*Nc2 - 3. )/(16.*Nc2); return -( Nc2 - 4. + 3./Nc2 )/16.; } if ( abBasis == id33bar88 ) { if ( a == b ) return ( Nc4 - 2.*Nc2 + 1 )/(4.*Nc); return -( Nc2 - 1. )/(4.*Nc); } if ( abBasis == id33bar33bar ) { if ( a == b ) return Nc2; return Nc; } } else { if ( a != b ) return 0.; if ( abBasis == id88 ) { return Nc2/4.; } if ( abBasis == id33bar ) { return Nc; } if ( abBasis == id888 ) { return Nc3/8.; } if ( abBasis == id33bar8 ) { return Nc2/2.; } if ( abBasis == id8888 ) { return Nc4/16.; } if ( abBasis == id33bar88 ) { return Nc3/4.; } if ( abBasis == id33bar33bar ) { return Nc2; } } throw Exception() << "SimpleColourBasis::scalarProduct(): Cannot handle colour configuration" << Exception::runerror; } double SimpleColourBasis::tMatrixElement(size_t i, size_t a, size_t b, const vector&, const vector& bBasis, #ifndef NDEBUG size_t k, size_t l, #else size_t , size_t , #endif const map& dict) const { // Check indices k and l assert( k == i ); assert( l == bBasis.size() ); // Check that dict is the standardMap assert( dict.size()+1 == bBasis.size() ); map::const_iterator tmp; for ( size_t ii = 0; ii < bBasis.size(); ii++ ) if ( ii != i ) { tmp = dict.find(ii); assert( tmp != dict.end() ); assert( tmp->second == ii ); } if ( id33bar.empty() ) makeIds(); if ( bBasis == id88 ) { if ( i == 0 ) return a == 0 ? -1. : 1.; else return a == 0 ? 1. : -1.; } if ( bBasis == id33bar ) { return i == 0 ? 1. : -1.; } if ( bBasis == id888 ) { if ( i == 0 ) { if ( a == 3 && b == 0 ) return 1.; if ( a == 0 && b == 0 ) return -1.; if ( a == 1 && b == 1 ) return 1.; if ( a == 2 && b == 1 ) return -1.; } if ( i == 1 ) { if ( a == 4 && b == 0 ) return 1.; if ( a == 3 && b == 0 ) return -1.; if ( a == 2 && b == 1 ) return 1.; if ( a == 5 && b == 1 ) return -1.; } if ( i == 2 ) { if ( a == 0 && b == 0 ) return 1.; if ( a == 4 && b == 0 ) return -1.; if ( a == 5 && b == 1 ) return 1.; if ( a == 1 && b == 1 ) return -1.; } return 0.; } if ( bBasis == id33bar8 ) { if ( i == 0 ) return a == 1 ? 1. : 0.; if ( i == 1 ) return a == 0 ? -1. : 0.; if ( i == 2 ) return a == 0 ? 1. : -1.; } throw Exception() << "SimpleColourBasis::tMatrixElement(): Cannot handle colour configuration" << Exception::runerror; return 0.; } bool SimpleColourBasis::colourConnected(const cPDVector& sub, const vector& basis, const pair& i, const pair& j, size_t a) const { if ( id33bar.empty() ) makeIds(); // translate process to basis ids map >::const_iterator trans = indexMap().find(sub); assert(trans != indexMap().end()); int idColoured = i.second ? j.first : i.first; idColoured = trans->second.find(idColoured)->second; int idAntiColoured = i.second ? i.first : j.first; idAntiColoured = trans->second.find(idAntiColoured)->second; if ( basis == id88 ) { return ( idColoured == 0 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 0 ); } if ( basis == id33bar ) { return idColoured == 0 && idAntiColoured == 1; } if ( basis == id888 ) { if ( a == 0 ) return ( idColoured == 0 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 0 ); if ( a == 1 ) return ( idColoured == 0 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 0 ); } if ( basis == id33bar8 ) { return ( idColoured == 0 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 1 ); } if ( basis == id8888 ) { if ( a == 0 ) return ( idColoured == 0 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 3 ) || ( idColoured == 3 && idAntiColoured == 0 ); if ( a == 1 ) return ( idColoured == 0 && idAntiColoured == 3 ) || ( idColoured == 3 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 0 ); if ( a == 2 ) return ( idColoured == 0 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 3 ) || ( idColoured == 3 && idAntiColoured == 0 ); if ( a == 3 ) return ( idColoured == 0 && idAntiColoured == 3 ) || ( idColoured == 3 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 0 ); if ( a == 4 ) return ( idColoured == 0 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 3 ) || ( idColoured == 3 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 0 ); if ( a == 5 ) return ( idColoured == 0 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 3 ) || ( idColoured == 3 && idAntiColoured == 1 ) || ( idColoured == 1 && idAntiColoured == 0 ); } if ( basis == id33bar88 ) { if ( a == 0 ) return ( idColoured == 0 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 3 ) || ( idColoured == 3 && idAntiColoured == 1 ); if ( a == 1 ) return ( idColoured == 0 && idAntiColoured == 3 ) || ( idColoured == 3 && idAntiColoured == 2 ) || ( idColoured == 2 && idAntiColoured == 1 ); } if ( basis == id33bar33bar ) { if ( a == 0 ) return ( idColoured == 0 && idAntiColoured == 1 ) || ( idColoured == 2 && idAntiColoured == 3 ); if ( a == 1 ) return ( idColoured == 0 && idAntiColoured == 3 ) || ( idColoured == 2 && idAntiColoured == 1 ); } return false; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void SimpleColourBasis::makeIds() const { id88.push_back(PDT::Colour8); id88.push_back(PDT::Colour8); id33bar.push_back(PDT::Colour3); id33bar.push_back(PDT::Colour3bar); id888.push_back(PDT::Colour8); id888.push_back(PDT::Colour8); id888.push_back(PDT::Colour8); id33bar8.push_back(PDT::Colour3); id33bar8.push_back(PDT::Colour3bar); id33bar8.push_back(PDT::Colour8); id8888.push_back(PDT::Colour8); id8888.push_back(PDT::Colour8); id8888.push_back(PDT::Colour8); id8888.push_back(PDT::Colour8); id33bar88.push_back(PDT::Colour3); id33bar88.push_back(PDT::Colour3bar); id33bar88.push_back(PDT::Colour8); id33bar88.push_back(PDT::Colour8); id33bar33bar.push_back(PDT::Colour3); id33bar33bar.push_back(PDT::Colour3bar); id33bar33bar.push_back(PDT::Colour3); id33bar33bar.push_back(PDT::Colour3bar); } void SimpleColourBasis::persistentOutput(PersistentOStream &) const {} void SimpleColourBasis::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigSimpleColourBasis("Herwig::SimpleColourBasis", "Herwig.so"); void SimpleColourBasis::Init() { static ClassDocumentation documentation ("SimpleColourBasis implements the colour algebra needed for " "electroweak boson and electroweak boson + jet production at NLO. It mainly " "serves as an example for the general ColourBasis interface."); } diff --git a/MatrixElement/Matchbox/Utility/SimpleColourBasis.h b/MatrixElement/Matchbox/Utility/SimpleColourBasis.h --- a/MatrixElement/Matchbox/Utility/SimpleColourBasis.h +++ b/MatrixElement/Matchbox/Utility/SimpleColourBasis.h @@ -1,209 +1,194 @@ // -*- C++ -*- // // SimpleColourBasis.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_SimpleColourBasis_H #define Herwig_SimpleColourBasis_H // // This is the declaration of the SimpleColourBasis class. // #include "Herwig/MatrixElement/Matchbox/Utility/ColourBasis.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief SimpleColourBasis implements the colour algebra needed for * electroweak boson and electroweak boson + jet production at NLO. It * mainly serves as an example for the general ColourBasis interface. * */ class SimpleColourBasis: public ColourBasis { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - SimpleColourBasis(); - - /** - * The destructor. - */ - virtual ~SimpleColourBasis(); - //@} - -public: - /** * Prepare the basis for the normal ordered legs and return the * dimensionality of the basis. */ virtual size_t prepareBasis(const vector&); /** * Return the scalar product of basis tensors labelled a and b in * the basis used for the given normal ordered legs. */ virtual double scalarProduct(size_t a, size_t b, const vector& abBasis) const; /** * Return the matrix element of a colour charge * between basis tensors a and b, with * respect to aBasis and bBasis */ virtual double tMatrixElement(size_t i, size_t a, size_t b, const vector& aBasis, const vector& bBasis, size_t k, size_t l, const map& dict ) const; virtual double sMatrixElement(size_t, size_t, size_t, const vector&, const vector&, size_t, size_t, const map& ) const { assert( 0 == 1 ); return 0; } /** * Return true, if this colour basis supports gluon splittings. */ virtual bool canSplitGluons() const { return false; } /** * Return true, if a large-N colour connection exists for the * given external legs and basis tensor. */ virtual bool colourConnected(const cPDVector&, const vector&, const pair&, const pair&, size_t) const; /** * Return true, if the colour basis is capable of assigning colour * flows. */ virtual bool haveColourFlows() const { return true; } /** * Create ids for bases */ void makeIds() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * id for 88 */ mutable vector id88; /** * id for 33bar */ mutable vector id33bar; /** * id for 888 */ mutable vector id888; /** * id for 33bar8 */ mutable vector id33bar8; /** * id for 8888 */ mutable vector id8888; /** * id for 33bar88 */ mutable vector id33bar88; /** * id for 33bar33bar */ mutable vector id33bar33bar; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SimpleColourBasis & operator=(const SimpleColourBasis &) = delete; }; } #endif /* Herwig_SimpleColourBasis_H */ diff --git a/MatrixElement/Matchbox/Utility/SimpleColourBasis2.cc b/MatrixElement/Matchbox/Utility/SimpleColourBasis2.cc --- a/MatrixElement/Matchbox/Utility/SimpleColourBasis2.cc +++ b/MatrixElement/Matchbox/Utility/SimpleColourBasis2.cc @@ -1,2882 +1,2877 @@ // -*- C++ -*- // // SimpleColourBasis2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SimpleColourBasis2 class. // #include "SimpleColourBasis2.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 "ThePEG/StandardModel/StandardModelBase.h" - #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; -SimpleColourBasis2::SimpleColourBasis2() {} - -SimpleColourBasis2::~SimpleColourBasis2() {} - IBPtr SimpleColourBasis2::clone() const { return new_ptr(*this); } IBPtr SimpleColourBasis2::fullclone() const { return new_ptr(*this); } size_t SimpleColourBasis2::prepareBasis(const vector& basis) { if ( id33bar.empty() ) makeIds(); if ( basis == id88 ) { return 1; } if ( basis == id33bar ) { return 1; } if ( basis == id888 ) { return 2; } if ( basis == id33bar8 ) { return 1; } if ( basis == id8888 ) { return 9; } if ( basis == id33bar88 ) { return 3; } if ( basis == id33bar33bar ) { return 2; } if ( basis == id88888 ) { return 44; } if ( basis == id33bar888 ) { return 11; } if ( basis == id33bar33bar8 ) { return 4; } throw Exception() << "SimpleColourBasis2::prepareBasis(): Cannot handle colour configuration" << Exception::runerror; return 0; } double SimpleColourBasis2::scalarProduct(size_t a, size_t b, const vector& basis) const { if ( id33bar.empty() ) makeIds(); double Nc = SM().Nc(); double Nc2 = sqr(Nc); double Nc3 = Nc*Nc2; double Nc4 = sqr(Nc2); double Nc5 = Nc*Nc4; double Nc6 = Nc2*Nc4; double Nc8 = Nc2*Nc6; if ( a > b ) swap(a,b); if ( !largeN() ) { if ( basis == id88 ) { if( a == 0 && b == 0 ) return (-1 + Nc2)/4.; } if ( basis == id33bar ) { if( a == 0 && b == 0 ) return Nc; } if ( basis == id888 ) { if( ( a == 0 && b == 0 ) || ( a == 1 && b == 1 ) ) return (2 - 3*Nc2 + Nc4)/(8.*Nc); if( ( a == 0 ) && ( b == 1 ) ) return -(-1 + Nc2)/(4.*Nc); } if ( basis == id33bar8 ) { if( a == 0 && b == 0 ) return (-1 + Nc2)/2.; } if ( basis == id8888 ) { if( ( a == 0 && b == 0 ) || ( a == 1 && b == 1 ) || ( a == 2 && b == 2 ) ) return sqr(-1 + Nc2)/16.; if( ( a == 0 && b == 1 ) || ( a == 0 && b == 2 ) || ( a == 1 && b == 2 ) ) return (-1 + Nc2)/16.; if( ( a == 0 && b == 3 ) || ( a == 0 && b == 5 ) || ( a == 0 && b == 7 ) || ( a == 0 && b == 8 ) || ( a == 1 && b == 4 ) || ( a == 1 && b == 5 ) || ( a == 1 && b == 6 ) || ( a == 1 && b == 7 ) || ( a == 2 && b == 3 ) || ( a == 2 && b == 4 ) || ( a == 2 && b == 6 ) || ( a == 2 && b == 8 ) ) return sqr(-1 + Nc2)/(16.*Nc); if( ( a == 0 && b == 4 ) || ( a == 0 && b == 6 ) || ( a == 1 && b == 3 ) || ( a == 1 && b == 8 ) || ( a == 2 && b == 5 ) || ( a == 2 && b == 7 ) ) return -(-1 + Nc2)/(16.*Nc); if( ( a == 3 && b == 3 ) || ( a == 4 && b == 4 ) || ( a == 5 && b == 5 ) || ( a == 6 && b == 6 ) || ( a == 7 && b == 7 ) || ( a == 8 && b == 8 ) ) return (-3 + 6*Nc2 - 4*Nc4 + Nc6)/(16.*Nc2); if( ( a == 3 && b == 4 ) || ( a == 3 && b == 5 ) || ( a == 3 && b == 6 ) || ( a == 3 && b == 7 ) || ( a == 4 && b == 5 ) || ( a == 4 && b == 7 ) || ( a == 4 && b == 8 ) || ( a == 5 && b == 6 ) || ( a == 5 && b == 8 ) || ( a == 6 && b == 7 ) || ( a == 6 && b == 8 ) || ( a == 7 && b == 8 ) ) return (4 - 3/Nc2 - Nc2)/16.; if( ( a == 3 && b == 8 ) || ( a == 4 && b == 6 ) || ( a == 5 && b == 7 ) ) return (-3 + 2*Nc2 + Nc4)/(16.*Nc2); } if ( basis == id33bar88 ) { if( a == 0 && b == 0 ) return (Nc*(-1 + Nc2))/4.; if( ( a == 0 && b == 1 ) || ( a == 0 && b == 2 ) ) return (-1 + Nc2)/4.; if( ( a == 1 && b == 1 ) || ( a == 2 && b == 2 ) ) return sqr(-1 + Nc2)/(4.*Nc); if( a == 1 && b == 2 ) return -(-1 + Nc2)/(4.*Nc); } if ( basis == id33bar33bar ) { if( ( a == 0 && b == 0 ) || ( a == 1 && b == 1 ) ) return Nc2; if( a == 0 && b == 1 ) return Nc; } if ( basis == id88888 ) { if( ( a == 0 && b == 0 ) || ( a == 1 && b == 1 ) || ( a == 2 && b == 2 ) || ( a == 3 && b == 3 ) || ( a == 4 && b == 4 ) || ( a == 5 && b == 5 ) || ( a == 6 && b == 6 ) || ( a == 7 && b == 7 ) || ( a == 8 && b == 8 ) || ( a == 9 && b == 9 ) || ( a == 10 && b == 10 ) || ( a == 11 && b == 11 ) || ( a == 12 && b == 12 ) || ( a == 13 && b == 13 ) || ( a == 14 && b == 14 ) || ( a == 15 && b == 15 ) || ( a == 16 && b == 16 ) || ( a == 17 && b == 17 ) || ( a == 18 && b == 18 ) || ( a == 19 && b == 19 ) ) return ((-2 + Nc2)*sqr(-1 + Nc2))/(32.*Nc); if( ( a == 0 && b == 1 ) || ( a == 0 && b == 2 ) || ( a == 0 && b == 7 ) || ( a == 0 && b == 10 ) || ( a == 0 && b == 12 ) || ( a == 0 && b == 13 ) || ( a == 1 && b == 2 ) || ( a == 1 && b == 4 ) || ( a == 1 && b == 11 ) || ( a == 1 && b == 14 ) || ( a == 1 && b == 15 ) || ( a == 2 && b == 5 ) || ( a == 2 && b == 8 ) || ( a == 2 && b == 16 ) || ( a == 2 && b == 17 ) || ( a == 3 && b == 4 ) || ( a == 3 && b == 5 ) || ( a == 3 && b == 6 ) || ( a == 3 && b == 9 ) || ( a == 3 && b == 14 ) || ( a == 3 && b == 16 ) || ( a == 4 && b == 5 ) || ( a == 4 && b == 11 ) || ( a == 4 && b == 12 ) || ( a == 4 && b == 18 ) || ( a == 5 && b == 8 ) || ( a == 5 && b == 13 ) || ( a == 5 && b == 19 ) || ( a == 6 && b == 7 ) || ( a == 6 && b == 8 ) || ( a == 6 && b == 9 ) || ( a == 6 && b == 12 ) || ( a == 6 && b == 17 ) || ( a == 7 && b == 8 ) || ( a == 7 && b == 10 ) || ( a == 7 && b == 14 ) || ( a == 7 && b == 19 ) || ( a == 8 && b == 15 ) || ( a == 8 && b == 18 ) || ( a == 9 && b == 10 ) || ( a == 9 && b == 11 ) || ( a == 9 && b == 13 ) || ( a == 9 && b == 15 ) || ( a == 10 && b == 11 ) || ( a == 10 && b == 16 ) || ( a == 10 && b == 18 ) || ( a == 11 && b == 17 ) || ( a == 11 && b == 19 ) || ( a == 12 && b == 13 ) || ( a == 12 && b == 17 ) || ( a == 12 && b == 18 ) || ( a == 13 && b == 15 ) || ( a == 13 && b == 19 ) || ( a == 14 && b == 15 ) || ( a == 14 && b == 16 ) || ( a == 14 && b == 19 ) || ( a == 15 && b == 18 ) || ( a == 16 && b == 17 ) || ( a == 16 && b == 18 ) || ( a == 17 && b == 19 ) ) return (2 - 3*Nc2 + Nc4)/(32.*Nc); if( ( a == 0 && b == 3 ) || ( a == 1 && b == 6 ) || ( a == 2 && b == 9 ) || ( a == 4 && b == 7 ) || ( a == 5 && b == 10 ) || ( a == 8 && b == 11 ) || ( a == 12 && b == 14 ) || ( a == 13 && b == 16 ) || ( a == 15 && b == 17 ) || ( a == 18 && b == 19 ) ) return -sqr(-1 + Nc2)/(16.*Nc); if( ( a == 0 && b == 4 ) || ( a == 0 && b == 5 ) || ( a == 0 && b == 6 ) || ( a == 0 && b == 9 ) || ( a == 0 && b == 14 ) || ( a == 0 && b == 16 ) || ( a == 1 && b == 3 ) || ( a == 1 && b == 7 ) || ( a == 1 && b == 8 ) || ( a == 1 && b == 9 ) || ( a == 1 && b == 12 ) || ( a == 1 && b == 17 ) || ( a == 2 && b == 3 ) || ( a == 2 && b == 6 ) || ( a == 2 && b == 10 ) || ( a == 2 && b == 11 ) || ( a == 2 && b == 13 ) || ( a == 2 && b == 15 ) || ( a == 3 && b == 7 ) || ( a == 3 && b == 10 ) || ( a == 3 && b == 12 ) || ( a == 3 && b == 13 ) || ( a == 4 && b == 6 ) || ( a == 4 && b == 8 ) || ( a == 4 && b == 10 ) || ( a == 4 && b == 14 ) || ( a == 4 && b == 19 ) || ( a == 5 && b == 7 ) || ( a == 5 && b == 9 ) || ( a == 5 && b == 11 ) || ( a == 5 && b == 16 ) || ( a == 5 && b == 18 ) || ( a == 6 && b == 11 ) || ( a == 6 && b == 14 ) || ( a == 6 && b == 15 ) || ( a == 7 && b == 11 ) || ( a == 7 && b == 12 ) || ( a == 7 && b == 18 ) || ( a == 8 && b == 9 ) || ( a == 8 && b == 10 ) || ( a == 8 && b == 17 ) || ( a == 8 && b == 19 ) || ( a == 9 && b == 16 ) || ( a == 9 && b == 17 ) || ( a == 10 && b == 13 ) || ( a == 10 && b == 19 ) || ( a == 11 && b == 15 ) || ( a == 11 && b == 18 ) || ( a == 12 && b == 15 ) || ( a == 12 && b == 16 ) || ( a == 12 && b == 19 ) || ( a == 13 && b == 14 ) || ( a == 13 && b == 17 ) || ( a == 13 && b == 18 ) || ( a == 14 && b == 17 ) || ( a == 14 && b == 18 ) || ( a == 15 && b == 16 ) || ( a == 15 && b == 19 ) || ( a == 16 && b == 19 ) || ( a == 17 && b == 18 ) ) return -(-1 + Nc2)/(16.*Nc); if( ( a == 0 && b == 8 ) || ( a == 0 && b == 11 ) || ( a == 0 && b == 15 ) || ( a == 0 && b == 17 ) || ( a == 0 && b == 18 ) || ( a == 0 && b == 19 ) || ( a == 1 && b == 5 ) || ( a == 1 && b == 10 ) || ( a == 1 && b == 13 ) || ( a == 1 && b == 16 ) || ( a == 1 && b == 18 ) || ( a == 1 && b == 19 ) || ( a == 2 && b == 4 ) || ( a == 2 && b == 7 ) || ( a == 2 && b == 12 ) || ( a == 2 && b == 14 ) || ( a == 2 && b == 18 ) || ( a == 2 && b == 19 ) || ( a == 3 && b == 8 ) || ( a == 3 && b == 11 ) || ( a == 3 && b == 15 ) || ( a == 3 && b == 17 ) || ( a == 3 && b == 18 ) || ( a == 3 && b == 19 ) || ( a == 4 && b == 9 ) || ( a == 4 && b == 13 ) || ( a == 4 && b == 15 ) || ( a == 4 && b == 16 ) || ( a == 4 && b == 17 ) || ( a == 5 && b == 6 ) || ( a == 5 && b == 12 ) || ( a == 5 && b == 14 ) || ( a == 5 && b == 15 ) || ( a == 5 && b == 17 ) || ( a == 6 && b == 10 ) || ( a == 6 && b == 13 ) || ( a == 6 && b == 16 ) || ( a == 6 && b == 18 ) || ( a == 6 && b == 19 ) || ( a == 7 && b == 9 ) || ( a == 7 && b == 13 ) || ( a == 7 && b == 15 ) || ( a == 7 && b == 16 ) || ( a == 7 && b == 17 ) || ( a == 8 && b == 12 ) || ( a == 8 && b == 13 ) || ( a == 8 && b == 14 ) || ( a == 8 && b == 16 ) || ( a == 9 && b == 12 ) || ( a == 9 && b == 14 ) || ( a == 9 && b == 18 ) || ( a == 9 && b == 19 ) || ( a == 10 && b == 12 ) || ( a == 10 && b == 14 ) || ( a == 10 && b == 15 ) || ( a == 10 && b == 17 ) || ( a == 11 && b == 12 ) || ( a == 11 && b == 13 ) || ( a == 11 && b == 14 ) || ( a == 11 && b == 16 ) ) return 0; if( ( a == 0 && b == 20 ) || ( a == 0 && b == 21 ) || ( a == 0 && b == 23 ) || ( a == 0 && b == 25 ) || ( a == 0 && b == 36 ) || ( a == 0 && b == 42 ) || ( a == 1 && b == 21 ) || ( a == 1 && b == 22 ) || ( a == 1 && b == 23 ) || ( a == 1 && b == 24 ) || ( a == 1 && b == 30 ) || ( a == 1 && b == 40 ) || ( a == 2 && b == 20 ) || ( a == 2 && b == 22 ) || ( a == 2 && b == 24 ) || ( a == 2 && b == 25 ) || ( a == 2 && b == 28 ) || ( a == 2 && b == 34 ) || ( a == 3 && b == 26 ) || ( a == 3 && b == 27 ) || ( a == 3 && b == 29 ) || ( a == 3 && b == 31 ) || ( a == 3 && b == 37 ) || ( a == 3 && b == 43 ) || ( a == 4 && b == 24 ) || ( a == 4 && b == 27 ) || ( a == 4 && b == 28 ) || ( a == 4 && b == 29 ) || ( a == 4 && b == 30 ) || ( a == 4 && b == 38 ) || ( a == 5 && b == 22 ) || ( a == 5 && b == 26 ) || ( a == 5 && b == 28 ) || ( a == 5 && b == 30 ) || ( a == 5 && b == 31 ) || ( a == 5 && b == 32 ) || ( a == 6 && b == 31 ) || ( a == 6 && b == 32 ) || ( a == 6 && b == 33 ) || ( a == 6 && b == 35 ) || ( a == 6 && b == 37 ) || ( a == 6 && b == 41 ) || ( a == 7 && b == 25 ) || ( a == 7 && b == 33 ) || ( a == 7 && b == 34 ) || ( a == 7 && b == 35 ) || ( a == 7 && b == 36 ) || ( a == 7 && b == 39 ) || ( a == 8 && b == 20 ) || ( a == 8 && b == 26 ) || ( a == 8 && b == 32 ) || ( a == 8 && b == 34 ) || ( a == 8 && b == 36 ) || ( a == 8 && b == 37 ) || ( a == 9 && b == 29 ) || ( a == 9 && b == 35 ) || ( a == 9 && b == 38 ) || ( a == 9 && b == 39 ) || ( a == 9 && b == 41 ) || ( a == 9 && b == 43 ) || ( a == 10 && b == 23 ) || ( a == 10 && b == 33 ) || ( a == 10 && b == 39 ) || ( a == 10 && b == 40 ) || ( a == 10 && b == 41 ) || ( a == 10 && b == 42 ) || ( a == 11 && b == 21 ) || ( a == 11 && b == 27 ) || ( a == 11 && b == 38 ) || ( a == 11 && b == 40 ) || ( a == 11 && b == 42 ) || ( a == 11 && b == 43 ) || ( a == 12 && b == 20 ) || ( a == 12 && b == 28 ) || ( a == 12 && b == 32 ) || ( a == 12 && b == 38 ) || ( a == 12 && b == 41 ) || ( a == 12 && b == 42 ) || ( a == 13 && b == 21 ) || ( a == 13 && b == 30 ) || ( a == 13 && b == 32 ) || ( a == 13 && b == 35 ) || ( a == 13 && b == 36 ) || ( a == 13 && b == 38 ) || ( a == 14 && b == 22 ) || ( a == 14 && b == 26 ) || ( a == 14 && b == 34 ) || ( a == 14 && b == 39 ) || ( a == 14 && b == 40 ) || ( a == 14 && b == 43 ) || ( a == 15 && b == 23 ) || ( a == 15 && b == 26 ) || ( a == 15 && b == 29 ) || ( a == 15 && b == 30 ) || ( a == 15 && b == 36 ) || ( a == 15 && b == 39 ) || ( a == 16 && b == 24 ) || ( a == 16 && b == 27 ) || ( a == 16 && b == 33 ) || ( a == 16 && b == 34 ) || ( a == 16 && b == 37 ) || ( a == 16 && b == 40 ) || ( a == 17 && b == 25 ) || ( a == 17 && b == 27 ) || ( a == 17 && b == 28 ) || ( a == 17 && b == 31 ) || ( a == 17 && b == 33 ) || ( a == 17 && b == 42 ) || ( a == 18 && b == 20 ) || ( a == 18 && b == 23 ) || ( a == 18 && b == 24 ) || ( a == 18 && b == 29 ) || ( a == 18 && b == 37 ) || ( a == 18 && b == 41 ) || ( a == 19 && b == 21 ) || ( a == 19 && b == 22 ) || ( a == 19 && b == 25 ) || ( a == 19 && b == 31 ) || ( a == 19 && b == 35 ) || ( a == 19 && b == 43 ) ) return ((-2 + Nc2)*sqr(-1 + Nc2))/(32.*Nc2); if( ( a == 0 && b == 22 ) || ( a == 0 && b == 24 ) || ( a == 0 && b == 32 ) || ( a == 0 && b == 33 ) || ( a == 0 && b == 38 ) || ( a == 0 && b == 39 ) || ( a == 1 && b == 20 ) || ( a == 1 && b == 25 ) || ( a == 1 && b == 26 ) || ( a == 1 && b == 27 ) || ( a == 1 && b == 38 ) || ( a == 1 && b == 39 ) || ( a == 2 && b == 21 ) || ( a == 2 && b == 23 ) || ( a == 2 && b == 26 ) || ( a == 2 && b == 27 ) || ( a == 2 && b == 32 ) || ( a == 2 && b == 33 ) || ( a == 3 && b == 28 ) || ( a == 3 && b == 30 ) || ( a == 3 && b == 34 ) || ( a == 3 && b == 35 ) || ( a == 3 && b == 40 ) || ( a == 3 && b == 41 ) || ( a == 4 && b == 20 ) || ( a == 4 && b == 21 ) || ( a == 4 && b == 26 ) || ( a == 4 && b == 31 ) || ( a == 4 && b == 40 ) || ( a == 4 && b == 41 ) || ( a == 5 && b == 20 ) || ( a == 5 && b == 21 ) || ( a == 5 && b == 27 ) || ( a == 5 && b == 29 ) || ( a == 5 && b == 34 ) || ( a == 5 && b == 35 ) || ( a == 6 && b == 28 ) || ( a == 6 && b == 29 ) || ( a == 6 && b == 34 ) || ( a == 6 && b == 36 ) || ( a == 6 && b == 42 ) || ( a == 6 && b == 43 ) || ( a == 7 && b == 22 ) || ( a == 7 && b == 23 ) || ( a == 7 && b == 32 ) || ( a == 7 && b == 37 ) || ( a == 7 && b == 42 ) || ( a == 7 && b == 43 ) || ( a == 8 && b == 22 ) || ( a == 8 && b == 23 ) || ( a == 8 && b == 28 ) || ( a == 8 && b == 29 ) || ( a == 8 && b == 33 ) || ( a == 8 && b == 35 ) || ( a == 9 && b == 30 ) || ( a == 9 && b == 31 ) || ( a == 9 && b == 36 ) || ( a == 9 && b == 37 ) || ( a == 9 && b == 40 ) || ( a == 9 && b == 42 ) || ( a == 10 && b == 24 ) || ( a == 10 && b == 25 ) || ( a == 10 && b == 36 ) || ( a == 10 && b == 37 ) || ( a == 10 && b == 38 ) || ( a == 10 && b == 43 ) || ( a == 11 && b == 24 ) || ( a == 11 && b == 25 ) || ( a == 11 && b == 30 ) || ( a == 11 && b == 31 ) || ( a == 11 && b == 39 ) || ( a == 11 && b == 41 ) || ( a == 12 && b == 21 ) || ( a == 12 && b == 24 ) || ( a == 12 && b == 29 ) || ( a == 12 && b == 31 ) || ( a == 12 && b == 33 ) || ( a == 12 && b == 36 ) || ( a == 13 && b == 20 ) || ( a == 13 && b == 22 ) || ( a == 13 && b == 29 ) || ( a == 13 && b == 31 ) || ( a == 13 && b == 39 ) || ( a == 13 && b == 42 ) || ( a == 14 && b == 23 ) || ( a == 14 && b == 25 ) || ( a == 14 && b == 27 ) || ( a == 14 && b == 30 ) || ( a == 14 && b == 35 ) || ( a == 14 && b == 37 ) || ( a == 15 && b == 20 ) || ( a == 15 && b == 22 ) || ( a == 15 && b == 35 ) || ( a == 15 && b == 37 ) || ( a == 15 && b == 38 ) || ( a == 15 && b == 40 ) || ( a == 16 && b == 23 ) || ( a == 16 && b == 25 ) || ( a == 16 && b == 26 ) || ( a == 16 && b == 28 ) || ( a == 16 && b == 41 ) || ( a == 16 && b == 43 ) || ( a == 17 && b == 21 ) || ( a == 17 && b == 24 ) || ( a == 17 && b == 32 ) || ( a == 17 && b == 34 ) || ( a == 17 && b == 41 ) || ( a == 17 && b == 43 ) || ( a == 18 && b == 26 ) || ( a == 18 && b == 28 ) || ( a == 18 && b == 33 ) || ( a == 18 && b == 36 ) || ( a == 18 && b == 38 ) || ( a == 18 && b == 40 ) || ( a == 19 && b == 27 ) || ( a == 19 && b == 30 ) || ( a == 19 && b == 32 ) || ( a == 19 && b == 34 ) || ( a == 19 && b == 39 ) || ( a == 19 && b == 42 ) ) return -(2 - 3*Nc2 + Nc4)/(32.*Nc2); if( ( a == 0 && b == 26 ) || ( a == 0 && b == 27 ) || ( a == 0 && b == 29 ) || ( a == 0 && b == 31 ) || ( a == 0 && b == 37 ) || ( a == 0 && b == 43 ) || ( a == 1 && b == 31 ) || ( a == 1 && b == 32 ) || ( a == 1 && b == 33 ) || ( a == 1 && b == 35 ) || ( a == 1 && b == 37 ) || ( a == 1 && b == 41 ) || ( a == 2 && b == 29 ) || ( a == 2 && b == 35 ) || ( a == 2 && b == 38 ) || ( a == 2 && b == 39 ) || ( a == 2 && b == 41 ) || ( a == 2 && b == 43 ) || ( a == 3 && b == 20 ) || ( a == 3 && b == 21 ) || ( a == 3 && b == 23 ) || ( a == 3 && b == 25 ) || ( a == 3 && b == 36 ) || ( a == 3 && b == 42 ) || ( a == 4 && b == 25 ) || ( a == 4 && b == 33 ) || ( a == 4 && b == 34 ) || ( a == 4 && b == 35 ) || ( a == 4 && b == 36 ) || ( a == 4 && b == 39 ) || ( a == 5 && b == 23 ) || ( a == 5 && b == 33 ) || ( a == 5 && b == 39 ) || ( a == 5 && b == 40 ) || ( a == 5 && b == 41 ) || ( a == 5 && b == 42 ) || ( a == 6 && b == 21 ) || ( a == 6 && b == 22 ) || ( a == 6 && b == 23 ) || ( a == 6 && b == 24 ) || ( a == 6 && b == 30 ) || ( a == 6 && b == 40 ) || ( a == 7 && b == 24 ) || ( a == 7 && b == 27 ) || ( a == 7 && b == 28 ) || ( a == 7 && b == 29 ) || ( a == 7 && b == 30 ) || ( a == 7 && b == 38 ) || ( a == 8 && b == 21 ) || ( a == 8 && b == 27 ) || ( a == 8 && b == 38 ) || ( a == 8 && b == 40 ) || ( a == 8 && b == 42 ) || ( a == 8 && b == 43 ) || ( a == 9 && b == 20 ) || ( a == 9 && b == 22 ) || ( a == 9 && b == 24 ) || ( a == 9 && b == 25 ) || ( a == 9 && b == 28 ) || ( a == 9 && b == 34 ) || ( a == 10 && b == 22 ) || ( a == 10 && b == 26 ) || ( a == 10 && b == 28 ) || ( a == 10 && b == 30 ) || ( a == 10 && b == 31 ) || ( a == 10 && b == 32 ) || ( a == 11 && b == 20 ) || ( a == 11 && b == 26 ) || ( a == 11 && b == 32 ) || ( a == 11 && b == 34 ) || ( a == 11 && b == 36 ) || ( a == 11 && b == 37 ) || ( a == 12 && b == 22 ) || ( a == 12 && b == 26 ) || ( a == 12 && b == 34 ) || ( a == 12 && b == 39 ) || ( a == 12 && b == 40 ) || ( a == 12 && b == 43 ) || ( a == 13 && b == 24 ) || ( a == 13 && b == 27 ) || ( a == 13 && b == 33 ) || ( a == 13 && b == 34 ) || ( a == 13 && b == 37 ) || ( a == 13 && b == 40 ) || ( a == 14 && b == 20 ) || ( a == 14 && b == 28 ) || ( a == 14 && b == 32 ) || ( a == 14 && b == 38 ) || ( a == 14 && b == 41 ) || ( a == 14 && b == 42 ) || ( a == 15 && b == 25 ) || ( a == 15 && b == 27 ) || ( a == 15 && b == 28 ) || ( a == 15 && b == 31 ) || ( a == 15 && b == 33 ) || ( a == 15 && b == 42 ) || ( a == 16 && b == 21 ) || ( a == 16 && b == 30 ) || ( a == 16 && b == 32 ) || ( a == 16 && b == 35 ) || ( a == 16 && b == 36 ) || ( a == 16 && b == 38 ) || ( a == 17 && b == 23 ) || ( a == 17 && b == 26 ) || ( a == 17 && b == 29 ) || ( a == 17 && b == 30 ) || ( a == 17 && b == 36 ) || ( a == 17 && b == 39 ) || ( a == 18 && b == 21 ) || ( a == 18 && b == 22 ) || ( a == 18 && b == 25 ) || ( a == 18 && b == 31 ) || ( a == 18 && b == 35 ) || ( a == 18 && b == 43 ) || ( a == 19 && b == 20 ) || ( a == 19 && b == 23 ) || ( a == 19 && b == 24 ) || ( a == 19 && b == 29 ) || ( a == 19 && b == 37 ) || ( a == 19 && b == 41 ) ) return -sqr(-1 + Nc2)/(16.*Nc2); if( ( a == 0 && b == 28 ) || ( a == 0 && b == 30 ) || ( a == 0 && b == 34 ) || ( a == 0 && b == 35 ) || ( a == 0 && b == 40 ) || ( a == 0 && b == 41 ) || ( a == 1 && b == 28 ) || ( a == 1 && b == 29 ) || ( a == 1 && b == 34 ) || ( a == 1 && b == 36 ) || ( a == 1 && b == 42 ) || ( a == 1 && b == 43 ) || ( a == 2 && b == 30 ) || ( a == 2 && b == 31 ) || ( a == 2 && b == 36 ) || ( a == 2 && b == 37 ) || ( a == 2 && b == 40 ) || ( a == 2 && b == 42 ) || ( a == 3 && b == 22 ) || ( a == 3 && b == 24 ) || ( a == 3 && b == 32 ) || ( a == 3 && b == 33 ) || ( a == 3 && b == 38 ) || ( a == 3 && b == 39 ) || ( a == 4 && b == 22 ) || ( a == 4 && b == 23 ) || ( a == 4 && b == 32 ) || ( a == 4 && b == 37 ) || ( a == 4 && b == 42 ) || ( a == 4 && b == 43 ) || ( a == 5 && b == 24 ) || ( a == 5 && b == 25 ) || ( a == 5 && b == 36 ) || ( a == 5 && b == 37 ) || ( a == 5 && b == 38 ) || ( a == 5 && b == 43 ) || ( a == 6 && b == 20 ) || ( a == 6 && b == 25 ) || ( a == 6 && b == 26 ) || ( a == 6 && b == 27 ) || ( a == 6 && b == 38 ) || ( a == 6 && b == 39 ) || ( a == 7 && b == 20 ) || ( a == 7 && b == 21 ) || ( a == 7 && b == 26 ) || ( a == 7 && b == 31 ) || ( a == 7 && b == 40 ) || ( a == 7 && b == 41 ) || ( a == 8 && b == 24 ) || ( a == 8 && b == 25 ) || ( a == 8 && b == 30 ) || ( a == 8 && b == 31 ) || ( a == 8 && b == 39 ) || ( a == 8 && b == 41 ) || ( a == 9 && b == 21 ) || ( a == 9 && b == 23 ) || ( a == 9 && b == 26 ) || ( a == 9 && b == 27 ) || ( a == 9 && b == 32 ) || ( a == 9 && b == 33 ) || ( a == 10 && b == 20 ) || ( a == 10 && b == 21 ) || ( a == 10 && b == 27 ) || ( a == 10 && b == 29 ) || ( a == 10 && b == 34 ) || ( a == 10 && b == 35 ) || ( a == 11 && b == 22 ) || ( a == 11 && b == 23 ) || ( a == 11 && b == 28 ) || ( a == 11 && b == 29 ) || ( a == 11 && b == 33 ) || ( a == 11 && b == 35 ) || ( a == 12 && b == 23 ) || ( a == 12 && b == 25 ) || ( a == 12 && b == 27 ) || ( a == 12 && b == 30 ) || ( a == 12 && b == 35 ) || ( a == 12 && b == 37 ) || ( a == 13 && b == 23 ) || ( a == 13 && b == 25 ) || ( a == 13 && b == 26 ) || ( a == 13 && b == 28 ) || ( a == 13 && b == 41 ) || ( a == 13 && b == 43 ) || ( a == 14 && b == 21 ) || ( a == 14 && b == 24 ) || ( a == 14 && b == 29 ) || ( a == 14 && b == 31 ) || ( a == 14 && b == 33 ) || ( a == 14 && b == 36 ) || ( a == 15 && b == 21 ) || ( a == 15 && b == 24 ) || ( a == 15 && b == 32 ) || ( a == 15 && b == 34 ) || ( a == 15 && b == 41 ) || ( a == 15 && b == 43 ) || ( a == 16 && b == 20 ) || ( a == 16 && b == 22 ) || ( a == 16 && b == 29 ) || ( a == 16 && b == 31 ) || ( a == 16 && b == 39 ) || ( a == 16 && b == 42 ) || ( a == 17 && b == 20 ) || ( a == 17 && b == 22 ) || ( a == 17 && b == 35 ) || ( a == 17 && b == 37 ) || ( a == 17 && b == 38 ) || ( a == 17 && b == 40 ) || ( a == 18 && b == 27 ) || ( a == 18 && b == 30 ) || ( a == 18 && b == 32 ) || ( a == 18 && b == 34 ) || ( a == 18 && b == 39 ) || ( a == 18 && b == 42 ) || ( a == 19 && b == 26 ) || ( a == 19 && b == 28 ) || ( a == 19 && b == 33 ) || ( a == 19 && b == 36 ) || ( a == 19 && b == 38 ) || ( a == 19 && b == 40 ) ) return (1 - 1/Nc2)/16.; if( ( a == 20 && b == 20 ) || ( a == 21 && b == 21 ) || ( a == 22 && b == 22 ) || ( a == 23 && b == 23 ) || ( a == 24 && b == 24 ) || ( a == 25 && b == 25 ) || ( a == 26 && b == 26 ) || ( a == 27 && b == 27 ) || ( a == 28 && b == 28 ) || ( a == 29 && b == 29 ) || ( a == 30 && b == 30 ) || ( a == 31 && b == 31 ) || ( a == 32 && b == 32 ) || ( a == 33 && b == 33 ) || ( a == 34 && b == 34 ) || ( a == 35 && b == 35 ) || ( a == 36 && b == 36 ) || ( a == 37 && b == 37 ) || ( a == 38 && b == 38 ) || ( a == 39 && b == 39 ) || ( a == 40 && b == 40 ) || ( a == 41 && b == 41 ) || ( a == 42 && b == 42 ) || ( a == 43 && b == 43 ) ) return (4 - 10*Nc2 + 10*Nc4 - 5*Nc6 + Nc8)/(32.*Nc3); if( ( a == 20 && b == 21 ) || ( a == 20 && b == 22 ) || ( a == 20 && b == 26 ) || ( a == 20 && b == 29 ) || ( a == 20 && b == 38 ) || ( a == 21 && b == 24 ) || ( a == 21 && b == 27 ) || ( a == 21 && b == 31 ) || ( a == 21 && b == 32 ) || ( a == 22 && b == 23 ) || ( a == 22 && b == 32 ) || ( a == 22 && b == 35 ) || ( a == 22 && b == 39 ) || ( a == 23 && b == 25 ) || ( a == 23 && b == 26 ) || ( a == 23 && b == 33 ) || ( a == 23 && b == 37 ) || ( a == 24 && b == 25 ) || ( a == 24 && b == 33 ) || ( a == 24 && b == 38 ) || ( a == 24 && b == 41 ) || ( a == 25 && b == 27 ) || ( a == 25 && b == 39 ) || ( a == 25 && b == 43 ) || ( a == 26 && b == 27 ) || ( a == 26 && b == 28 ) || ( a == 26 && b == 40 ) || ( a == 27 && b == 30 ) || ( a == 27 && b == 34 ) || ( a == 28 && b == 29 ) || ( a == 28 && b == 33 ) || ( a == 28 && b == 34 ) || ( a == 28 && b == 41 ) || ( a == 29 && b == 31 ) || ( a == 29 && b == 35 ) || ( a == 29 && b == 36 ) || ( a == 30 && b == 31 ) || ( a == 30 && b == 35 ) || ( a == 30 && b == 39 ) || ( a == 30 && b == 40 ) || ( a == 31 && b == 41 ) || ( a == 31 && b == 42 ) || ( a == 32 && b == 33 ) || ( a == 32 && b == 34 ) || ( a == 32 && b == 42 ) || ( a == 33 && b == 36 ) || ( a == 34 && b == 35 ) || ( a == 34 && b == 43 ) || ( a == 35 && b == 37 ) || ( a == 36 && b == 37 ) || ( a == 36 && b == 38 ) || ( a == 36 && b == 42 ) || ( a == 37 && b == 40 ) || ( a == 37 && b == 43 ) || ( a == 38 && b == 39 ) || ( a == 38 && b == 40 ) || ( a == 39 && b == 42 ) || ( a == 40 && b == 41 ) || ( a == 41 && b == 43 ) || ( a == 42 && b == 43 ) ) return -(-4 + 7*Nc2 - 4*Nc4 + Nc6)/(32.*Nc3); if( ( a == 20 && b == 23 ) || ( a == 20 && b == 24 ) || ( a == 20 && b == 28 ) || ( a == 20 && b == 32 ) || ( a == 20 && b == 36 ) || ( a == 21 && b == 22 ) || ( a == 21 && b == 25 ) || ( a == 21 && b == 30 ) || ( a == 21 && b == 38 ) || ( a == 21 && b == 42 ) || ( a == 22 && b == 25 ) || ( a == 22 && b == 26 ) || ( a == 22 && b == 30 ) || ( a == 22 && b == 34 ) || ( a == 23 && b == 24 ) || ( a == 23 && b == 36 ) || ( a == 23 && b == 39 ) || ( a == 23 && b == 40 ) || ( a == 24 && b == 27 ) || ( a == 24 && b == 28 ) || ( a == 24 && b == 40 ) || ( a == 25 && b == 33 ) || ( a == 25 && b == 34 ) || ( a == 25 && b == 42 ) || ( a == 26 && b == 29 ) || ( a == 26 && b == 30 ) || ( a == 26 && b == 34 ) || ( a == 26 && b == 37 ) || ( a == 27 && b == 28 ) || ( a == 27 && b == 31 ) || ( a == 27 && b == 40 ) || ( a == 27 && b == 43 ) || ( a == 28 && b == 31 ) || ( a == 28 && b == 32 ) || ( a == 29 && b == 30 ) || ( a == 29 && b == 37 ) || ( a == 29 && b == 38 ) || ( a == 29 && b == 41 ) || ( a == 30 && b == 38 ) || ( a == 31 && b == 32 ) || ( a == 31 && b == 35 ) || ( a == 31 && b == 43 ) || ( a == 32 && b == 35 ) || ( a == 32 && b == 36 ) || ( a == 33 && b == 34 ) || ( a == 33 && b == 37 ) || ( a == 33 && b == 41 ) || ( a == 33 && b == 42 ) || ( a == 34 && b == 37 ) || ( a == 35 && b == 36 ) || ( a == 35 && b == 39 ) || ( a == 35 && b == 43 ) || ( a == 36 && b == 39 ) || ( a == 37 && b == 41 ) || ( a == 38 && b == 41 ) || ( a == 38 && b == 42 ) || ( a == 39 && b == 40 ) || ( a == 39 && b == 43 ) || ( a == 40 && b == 43 ) || ( a == 41 && b == 42 ) ) return (2 - 3*Nc2 + Nc4)/(16.*Nc3); if( ( a == 20 && b == 25 ) || ( a == 20 && b == 34 ) || ( a == 20 && b == 37 ) || ( a == 20 && b == 41 ) || ( a == 20 && b == 42 ) || ( a == 21 && b == 23 ) || ( a == 21 && b == 35 ) || ( a == 21 && b == 36 ) || ( a == 21 && b == 40 ) || ( a == 21 && b == 43 ) || ( a == 22 && b == 24 ) || ( a == 22 && b == 28 ) || ( a == 22 && b == 31 ) || ( a == 22 && b == 40 ) || ( a == 22 && b == 43 ) || ( a == 23 && b == 29 ) || ( a == 23 && b == 30 ) || ( a == 23 && b == 41 ) || ( a == 23 && b == 42 ) || ( a == 24 && b == 29 ) || ( a == 24 && b == 30 ) || ( a == 24 && b == 34 ) || ( a == 24 && b == 37 ) || ( a == 25 && b == 28 ) || ( a == 25 && b == 31 ) || ( a == 25 && b == 35 ) || ( a == 25 && b == 36 ) || ( a == 26 && b == 31 ) || ( a == 26 && b == 32 ) || ( a == 26 && b == 36 ) || ( a == 26 && b == 39 ) || ( a == 26 && b == 43 ) || ( a == 27 && b == 29 ) || ( a == 27 && b == 33 ) || ( a == 27 && b == 37 ) || ( a == 27 && b == 38 ) || ( a == 27 && b == 42 ) || ( a == 28 && b == 30 ) || ( a == 28 && b == 38 ) || ( a == 28 && b == 42 ) || ( a == 29 && b == 39 ) || ( a == 29 && b == 43 ) || ( a == 30 && b == 32 ) || ( a == 30 && b == 36 ) || ( a == 31 && b == 33 ) || ( a == 31 && b == 37 ) || ( a == 32 && b == 37 ) || ( a == 32 && b == 38 ) || ( a == 32 && b == 41 ) || ( a == 33 && b == 35 ) || ( a == 33 && b == 39 ) || ( a == 33 && b == 40 ) || ( a == 34 && b == 36 ) || ( a == 34 && b == 39 ) || ( a == 34 && b == 40 ) || ( a == 35 && b == 38 ) || ( a == 35 && b == 41 ) || ( a == 38 && b == 43 ) || ( a == 39 && b == 41 ) || ( a == 40 && b == 42 ) ) return (4 - 3*Nc2 - 2*Nc4 + Nc6)/(32.*Nc3); if( ( a == 20 && b == 27 ) || ( a == 20 && b == 31 ) || ( a == 20 && b == 35 ) || ( a == 20 && b == 39 ) || ( a == 20 && b == 40 ) || ( a == 21 && b == 26 ) || ( a == 21 && b == 29 ) || ( a == 21 && b == 33 ) || ( a == 21 && b == 34 ) || ( a == 21 && b == 41 ) || ( a == 22 && b == 29 ) || ( a == 22 && b == 33 ) || ( a == 22 && b == 37 ) || ( a == 22 && b == 38 ) || ( a == 22 && b == 42 ) || ( a == 23 && b == 27 ) || ( a == 23 && b == 28 ) || ( a == 23 && b == 32 ) || ( a == 23 && b == 35 ) || ( a == 23 && b == 43 ) || ( a == 24 && b == 31 ) || ( a == 24 && b == 32 ) || ( a == 24 && b == 36 ) || ( a == 24 && b == 39 ) || ( a == 24 && b == 43 ) || ( a == 25 && b == 26 ) || ( a == 25 && b == 30 ) || ( a == 25 && b == 37 ) || ( a == 25 && b == 38 ) || ( a == 25 && b == 41 ) || ( a == 26 && b == 33 ) || ( a == 26 && b == 38 ) || ( a == 26 && b == 41 ) || ( a == 27 && b == 32 ) || ( a == 27 && b == 35 ) || ( a == 27 && b == 39 ) || ( a == 28 && b == 35 ) || ( a == 28 && b == 36 ) || ( a == 28 && b == 40 ) || ( a == 28 && b == 43 ) || ( a == 29 && b == 33 ) || ( a == 29 && b == 34 ) || ( a == 29 && b == 42 ) || ( a == 30 && b == 34 ) || ( a == 30 && b == 37 ) || ( a == 30 && b == 41 ) || ( a == 30 && b == 42 ) || ( a == 31 && b == 36 ) || ( a == 31 && b == 39 ) || ( a == 31 && b == 40 ) || ( a == 32 && b == 39 ) || ( a == 32 && b == 43 ) || ( a == 33 && b == 38 ) || ( a == 34 && b == 41 ) || ( a == 34 && b == 42 ) || ( a == 35 && b == 40 ) || ( a == 36 && b == 40 ) || ( a == 36 && b == 43 ) || ( a == 37 && b == 38 ) || ( a == 37 && b == 42 ) ) return -(-1 + Nc2)/(8.*Nc3); if( ( a == 20 && b == 30 ) || ( a == 20 && b == 33 ) || ( a == 21 && b == 28 ) || ( a == 21 && b == 39 ) || ( a == 22 && b == 27 ) || ( a == 22 && b == 36 ) || ( a == 23 && b == 34 ) || ( a == 23 && b == 38 ) || ( a == 24 && b == 26 ) || ( a == 24 && b == 42 ) || ( a == 25 && b == 32 ) || ( a == 25 && b == 40 ) || ( a == 26 && b == 35 ) || ( a == 27 && b == 41 ) || ( a == 28 && b == 37 ) || ( a == 29 && b == 32 ) || ( a == 29 && b == 40 ) || ( a == 30 && b == 43 ) || ( a == 31 && b == 34 ) || ( a == 31 && b == 38 ) || ( a == 33 && b == 43 ) || ( a == 35 && b == 42 ) || ( a == 36 && b == 41 ) || ( a == 37 && b == 39 ) ) return (4 - 5*Nc2 + Nc4)/(32.*Nc3); if( ( a == 20 && b == 43 ) || ( a == 21 && b == 37 ) || ( a == 22 && b == 41 ) || ( a == 23 && b == 31 ) || ( a == 24 && b == 35 ) || ( a == 25 && b == 29 ) || ( a == 26 && b == 42 ) || ( a == 27 && b == 36 ) || ( a == 28 && b == 39 ) || ( a == 30 && b == 33 ) || ( a == 32 && b == 40 ) || ( a == 34 && b == 38 ) ) return -(-1 + Nc4)/(8.*Nc3); } if ( basis == id33bar888 ) { if( ( a == 0 && b == 0 ) || ( a == 1 && b == 1 ) ) return (2 - 3*Nc2 + Nc4)/8.; if( a == 0 && b == 1 ) return (1 - Nc2)/4.; if( ( a == 0 && b == 2 ) || ( a == 0 && b == 3 ) || ( a == 0 && b == 4 ) || ( a == 1 && b == 2 ) || ( a == 1 && b == 3 ) || ( a == 1 && b == 4 ) ) return 0; if( ( a == 0 && b == 5 ) || ( a == 0 && b == 8 ) || ( a == 0 && b == 9 ) || ( a == 1 && b == 6 ) || ( a == 1 && b == 7 ) || ( a == 1 && b == 10 ) ) return (2 - 3*Nc2 + Nc4)/(8.*Nc); if( ( a == 0 && b == 6 ) || ( a == 0 && b == 7 ) || ( a == 0 && b == 10 ) || ( a == 1 && b == 5 ) || ( a == 1 && b == 8 ) || ( a == 1 && b == 9 ) ) return -(-1 + Nc2)/(4.*Nc); if( ( a == 2 && b == 2 ) || ( a == 3 && b == 3 ) || ( a == 4 && b == 4 ) ) return sqr(-1 + Nc2)/8.; if( ( a == 2 && b == 3 ) || ( a == 2 && b == 4 ) || ( a == 3 && b == 4 ) ) return (-1 + Nc2)/8.; if( ( a == 2 && b == 5 ) || ( a == 2 && b == 6 ) || ( a == 2 && b == 8 ) || ( a == 2 && b == 10 ) || ( a == 3 && b == 6 ) || ( a == 3 && b == 7 ) || ( a == 3 && b == 8 ) || ( a == 3 && b == 9 ) || ( a == 4 && b == 5 ) || ( a == 4 && b == 7 ) || ( a == 4 && b == 9 ) || ( a == 4 && b == 10 ) ) return sqr(-1 + Nc2)/(8.*Nc); if( ( a == 2 && b == 7 ) || ( a == 2 && b == 9 ) || ( a == 3 && b == 5 ) || ( a == 3 && b == 10 ) || ( a == 4 && b == 6 ) || ( a == 4 && b == 8 ) ) return -(-1 + Nc2)/(8.*Nc); if( ( a == 5 && b == 5 ) || ( a == 6 && b == 6 ) || ( a == 7 && b == 7 ) || ( a == 8 && b == 8 ) || ( a == 9 && b == 9 ) || ( a == 10 && b == 10 ) ) return pow(-1 + Nc2,3.)/(8.*Nc2); if( ( a == 5 && b == 6 ) || ( a == 5 && b == 7 ) || ( a == 6 && b == 9 ) || ( a == 7 && b == 8 ) || ( a == 8 && b == 10 ) || ( a == 9 && b == 10 ) ) return -sqr(-1 + Nc2)/(8.*Nc2); if( ( a == 5 && b == 8 ) || ( a == 5 && b == 9 ) || ( a == 6 && b == 7 ) || ( a == 6 && b == 10 ) || ( a == 7 && b == 10 ) || ( a == 8 && b == 9 ) ) return 0.125 - 1/(8.*Nc2); if( ( a == 5 && b == 10 ) || ( a == 6 && b == 8 ) || ( a == 7 && b == 9 ) ) return (-1 + Nc4)/(8.*Nc2); } if ( basis == id33bar33bar8 ) { if( ( a == 0 && b == 0 ) || ( a == 1 && b == 1 ) || ( a == 2 && b == 2 ) || ( a == 3 && b == 3 ) ) return (Nc*(-1 + Nc2))/2.; if( ( a == 0 && b == 1 ) || ( a == 0 && b == 3 ) || ( a == 1 && b == 2 ) || ( a == 2 && b == 3 ) ) return (-1 + Nc2)/2.; if( ( a == 0 && b == 2 ) || ( a == 1 && b == 3 ) ) return 0; } } else { if ( a != b ) return 0.; if ( basis == id88 ) { return Nc2/4.; } if ( basis == id33bar ) { return Nc; } if ( basis == id888 ) { return Nc3/8.; } if ( basis == id33bar8 ) { return Nc2/2.; } if ( basis == id8888 ) { return Nc4/16.; } if ( basis == id33bar88 ) { return Nc3/4.; } if ( basis == id33bar33bar ) { return Nc2; } if ( basis == id88888 ) { return Nc5/32.; } if ( basis == id33bar888 ) { return Nc4/8.; } if ( basis == id33bar33bar8 ) { return Nc3/2.; } } throw Exception() << "SimpleColourBasis2::scalarProduct(): Cannot handle colour configuration" << Exception::runerror; } double SimpleColourBasis2::tMatrixElement(size_t i, size_t a, size_t b, const vector&, const vector& basis, #ifndef NDEBUG size_t k, size_t l, #else size_t , size_t , #endif const map& dict) const { // Check indices k and l assert( k == i ); assert( l == basis.size() ); // Check that dict is the standardMap assert( dict.size()+1 == basis.size() ); map::const_iterator tmp; for ( size_t ii = 0; ii < basis.size(); ii++ ) if ( ii != i ) { tmp = dict.find(ii); assert( tmp != dict.end() ); assert( tmp->second == ii ); } if ( id33bar.empty() ) makeIds(); if ( basis == id88 ) { if(i == 0 && a == 0 && b == 0) return -1; if(i == 0 && a == 1 && b == 0) return 1; if(i == 1 && a == 0 && b == 0) return 1; if(i == 1 && a == 1 && b == 0) return -1; return 0.; } if ( basis == id33bar ) { if(i == 0 && a == 0 && b == 0) return 1; if(i == 1 && a == 0 && b == 0) return -1; return 0.; } if ( basis == id888 ) { if(i == 0 && a == 3 && b == 0) return -1; if(i == 0 && a == 5 && b == 1) return -1; if(i == 0 && a == 7 && b == 0) return 1; if(i == 0 && a == 8 && b == 1) return 1; if(i == 1 && a == 4 && b == 0) return 1; if(i == 1 && a == 5 && b == 1) return 1; if(i == 1 && a == 6 && b == 1) return -1; if(i == 1 && a == 7 && b == 0) return -1; if(i == 2 && a == 3 && b == 0) return 1; if(i == 2 && a == 4 && b == 0) return -1; if(i == 2 && a == 6 && b == 1) return 1; if(i == 2 && a == 8 && b == 1) return -1; return 0.; } if ( basis == id33bar8 ) { if(i == 0 && a == 2 && b == 0) return 1; if(i == 1 && a == 1 && b == 0) return -1; if(i == 2 && a == 1 && b == 0) return 1; if(i == 2 && a == 2 && b == 0) return -1; return 0.; } if ( basis == id8888 ) { if(i == 0 && a == 2 && b == 2) return -1; if(i == 0 && a == 5 && b == 1) return -1; if(i == 0 && a == 8 && b == 0) return -1; if(i == 0 && a == 9 && b == 2) return 1; if(i == 0 && a == 10 && b == 1) return 1; if(i == 0 && a == 11 && b == 0) return 1; if(i == 0 && a == 20 && b == 3) return -1; if(i == 0 && a == 22 && b == 4) return -1; if(i == 0 && a == 26 && b == 5) return -1; if(i == 0 && a == 28 && b == 6) return -1; if(i == 0 && a == 32 && b == 7) return -1; if(i == 0 && a == 34 && b == 8) return -1; if(i == 0 && a == 38 && b == 3) return 1; if(i == 0 && a == 39 && b == 4) return 1; if(i == 0 && a == 40 && b == 5) return 1; if(i == 0 && a == 41 && b == 6) return 1; if(i == 0 && a == 42 && b == 7) return 1; if(i == 0 && a == 43 && b == 8) return 1; if(i == 1 && a == 2 && b == 2) return 1; if(i == 1 && a == 9 && b == 2) return -1; if(i == 1 && a == 13 && b == 0) return -1; if(i == 1 && a == 15 && b == 1) return -1; if(i == 1 && a == 16 && b == 0) return 1; if(i == 1 && a == 17 && b == 1) return 1; if(i == 1 && a == 24 && b == 3) return 1; if(i == 1 && a == 25 && b == 4) return 1; if(i == 1 && a == 27 && b == 5) return 1; if(i == 1 && a == 28 && b == 6) return 1; if(i == 1 && a == 29 && b == 6) return -1; if(i == 1 && a == 30 && b == 5) return -1; if(i == 1 && a == 33 && b == 7) return 1; if(i == 1 && a == 34 && b == 8) return 1; if(i == 1 && a == 35 && b == 8) return -1; if(i == 1 && a == 36 && b == 7) return -1; if(i == 1 && a == 38 && b == 3) return -1; if(i == 1 && a == 39 && b == 4) return -1; if(i == 2 && a == 5 && b == 1) return 1; if(i == 2 && a == 10 && b == 1) return -1; if(i == 2 && a == 13 && b == 0) return 1; if(i == 2 && a == 16 && b == 0) return -1; if(i == 2 && a == 18 && b == 2) return -1; if(i == 2 && a == 19 && b == 2) return 1; if(i == 2 && a == 21 && b == 3) return 1; if(i == 2 && a == 22 && b == 4) return 1; if(i == 2 && a == 23 && b == 4) return -1; if(i == 2 && a == 24 && b == 3) return -1; if(i == 2 && a == 30 && b == 5) return 1; if(i == 2 && a == 31 && b == 6) return 1; if(i == 2 && a == 32 && b == 7) return 1; if(i == 2 && a == 33 && b == 7) return -1; if(i == 2 && a == 35 && b == 8) return 1; if(i == 2 && a == 37 && b == 8) return -1; if(i == 2 && a == 40 && b == 5) return -1; if(i == 2 && a == 41 && b == 6) return -1; if(i == 3 && a == 8 && b == 0) return 1; if(i == 3 && a == 11 && b == 0) return -1; if(i == 3 && a == 15 && b == 1) return 1; if(i == 3 && a == 17 && b == 1) return -1; if(i == 3 && a == 18 && b == 2) return 1; if(i == 3 && a == 19 && b == 2) return -1; if(i == 3 && a == 20 && b == 3) return 1; if(i == 3 && a == 21 && b == 3) return -1; if(i == 3 && a == 23 && b == 4) return 1; if(i == 3 && a == 25 && b == 4) return -1; if(i == 3 && a == 26 && b == 5) return 1; if(i == 3 && a == 27 && b == 5) return -1; if(i == 3 && a == 29 && b == 6) return 1; if(i == 3 && a == 31 && b == 6) return -1; if(i == 3 && a == 36 && b == 7) return 1; if(i == 3 && a == 37 && b == 8) return 1; if(i == 3 && a == 42 && b == 7) return -1; if(i == 3 && a == 43 && b == 8) return -1; return 0.; } if ( basis == id33bar88 ) { if(i == 0 && a == 4 && b == 0) return 1; if(i == 0 && a == 9 && b == 1) return 1; if(i == 0 && a == 10 && b == 2) return 1; if(i == 1 && a == 4 && b == 0) return -1; if(i == 1 && a == 5 && b == 1) return -1; if(i == 1 && a == 7 && b == 2) return -1; if(i == 2 && a == 0 && b == 0) return -1; if(i == 2 && a == 1 && b == 0) return 1; if(i == 2 && a == 6 && b == 1) return 1; if(i == 2 && a == 7 && b == 2) return 1; if(i == 2 && a == 8 && b == 2) return -1; if(i == 2 && a == 9 && b == 1) return -1; if(i == 3 && a == 0 && b == 0) return 1; if(i == 3 && a == 1 && b == 0) return -1; if(i == 3 && a == 5 && b == 1) return 1; if(i == 3 && a == 6 && b == 1) return -1; if(i == 3 && a == 8 && b == 2) return 1; if(i == 3 && a == 10 && b == 2) return -1; return 0.; } if ( basis == id33bar33bar ) { if(i == 0 && a == 0 && b == 0) return 1; if(i == 0 && a == 1 && b == 1) return 1; if(i == 1 && a == 1 && b == 1) return -1; if(i == 1 && a == 2 && b == 0) return -1; if(i == 2 && a == 2 && b == 0) return 1; if(i == 2 && a == 3 && b == 1) return 1; if(i == 3 && a == 0 && b == 0) return -1; if(i == 3 && a == 3 && b == 1) return -1; return 0.; } throw Exception() << "SimpleColourBasis2::tMatrixElement(): Cannot handle colour configuration" << Exception::runerror; return 0.; } bool SimpleColourBasis2::colourConnected(const cPDVector& sub, const vector& basis, const pair& i, const pair& j, size_t a) const { if ( id33bar.empty() ) makeIds(); // translate process to basis ids map >::const_iterator trans = indexMap().find(sub); assert(trans != indexMap().end()); int idColoured = i.second ? j.first : i.first; idColoured = trans->second.find(idColoured)->second; int idAntiColoured = i.second ? i.first : j.first; idAntiColoured = trans->second.find(idAntiColoured)->second; if ( basis == id88 ) { return a == 0 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0)); } if ( basis == id33bar ) { return a == 0 && (idColoured == 0 && idAntiColoured == 1); } if ( basis == id888 ) { return (a == 0 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 1 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))); } if ( basis == id33bar8 ) { return a == 0 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1)); } if ( basis == id8888 ) { return (a == 0 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1))) || (a == 1 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1))) || (a == 2 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2))) || (a == 3 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 4 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 5 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 6 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 7 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 8 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))); } if ( basis == id33bar88 ) { return (a == 0 && ((idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 1))) || (a == 1 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 2 && idAntiColoured == 3))) || (a == 2 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 3 && idAntiColoured == 2))); } if ( basis == id33bar33bar ) { return (a == 0 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 2 && idAntiColoured == 1))) || (a == 1 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 2 && idAntiColoured == 3))); } if ( basis == id88888 ) { return (a == 0 && ((idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 1 && ((idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 2 && ((idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 3 && ((idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 4 && ((idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 5 && ((idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 6 && ((idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 7 && ((idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 8 && ((idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 9 && ((idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 10 && ((idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 11 && ((idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 12 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1))) || (a == 13 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1))) || (a == 14 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1))) || (a == 15 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1))) || (a == 16 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1))) || (a == 17 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1))) || (a == 18 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2))) || (a == 19 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2))) || (a == 20 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 21 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 22 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 23 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 24 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 25 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 26 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 27 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 28 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 29 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 30 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 31 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 32 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 33 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 34 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 0))) || (a == 35 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 36 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 37 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 38 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 39 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 40 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 0))) || (a == 41 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))) || (a == 42 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 0))) || (a == 43 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 1 && idAntiColoured == 0))); } if ( basis == id33bar888 ) { return (a == 0 && ((idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 1))) || (a == 1 && ((idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 1))) || (a == 2 && ((idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 0 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 1))) || (a == 3 && ((idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 1))) || (a == 4 && ((idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1))) || (a == 5 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 2 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 4))) || (a == 6 && ((idColoured == 0 && idAntiColoured == 2) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3))) || (a == 7 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 3 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 4))) || (a == 8 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 3 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 2))) || (a == 9 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 3 && idAntiColoured == 1) || (idColoured == 4 && idAntiColoured == 2) || (idColoured == 2 && idAntiColoured == 3))) || (a == 10 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 2 && idAntiColoured == 1) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 3 && idAntiColoured == 2))); } if ( basis == id33bar33bar8 ) { return (a == 0 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3) || (idColoured == 2 && idAntiColoured == 1))) || (a == 1 && ((idColoured == 0 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1) || (idColoured == 2 && idAntiColoured == 3))) || (a == 2 && ((idColoured == 0 && idAntiColoured == 3) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 1))) || (a == 3 && ((idColoured == 0 && idAntiColoured == 1) || (idColoured == 2 && idAntiColoured == 4) || (idColoured == 4 && idAntiColoured == 3))); } throw Exception() << "SimpleColourBasis2::colourConnected(): Cannot handle colour configuration" << Exception::runerror; return false; } map > > SimpleColourBasis2::basisList(const vector& basis) const { if ( id33bar.empty() ) makeIds(); map > > blist; vector > structures; vector structure; if ( basis == id88 ) { structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); blist[0] = structures; return blist; } if ( basis == id33bar ) { structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); blist[0] = structures; return blist; } if ( basis == id888 ) { structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(2); structures.push_back(structure); blist[0] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[1] = structures; return blist; } if ( basis == id33bar8 ) { structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[0] = structures; return blist; } if ( basis == id8888 ) { structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(1); structure.push_back(2); structures.push_back(structure); blist[0] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structures.push_back(structure); structure.clear(); structure.push_back(1); structure.push_back(3); structures.push_back(structure); blist[1] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(3); structures.push_back(structure); blist[2] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(2); structure.push_back(3); structures.push_back(structure); blist[3] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(3); structure.push_back(2); structures.push_back(structure); blist[4] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(1); structure.push_back(3); structures.push_back(structure); blist[5] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(3); structure.push_back(1); structures.push_back(structure); blist[6] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(1); structure.push_back(2); structures.push_back(structure); blist[7] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[8] = structures; return blist; } if ( basis == id33bar88 ) { structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); blist[0] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(3); structure.push_back(1); structures.push_back(structure); blist[1] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[2] = structures; return blist; } if ( basis == id33bar33bar ) { structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[0] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(3); structures.push_back(structure); blist[1] = structures; return blist; } if ( basis == id88888 ) { structures.clear(); structure.clear(); structure.push_back(3); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(2); structures.push_back(structure); blist[0] = structures; structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(3); structures.push_back(structure); blist[1] = structures; structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(4); structures.push_back(structure); blist[2] = structures; structures.clear(); structure.clear(); structure.push_back(3); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[3] = structures; structures.clear(); structure.clear(); structure.push_back(1); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(3); structures.push_back(structure); blist[4] = structures; structures.clear(); structure.clear(); structure.push_back(1); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(4); structures.push_back(structure); blist[5] = structures; structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(1); structures.push_back(structure); blist[6] = structures; structures.clear(); structure.clear(); structure.push_back(1); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(2); structures.push_back(structure); blist[7] = structures; structures.clear(); structure.clear(); structure.push_back(1); structure.push_back(2); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(4); structures.push_back(structure); blist[8] = structures; structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(1); structures.push_back(structure); blist[9] = structures; structures.clear(); structure.clear(); structure.push_back(1); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(2); structures.push_back(structure); blist[10] = structures; structures.clear(); structure.clear(); structure.push_back(1); structure.push_back(2); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(3); structures.push_back(structure); blist[11] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(1); structure.push_back(2); structure.push_back(3); structures.push_back(structure); blist[12] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(1); structure.push_back(2); structure.push_back(4); structures.push_back(structure); blist[13] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(1); structure.push_back(3); structure.push_back(2); structures.push_back(structure); blist[14] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structures.push_back(structure); structure.clear(); structure.push_back(1); structure.push_back(3); structure.push_back(4); structures.push_back(structure); blist[15] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(1); structure.push_back(4); structure.push_back(2); structures.push_back(structure); blist[16] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structures.push_back(structure); structure.clear(); structure.push_back(1); structure.push_back(4); structure.push_back(3); structures.push_back(structure); blist[17] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(3); structure.push_back(4); structures.push_back(structure); blist[18] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(4); structure.push_back(3); structures.push_back(structure); blist[19] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(2); structure.push_back(3); structure.push_back(4); structures.push_back(structure); blist[20] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(2); structure.push_back(4); structure.push_back(3); structures.push_back(structure); blist[21] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(3); structure.push_back(2); structure.push_back(4); structures.push_back(structure); blist[22] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(3); structure.push_back(4); structure.push_back(2); structures.push_back(structure); blist[23] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(4); structure.push_back(2); structure.push_back(3); structures.push_back(structure); blist[24] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structure.push_back(4); structure.push_back(3); structure.push_back(2); structures.push_back(structure); blist[25] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(1); structure.push_back(3); structure.push_back(4); structures.push_back(structure); blist[26] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(1); structure.push_back(4); structure.push_back(3); structures.push_back(structure); blist[27] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(3); structure.push_back(1); structure.push_back(4); structures.push_back(structure); blist[28] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(3); structure.push_back(4); structure.push_back(1); structures.push_back(structure); blist[29] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(4); structure.push_back(1); structure.push_back(3); structures.push_back(structure); blist[30] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(4); structure.push_back(3); structure.push_back(1); structures.push_back(structure); blist[31] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(1); structure.push_back(2); structure.push_back(4); structures.push_back(structure); blist[32] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(1); structure.push_back(4); structure.push_back(2); structures.push_back(structure); blist[33] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(2); structure.push_back(1); structure.push_back(4); structures.push_back(structure); blist[34] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(2); structure.push_back(4); structure.push_back(1); structures.push_back(structure); blist[35] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(4); structure.push_back(1); structure.push_back(2); structures.push_back(structure); blist[36] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(4); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[37] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(1); structure.push_back(2); structure.push_back(3); structures.push_back(structure); blist[38] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(1); structure.push_back(3); structure.push_back(2); structures.push_back(structure); blist[39] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(2); structure.push_back(1); structure.push_back(3); structures.push_back(structure); blist[40] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(2); structure.push_back(3); structure.push_back(1); structures.push_back(structure); blist[41] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(3); structure.push_back(1); structure.push_back(2); structures.push_back(structure); blist[42] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(3); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[43] = structures; return blist; } if ( basis == id33bar888 ) { structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(3); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); blist[0] = structures; structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(4); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); blist[1] = structures; structures.clear(); structure.clear(); structure.push_back(3); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[2] = structures; structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(4); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(1); structures.push_back(structure); blist[3] = structures; structures.clear(); structure.clear(); structure.push_back(2); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(1); structures.push_back(structure); blist[4] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(3); structure.push_back(4); structure.push_back(1); structures.push_back(structure); blist[5] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(2); structure.push_back(4); structure.push_back(3); structure.push_back(1); structures.push_back(structure); blist[6] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(2); structure.push_back(4); structure.push_back(1); structures.push_back(structure); blist[7] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structure.push_back(4); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[8] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(2); structure.push_back(3); structure.push_back(1); structures.push_back(structure); blist[9] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(3); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[10] = structures; return blist; } if ( basis == id33bar33bar8 ) { structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(1); structures.push_back(structure); blist[0] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(4); structure.push_back(1); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(3); structures.push_back(structure); blist[1] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(3); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(4); structure.push_back(1); structures.push_back(structure); blist[2] = structures; structures.clear(); structure.clear(); structure.push_back(0); structure.push_back(1); structures.push_back(structure); structure.clear(); structure.push_back(2); structure.push_back(4); structure.push_back(3); structures.push_back(structure); blist[3] = structures; return blist; } throw Exception() << "SimpleColourBasis2::basisList(): Cannot handle colour configuration" << Exception::runerror; return blist; } void SimpleColourBasis2::makeIds() const { id88 = vector(2,PDT::Colour8); id33bar.push_back(PDT::Colour3); id33bar.push_back(PDT::Colour3bar); id888 = vector(3,PDT::Colour8); id33bar8 = id33bar; id33bar8.push_back(PDT::Colour8); id8888 = vector(4,PDT::Colour8); id33bar88 = id33bar8; id33bar88.push_back(PDT::Colour8); id33bar33bar = id33bar; id33bar33bar.push_back(PDT::Colour3); id33bar33bar.push_back(PDT::Colour3bar); id88888 = vector(5,PDT::Colour8); id33bar888 = id33bar88; id33bar888.push_back(PDT::Colour8); id33bar33bar8 = id33bar33bar; id33bar33bar8.push_back(PDT::Colour8); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void SimpleColourBasis2::persistentOutput(PersistentOStream &) const {} void SimpleColourBasis2::persistentInput(PersistentIStream &, int) {} // *** 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 describeHerwigSimpleColourBasis2("Herwig::SimpleColourBasis2", "Herwig.so"); void SimpleColourBasis2::Init() { static ClassDocumentation documentation ("SimpleColourBasis2 implements the colour algebra needed for " "processes with four coloured legs at NLO. It mainly " "serves as an example for the general ColourBasis interface."); } diff --git a/MatrixElement/Matchbox/Utility/SimpleColourBasis2.h b/MatrixElement/Matchbox/Utility/SimpleColourBasis2.h --- a/MatrixElement/Matchbox/Utility/SimpleColourBasis2.h +++ b/MatrixElement/Matchbox/Utility/SimpleColourBasis2.h @@ -1,233 +1,218 @@ // -*- C++ -*- // // SimpleColourBasis2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_SimpleColourBasis2_H #define Herwig_SimpleColourBasis2_H // // This is the declaration of the SimpleColourBasis2 class. // #include "Herwig/MatrixElement/Matchbox/Utility/ColourBasis.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief SimpleColourBasis2 implements the colour algebra needed for * processes with four coloured legs at NLO. It mainly serves as an * example for the general ColourBasis interface. * */ class SimpleColourBasis2: public ColourBasis { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - SimpleColourBasis2(); - - /** - * The destructor. - */ - virtual ~SimpleColourBasis2(); - //@} - -public: - /** * Prepare the basis for the normal ordered legs and return the * dimensionality of the basis. */ virtual size_t prepareBasis(const vector&); /** * Return the scalar product of basis tensors labelled a and b in * the basis used for the given normal ordered legs. */ virtual double scalarProduct(size_t a, size_t b, const vector& abBasis) const; /** * Return the matrix element of a colour charge * between basis tensors a and b, with * respect to aBasis and bBasis */ virtual double tMatrixElement(size_t i, size_t a, size_t b, const vector& aBasis, const vector& bBasis, size_t k, size_t l, const map& dict) const; /* * Temporary to make it compile */ virtual double sMatrixElement(size_t, size_t, size_t, const vector&, const vector&, size_t, size_t, const map& ) const { assert( 0 == 1 ); return 0; } /** * Return true, if this colour basis supports gluon splittings. */ virtual bool canSplitGluons() const { return false; } /** * Return true, if a large-N colour connection exists for the * given external legs and basis tensor. */ virtual bool colourConnected(const cPDVector&, const vector&, const pair&, const pair&, size_t) const; /** * Return true, if the colour basis is capable of assigning colour * flows. */ virtual bool haveColourFlows() const { return true; } /** * Create ids for bases */ void makeIds() const; /** * Return a map of basis tensor indices to vectors identifying a * certain ordering corresponding to the given colour structure. May * not be supported by all colour basis implementations. */ virtual map > > basisList(const vector&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * id for 88 */ mutable vector id88; /** * id for 33bar */ mutable vector id33bar; /** * id for 888 */ mutable vector id888; /** * id for 33bar8 */ mutable vector id33bar8; /** * id for 8888 */ mutable vector id8888; /** * id for 33bar88 */ mutable vector id33bar88; /** * id for 33bar33bar */ mutable vector id33bar33bar; /** * id for 88888 */ mutable vector id88888; /** * id for 33bar888 */ mutable vector id33bar888; /** * id for 33bar33bar8 */ mutable vector id33bar33bar8; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SimpleColourBasis2 & operator=(const SimpleColourBasis2 &) = delete; }; } #endif /* Herwig_SimpleColourBasis2_H */ diff --git a/MatrixElement/Matchbox/Utility/Tree2toNGenerator.cc b/MatrixElement/Matchbox/Utility/Tree2toNGenerator.cc --- a/MatrixElement/Matchbox/Utility/Tree2toNGenerator.cc +++ b/MatrixElement/Matchbox/Utility/Tree2toNGenerator.cc @@ -1,490 +1,488 @@ // -*- C++ -*- // // Tree2toNGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Tree2toNGenerator class. // #include "Tree2toNGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Utilities/StringUtils.h" using namespace Herwig; Tree2toNGenerator::Tree2toNGenerator() : maxOrderGs(0), maxOrderGem(0), prepared(false) {} -Tree2toNGenerator::~Tree2toNGenerator() {} - IBPtr Tree2toNGenerator::clone() const { return new_ptr(*this); } IBPtr Tree2toNGenerator::fullclone() const { return new_ptr(*this); } vector::ptr> Tree2toNGenerator:: generate(const PDVector& legs, unsigned int orderInGs, unsigned int orderInGem) { vector::ptr> res; list > prog = clusterAll(legs,orderInGs,orderInGem); int count = 1; for ( auto & d : prog ) { assert(d.size() == 1); Tree2toNDiagram diag = d.front().generate(count); if ( !spaceLikeAllowed.empty() ) { map counts; for ( int k = 1; k < diag.nSpace()-1; ++k ) counts[diag.allPartons()[k]] += 1; for ( auto & m : spaceLikeAllowed ) { m.reset(); for ( auto const & c : counts ) m.add(c.first,c.second); } bool failed = false; for ( auto const & m : spaceLikeAllowed) { if ( !m.check() ) { failed = true; break; } } if ( failed ) continue; } if ( !timeLikeAllowed.empty() ) { map counts; int all = diag.allPartons().size(); for ( int k = diag.nSpace(); k < all; ++k ) { if ( diag.children(k).first < 0 ) continue; counts[diag.allPartons()[k]] += 1; } for ( auto & m : timeLikeAllowed ) { m.reset(); for ( auto const & c : counts ) m.add(c.first,c.second); } bool failed = false; for ( auto const & m : timeLikeAllowed ) { if ( !m.check() ) { failed = true; break; } } if ( failed ) continue; } bool internalVeto = false; set external; int nex = diag.partons().size(); for ( int i = 0; i < nex; ++i ) { external.insert(diag.diagramId(i)); } int n = diag.allPartons().size(); for ( int i = 0; i < n; ++i ) { if ( external.find(i) != external.end() ) continue; if ( find(excludeInternal().begin(), excludeInternal().end(), diag.allPartons()[i]) != excludeInternal().end() ) { internalVeto = true; break; } } if ( internalVeto ) continue; bool gotit = false; for ( auto const & d : res) { map checkPermutation; if ( diag.isSame(d,checkPermutation) ) { gotit = true; for ( auto const & p : checkPermutation ) if ( p.first != p.second ) gotit = false; if ( gotit ) break; } } if ( !gotit ) { res.push_back(new_ptr(diag)); ++count; } } return res; } list > Tree2toNGenerator:: cluster(const vector& children, unsigned int orderInGs, unsigned int orderInGem) const { list > res; bool externalCluster = children[1].externalId != -1; if ( children.size() == 3 ) { for ( auto const & v : theVertices ) { if ( v->getNpoint() != 3 ) continue; if ( find(theExcludeVertices.begin(), theExcludeVertices.end(), v) != theExcludeVertices.end() ) continue; bool noMatch = v->orderInGs() != int(orderInGs) || v->orderInGem() != int(orderInGem) || !v->isIncoming(children[0].parent); long idij = children[0].parent->id(); long idi = children[2].parent->id(); long idj = children[1].parent->id(); if ( externalCluster && children[1].parent->CC() ) idj = -idj; if ( children[0].parent->CC() ) idij = -idij; if ( !externalCluster ) noMatch |= !v->isOutgoing(children[1].parent) || !v->isOutgoing(children[2].parent); else noMatch |= !v->isIncoming(children[1].parent) || !v->isOutgoing(children[2].parent); noMatch |= !( v->allowed(idij,idi,idj) || v->allowed(idj,idij,idi) || v->allowed(idi,idj,idij) || v->allowed(idij,idj,idi) || v->allowed(idi,idij,idj) || v->allowed(idj,idi,idij) ); if ( noMatch ) continue; Vertex last; last.spacelike = true; last.parent = children[0].parent; last.externalId = 0; last.children.push_back(children[1]); last.children.push_back(children[2]); res.push_back(vector(1,last)); // only one possible break; } return res; } // spacelike clusterings (cluster on second one) for ( size_t i = 2; i < children.size(); ++i ) { for ( auto const & v : theVertices ) { if ( v->getNpoint() != 3 ) continue; if ( find(theExcludeVertices.begin(), theExcludeVertices.end(), v) != theExcludeVertices.end() ) continue; bool noMatch = false; noMatch |= v->orderInGs() != int(orderInGs) || v->orderInGem() != int(orderInGem); if ( !externalCluster ) noMatch |= !v->isOutgoing(children[1].parent) || !v->isOutgoing(children[i].parent); else noMatch |= !v->isIncoming(children[1].parent) || !v->isOutgoing(children[i].parent); if ( noMatch ) continue; long idi = children[i].parent->id(); long idj = children[1].parent->id(); if ( externalCluster && children[1].parent->CC() ) idj = -idj; for ( set::const_iterator pij = v->outgoing().begin(); pij != v->outgoing().end() ; ++pij ) { long idij = (**pij).id(); if ( v->allowed(idij,idi,idj) || v->allowed(idj,idij,idi) || v->allowed(idi,idj,idij) || v->allowed(idij,idj,idi) || v->allowed(idi,idij,idj) || v->allowed(idj,idi,idij) ) { PDPtr dij = (**pij).CC() ? (**pij).CC() : *pij; vector cled; for ( size_t k = 0; k < children.size(); ++k ) { if ( k != 1 && k != i ) cled.push_back(children[k]); if ( k == 1 ) { Vertex merge; merge.children.push_back(children[1]); merge.children.push_back(children[i]); merge.parent = dij; merge.spacelike = true; cled.push_back(merge); } if ( k == i ) continue; } res.push_back(cled); } } } } // timelike clusterings for ( size_t i = 2; i < children.size(); ++i ) { for ( size_t j = i+1; j < children.size(); ++j ) { for ( auto const & v : theVertices ) { if ( v->getNpoint() != 3 ) continue; if ( find(theExcludeVertices.begin(), theExcludeVertices.end(), v) != theExcludeVertices.end() ) continue; if ( v->orderInGs() != int(orderInGs) || v->orderInGem() != int(orderInGem) || !v->isOutgoing(children[i].parent) || !v->isOutgoing(children[j].parent) ) continue; long idi = children[i].parent->id(); long idj = children[j].parent->id(); for ( set::const_iterator pij = v->outgoing().begin(); pij != v->outgoing().end() ; ++pij ) { long idij = (**pij).id(); if ( v->allowed(idij,idi,idj) || v->allowed(idj,idij,idi) || v->allowed(idi,idj,idij) || v->allowed(idij,idj,idi) || v->allowed(idi,idij,idj) || v->allowed(idj,idi,idij) ) { PDPtr dij = (**pij).CC() ? (**pij).CC() : *pij; vector cled; for ( size_t k = 0; k < children.size(); ++k ) { if ( k != i && k != j ) cled.push_back(children[k]); if ( k == i ) { Vertex merge; merge.children.push_back(children[i]); merge.children.push_back(children[j]); merge.parent = dij; merge.spacelike = false; cled.push_back(merge); } if ( k == j ) continue; } res.push_back(cled); } } } } } return res; } list > Tree2toNGenerator:: clusterAll(const list >& current, unsigned int orderInGs, unsigned int orderInGem) const { list > res; for ( list >::const_iterator c = current.begin(); c != current.end(); ++c ) { if ( c->size() == 1 ) { if ( orderInGs == 0 && orderInGem == 0 ) res.push_back(*c); continue; } for ( unsigned int gs = 0; gs <= maxOrderGs; ++gs ) for ( unsigned int gem = 0; gem <= maxOrderGem; ++gem ) { if ( gs == 0 && gem == 0 ) continue; if ( gs > orderInGs || gem > orderInGem ) continue; list > next = cluster(*c,gs,gem); if ( next.empty() ) continue; list > cled = clusterAll(next,orderInGs-gs,orderInGem-gem); copy(cled.begin(),cled.end(),back_inserter(res)); } } return res; } list > Tree2toNGenerator:: clusterAll(const PDVector& external, unsigned int orderInGs, unsigned int orderInGem) { if ( !prepared ) { for ( auto & v : theVertices ) { if ( find(theExcludeVertices.begin(), theExcludeVertices.end(), v) != theExcludeVertices.end() ) continue; v->init(); maxOrderGs = max(maxOrderGs,v->orderInGs()); maxOrderGem = max(maxOrderGem,v->orderInGem()); } for ( auto & m : spaceLikeAllowed) m.rebind(this); for ( auto & m : timeLikeAllowed ) m.rebind(this); prepared = true; } vector legs; for ( unsigned int k = 0; k < external.size(); ++k ) { Vertex v; v.parent = external[k]; v.externalId = k; v.spacelike = k < 2; legs.push_back(v); } list > firstlegs; firstlegs.push_back(legs); return clusterAll(firstlegs,orderInGs,orderInGem); } string Tree2toNGenerator::doSpaceLikeRange(string range) { if ( theRestrictLines.empty() ) return "No particle data specified to restrict internal lines."; vector bounds = StringUtils::split(range); if ( bounds.empty() || bounds.size() > 2 ) return "Need to specify a minimum, or a minimum and maximum number of internal lines."; pair irange(0,-1); istringstream in1(bounds[0]); in1 >> irange.first; if ( bounds.size() == 2 ) { istringstream in2(bounds[1]); in2 >> irange.second; } else { irange.second = irange.first; } if ( irange.second >= 0 && irange.first > irange.second ) return "invalid range specified"; spaceLikeAllowed.push_back(LineMatcher(theRestrictLines,irange)); return ""; } string Tree2toNGenerator::doTimeLikeRange(string range) { if ( theRestrictLines.empty() ) return "No particle data specified to restrict internal lines."; vector bounds = StringUtils::split(range); if ( bounds.empty() || bounds.size() > 2 ) return "Need to specify a minimum, or a minimum and maximum number of internal lines."; pair irange(0,-1); istringstream in1(bounds[0]); in1 >> irange.first; if ( bounds.size() == 2 ) { istringstream in2(bounds[1]); in2 >> irange.second; } else { irange.second = irange.first; } if ( irange.second >= 0 && irange.first > irange.second ) return "invalid range specified"; timeLikeAllowed.push_back(LineMatcher(theRestrictLines,irange)); return ""; } string Tree2toNGenerator::doClearRestrictLines(string) { theRestrictLines.clear(); return ""; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void Tree2toNGenerator::persistentOutput(PersistentOStream & os) const { os << theVertices << theExcludeInternal << maxOrderGs << maxOrderGem << prepared << theExcludeVertices << spaceLikeAllowed << timeLikeAllowed; } void Tree2toNGenerator::persistentInput(PersistentIStream & is, int) { is >> theVertices >> theExcludeInternal >> maxOrderGs >> maxOrderGem >> prepared >> theExcludeVertices >> spaceLikeAllowed >> timeLikeAllowed; } // *** 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 describeHerwigTree2toNGenerator("Herwig::Tree2toNGenerator", "Herwig.so"); void Tree2toNGenerator::Init() { static ClassDocumentation documentation ("Generate Tree2toNDiagrams for a given process."); static RefVector interfaceVertices ("Vertices", "All vertices to consider.", &Tree2toNGenerator::theVertices, -1, false, false, true, false, false); static RefVector interfaceExcludeVertices ("ExcludeVertices", "The vertices to exclude.", &Tree2toNGenerator::theExcludeVertices, -1, false, false, true, false, false); static RefVector interfaceExcludeInternal ("ExcludeInternal", "Particles to be exluded from becoming internal lines.", &Tree2toNGenerator::theExcludeInternal, -1, false, false, true, false, false); static RefVector interfaceRestrictLines ("RestrictLines", "Particles to be exluded from becoming internal lines.", &Tree2toNGenerator::theRestrictLines, -1, false, false, true, false, false); static Command interfaceSpaceLikeRange ("SpaceLikeRange", "Limit the number of spacelike occurences of the specified particle.", &Tree2toNGenerator::doSpaceLikeRange, false); static Command interfaceTimeLikeRange ("TimeLikeRange", "Limit the number of timelike occurences of the specified particle.", &Tree2toNGenerator::doTimeLikeRange, false); static Command interfaceClearRestrictLines ("ClearRestrictLines", "Clear the container of lines to be considered for restrictions.", &Tree2toNGenerator::doClearRestrictLines, false); } diff --git a/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h b/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h --- a/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h +++ b/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h @@ -1,438 +1,430 @@ // -*- C++ -*- // // Tree2toNGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_Tree2toNGenerator_H #define Herwig_Tree2toNGenerator_H // // This is the declaration of the Tree2toNGenerator class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Helicity/Vertex/VertexBase.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief Generate Tree2toNDiagrams for a given process. * * @see \ref Tree2toNGeneratorInterfaces "The interfaces" * defined for Tree2toNGenerator. */ class Tree2toNGenerator: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ Tree2toNGenerator(); - /** - * The destructor. - */ - virtual ~Tree2toNGenerator(); - //@} - public: /** * Generate all diagrams for the given process. */ vector::ptr> generate(const PDVector&, unsigned int orderInGs, unsigned int orderInGem); typedef vector::ptr> VertexVector; /** * Access the vertices */ VertexVector& vertices() { return theVertices; } /** * Return the vertices */ const VertexVector& vertices() const { return theVertices; } /** * Access the particles to be excluded from internal lines */ PDVector& excludeInternal() { return theExcludeInternal; } /** * Return the particles to be excluded from internal lines */ const PDVector& excludeInternal() const { return theExcludeInternal; } 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(); public: /** * A node in internally used trees. */ struct Vertex { /** * The outgoing particles. If this is a spacelike node, the first * child is considered the next spacelike (or second incoming) * line. If children are empty, this is an external line. */ vector children; /** * The incoming line at this node. */ PDPtr parent; /** * True, if this is spacelike node. */ bool spacelike; /** * The external leg id. */ int externalId; /** * The parent diagram id. */ int parentId; /** * The default constructor. */ Vertex() : spacelike(false), externalId(-1), parentId(-1) {} /** * Debug printout. */ void print(ostream& os, const string& prefix = "") const { os << prefix << parent->PDGName() << "[" << (spacelike ? "s" : "t") << "] ("; if ( externalId < 0 ) os << "x)\n"; else os << externalId << ")\n"; if ( !children.empty() ) { os << prefix << "|__\n"; children[0].print(os,prefix + "| "); os << prefix << "|__\n"; children[1].print(os,prefix + "| "); } } /** * Count the number of spacelike lines */ int nspace() const { if ( children.empty() ) return 1; int ret = 1; ret += children[0].nspace(); return ret; } /** * Update diagram returning a map of external ids to diagram id * parents. */ void update(Tree2toNDiagram& diag, map >& outgoing, int& lastUsed) { if ( externalId == 0 ) { assert(lastUsed==0); ++lastUsed; diag.operator,(parent); children[0].parentId = lastUsed; children[1].parentId = lastUsed; children[0].update(diag,outgoing,lastUsed); children[1].update(diag,outgoing,lastUsed); for ( map >::iterator out = outgoing.begin(); out != outgoing.end(); ++out ) { diag.operator,(out->second.first); diag.operator,(out->second.second); } return; } if ( spacelike ) { ++lastUsed; diag.operator,(parent); if ( externalId == 1 ) return; children[0].parentId = lastUsed; children[1].parentId = lastUsed; children[0].update(diag,outgoing,lastUsed); children[1].update(diag,outgoing,lastUsed); return; } if ( children.empty() ) { outgoing[externalId] = make_pair(parentId,parent); return; } diag.operator,(parentId); diag.operator,(parent); ++lastUsed; children[0].parentId = lastUsed; children[1].parentId = lastUsed; children[0].update(diag,outgoing,lastUsed); children[1].update(diag,outgoing,lastUsed); } /** * Generate a diagram of given id. */ Tree2toNDiagram generate(int id) { int nsp = nspace(); Tree2toNDiagram res(nsp); int diagid = 0; map > out; update(res,out,diagid); res.operator,(-id); return res; } }; /** * For the given set of trees determine all allowed clusterings. */ list > cluster(const vector& children, unsigned int orderInGs, unsigned int orderInGem) const; /** * For the given set of outgoing lines cluster recursively. */ list > clusterAll(const list >& current, unsigned int orderInGs, unsigned int orderInGem) const; /** * For the given set of outgoing lines cluster recursively. */ list > clusterAll(const PDVector& external, unsigned int orderInGs, unsigned int orderInGem); /** * Helper for topology restrictions */ struct LineMatcher { /** * The group of lines to be considered */ set particles; /** * The range allowed */ pair range; /** * The current count */ int count; /** * Default constructor */ LineMatcher() : range(0,0), count(0) {} /** * Construct given particles and a range */ LineMatcher(const PDVector& p, const pair& r) : range(r), count(0) { copy(p.begin(),p.end(),inserter(particles,particles.begin())); } /** * Rebind the particle data pointers */ void rebind(Tree2toNGenerator* g) { set oldp = particles; particles.clear(); for ( set::const_iterator p = oldp.begin(); p != oldp.end(); ++p ) particles.insert(g->getParticleData((**p).id())); } /** * Reset this matcher */ void reset() { count = 0; } /** * Count the given multiplicity */ void add(tcPDPtr p, int n) { if ( particles.find(p) == particles.end() ) return; count += n; } /** * Ceck if restrictions are met */ bool check() const { return count >= range.first && count <= range.second; } }; 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: /** * The vertices to be used. */ VertexVector theVertices; /** * The particles to be excluded from internal lines */ PDVector theExcludeInternal; /** * Maximum order in gs to consider. */ unsigned int maxOrderGs; /** * Maximum order in gem to consider. */ unsigned int maxOrderGem; /** * Wether or not the generator has been prepared */ bool prepared; /** * The vertices to be excluded. */ VertexVector theExcludeVertices; /** * Minimal and maximal occurences of spacelike internal lines */ vector spaceLikeAllowed; /** * Minimal and maximal occurences of timelike internal lines */ vector timeLikeAllowed; /** * The next particle for which internal lines need to be restricted */ PDVector theRestrictLines; /** * Command to set an allowed range of spacelike internal lines */ string doSpaceLikeRange(string); /** * Command to set an allowed range of timelike internal lines */ string doTimeLikeRange(string); /** * Command to clear the restrict lines container */ string doClearRestrictLines(string); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Tree2toNGenerator & operator=(const Tree2toNGenerator &) = delete; }; inline PersistentOStream& operator<<(PersistentOStream& os, const Tree2toNGenerator::LineMatcher& m) { os << m.particles << m.range << m.count; return os; } inline PersistentIStream& operator>>(PersistentIStream& is, Tree2toNGenerator::LineMatcher& m) { is >> m.particles >> m.range >> m.count; return is; } } #endif /* Herwig_Tree2toNGenerator_H */ diff --git a/Models/General/FourBodyDecayConstructor.cc b/Models/General/FourBodyDecayConstructor.cc --- a/Models/General/FourBodyDecayConstructor.cc +++ b/Models/General/FourBodyDecayConstructor.cc @@ -1,259 +1,257 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FourBodyDecayConstructor class. // #include "FourBodyDecayConstructor.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/Decay/General/GeneralFourBodyDecayer.h" #include "DecayConstructor.h" using namespace Herwig; -FourBodyDecayConstructor::~FourBodyDecayConstructor() {} - IBPtr FourBodyDecayConstructor::clone() const { return new_ptr(*this); } IBPtr FourBodyDecayConstructor::fullclone() const { return new_ptr(*this); } void FourBodyDecayConstructor::persistentOutput(PersistentOStream & os) const { os << interOpt_ << widthOpt_ << particles_; } void FourBodyDecayConstructor::persistentInput(PersistentIStream & is, int) { is >> interOpt_ >> widthOpt_ >> particles_; } DescribeClass describeFourBodyDecayConstructor("Herwig::FourBodyDecayConstructor","Herwig.so"); void FourBodyDecayConstructor::Init() { static ClassDocumentation documentation ("The FourBodyDecayConstructor class implements a small number" " of 4-body decays in general models"); static Switch interfaceWidthOption ("WidthOption", "Option for the treatment of the widths of the intermediates", &FourBodyDecayConstructor::widthOpt_, 1, false, false); static SwitchOption interfaceWidthOptionFixed (interfaceWidthOption, "Fixed", "Use fixed widths", 1); static SwitchOption interfaceWidthOptionRunning (interfaceWidthOption, "Running", "Use running widths", 2); static SwitchOption interfaceWidthOptionZero (interfaceWidthOption, "Zero", "Set the widths to zero", 3); static Switch interfaceIntermediateOption ("IntermediateOption", "Option for the inclusion of intermediates in the event", &FourBodyDecayConstructor::interOpt_, 0, false, false); static SwitchOption interfaceIntermediateOptionAlways (interfaceIntermediateOption, "Always", "Always include the intermediates", 1); static SwitchOption interfaceIntermediateOptionNever (interfaceIntermediateOption, "Never", "Never include the intermediates", 2); static SwitchOption interfaceIntermediateOptionOnlyIfOnShell (interfaceIntermediateOption, "OnlyIfOnShell", "Only if there are on-shell diagrams", 0); static RefVector interfaceParticles ("Particles", "Particles to override the choice in the DecayConstructor for 4-body decays," " if empty the defaults from the DecayConstructor are used.", &FourBodyDecayConstructor::particles_, -1, false, false, true, true, false); static Switch interfaceParticleType ("ParticleType", "Which types of particles to calculate four body decay modes for", &FourBodyDecayConstructor::particleType_, false, false, false); static SwitchOption interfaceParticleTypeStable (interfaceParticleType, "Stable", "Only calculate four-body decays in no 2/3 body modes", false); static SwitchOption interfaceParticleTypeAll (interfaceParticleType, "All", "Calculate 4-body modes for all particles", true); } void FourBodyDecayConstructor::DecayList(const set & particles) { if( particles.empty() ) return; set new_particles; for(set::const_iterator it=particles.begin();it!=particles.end();++it) { if(!particles_.empty() && find(particles_.begin(),particles_.end(),*it)==particles_.end()) continue; if(!(**it).stable()&&!particleType_) continue; new_particles.insert(*it); } if(!new_particles.empty()) NBodyDecayConstructorBase::DecayList(new_particles); } void FourBodyDecayConstructor:: createDecayMode(vector & diagrams, bool possibleOnShell, double symfac) { // some basic checks for the modes we are interested in // only looking at scalars if(diagrams[0].incoming->iSpin()!=PDT::Spin0) return; // which decay to 4 fermions unsigned int nferm=0; for(OrderedParticles::const_iterator it=diagrams[0].outgoing.begin(); it!=diagrams[0].outgoing.end();++it) { if((**it).iSpin()==PDT::Spin1Half) ++nferm; } if(nferm!=4) return; // check for on-shell intermediates bool inter = interOpt_ == 1 || (interOpt_ == 0 && possibleOnShell); // incoming particle tPDPtr inpart = diagrams[0].incoming; // outgoing particles OrderedParticles outgoing=diagrams[0].outgoing; // incoming particle is now unstable inpart->stable(false); // construct the tag for the decay mode string tag = inpart->name() + "->"; for(OrderedParticles::const_iterator it = outgoing.begin(); it != outgoing.end(); ++it) { if(it!=outgoing.begin()) tag += ","; tag += (**it).name(); } tag += ";"; tDMPtr dm = generator()->findDecayMode(tag); // create mode if needed if( createDecayModes() && (!dm || inpart->id() == ParticleID::h0) ) { // create the decayer GeneralFourBodyDecayerPtr decayer = createDecayer(diagrams,inter,symfac); if(!decayer) { if(Debug::level > 1 ) generator()->log() << "Can't create the decayer for " << tag << " so mode not created\n"; return; } // create the decay mode tDMPtr ndm = generator()->preinitCreateDecayMode(tag); if(ndm) { string test = generator()->preinitInterface(ndm, "Decayer", "set", decayer->fullName()); generator()->preinitInterface(ndm, "Active", "set", "Yes"); Energy width = decayer->partialWidth(inpart,outgoing); setBranchingRatio(ndm, width); } else throw NBodyDecayConstructorError() << "FourBodyDecayConstructor::createDecayMode - Needed to create " << "new decaymode but one could not be created for the tag " << tag << Exception::warning; } // otherwise else if (dm && (dm->decayer()->fullName()).find("Mambo") != string::npos) { // create the decayer GeneralFourBodyDecayerPtr decayer = createDecayer(diagrams,inter,symfac); if(!decayer) { if(Debug::level > 1 ) generator()->log() << "Can't create the decayer for " << tag << " so mode not created\n"; return; } generator()->preinitInterface(dm, "Decayer", "set", decayer->fullName()); } //update CC mode if it exists if( inpart->CC() ) inpart->CC()->synchronize(); } GeneralFourBodyDecayerPtr FourBodyDecayConstructor::createDecayer(vector & diagrams, bool inter, double symfac) const { if(diagrams.empty()) return GeneralFourBodyDecayerPtr(); // extract the external particles for the process PDPtr incoming = diagrams[0].incoming; // outgoing particles vector outgoing(diagrams[0].outgoing.begin(), diagrams[0].outgoing.end()); // get the name for the object string objectname ("/Herwig/Decays/"); string classname = DecayerClassName(incoming, diagrams[0].outgoing, objectname); if(classname=="") return GeneralFourBodyDecayerPtr(); // create the object GeneralFourBodyDecayerPtr decayer = dynamic_ptr_cast (generator()->preinitCreate(classname, objectname)); // set up the decayer and return if doesn't work if(!decayer->setDecayInfo(incoming,outgoing,diagrams,symfac)) return GeneralFourBodyDecayerPtr(); // set decayer options from base class setDecayerInterfaces(objectname); // set the width option ostringstream value; value << widthOpt_; generator()->preinitInterface(objectname, "WidthOption", "set", value.str()); // set the intermediates option ostringstream value2; value2 << inter; generator()->preinitInterface(objectname, "GenerateIntermediates", "set", value2.str()); // initialize the decayer decayer->init(); // return the decayer return decayer; } string FourBodyDecayConstructor::DecayerClassName(tcPDPtr incoming, const OrderedParticles & outgoing, string & objname) const { string classname("Herwig::"); // spins of the outgoing particles unsigned int ns(0),nf(0),nv(0); objname += incoming->PDGName() + "2"; for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) { if ((**it).iSpin()==PDT::Spin0 ) ++ns; else if((**it).iSpin()==PDT::Spin1Half) ++nf; else if((**it).iSpin()==PDT::Spin1 ) ++nv; objname += (**it).PDGName(); } objname += "Decayer"; if(incoming->iSpin()==PDT::Spin0) { if(nf==4) classname += "StoFFFFDecayer"; else classname = ""; } else { classname=""; } return classname; } diff --git a/Models/General/FourBodyDecayConstructor.h b/Models/General/FourBodyDecayConstructor.h --- a/Models/General/FourBodyDecayConstructor.h +++ b/Models/General/FourBodyDecayConstructor.h @@ -1,150 +1,145 @@ // -*- C++ -*- #ifndef THEPEG_FourBodyDecayConstructor_H #define THEPEG_FourBodyDecayConstructor_H // // This is the declaration of the FourBodyDecayConstructor class. // #include "NBodyDecayConstructorBase.h" #include "ThePEG/Helicity/Vertex/VertexBase.h" #include "Herwig/Decay/General/GeneralFourBodyDecayer.fh" #include "PrototypeVertex.h" namespace Herwig { using namespace ThePEG; using Helicity::VertexBasePtr; /** * Here is the documentation of the FourBodyDecayConstructor class. * * @see \ref FourBodyDecayConstructorInterfaces "The interfaces" * defined for FourBodyDecayConstructor. */ class FourBodyDecayConstructor: public NBodyDecayConstructorBase { public: /** * The default constructor. */ FourBodyDecayConstructor() : interOpt_(0), widthOpt_(1), particleType_(false) {} /** - * Destructor - */ - ~FourBodyDecayConstructor(); - - /** * Function used to determine allowed decaymodes, to be implemented * in derived class. * @param particles vector of ParticleData pointers containing * particles in model */ virtual void DecayList(const set & particles); /** * Number of outgoing lines. Required for correct ordering. */ virtual unsigned int numBodies() const {return 4;} /** * Create a decay mode */ void createDecayMode(vector &,bool,double); /** * Create the decayer * @param diagrams The diagrams for the decay * @param inter Option for intermediates */ GeneralFourBodyDecayerPtr createDecayer(vector & diagrams, bool inter, double symfac) const; /** * Contruct the classname and object name for the Decayer * @param incoming The incoming particle * @param outgoing The decay products * @param objname a string containing the default path of the Decayer object */ string DecayerClassName(tcPDPtr incoming, const OrderedParticles & outgoing, string & objname) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FourBodyDecayConstructor & operator=(const FourBodyDecayConstructor &) = delete; private: /** * Option for the inclusion of intermediates */ unsigned int interOpt_; /** * How to treat the widths of the intermediate particles */ unsigned int widthOpt_; /** * Particles to override the default list */ vector particles_; /** * Types of particles */ bool particleType_; }; } #endif /* THEPEG_FourBodyDecayConstructor_H */ diff --git a/PDF/MPIPDF.cc b/PDF/MPIPDF.cc --- a/PDF/MPIPDF.cc +++ b/PDF/MPIPDF.cc @@ -1,85 +1,82 @@ // -*- C++ -*- // // MPIPDF.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MPIPDF class. // #include "MPIPDF.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include using namespace Herwig; using namespace ThePEG; -MPIPDF::~MPIPDF() {} - - IBPtr MPIPDF::clone() const { return new_ptr(*this); } IBPtr MPIPDF::fullclone() const { return new_ptr(*this); } bool MPIPDF::canHandleParticle(tcPDPtr particle) const { assert(thePDF); return thePDF->canHandleParticle(particle); } cPDVector MPIPDF::partons(tcPDPtr particle) const { assert(thePDF); return thePDF->partons(particle); } double MPIPDF::xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const { // returns the density with removed valence part. assert(thePDF); return thePDF->xfsx(particle, parton, partonScale, x, eps, particleScale); } double MPIPDF::xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const { // Here we should return the actual valence density. assert(thePDF); return thePDF->xfvx(particle, parton, partonScale, x, eps, particleScale); } void MPIPDF::persistentOutput(PersistentOStream & os) const { os << thePDF; } void MPIPDF::persistentInput(PersistentIStream & is, int) { is >> thePDF; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMPIPDF("Herwig::MPIPDF", "HwShower.so"); void MPIPDF::Init() { static ClassDocumentation documentation ("The MPIPDF class wraps other PDF classes to provide " "sea-quark-only PDFs."); } diff --git a/PDF/MPIPDF.h b/PDF/MPIPDF.h --- a/PDF/MPIPDF.h +++ b/PDF/MPIPDF.h @@ -1,156 +1,147 @@ // -*- C++ -*- // // MPIPDF.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MPIPDF_H #define HERWIG_MPIPDF_H // // This is the declaration of the MPIPDF class. // #include "ThePEG/PDF/PDFBase.h" #include "MPIPDF.fh" namespace Herwig { using namespace ThePEG; /** * The MPIPDF class defines * a modified pdf which uses an existing pdf object to add * modifications like removing the valence part of it, which * is needed in the backward evolution of secondary scatters. * * \author Manuel B\"ahr * * @see \ref MPIPDFInterfaces "The interfaces" * defined for MPIPDF. */ class MPIPDF: public PDFBase { public: - /** @name Standard constructors and destructors. */ - //@{ - /** * The constructor which takes a PDF object as argument, to work with. */ MPIPDF(cPDFPtr orig = cPDFPtr()) : thePDF(orig) {} - /** - * The destructor. - */ - virtual ~MPIPDF(); - //@} - public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this PDF can handle the extraction of partons from * the given \a particle. */ virtual bool canHandleParticle(tcPDPtr particle) const; /** * Return the partons which this PDF may extract from the given * \a particle. */ virtual cPDVector partons(tcPDPtr particle) const; /** * The density. Return the pdf for the given \a parton inside the * given \a particle for the virtuality \a partonScale and momentum * fraction \a x. The \a particle is assumed to have a virtuality \a * particleScale. For MPIPDF, only the sea quark densities * are included here! */ virtual double xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const; /** * The valence density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and momentum fraction \a x. The \a particle is * assumed to have a virtuality \a particleScale. If not overidden * by a sub class this implementation will assume that the * difference between a quark and anti-quark distribution is due do * valense quarks, but return zero for anything else. */ virtual double xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MPIPDF & operator=(const MPIPDF &) = delete; /** * pointer to the underlying ThePEG::PDFBase object, we are modifying. */ cPDFPtr thePDF; }; } #endif /* HERWIG_MPIPDF_H */ diff --git a/PDF/MinBiasPDF.h b/PDF/MinBiasPDF.h --- a/PDF/MinBiasPDF.h +++ b/PDF/MinBiasPDF.h @@ -1,161 +1,146 @@ // -*- C++ -*- // // MinBiasPDF.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MinBiasPDF_H #define HERWIG_MinBiasPDF_H // // This is the declaration of the MinBiasPDF class. // #include "ThePEG/PDF/PDFBase.h" #include "MinBiasPDF.fh" namespace Herwig { using namespace ThePEG; /** * The MinBiasPDF class defines * a modified pdf which uses an existing pdf object to add * modifications like removing the valence part of it, which * is needed in the backward evolution of secondary scatters. * * \author Manuel B\"ahr * * @see \ref MinBiasPDFInterfaces "The interfaces" * defined for MinBiasPDF. */ class MinBiasPDF: public PDFBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MinBiasPDF() : thePDF(PDFPtr()) {} - /** - * The copy constructor. - */ - MinBiasPDF(const MinBiasPDF & x) : - PDFBase(x), thePDF(x.thePDF) {} - - /** - * The destructor. - */ - virtual ~MinBiasPDF() {} - - //@} - public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this PDF can handle the extraction of partons from * the given \a particle. */ virtual bool canHandleParticle(tcPDPtr particle) const; /** * Return the partons which this PDF may extract from the given * \a particle. */ virtual cPDVector partons(tcPDPtr particle) const; /** * The density. Return the pdf for the given \a parton inside the * given \a particle for the virtuality \a partonScale and momentum * fraction \a x. The \a particle is assumed to have a virtuality \a * particleScale. */ virtual double xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps=0.0, Energy2 particleScale = ZERO) const; /** * The valence density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and momentum fraction \a x. The \a particle is * assumed to have a virtuality \a particleScale. If not overidden * by a sub class this implementation will assume that the * difference between a quark and anti-quark distribution is due do * valense quarks, but return zero for anything else. */ virtual double xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps=0.0, Energy2 particleScale = ZERO) const; //@} /** return the underlying PDFBase pointer*/ tcPDFPtr originalPDF() const {return thePDF;} 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 { return new_ptr(*this); } /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const { return new_ptr(*this); } //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MinBiasPDF & operator=(const MinBiasPDF &) = delete; /** * pointer to the underlying ThePEG::PDFBase object, we are modifying. */ PDFPtr thePDF; }; } #endif /* HERWIG_MinBiasPDF_H */ diff --git a/PDF/SatPDF.cc b/PDF/SatPDF.cc --- a/PDF/SatPDF.cc +++ b/PDF/SatPDF.cc @@ -1,118 +1,116 @@ // -*- C++ -*- // // SatPDF.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SatPDF class. // #include "SatPDF.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "SatPDF.tcc" #endif #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include using namespace Herwig; using namespace ThePEG; -SatPDF::~SatPDF() {} - bool SatPDF::canHandleParticle(tcPDPtr particle) const { assert(thePDF); return thePDF->canHandleParticle(particle); } cPDVector SatPDF::partons(tcPDPtr particle) const { assert(thePDF); return thePDF->partons(particle); } double SatPDF::xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const { assert(thePDF); double xUsed(x); if( x < theX0 ) xUsed = theX0; double pdf(thePDF->xfx(particle, parton, partonScale, xUsed, eps, particleScale)); if( x < theX0 ) pdf *= pow(x/theX0, theExp); return pdf; } double SatPDF::xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const { // Here we should return the actual valence density. assert(thePDF); double xUsed(x); if( x < theX0 ) xUsed = theX0; double pdf(thePDF->xfvx(particle, parton, partonScale, xUsed, eps, particleScale)); if( x < theX0 ) pdf *= pow(x/theX0, theExp); return pdf; } void SatPDF::persistentOutput(PersistentOStream & os) const { os << thePDF << theX0 << theExp; } void SatPDF::persistentInput(PersistentIStream & is, int) { is >> thePDF >> theX0 >> theExp; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSatPDF("Herwig::SatPDF", "HwSatPDF.so"); void SatPDF::Init() { static ClassDocumentation documentation ("SatPDF is used to modify any given parton density for small values of x. That can be used to mimic saturation effects."); static Reference interfacePDF ("PDF", "pointer to the pdf, which will be modified", &SatPDF::thePDF, false, false, true, false); static Parameter interfaceX0 ("X0", "For x values below this one the parametrisation: f(x) = f(x0) * (x/x0)**exp is used", &SatPDF::theX0, 1.E-4, 0.0, 1.0, true, false, Interface::limited); static Parameter interfaceExp ("Exp", "For x values below X0 the parametrisation: f(x) = f(x0) * (x/x0)**exp is used", &SatPDF::theExp, 0.0, -10.0, 10.0, true, false, Interface::limited); } diff --git a/PDF/SatPDF.h b/PDF/SatPDF.h --- a/PDF/SatPDF.h +++ b/PDF/SatPDF.h @@ -1,172 +1,158 @@ // -*- C++ -*- // // SatPDF.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_SatPDF_H #define HERWIG_SatPDF_H // // This is the declaration of the SatPDF class. // #include "ThePEG/PDF/PDFBase.h" namespace Herwig { using namespace ThePEG; /** * The SatPDF class defines * a modified pdf which uses an existing pdf object to add * modifications like removing the valence part of it, which * is needed in the backward evolution of secondary scatters. * * \author Manuel B\"ahr * * @see \ref SatPDFInterfaces "The interfaces" * defined for SatPDF. */ class SatPDF: public PDFBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ inline SatPDF() : thePDF(PDFPtr()), theX0(1E-4), theExp(0.0) {} - /** - * The copy constructor. - */ - inline SatPDF(const SatPDF & x) : - PDFBase(x), thePDF(x.thePDF), theX0(x.theX0), theExp(x.theExp) {} - - /** - * The destructor. - */ - virtual ~SatPDF(); - //@} - public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this PDF can handle the extraction of partons from * the given \a particle. */ virtual bool canHandleParticle(tcPDPtr particle) const; /** * Return the partons which this PDF may extract from the given * \a particle. */ virtual cPDVector partons(tcPDPtr particle) const; /** * The density. Return the pdf for the given \a parton inside the * given \a particle for the virtuality \a partonScale and momentum * fraction \a x. The \a particle is assumed to have a virtuality \a * particleScale. */ virtual double xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps=0.0, Energy2 particleScale = ZERO) const; /** * The valence density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and momentum fraction \a x. The \a particle is * assumed to have a virtuality \a particleScale. If not overidden * by a sub class this implementation will assume that the * difference between a quark and anti-quark distribution is due do * valense quarks, but return zero for anything else. */ virtual double xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps=0.0, Energy2 particleScale = ZERO) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ 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); } //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SatPDF & operator=(const SatPDF &) = delete; /** * pointer to the underlying ThePEG::PDFBase object, we are modifying. */ PDFPtr thePDF; /** * x from where the extrapolation f(x) = f(theX0) * (x/theX0)**theExp * is used for the pdf's. */ double theX0; /** * the exponent of the pdf extrapolation for small x (x < theX0). */ double theExp; }; } #ifndef HERWIG_TEMPLATES_IN_CC_FILE // #include "SatPDF.tcc" #endif #endif /* HERWIG_SatPDF_H */ diff --git a/Sampling/BinSampler.cc b/Sampling/BinSampler.cc --- a/Sampling/BinSampler.cc +++ b/Sampling/BinSampler.cc @@ -1,730 +1,728 @@ // -*- C++ -*- // // BinSampler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the BinSampler class. // #include "BinSampler.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 "ThePEG/Repository/Repository.h" #include "ThePEG/Utilities/ColourOutput.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/Utilities/Progress.h" #include "GeneralSampler.h" using namespace Herwig; BinSampler::BinSampler() : MultiIterationStatistics(), theBias(1.), theWeighted(false), theInitialPoints(1000000), theNIterations(1), theEnhancementFactor(1.0), theNonZeroInPresampling(false), theHalfPoints(false), theMaxNewMax(30), theReferenceWeight(1.0), theBin(-1), theInitialized(false), theRemapperPoints(0), theRemapChannelDimension(false), theLuminosityMapperBins(0), theGeneralMapperBins(0), theRemapperMinSelection(0.00001), theIntegrated(false), theRemappersFilled(false), theHasGrids(false), theKappa(1.){} -BinSampler::~BinSampler() {} - IBPtr BinSampler::clone() const { return new_ptr(*this); } IBPtr BinSampler::fullclone() const { return new_ptr(*this); } void BinSampler::sampler(Ptr::tptr s) { theSampler = s; } Ptr::tptr BinSampler::sampler() const { return theSampler; } string BinSampler::process() const { ostringstream os(""); const StandardEventHandler& eh = *theEventHandler; const StandardXComb& xc = *eh.xCombs()[theBin]; os << xc.matrixElement()->name() << " : "; os << xc.mePartonData()[0]->PDGName() << " " << xc.mePartonData()[1]->PDGName() << " -> "; for ( cPDVector::const_iterator pid = xc.mePartonData().begin() + 2; pid != xc.mePartonData().end(); ++pid ) os << (**pid).PDGName() << " "; return os.str(); } string BinSampler::shortprocess() const { ostringstream os(""); const StandardEventHandler& eh = *theEventHandler; const StandardXComb& xc = *eh.xCombs()[theBin]; os << xc.mePartonData()[0]->id() << " " << xc.mePartonData()[1]->id() << " : "; for ( cPDVector::const_iterator pid = xc.mePartonData().begin() + 2; pid != xc.mePartonData().end(); ++pid ) os << (**pid).id() << " "; return os.str(); } string BinSampler::id() const { ostringstream os(""); const StandardEventHandler& eh = *theEventHandler; const StandardXComb& xc = *eh.xCombs()[theBin]; string name = xc.matrixElement()->name(); string::size_type i = name.find_first_of("["); string nameFirst = name.substr(0,i); i = name.find_first_of("]"); string nameSecond = name.substr(i+1); os << nameFirst << nameSecond << ":"; for ( cPDVector::const_iterator pid = xc.mePartonData().begin(); pid != xc.mePartonData().end(); ++pid ) os << (**pid).id() << (pid != (--xc.mePartonData().end()) ? "," : ""); return os.str(); } double BinSampler::evaluate(vector p, bool remap) { double w = 1.0; if ( remap && !remappers.empty() ) { for ( size_t k = 0; k < p.size(); ++k ) { map::const_iterator r = remappers.find(k); if ( r != remappers.end() ) { pair f = r->second.generate(p[k]); p[k] = f.first; w /= f.second; } } } try { w *= eventHandler()->dSigDR(p) / nanobarn; } catch (Veto&) { w = 0.0; } catch (...) { throw; } if (randomNumberString()!="") for ( size_t k = 0; k < p.size(); ++k ) { RandomNumberHistograms[RandomNumberIndex(id(),k)].first.book(p[k],w); RandomNumberHistograms[RandomNumberIndex(id(),k)].second+=w; } return w; } double BinSampler::generate() { double w = 1.; for ( size_t k = 0; k < lastPoint().size(); ++k ) { lastPoint()[k] = UseRandom::rnd(); } try { w = evaluate(lastPoint()); } catch (Veto&) { w = 0.0; } catch (...) { throw; } if ( !weighted() && initialized() ) { double p = min(abs(w),kappa()*referenceWeight())/(kappa()*referenceWeight()); double sign = w >= 0. ? 1. : -1.; if ( p < 1 && UseRandom::rnd() > p ) w = 0.; else w = sign*max(abs(w),referenceWeight()*kappa()); } select(w); if ( w != 0.0 ) accept(); assert(kappa()==1.||sampler()->almostUnweighted()); return w; } void BinSampler::fillRemappers(bool progress) { if ( remappers.empty() ) return; unsigned long nanPoints = 0; progress_display* progressBar = nullptr; if ( progress ) { Repository::clog() << "warming up " << ANSI::red << process() << ANSI::reset; progressBar = new progress_display{ theRemapperPoints, Repository::clog() }; } unsigned long countzero =0; for ( unsigned long k = 0; k < theRemapperPoints; ++k,++countzero ) { if (countzero>=theRemapperPoints)break; double w = 1.; for ( size_t j = 0; j < lastPoint().size(); ++j ) { lastPoint()[j] = UseRandom::rnd(); } try { w = evaluate(lastPoint(),false); } catch (Veto&) { w = 0.0; } catch (...) { throw; } if ( ! isfinite(w) ) ++nanPoints; if ( theNonZeroInPresampling && w==0. ){ k--; continue; } if ( w != 0.0 ) { countzero=0; for ( map::iterator r = remappers.begin(); r != remappers.end(); ++r ) r->second.fill(lastPoint()[r->first],w); } if ( progressBar ) ++(*progressBar); } if ( progressBar ) { delete progressBar; } if ( nanPoints ) { Repository::clog() << "Warning: " << nanPoints << " out of " << theRemapperPoints << " points with nan or inf " << "weight encountered while filling remappers.\n" << flush; } } void BinSampler::saveIntegrationData() const { XML::Element stats = MultiIterationStatistics::toXML(); stats.appendAttribute("process",id()); sampler()->grids().append(stats); } void BinSampler::readIntegrationData() { if ( theIntegrated ) return; bool haveStats = false; list::iterator sit = sampler()->grids().children().begin(); for ( ; sit != sampler()->grids().children().end(); ++sit ) { if ( sit->type() != XML::ElementTypes::Element ) continue; if ( sit->name() != "MultiIterationStatistics" ) continue; string proc; sit->getFromAttribute("process",proc); if ( proc == id() ) { haveStats = true; break; } } if ( haveStats ) { MultiIterationStatistics::fromXML(*sit); sampler()->grids().erase(sit); theIntegrated = true; } else { throw Exception() << "\n---------------------------------------------------\n\n" << "Expected integration data.\n\n" << "* When using the build setup make sure the integrate command has been run.\n\n" << "* Check the [EventGenerator].log file for further information.\n\n" << "* Make sure that the Herwig folder can be found and that it contains a HerwigGrids.xml file.\n\n" << "* If you have split the integration jobs, make sure that each integration job was finished.\n" << " Afterwards delete the global HerwigGrids.xml file in the Herwig subfolder\n" << " to automatically create an updated version of the global HerwigGrids.xml file.\n\n" << "---------------------------------------------------\n" << Exception::abortnow; } } void BinSampler::saveRemappers() const { if ( remappers.empty() ) return; XML::Element maps(XML::ElementTypes::Element,"Remappers"); maps.appendAttribute("process",id()); for ( map::const_iterator r = remappers.begin(); r != remappers.end(); ++r ) { XML::Element rmap = r->second.toXML(); rmap.appendAttribute("dimension",r->first); maps.append(rmap); } sampler()->grids().append(maps); } void BinSampler::setupRemappers(bool progress) { if ( !theRemapperPoints ) return; if ( theRemappersFilled ) return; lastPoint().resize(dimension()); bool haveGrid = false; list::iterator git = sampler()->grids().children().begin(); for ( ; git != sampler()->grids().children().end(); ++git ) { if ( git->type() != XML::ElementTypes::Element ) continue; if ( git->name() != "Remappers" ) continue; string proc; git->getFromAttribute("process",proc); if ( proc == id() ) { haveGrid = true; break; } } if ( haveGrid ) { for ( list::iterator cit = git->children().begin(); cit != git->children().end(); ++cit ) { if ( cit->type() != XML::ElementTypes::Element ) continue; if ( cit->name() != "Remapper" ) continue; size_t dimension = 0; cit->getFromAttribute("dimension",dimension); remappers[dimension].fromXML(*cit); } sampler()->grids().erase(git); } if ( !haveGrid ) { const StandardEventHandler& eh = *eventHandler(); const StandardXComb& xc = *eh.xCombs()[bin()]; const pair& pdims = xc.partonDimensions(); set remapped; if ( theRemapChannelDimension && xc.diagrams().size() > 1 && dimension() > pdims.first + pdims.second ) { remappers[pdims.first] = Remapper(xc.diagrams().size(),theRemapperMinSelection,false); remapped.insert(pdims.first); } if ( theLuminosityMapperBins > 1 && dimension() >= pdims.first + pdims.second ) { for ( int n = 0; n < pdims.first; ++n ) { remappers[n] = Remapper(theLuminosityMapperBins,theRemapperMinSelection,true); remapped.insert(n); } for ( int n = dimension() - pdims.second; n < dimension(); ++n ) { remappers[n] = Remapper(theLuminosityMapperBins,theRemapperMinSelection,true); remapped.insert(n); } } if ( theGeneralMapperBins > 1 ) { for ( int n = 0; n < dimension(); n++ ) { if ( remapped.find(n) == remapped.end() ) { remappers[n] = Remapper(theGeneralMapperBins,theRemapperMinSelection,true); remapped.insert(n); } } } fillRemappers(progress); for ( map::iterator r = remappers.begin(); r != remappers.end(); ++r ) { r->second.finalize(); } } theRemappersFilled = true; } void BinSampler::runIteration(unsigned long points, bool progress) { progress_display* progressBar = 0; if ( progress ) { Repository::clog() << "integrating " << ANSI::red << process()<< ANSI::reset << ", iteration " << (iterations().size() + 1); progressBar = new progress_display(points,Repository::clog()); } double w=0.; double maxweight=0; int numlastmax=0; unsigned long countzero =0; int newmax=0; for ( unsigned long k = 0; k < points; ++k,++countzero ) { if (countzero>=points)break; w=abs(generate()); if(theNonZeroInPresampling && w==0.0){ k--; continue; } if (w!=0.0) countzero =0; numlastmax++; if (theHalfPoints&&maxweighttheMaxNewMax){ throw Exception() << "\n---------------------------------------------------\n\n" << "To many new Maxima.\n\n" << "* With the option:\n\n" << "* set Sampler:BinSampler:HalfPoints Yes\n\n" << "* for every new maximum weight found until the half of the persampling points\n" << "* the counter is set to zero. We count the number of new maxima.\n" << "* You have reached: "<grids().children().empty() ) { nIterations(1); } if ( !integrated() ) { unsigned long points = initialPoints(); for ( unsigned long k = 0; k < nIterations(); ++k ) { runIteration(points,progress); if ( k < nIterations() - 1 ) { points = (unsigned long)(points*enhancementFactor()); adapt(); nextIteration(); } } } isInitialized(); } void BinSampler::finalize(bool){ if (theRandomNumbers!="") for ( map >:: const_iterator b = RandomNumberHistograms.begin(); b != RandomNumberHistograms.end(); ++b ) { b->second.first.dump(randomNumberString(), b->first.first,shortprocess(),b->first.second); } } BinSampler::RandomNumberHistogram:: RandomNumberHistogram(double low, double up, unsigned int nbins) : lower(low) { nbins = nbins + 1; double c = up / (nbins-1.); for ( unsigned int k = 1; k < nbins; ++k ) { bins[low+c*k] = 0.; binsw1[low+c*k] = 0.; } } void BinSampler::RandomNumberHistogram:: dump(const std::string& folder,const std::string& prefix, const std::string& process, const int NR) const { ostringstream fname(""); std::string prefix2; std::string prefix3=prefix; std::remove_copy(prefix.begin(), prefix.end(), std::back_inserter(prefix2), '.'); prefix3=prefix2;prefix2.clear(); std::remove_copy(prefix3.begin(), prefix3.end(), std::back_inserter(prefix2), ':'); prefix3=prefix2;prefix2.clear(); std::remove_copy(prefix3.begin(), prefix3.end(), std::back_inserter(prefix2), ','); fname << "RN-"<< NR ; ofstream out((folder+"/"+prefix2+fname.str()+".dat").c_str()); double sumofweights=0.; for ( map::const_iterator b = bins.begin();b != bins.end(); ++b ) sumofweights+=b->second; double sumofweights2=0.; for ( map::const_iterator b = binsw1.begin();b != binsw1.end(); ++b ) sumofweights2+=b->second; map::const_iterator b2 = binsw1.begin(); if ( sumofweights == 0 ) { cerr << "Not enough statistic accumulated for " << process << " skipping random number diagnostic.\n" << flush; return; } for ( map::const_iterator b = bins.begin(); b != bins.end(); ++b, ++b2) { out << " " << b->first << " " << b->second/sumofweights*100. << " " << b2->second/sumofweights2*100. << "\n" << flush; } double xmin = -0.01; double xmax = 1.01; ofstream gpout((folder+"/"+prefix2+fname.str()+".gp").c_str()); gpout << "set terminal epslatex color solid\n" << "set output '" << prefix2+fname.str() << "-plot.tex'\n" << "set xrange [" << xmin << ":" << xmax << "]\n"; gpout << "set xlabel 'rn "<> theBias >> theWeighted >> theInitialPoints >> theNIterations >> theEnhancementFactor >> theNonZeroInPresampling >> theHalfPoints >> theMaxNewMax >> theReferenceWeight >> theBin >> theInitialized >> theLastPoint >> theEventHandler >> theSampler >> theRandomNumbers >> theRemapperPoints >> theRemapChannelDimension >> theLuminosityMapperBins >> theGeneralMapperBins >> theKappa; } // *** 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 describeHerwigBinSampler("Herwig::BinSampler", "HwSampling.so"); void BinSampler::Init() { static ClassDocumentation documentation ("BinSampler samples XCombs bins. This default implementation performs flat MC integration."); static Parameter interfaceInitialPoints ("InitialPoints", "The number of points to use for initial integration.", &BinSampler::theInitialPoints, 1000000, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceNIterations ("NIterations", "The number of iterations to perform initially.", &BinSampler::theNIterations, 1, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceEnhancementFactor ("EnhancementFactor", "The enhancement factor for the number of points in the next iteration.", &BinSampler::theEnhancementFactor, 2.0, 1.0, 0, false, false, Interface::lowerlim); static Switch interfaceNonZeroInPresampling ("NonZeroInPresampling", "Switch on to count only non zero weights in presampling.", &BinSampler::theNonZeroInPresampling, true, false, false); static SwitchOption interfaceNonZeroInPresamplingYes (interfaceNonZeroInPresampling, "Yes", "", true); static SwitchOption interfaceNonZeroInPresamplingNo (interfaceNonZeroInPresampling, "No", "", false); static Switch interfaceHalfPoints ("HalfPoints", "Switch on to reset the counter of points if new maximumis was found in the first 1/2 points.", &BinSampler::theHalfPoints, true, false, false); static SwitchOption interfaceHalfPointsYes (interfaceHalfPoints, "Yes", "", true); static SwitchOption interfaceHalfPointsNo (interfaceHalfPoints, "No", "", false); static Parameter interfaceMaxNewMax ("MaxNewMax", "The maximum number of allowed new maxima in combination with the HalfPoints option.", &BinSampler::theMaxNewMax, 30, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceRandomNumbers ("RandomNumbers", "Prefix for distributions of the random numbers.", &BinSampler::theRandomNumbers, "", false, false); static Parameter interfaceRemapperPoints ("RemapperPoints", "The number of points to be used for filling remappers.", &BinSampler::theRemapperPoints, 10000, 0, 0, false, false, Interface::lowerlim); static Switch interfaceRemapChannelDimension ("RemapChannelDimension", "Switch on remapping of the channel dimension.", &BinSampler::theRemapChannelDimension, true, false, false); static SwitchOption interfaceRemapChannelDimensionYes (interfaceRemapChannelDimension, "Yes", "", true); static SwitchOption interfaceRemapChannelDimensionNo (interfaceRemapChannelDimension, "No", "", false); static Parameter interfaceLuminosityMapperBins ("LuminosityMapperBins", "The number of bins to be used for remapping parton luminosities.", &BinSampler::theLuminosityMapperBins, 0, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceGeneralMapperBins ("GeneralMapperBins", "The number of bins to be used for remapping other phase space dimensions.", &BinSampler::theGeneralMapperBins, 0, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceRemapperMinSelection ("RemapperMinSelection", "The minimum bin selection probability for remappers.", &BinSampler::theRemapperMinSelection, 0.00001, 0.0, 1.0, false, false, Interface::limited); static Parameter interfaceKappa ("Kappa", "In AllmostUnweighted mode unweight to Kappa ReferenceWeight.", &BinSampler::theKappa, 1., 0.000001, 1.0, false, false, Interface::limited); } diff --git a/Sampling/BinSampler.h b/Sampling/BinSampler.h --- a/Sampling/BinSampler.h +++ b/Sampling/BinSampler.h @@ -1,592 +1,584 @@ // -*- C++ -*- // // BinSampler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_BinSampler_H #define Herwig_BinSampler_H // // This is the declaration of the BinSampler class. // #include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Repository/UseRandom.h" #include "MultiIterationStatistics.h" #include "Remapper.h" namespace Herwig { using namespace ThePEG; class GeneralSampler; /** * \ingroup Matchbox * \author Simon Platzer * * \brief BinSampler samples XCombs bins. This default implementation * performs flat MC integration. * * @see \ref BinSamplerInterfaces "The interfaces" * defined for BinSampler. */ class BinSampler: public Herwig::MultiIterationStatistics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ BinSampler(); - /** - * The destructor. - */ - virtual ~BinSampler(); - //@} - public: /** * Clone this object. */ Ptr::ptr cloneMe() const { return dynamic_ptr_cast::ptr>(clone()); } public: /** * Evaluate the cross section */ double evaluate(vector p, bool remap = true); /** * Return the bias with which this sampler is selected. The sampler * needs to divide out this bias in its weight calculation. */ double bias() const { return theBias; } /** * Set the bias with which this sampler is selected. */ void bias(double b) { theBias = b; } /** * Set the event handler */ void eventHandler(tStdEHPtr eh) { theEventHandler = eh; } /** * Return the event handler */ tStdEHPtr eventHandler() const { return theEventHandler; } /** * Set the containing sampler */ void sampler(Ptr::tptr); /** * Get the containing sampler */ Ptr::tptr sampler() const; /** * Return the bin */ int bin() const { return theBin; } /** * Set the bin */ void bin(int b) { theBin = b; } /** * Return a string describing the process handled by this sampler. */ string process() const; /** * Return a short string describing the process handled by this sampler. */ string shortprocess() const; /** * Return a string identifying the process handled by this sampler. */ string id() const; /** * Return the last generated point. */ const vector& lastPoint() const { return theLastPoint; } /** * Access the last generated point. */ vector& lastPoint() { return theLastPoint; } /** * Return the reference weight to be used */ double referenceWeight() const { return theReferenceWeight; } /** * Set the reference weight to be used */ void referenceWeight(double w) { theReferenceWeight = w; } /** * Return true, if this sampler can provide unweighted events; if * the proposal density is not an overestimate, weights larger than * one can be generated, the handling of these points being subject * to the GeneralSampler class. */ virtual bool canUnweight() const { return true; } /** * Return true, if this sampler adapts on the fly while generating * events. Cross sections in the GeneralSampler class are calculated * from adding up the cross sections quoted by individual samplers. */ virtual bool adaptsOnTheFly() const { return false; } /** * If this sampler features a compensation algorithm, return true if * more events need to be generated to finish the compensation. */ virtual bool compensating() const { return false; } /** * Return true, if weighted events should be generated */ bool weighted() const { return theWeighted; } /** * Indicate that weighted events should be generated */ void doWeighted(bool yes = true) { theWeighted = yes; } /** * Exception to be thrown if cross section information should be updated. */ struct NextIteration {}; /** * Generate the next point and return its weight; store the point in * lastPoint(). */ virtual double generate(); /** * Fill and finalize the remappers present */ void fillRemappers(bool progress); /** * Write remappers to grid file */ void saveRemappers() const; /** * Write integration data to grid files */ void saveIntegrationData() const; /** * Save grid data */ virtual void saveGrid() const {} /** * Read integration data from grid files */ void readIntegrationData(); /** * Read remappers from grid file */ void setupRemappers(bool progress); /** * Run a single iteration of n points, optionally printing a * progress bar to cout. Calls generate n times. */ void runIteration(unsigned long n, bool progress); /** * Adapt this sampler after an iteration has been run */ virtual void adapt() {} /** * Initialize this bin sampler. This default version calls runIteration. */ virtual void initialize(bool progress); /** * Return true, if this sampler has already been initialized. */ bool initialized() const { return theInitialized; } /** * Indicate that this sampler has already been initialized. */ void isInitialized() { theInitialized = true; } /** * Return true, if integration has already been performed */ bool integrated() const { return theIntegrated; } /** * Return true, if remappers have been set up */ bool remappersFilled() const { return theRemappersFilled; } /** * Return true, if grid data exists for this sampler. */ virtual bool existsGrid() const { return false; } /** * Return true, if this sampler has already read grid data. */ bool hasGrids() const { return theHasGrids; } /** * Indicate that this sampler has already read grid data. */ void didReadGrids() { theHasGrids = true; } /** * Finalize this sampler. */ virtual void finalize(bool); /** * Return the total integrated cross section determined from the * Monte Carlo sampling so far. */ virtual CrossSection integratedXSec() const { return averageWeight()*nanobarn; } /** * Return the error on the total integrated cross section determined * from the Monte Carlo sampling so far. */ virtual CrossSection integratedXSecErr() const { return sqrt(abs(averageWeightVariance()))*nanobarn; } /** * Define the key for the collinear subtraction data. */ struct RandomNumberHistogram { /** * The lower bound */ double lower; /** * The bins, indexed by upper bound. */ map bins; map binsw1; /** * Constructor */ RandomNumberHistogram(double low = 0.0, double up = 1., unsigned int nbins = 20); /** * Book an event. */ void book(double inv, double weight) { map::iterator b = bins.upper_bound(inv); if ( b == bins.end() ) return; b->second = b->second+weight; map::iterator b2 = binsw1.upper_bound(inv); if ( b2 == binsw1.end() ) return; b2->second = b2->second+1.; } /** * Write to file given name and invariant. */ void dump(const std::string& folder,const std::string& prefix, const std::string& process,const int NR)const; }; typedef pair RandomNumberIndex; map > RandomNumberHistograms; public: /** * Return the dimension. */ int dimension() const { return theEventHandler->nDim(bin()); } /** * Return the number of points to be used for initial integration. */ unsigned long initialPoints() const { return theInitialPoints; } /** * Set the number of points to be used for initial integration. */ void initialPoints(unsigned long n) { theInitialPoints = n; } /** * Return the number of iterations to be considered for initialization. */ size_t nIterations() const { return theNIterations; } /** * Set the number of iterations to be considered for initialization. */ void nIterations(size_t n) { theNIterations = n; } /** * Set the factor to enhance the number of points for the next * iteration. */ void enhancementFactor(double f) { theEnhancementFactor = f; } /** * Return the factor to enhance the number of points for the next * iteration. */ double enhancementFactor() const { return theEnhancementFactor; } /** * Return the folder for the random number plots. */ string randomNumberString() const {return theRandomNumbers;} /** * In the AlmostUnweighted mode we do not need to unweight * the events to the reference weight. * Kappa reduces effectivly the reference weight. * This can be used for processes, where unweighting * is hardly feasable. */ double kappa() const {return theKappa;} 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: /** * The bias with which this sampler is selected. */ double theBias; /** * True, if weighted events should be generated */ bool theWeighted; /** * The number of points to use for initial integration. */ unsigned long theInitialPoints; /** * The number of iterations to be considered for initialization. */ size_t theNIterations; /** * Factor to enhance the number of points for the next iteration. */ double theEnhancementFactor; /** * Switch to count only non zero weights in presampling. */ bool theNonZeroInPresampling; /** * Switch to require that we get half of the points * in each iteration below the maximum weight of the iteration. */ bool theHalfPoints; /** * The maximum number of allowed new maxima, * in combination with HalfPoints, in order to prevent unstable * processes. */ int theMaxNewMax; /** * The reference weight to be used */ double theReferenceWeight; /** * The bin to be sampled. */ int theBin; /** * Wether or not this sampler has already been initialized. */ bool theInitialized; /** * The last generated point. */ vector theLastPoint; /** * The event handler to be used. */ tStdEHPtr theEventHandler; /** * The containing sampler */ Ptr::tptr theSampler; /** * Folder for the random number plots. */ string theRandomNumbers; /** * Remapper objects indexed by dimension */ map remappers; /** * The number of points to be used for initial filling of the remappers */ unsigned long theRemapperPoints; /** * True if channels should get a remapper */ bool theRemapChannelDimension; /** * The number of bins to be used for luminosity dimensions */ unsigned long theLuminosityMapperBins; /** * The number of bins to be used for any other dimension */ unsigned long theGeneralMapperBins; /** * The minimum selection probability for remapper bins */ double theRemapperMinSelection; /** * True, if integration has already be performed */ bool theIntegrated; /** * True, if remappers have been set up */ bool theRemappersFilled; /** * True, if this sampler has already read grid data. */ bool theHasGrids; /** * In the AlmostUnweighted mode we do not need to unweight * the events to the reference weight. * Kappa reduces effectivly the reference weight. * This can be used for processes, where unweighting * is hardly feasable. */ double theKappa; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ BinSampler & operator=(const BinSampler &) = delete; }; } #endif /* Herwig_BinSampler_H */ diff --git a/Shower/Dipole/AlphaS/alpha_s.cc b/Shower/Dipole/AlphaS/alpha_s.cc --- a/Shower/Dipole/AlphaS/alpha_s.cc +++ b/Shower/Dipole/AlphaS/alpha_s.cc @@ -1,236 +1,234 @@ // -*- C++ -*- // couplings/alpha_s.cc is part of matchbox // (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de #include "alpha_s.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/PDT/ParticleData.h" using namespace matchbox; alpha_s::alpha_s() : AlphaSBase(), min_active_flavours_(3), max_active_flavours_(6), matched_(false), scale_factor_(1.), quark_masses_squared_(), lambda_squared_(), alpha_s_in_(.1176), scale_in_(91.1876*GeV), lambda_range_(1.*MeV2,1.e6*MeV2), fixed_(false) { } -alpha_s::~alpha_s() {} - void alpha_s::persistentOutput(PersistentOStream & os) const { os << min_active_flavours_ << max_active_flavours_ << matched_ << scale_factor_; for (size_t f = 0; f < 7; ++f) os << ounit(quark_masses_squared_[f],MeV2) << ounit(lambda_squared_[f],MeV2); for (size_t f = 0; f < 6; ++f) os << ounit(nfvector[f],MeV2); os << alpha_s_in_ << ounit(scale_in_,GeV) << ounit(lambda_range_.first,MeV2) << ounit(lambda_range_.second,MeV2) << fixed_; } void alpha_s::persistentInput(PersistentIStream & is, int) { is >> min_active_flavours_ >> max_active_flavours_ >> matched_ >> scale_factor_; for (size_t f = 0; f < 7; ++f) is >> iunit(quark_masses_squared_[f],MeV2) >> iunit(lambda_squared_[f],MeV2); for (size_t f = 0; f < 6; ++f) is >> iunit(nfvector[f],MeV2); is >> alpha_s_in_ >> iunit(scale_in_,GeV) >> iunit(lambda_range_.first,MeV2) >> iunit(lambda_range_.second,MeV2) >> fixed_; } AbstractClassDescription alpha_s::initalpha_s; // Definition of the static class description member. void alpha_s::Init() { static ClassDocumentation documentation ("Base class for strong coupoling as used in matchbox"); static Parameter interfacemin_active_flavours ("min_active_flavours", "Minimum number of active flavours", &alpha_s::min_active_flavours_, 3, 0, 6, true, false, Interface::limited); static Parameter interfacemax_active_flavours ("max_active_flavours", "Maximum number of active flavours", &alpha_s::max_active_flavours_, 6, 0, 6, true, false, Interface::limited); static Parameter interfaceinput_alpha_s ("input_alpha_s", "alpha_s value at input scale", &alpha_s::alpha_s_in_, .1176, 0.0, 1.0, true, false, Interface::limited); static Parameter interfaceinput_scale ("input_scale", "Input scale for alpha_s value", &alpha_s::scale_in_, GeV, 91.1876*GeV, 0.*GeV, 0.*GeV, true, false, Interface::lowerlim); static Command interfacecheck ("check", "check", &alpha_s::check, false); static Parameter interfacescale_factor ("scale_factor", "scale factor for argument", &alpha_s::scale_factor_, 1., 0.0, 100.0, true, false, Interface::limited); static Switch interfacefixed ("fixed", "", &alpha_s::fixed_, false, false, false); static SwitchOption interfacefixedYes (interfacefixed, "Yes", "", true); static SwitchOption interfacefixedNo (interfacefixed, "No", "", false); } string alpha_s::check (string args) { istringstream argin(args); double Q_low, Q_high; long n_steps; argin >> Q_low >> Q_high >> n_steps; string fname; argin >> fname; Repository::clog() << "checking alpha_s in range [" << Q_low << "," << Q_high << "] GeV in " << n_steps << " steps.\nResults are written to " << fname << "\n"; double step_width = (Q_high-Q_low)/n_steps; match_thresholds(); Repository::clog() << "threshold matching results:\n" << "(m_Q^2 -> Lambda^2) / GeV^2 for dynamic flavours in range [" << min_active_flavours_ << "," << max_active_flavours_ << "]\n"; for (size_t f = 0; f < 7; ++f) { Repository::clog() << (quark_masses_squared_[f]/GeV2) << " " << (lambda_squared_[f]/GeV2) << "\n"; } ofstream out (fname.c_str()); for (long k = 0; k <= n_steps; ++k) { Energy Q = Q_low*GeV + k*step_width*GeV; out << (Q/GeV) << " " << (operator () (Q*Q)) << "\n"; } return "alpha_s check finished"; } void alpha_s::match_thresholds () { if (matched_) return; // get the quark masses quark_masses_squared_[0] = 0.*MeV2; for (long f = 1; f < 7; ++f) { if ( quarkMasses().empty() ) quark_masses_squared_[static_cast(f)] = sqr(getParticleData(f)->mass()); else quark_masses_squared_[static_cast(f)] = sqr(quarkMasses()[static_cast(f-1)]); } if ( quark_masses_squared_[1] > quark_masses_squared_[2] ) swap(quark_masses_squared_[1],quark_masses_squared_[2]); unsigned int active_at_input = active_flavours(sqr(scale_in_)); // solve for input lambda solve_input_lambda input_equation (this,active_at_input,alpha_s_in_,sqr(scale_in_)); gsl::bisection_root_solver,100> input_solver(input_equation); lambda_squared_[active_at_input] = MeV2 * input_solver.solve({lambda_range_.first/MeV2,lambda_range_.second/MeV2}); // get lambdas down to min active flavours unsigned int below = active_at_input; while (below > min_active_flavours_) { solve_lambda_below match_equation (this,below, lambda_squared_[below], quark_masses_squared_[below]); gsl::bisection_root_solver,100> match_solver(match_equation); lambda_squared_[below-1] = MeV2 * match_solver.solve({lambda_range_.first/MeV2,lambda_range_.second/MeV2}); --below; } // get lambdas up to max active flavours unsigned int above = active_at_input; while (above < max_active_flavours_) { solve_lambda_above match_equation (this,above, lambda_squared_[above], quark_masses_squared_[above+1]); gsl::bisection_root_solver,100> match_solver(match_equation); lambda_squared_[above+1] = MeV2 *match_solver.solve({lambda_range_.first/MeV2,lambda_range_.second/MeV2}); ++above; } if (min_active_flavours_ > 0) { for (size_t f = 0; f < min_active_flavours_; ++f) { lambda_squared_[f] = lambda_squared_[min_active_flavours_]; } } if (max_active_flavours_ < 6) { for (size_t f = max_active_flavours_+1; f < 7; ++f) { lambda_squared_[f] = lambda_squared_[max_active_flavours_]; } } matched_ = true; return; } diff --git a/Shower/Dipole/AlphaS/alpha_s.h b/Shower/Dipole/AlphaS/alpha_s.h --- a/Shower/Dipole/AlphaS/alpha_s.h +++ b/Shower/Dipole/AlphaS/alpha_s.h @@ -1,352 +1,344 @@ // -*- C++ -*- // couplings/alpha_s.h is part of matchbox // (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de #ifndef matchbox_couplings_alpha_s_h #define matchbox_couplings_alpha_s_h #include #include #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/StandardModel/AlphaSBase.h" #include "gsl.h" namespace matchbox { using namespace ThePEG; template struct solve_lambda_below { typedef AlphaS alpha_s; inline solve_lambda_below (alpha_s* a, unsigned int n, Energy2 lambda2n, Energy2 mass2) : alpha(a), nf_in(n), lambda2_nf_in(lambda2n), threshold(mass2) {} alpha_s * alpha; unsigned int nf_in; Energy2 lambda2_nf_in; Energy2 threshold; inline double operator () (double lambda2) { return ((*alpha)(threshold,lambda2_nf_in,nf_in) - (*alpha)(threshold,lambda2*MeV2,nf_in-1)); } }; template struct solve_lambda_above { typedef AlphaS alpha_s; inline solve_lambda_above (alpha_s * a, unsigned int n, Energy2 lambda2n, Energy2 mass2) : alpha(a), nf_in(n), lambda2_nf_in(lambda2n), threshold(mass2) {} alpha_s * alpha; unsigned int nf_in; Energy2 lambda2_nf_in; Energy2 threshold; inline double operator () (double lambda2) { return ((*alpha)(threshold,lambda2_nf_in,nf_in) - (*alpha)(threshold,lambda2*MeV2,nf_in+1)); } }; template struct solve_input_lambda { typedef AlphaS alpha_s; inline solve_input_lambda (alpha_s * a, unsigned int n, double inalpha, Energy2 inscale) : alpha(a), nf_in(n), alpha_in(inalpha), scale_in(inscale) {} alpha_s * alpha; unsigned int nf_in; double alpha_in; Energy2 scale_in; inline double operator () (double lambda2) { return ((*alpha)(scale_in,lambda2*MeV2,nf_in) - alpha_in); } }; /** * Base class for the strong coupling. * * @see \ref alpha_sInterfaces "The interfaces" * defined for alpha_s. */ class alpha_s : public AlphaSBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ alpha_s(); - - /** - * The destructor. - */ - virtual ~alpha_s(); - //@} public: /** @name Virtual functions as required by AlphaSBase. */ //@{ /** * The \f$\alpha_S\f$. Return the QCD coupling for a given \a scale * using the given standard model object \a sm. */ virtual inline double value(Energy2 scale, const StandardModelBase &) const { return operator() (scale); } /** * Return the flavour thresholds used. The returned vector contains * (in position i) the scales when the active number of * flavours changes from i to i+1. */ virtual inline vector flavourThresholds() const { assert(!nfvector.empty()); return nfvector; } /** * Return the \f$\Lambda_{QCD}\f$ used for different numbers of * active flavours. */ virtual inline vector LambdaQCDs() const { vector res; for (size_t k = 0; k < 7; ++k) res.push_back(sqrt(lambda_squared_[k])); return res; } //@} public: /// return alpha_s as function of scale inline double operator () (Energy2 scale) const { if ( fixed_ ) return alpha_s_in_; assert(matched()); unsigned int active = active_flavours(scale_factor_*scale); return operator () (scale_factor_*scale,lambda_squared_[active],active); } /// return alpha_s as function of scale, QCD scale /// and number of active flavours virtual double operator () (Energy2 scale, Energy2 lambda2, unsigned int nf) const = 0; /// match thresholds and write alpha_s /// to specified file; arguments are /// Q_low/GeV Q_high/GeV n_steps filename string check (string args); public: /// return minimum number of active flavours inline unsigned int min_active_flavours () const { return min_active_flavours_; } /// set minimum number of active flavours inline void min_active_flavours (unsigned int nf) { min_active_flavours_ = nf; } /// return maximum number of active flavours inline unsigned int max_active_flavours () const { return max_active_flavours_; } /// set maximum number of active flavours inline void max_active_flavours (unsigned int nf) { max_active_flavours_ = nf; } /// return the number of active flavours at the given scale inline unsigned int active_flavours (Energy2 scale) const { unsigned int active = 0; if (scale > 0.*GeV2) { while(quark_mass_squared(active) < scale) { if (++active == max_active_flavours_+1) break; } active -= 1; } else { active = 0; } return active; } /// return the lambda squared for the given number of flavours inline Energy2 lambda_squared (unsigned int f) const { assert(f < 7); return lambda_squared_[f]; } /// return the mass squared for given flavour inline Energy2 quark_mass_squared (unsigned int f) const { assert(f < 7); return quark_masses_squared_[f]; } /// set the mass squared for given flavour inline void quark_mass_squared (unsigned int f, Energy2 m2) { assert(f < 7); quark_masses_squared_[f] = m2; matched_ = false; } public: /// perform the threshold matching /// given alpha_s value at reference scale void match_thresholds (); /// return true, if threshold matching has been /// performed inline bool matched () const { return matched_; } 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 inline void doinit() { match_thresholds(); copy(quark_masses_squared_.begin()+1, quark_masses_squared_.end(),nfvector.begin()); AlphaSBase::doinit(); } //@} /// return the scale factor double scale_factor () const { return scale_factor_; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @name os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @name is the persistent input stream read from. * @name 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(); private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initalpha_s; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ alpha_s & operator=(const alpha_s &) = delete; private: unsigned int min_active_flavours_; unsigned int max_active_flavours_; bool matched_; double scale_factor_; std::array quark_masses_squared_; std::array lambda_squared_; vector nfvector=vector(6); double alpha_s_in_; Energy scale_in_; pair lambda_range_; bool fixed_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of alpha_s. */ template <> struct BaseClassTrait { /** Typedef of the first base class of alpha_s. */ typedef AlphaSBase NthBase; }; /** This template specialization informs ThePEG about the name of * the alpha_s class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "matchbox::alpha_s"; } /** * The name of a file containing the dynamic library where the class * alpha_s is implemented. It may also include several, space-separated, * libraries if the class alpha_s 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 "HwDipoleShowerAlphaS.so"; } }; /** @endcond */ } #endif /* matchbox_couplings_alpha_s_h */ diff --git a/Shower/Dipole/AlphaS/lo_alpha_s.cc b/Shower/Dipole/AlphaS/lo_alpha_s.cc --- a/Shower/Dipole/AlphaS/lo_alpha_s.cc +++ b/Shower/Dipole/AlphaS/lo_alpha_s.cc @@ -1,67 +1,65 @@ // -*- C++ -*- // couplings/lo_alpha_s.cc is part of matchbox // (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de #include "lo_alpha_s.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace matchbox; lo_alpha_s::lo_alpha_s() : alpha_s(), freezing_scale_(1.*GeV) {} -lo_alpha_s::~lo_alpha_s() {} - IBPtr lo_alpha_s::clone() const { return new_ptr(*this); } IBPtr lo_alpha_s::fullclone() const { return new_ptr(*this); } void lo_alpha_s::persistentOutput(PersistentOStream & os) const { os << ounit(freezing_scale_,GeV); } void lo_alpha_s::persistentInput(PersistentIStream & is, int) { is >> iunit(freezing_scale_,GeV); } ClassDescription lo_alpha_s::initlo_alpha_s; // Definition of the static class description member. void lo_alpha_s::Init() { static ClassDocumentation documentation ("LO running alpha_s"); static Parameter interfacefreezing_scale ("freezing_scale", "Freeze alpha_s below given scale", &lo_alpha_s::freezing_scale_, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, true, false, Interface::lowerlim); } double lo_alpha_s::operator () (Energy2 scale, Energy2 lambda2, unsigned int nf) const { if (scale < sqr(freezing_scale_)) { scale = sqr(freezing_scale_); nf = active_flavours(scale); lambda2 = lambda_squared(nf); } double beta0 = (33.-2.*nf)/(12.*Constants::pi); return 1./(beta0*log(scale/lambda2)); } diff --git a/Shower/Dipole/AlphaS/lo_alpha_s.h b/Shower/Dipole/AlphaS/lo_alpha_s.h --- a/Shower/Dipole/AlphaS/lo_alpha_s.h +++ b/Shower/Dipole/AlphaS/lo_alpha_s.h @@ -1,167 +1,159 @@ // -*- C++ -*- // couplings/lo_alpha_s.h is part of matchbox // (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de #ifndef matchbox_couplings_lo_alpha_s_h #define matchbox_couplings_lo_alpha_s_h #include "alpha_s.h" namespace matchbox { using namespace ThePEG; /** * LO running alpha_s * * @see \ref lo_alpha_sInterfaces "The interfaces" * defined for lo_alpha_s. */ class lo_alpha_s : public alpha_s { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ lo_alpha_s(); - /** - * The destructor. - */ - virtual ~lo_alpha_s(); - //@} - public: /// return alpha_s as function of scale, QCD scale /// and number of active flavours virtual double operator () (Energy2 scale, Energy2 lambda2, unsigned int nf) const; /// return the number of loops which determine this running virtual unsigned int nloops () const { return 1; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @name os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @name is the persistent input stream read from. * @name 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 inline void doinit() { freezing_scale_ *= scale_factor(); alpha_s::doinit(); } //@} 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; //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static ClassDescription initlo_alpha_s; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ lo_alpha_s & operator=(const lo_alpha_s &) = delete; private: Energy freezing_scale_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of lo_alpha_s. */ template <> struct BaseClassTrait { /** Typedef of the first base class of lo_alpha_s. */ typedef matchbox::alpha_s NthBase; }; /** This template specialization informs ThePEG about the name of * the lo_alpha_s class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "matchbox::lo_alpha_s"; } /** * The name of a file containing the dynamic library where the class * lo_alpha_s is implemented. It may also include several, space-separated, * libraries if the class lo_alpha_s 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 "HwDipoleShowerAlphaS.so"; } }; /** @endcond */ } #endif /* matchbox_couplings_lo_alpha_s_h */ diff --git a/Shower/Dipole/AlphaS/nlo_alpha_s.cc b/Shower/Dipole/AlphaS/nlo_alpha_s.cc --- a/Shower/Dipole/AlphaS/nlo_alpha_s.cc +++ b/Shower/Dipole/AlphaS/nlo_alpha_s.cc @@ -1,135 +1,133 @@ // -*- C++ -*- // couplings/nlo_alpha_s.cc is part of matchbox // (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de #include "nlo_alpha_s.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace matchbox; nlo_alpha_s::nlo_alpha_s() : alpha_s(), freezing_scale_(1.*GeV), exact_evaluation_(true), two_largeq_terms_(true) { } -nlo_alpha_s::~nlo_alpha_s() {} - IBPtr nlo_alpha_s::clone() const { return new_ptr(*this); } IBPtr nlo_alpha_s::fullclone() const { return new_ptr(*this); } void nlo_alpha_s::persistentOutput(PersistentOStream & os) const { os << ounit(freezing_scale_,GeV) << exact_evaluation_ << two_largeq_terms_; } void nlo_alpha_s::persistentInput(PersistentIStream & is, int) { is >> iunit(freezing_scale_,GeV) >> exact_evaluation_ >> two_largeq_terms_; } ClassDescription nlo_alpha_s::initnlo_alpha_s; // Definition of the static class description member. void nlo_alpha_s::Init() { static ClassDocumentation documentation ("NLO running alpha_s"); static Parameter interfacefreezing_scale ("freezing_scale", "Freeze alpha_s below given scale", &nlo_alpha_s::freezing_scale_, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, true, false, Interface::lowerlim); static Switch interfaceexact_evaluation ("exact_evaluation", "Wether to exactly evaluate the running or use running for large scales", &nlo_alpha_s::exact_evaluation_, true, true, false); static SwitchOption interfaceexact_evaluationexact (interfaceexact_evaluation, "exact", "Perform exact evaluation", true); static SwitchOption interfaceexact_evaluationlarge_scale (interfaceexact_evaluation, "large_scale", "Perform approximate evaluation for large scales", false); static Switch interfacetwo_largeq_terms ("two_largeq_terms", "Include two terms in the large q expansion.", &nlo_alpha_s::two_largeq_terms_, true, false, false); static SwitchOption interfacetwo_largeq_termsYes (interfacetwo_largeq_terms, "Yes", "Include two terms.", true); static SwitchOption interfacetwo_largeq_termsNo (interfacetwo_largeq_terms, "No", "Only include one term.", false); } double nlo_alpha_s::operator () (Energy2 scale, Energy2 lambda2, unsigned int nf) const { if (scale < sqr(freezing_scale_)) { scale = sqr(freezing_scale_); nf = active_flavours(scale); lambda2 = lambda_squared(nf); } double beta0 = (33.-2.*nf)/(12.*Constants::pi); double beta1 = (153.-19.*nf)/(24.*sqr(Constants::pi)); if (exact_evaluation_) { rg_solver().f.slog = log(scale/lambda2); rg_solver().f.nf = nf; double slog = rg_solver().f.slog; double center = (1./(beta0*slog))* (1. - (beta1/sqr(beta0)) * log(slog)/slog + sqr(beta1/(sqr(beta0)*slog)) * (sqr(log(slog)-.5) - 5./4.)); return rg_solver().solve({.5*center,1.5*center}); } else { double slog = log(scale/lambda2); double res = (1./(beta0*slog))* (1. - (beta1/sqr(beta0)) * log(slog)/slog); if ( two_largeq_terms_ ) res += (1./(beta0*slog))* (sqr(beta1/(sqr(beta0)*slog)) * (sqr(log(slog)-.5) - 5./4.)); return res; } return 0.; } diff --git a/Shower/Dipole/AlphaS/nlo_alpha_s.h b/Shower/Dipole/AlphaS/nlo_alpha_s.h --- a/Shower/Dipole/AlphaS/nlo_alpha_s.h +++ b/Shower/Dipole/AlphaS/nlo_alpha_s.h @@ -1,197 +1,189 @@ // -*- C++ -*- // couplings/nlo_alpha_s.h is part of matchbox // (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de #ifndef matchbox_couplings_nlo_alpha_s_h #define matchbox_couplings_nlo_alpha_s_h #include "alpha_s.h" namespace matchbox { using namespace ThePEG; /** * NLO running alpha_s * * @see \ref nlo_alpha_sInterfaces "The interfaces" * defined for nlo_alpha_s. */ class nlo_alpha_s : public alpha_s { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ nlo_alpha_s(); - /** - * The destructor. - */ - virtual ~nlo_alpha_s(); - //@} - public: /// return alpha_s as function of scale, QCD scale /// and number of active flavours virtual double operator () (Energy2 scale, Energy2 lambda2, unsigned int nf) const; /// return the number of loops which determine this running virtual unsigned int nloops () const { return 2; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @name os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @name is the persistent input stream read from. * @name 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 inline void doinit() { freezing_scale_ *= scale_factor(); alpha_s::doinit(); } //@} 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; //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static ClassDescription initnlo_alpha_s; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ nlo_alpha_s & operator=(const nlo_alpha_s &) = delete; private: struct rg_solution { inline double operator () (double alpha) { double beta0 = (33.-2.*nf)/(12.*Constants::pi); double beta1 = (153.-19.*nf)/(24.*sqr(Constants::pi)); return ((1./alpha)+(beta1/beta0)*log(alpha/(beta0+beta1*alpha))- beta0*slog); } double slog; unsigned int nf; }; Energy freezing_scale_; bool exact_evaluation_; static rg_solution& rg () { static rg_solution rg_; return rg_; } static gsl::bisection_root_solver& rg_solver () { static gsl::bisection_root_solver rg_solver_(rg()); return rg_solver_; } bool two_largeq_terms_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of nlo_alpha_s. */ template <> struct BaseClassTrait { /** Typedef of the first base class of nlo_alpha_s. */ typedef matchbox::alpha_s NthBase; }; /** This template specialization informs ThePEG about the name of * the nlo_alpha_s class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "matchbox::nlo_alpha_s"; } /** * The name of a file containing the dynamic library where the class * nlo_alpha_s is implemented. It may also include several, space-separated, * libraries if the class nlo_alpha_s 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 "HwDipoleShowerAlphaS.so"; } }; /** @endcond */ } #endif /* matchbox_couplings_nlo_alpha_s_h */ diff --git a/Shower/Dipole/Base/DipoleChainOrdering.cc b/Shower/Dipole/Base/DipoleChainOrdering.cc --- a/Shower/Dipole/Base/DipoleChainOrdering.cc +++ b/Shower/Dipole/Base/DipoleChainOrdering.cc @@ -1,146 +1,144 @@ // -*- C++ -*- // // DipoleChainOrdering.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleChainOrdering class. // #include "DipoleChainOrdering.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; DipoleChainOrdering::DipoleChainOrdering() : DipoleEvolutionOrdering(), virtualityOrdering(false) {} -DipoleChainOrdering::~DipoleChainOrdering() {} - IBPtr DipoleChainOrdering::clone() const { return new_ptr(*this); } IBPtr DipoleChainOrdering::fullclone() const { return new_ptr(*this); } Energy DipoleChainOrdering::hardScale(tPPtr emitter, tPPtr spectator, double emitterX, double spectatorX, const DipoleSplittingKernel& split, const DipoleIndex& index) const { Energy scale = split.splittingKinematics()->dipoleScale(emitter->momentum(), spectator->momentum()); return virtualityOrdering ? split.splittingKinematics()->QMax(scale,emitterX,spectatorX, index,split,emitter,spectator) : split.splittingKinematics()->ptMax(scale,emitterX,spectatorX, index,split,emitter,spectator); } void DipoleChainOrdering::setEvolutionScale(Energy scale, const DipoleSplittingInfo&, DipoleChain& chain, pair::iterator,list::iterator>) const { for ( list::iterator dip = chain.dipoles().begin(); dip != chain.dipoles().end(); ++dip ) { if ( dip->emitterScale({true,false}) > scale ) dip->emitterScale({true,false},scale); if ( dip->emitterScale({false,true}) > scale ) dip->emitterScale({false,true},scale); } } void DipoleChainOrdering::setEvolutionScale(Energy scale, const DipoleSplittingInfo&, DipoleChain& chain, list::iterator) const { for ( list::iterator dip = chain.dipoles().begin(); dip != chain.dipoles().end(); ++dip ) { if ( dip->emitterScale({true,false}) > scale ) dip->emitterScale({true,false},scale); if ( dip->emitterScale({false,true}) > scale ) dip->emitterScale({false,true},scale); } } Energy DipoleChainOrdering::evolutionScale(const DipoleSplittingInfo& split, const DipoleSplittingKernel& spkernel) const { return virtualityOrdering ? spkernel.splittingKinematics()->QFromPt(split.lastPt(),split) : split.lastPt(); } Energy DipoleChainOrdering::maxPt(Energy scale, const DipoleSplittingInfo& split, const DipoleSplittingKernel& spkernel) const { return virtualityOrdering ? spkernel.splittingKinematics()->ptMax(scale,split.emitterX(),split.spectatorX(),split,spkernel) : scale; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleChainOrdering::persistentOutput(PersistentOStream & os) const { os << virtualityOrdering; } void DipoleChainOrdering::persistentInput(PersistentIStream & is, int) { is >> virtualityOrdering; } ClassDescription DipoleChainOrdering::initDipoleChainOrdering; // Definition of the static class description member. void DipoleChainOrdering::Init() { static ClassDocumentation documentation ("DipoleChainOrdering performs ordering on " "complete colour singlet dipole chains."); static Switch interfaceVirtualityOrdering ("Ordering", "[experimental] Switch between virtuality and pt ordering.", &DipoleChainOrdering::virtualityOrdering, false, false, false); static SwitchOption interfaceVirtualityOrderingPt (interfaceVirtualityOrdering, "Pt", "Perform pt ordering", false); static SwitchOption interfaceVirtualityOrderingVirtuality (interfaceVirtualityOrdering, "Virtuality", "Perform virtuality ordering", true); interfaceVirtualityOrdering.rank(-1); } diff --git a/Shower/Dipole/Base/DipoleChainOrdering.h b/Shower/Dipole/Base/DipoleChainOrdering.h --- a/Shower/Dipole/Base/DipoleChainOrdering.h +++ b/Shower/Dipole/Base/DipoleChainOrdering.h @@ -1,200 +1,192 @@ // -*- C++ -*- // // DipoleChainOrdering.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_DipoleChainOrdering_H #define HERWIG_DipoleChainOrdering_H // // This is the declaration of the DipoleChainOrdering class. // #include "DipoleEvolutionOrdering.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleChainOrdering performs ordering on * complete colour singlet dipole chains. * */ class DipoleChainOrdering: public DipoleEvolutionOrdering { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ DipoleChainOrdering(); - /** - * The destructor. - */ - virtual ~DipoleChainOrdering(); - //@} - public: /** * For the given dipole and splitting kernel return * the hard scale. */ virtual Energy hardScale(tPPtr emitter, tPPtr spectator, double emitterX, double spectatorX, const DipoleSplittingKernel&, const DipoleIndex&) const; /** * For the given performed splitting, dipole chain * and dipoles originating from the splitting, set the next * scale. */ virtual void setEvolutionScale(Energy scale, const DipoleSplittingInfo&, DipoleChain&, pair::iterator,list::iterator>) const; /** * For the given performed splitting, dipole chain * and dipole taking a recoil, set the next * scale. */ virtual void setEvolutionScale(Energy scale, const DipoleSplittingInfo&, DipoleChain&, list::iterator) const; /** * For the given selected splitting return * the evolution scale. */ virtual Energy evolutionScale(const DipoleSplittingInfo& split, const DipoleSplittingKernel&) const; /** * Return the maximum pt corresponding to the given * evolution scale. */ virtual Energy maxPt(Energy scale, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * True, if virtuality instead of pt ordering * should be performed. */ bool virtualityOrdering; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initDipoleChainOrdering; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleChainOrdering & operator=(const DipoleChainOrdering &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleChainOrdering. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleChainOrdering. */ typedef Herwig::DipoleEvolutionOrdering NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleChainOrdering class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleChainOrdering"; } /** * The name of a file containing the dynamic library where the class * DipoleChainOrdering is implemented. It may also include several, space-separated, * libraries if the class DipoleChainOrdering 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_DipoleChainOrdering_H */ diff --git a/Shower/Dipole/DipoleShowerHandler.cc b/Shower/Dipole/DipoleShowerHandler.cc --- a/Shower/Dipole/DipoleShowerHandler.cc +++ b/Shower/Dipole/DipoleShowerHandler.cc @@ -1,1906 +1,1904 @@ // -*- C++ -*- // // DipoleShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleShowerHandler class. // #include #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/ParVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" // include theses to have complete types #include "Herwig/PDF/MPIPDF.h" #include "Herwig/PDF/MinBiasPDF.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" #include "Herwig/MatrixElement/Matchbox/Base/MergerBase.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include using namespace Herwig; bool DipoleShowerHandler::firstWarn = true; DipoleShowerHandler::DipoleShowerHandler() : ShowerHandler(), chainOrderVetoScales(true), nEmissions(0), discardNoEmissions(false), firstMCatNLOEmission(false), thePowhegDecayEmission(true), //theAnalyseSpinCorrelations(false), realignmentScheme(0), doSubleadingNc(false),subleadingNcEmissionsLimit(0), densityOperatorEvolution(0),densityOperatorCutoff(1.0*GeV2), doPartialUnweightingAtEmission(false), doPartialUnweighting(false),referenceWeight(0.1), cmecReweightFactor(1.0),negCMECScaling(1.0), verbosity(0), printEvent(0), nTries(0), didRadiate(false), didRealign(false), theRenormalizationScaleFreeze(1.*GeV), theFactorizationScaleFreeze(2.*GeV), theDoCompensate(false), theFreezeGrid(500000), theDetuning(1.0), maxPt(ZERO), muPt(ZERO), theInputColouredOffShellInShower(), theZBoundaries(1) {} -DipoleShowerHandler::~DipoleShowerHandler() {} - IBPtr DipoleShowerHandler::clone() const { return new_ptr(*this); } IBPtr DipoleShowerHandler::fullclone() const { return new_ptr(*this); } void DipoleShowerHandler::cascade(tPVector ) { throw Exception() << "DipoleShowerHandler: Dipoleshower not implemented as second shower." << "Check your setup or contact Herwig authors." << Exception::runerror; } tPPair DipoleShowerHandler::cascade(tSubProPtr sub, XCombPtr, Energy optHardPt, Energy optCutoff) { useMe(); prepareCascade(sub); resetWeights(); if ( !doFSR() && ! doISR() ) return sub->incoming(); eventRecord().setSubleadingNc(doSubleadingNc, subleadingNcEmissionsLimit); eventRecord().clear(); eventRecord().prepare(sub,dynamic_ptr_cast(lastXCombPtr()),newStep(),pdfs(), ShowerHandler::currentHandler()->generator()->currentEvent()->incoming(), firstInteraction(), offShellPartons(), !doSubleadingNc); if ( doSubleadingNc ) { if ( !theSplittingReweight ) { throw Exception() << "No splitting reweight was found. " << "A ColourMatrixElementCorrection " << "splitting reweight is required " << "for the subleading colour shower." << Exception::runerror; } //Set the evolution scheme for the density operator eventRecord().setDensityOperatorEvolution( densityOperatorEvolution, densityOperatorCutoff ); //Set the CMEC reweight factor theSplittingReweight->reweightFactor(cmecReweightFactor); theSplittingReweight->negativeScaling(negCMECScaling); theSplittingReweight->updateCurrentHandler(); } // SW: Removed simple test on doFSR and doISR and moved // here to account for the case of a hard event involving // no coloured particles but with unstable outgoing particles if ( !doFSR() && ! doISR() && eventRecord().decays().empty() ) return sub->incoming(); if ( !doISR() && eventRecord().outgoing().empty() && eventRecord().decays().empty() ) return sub->incoming(); if ( !doFSR() && !eventRecord().incoming().first->coloured() && !eventRecord().incoming().second->coloured() && eventRecord().decays().empty() ) return sub->incoming(); nTries = 0; // Clear the vertex record for spin correlations if ( spinCorrelations() ) //|| theAnalyseSpinCorrelations ) vertexRecord().clear(); while ( true ) { try { didRadiate = false; didRealign = false; if ( eventRecord().truncatedShower() ) { throw Exception() << "Inconsistent hard emission set-up in DipoleShowerHandler::cascade. " << "No truncated shower needed with DipoleShowerHandler. Add " << "'set MEMatching:TruncatedShower No' to 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 ( !eventRecord().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() ) { LorentzRotation rot = intrinsicPtGenerator->kick(eventRecord().incoming(), eventRecord().intermediates()); eventRecord().transform(rot); } } didRealign = realign(); constituentReshuffle(); // backup subleading switch if decays fail bool doneSubleadingNc = doSubleadingNc; // subleading N can't handle decays doSubleadingNc = false; try { // Decay and shower any particles that require decaying while ( !eventRecord().decays().empty() ) { map::const_iterator decayIt = eventRecord().decays().begin(); if ( eventRecord().nextDecay() ) { decayIt = eventRecord().decays().find(eventRecord().nextDecay() ); } else { // find the decay to do, one with greatest width and parent showered while(find(eventRecord().outgoing().begin(),eventRecord().outgoing().end(),decayIt->first)== eventRecord().outgoing().end() && find(eventRecord().hard().begin(),eventRecord().hard().end(),decayIt->first)== eventRecord().hard().end()) ++decayIt; } assert(decayIt!=eventRecord().decays().end()); PPtr incoming = decayIt->first; eventRecord().currentDecay(decayIt->second); // Use this to record if an emission actually happens bool powhegEmission = !( nEmissions && nEmitted==nEmissions) ? thePowhegDecayEmission : false; // Decay the particle / sort out its pert proc Energy showerScale = eventRecord().decay(incoming, powhegEmission); // Following the decay, the bool powheg emission is updated // to indicate whether or not an emission occurred if ( powhegEmission ) nEmitted += 1; // Check that there is only one particle incoming to the decay assert(eventRecord().currentDecay()->incoming().size()==1); // Prepare the event record for the showering of the decay bool needToShower = eventRecord().prepareDecay(eventRecord().currentDecay(), offShellPartons()); // Only need to shower if we have coloured outgoing particles if ( needToShower ) { // The decays currently considered produce a maximum of 2 chains (with powheg emission) // so all dipole should have the same scale as returned by the decay function. assert( eventRecord().chains().size() <= 2 ); for ( auto & ch : eventRecord().chains()) { for ( auto & dip : ch.dipoles()) { assert ( showerScale > ZERO ); dip.leftScale( showerScale ); dip.rightScale( showerScale ); } } // Prepare vertex record for spin correlations in decay shower if ( spinCorrelations() ) vertexRecord().prepareParticleDecay(incoming); // Perform the cascade doCascade(nEmitted,optHardPt,optCutoff,true); if ( spinCorrelations() ) vertexRecord().updateParticleDecay(); // Do the constituent mass shell reshuffling decayConstituentReshuffle(eventRecord().currentDecay()); } // Update the decays, adding any decays and updating momenta eventRecord().updateDecays(eventRecord().currentDecay()); eventRecord().decays().erase(decayIt); } } catch(...) { // reset flag doSubleadingNc = doneSubleadingNc; throw; } doSubleadingNc = doneSubleadingNc; break; } catch (RedoShower&) { resetWeights(); if ( ++nTries > maxtry() ) throw ShowerTriesVeto(maxtry()); eventRecord().clear(); // reset the spininfos if(sub->incoming().first->spinInfo()) sub->incoming().first->spinInfo()->reset(); if(sub->incoming().second->spinInfo()) sub->incoming().second->spinInfo()->reset(); for(PPtr out : sub->outgoing()) { if(out->spinInfo()) out->spinInfo()->reset(); } // prepare for the new shower eventRecord().prepare(sub, dynamic_ptr_cast(lastXCombPtr()), newStep(), pdfs(), ShowerHandler::currentHandler()->generator()->currentEvent()->incoming(), firstInteraction(), offShellPartons(), !doSubleadingNc); if ( doSubleadingNc ) { theSplittingReweight->updateCurrentHandler(); } continue; } catch (...) { throw; } } tPPair incoming=eventRecord().fillEventRecord(newStep(),firstInteraction(),didRealign); setDidRunCascade(true); return incoming; } // Reshuffle the outgoing partons from the hard process onto their constituent mass shells void DipoleShowerHandler::constituentReshuffle() { if ( constituentReshuffler && ShowerHandler::currentHandler()->retConstituentMasses() ) { if ( eventRecord().decays().empty() ) { constituentReshuffler->reshuffle(eventRecord().outgoing(), eventRecord().incoming(), eventRecord().intermediates()); return; } else { PList decaying; for(auto const & dec : eventRecord().decays()) decaying.push_back(dec.first); constituentReshuffler->hardProcDecayReshuffle( decaying, eventRecord().outgoing(), eventRecord().hard(), eventRecord().incoming(), eventRecord().intermediates()); } } // After reshuffling the hard process, the decays need to be updated // as this is not done in reshuffle vector > decays; for(auto const & dec : eventRecord().decays() ) decays.push_back({dec.first,dec.second}); for(auto const & dec : decays) { PPtr unstable = dec.first; PList::iterator pos = find(eventRecord().intermediates().begin(), eventRecord().intermediates().end(), dec.first); // Update the PPtr in theDecays if(pos!=eventRecord().intermediates().end()) { unstable = *pos; while(!unstable->children().empty()) { unstable = unstable->children()[0]; } eventRecord().decays().erase(dec.first); eventRecord().decays()[unstable] = dec.second; // Update the momenta of any other particles in the decay chain // (for externally provided events) if ( !(eventRecord().decays()[unstable]->outgoing().empty()) ) eventRecord().updateDecayChainMom( unstable , eventRecord().decays()[unstable]); } else { if ( !(eventRecord().decays()[unstable]->outgoing().empty()) ) { // Update the momenta of any other particles in the decay chain // (for externally provided events) // Note this needs to be done for all decaying particles in the // outgoing/hard regardless of whether that particle radiated // or was involved in the reshuffling, this is due to the // transformation performed for IILightKinematics. if ( (find(eventRecord().outgoing().begin(), eventRecord().outgoing().end(), unstable) != eventRecord().outgoing().end()) || (find(eventRecord().hard().begin(), eventRecord().hard().end(), unstable) != eventRecord().hard().end()) ) eventRecord().updateDecayChainMom( unstable , eventRecord().decays()[unstable]); } } } eventRecord().currentDecay(PerturbativeProcessPtr()); } // Reshuffle outgoing partons from a decay process onto their constituent mass shells void DipoleShowerHandler::decayConstituentReshuffle(PerturbativeProcessPtr decayProc) { if ( Debug::level > 2 ){ // Test this function by comparing the // invariant mass of the outgoing decay // systems before and after reshuffling Lorentz5Momentum testOutMomBefore (ZERO,ZERO,ZERO,ZERO); Energy testInvMassBefore = ZERO; for ( auto const & testDecayOutItBefore : decayProc->outgoing() ) { testOutMomBefore += testDecayOutItBefore.first->momentum(); } testInvMassBefore = testOutMomBefore.m(); // decayReshuffle updates both the event record and the decay perturbative process if ( constituentReshuffler && ShowerHandler::currentHandler()->retConstituentMasses()) { constituentReshuffler->decayReshuffle(decayProc, eventRecord().outgoing(), eventRecord().hard(), eventRecord().intermediates()); } Lorentz5Momentum testOutMomAfter (ZERO,ZERO,ZERO,ZERO); Energy testInvMassAfter = ZERO; for ( auto const & testDecayOutItAfter : decayProc->outgoing() ) { testOutMomAfter += testDecayOutItAfter.first->momentum(); } testInvMassAfter = testOutMomAfter.m(); #ifndef NDEBUG Energy incomingMass = decayProc->incoming()[0].first->momentum().m(); #endif assert( abs(testInvMassBefore-incomingMass)/GeV < 1e-5 ); assert( abs(testInvMassBefore-testInvMassAfter)/GeV < 1e-5); }else{ // decayReshuffle updates both the event record and the decay perturbative process if ( constituentReshuffler && ShowerHandler::currentHandler()->retConstituentMasses() ) { constituentReshuffler->decayReshuffle(decayProc, eventRecord().outgoing(), eventRecord().hard(), eventRecord().intermediates()); } return; } } // Sets the scale of each particle in the dipole chains by finding the smallest //of several upper bound energy scales: the CMEnergy of the event, //the transverse mass of outgoing particles, the hardScale (maxPT or maxQ) //calculated for each dipole (in both configurations) and the veto scale for each particle void DipoleShowerHandler::hardScales(Energy2 muf) { // Initalise maximum pt as max CMEnergy of the event maxPt = generator()->maximumCMEnergy(); if ( restrictPhasespace() ) { // First interaction == hard collision (i.e. not a MPI collision) if ( !hardScaleIsMuF() || !firstInteraction() ) { if ( !eventRecord().outgoing().empty() ) { for ( auto const & p : eventRecord().outgoing() ) maxPt = min(maxPt,p->momentum().mt()); } //Look at any non-coloured outgoing particles in the current subprocess else { assert(!eventRecord().hard().empty()); Lorentz5Momentum phard(ZERO,ZERO,ZERO,ZERO); for ( auto const & p : eventRecord().hard()) phard += p->momentum(); Energy mhard = phard.m(); maxPt = mhard; } maxPt *= hardScaleFactor(); } else { maxPt = hardScaleFactor()*sqrt(muf); } muPt = maxPt; } else { muPt = hardScaleFactor()*sqrt(muf); } if ( doSubleadingNc ) { return; } for ( auto & ch : eventRecord().chains()) { // Note that minVetoScale is a value for each DipoleChain, not each dipole // It will contain the minimum veto scale from all of the dipoles in the chain Energy minVetoScale = -1.*GeV; for ( auto & dip : ch.dipoles()) { // max scale per config Energy maxFirst = ZERO; Energy maxSecond = ZERO; // Loop over the kernels for the given dipole. // For each dipole configuration, calculate ptMax (or QMax if virtuality ordering) // for each kernel and find the maximum for ( auto const & k : kernels) { pair conf = {true,false}; if ( k->canHandle(dip.index(conf)) ) { // Look in DipoleChainOrdering for this 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 = {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); } } // Find the maximum value from comparing the maxScale found from maxPt and the vetoScale of the particle if ( dip.leftParticle()->vetoScale() >= ZERO ) { maxFirst = min(maxFirst,sqrt(dip.leftParticle()->vetoScale())); // minVetoScale is a value for each DipoleChain, not each dipole // It contains the minimum veto scale for all the dipoles in the entire DipoleChain 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()); } // Set the emitterScale for both members of each dipole maxFirst = min(maxPt,maxFirst); dip.emitterScale({true,false},maxFirst); maxSecond = min(maxPt,maxSecond); dip.emitterScale({false,true},maxSecond); } // if the smallest veto scale (i.e. from all of the dipoles) // is smaller than the scale calculated for a particular // particle in a particular dipole, // replace the scale with the veto scale if ( !evolutionOrdering()->independentDipoles() && chainOrderVetoScales && minVetoScale >= ZERO ) { for ( auto & dip : ch.dipoles() ) { dip.leftScale(min(dip.leftScale(),minVetoScale)); dip.rightScale(min(dip.rightScale(),minVetoScale)); } } } } void DipoleShowerHandler::hardScalesSubleading(list candidates, Energy hardPt) { maxPt = hardPt;//generator()->maximumCMEnergy(); // Note that minVetoScale is a value for each competing dipole (i.e. all dipoles // for the subleading shower. // It will contain the minimum veto scale from all of the dipoles Energy minVetoScale = -1.*GeV; for ( list::iterator cand = candidates.begin(); cand != candidates.end(); ++cand ) { // max scale Energy maxScale = ZERO; // Loop over kernels for ( vector::ptr>::iterator k = kernels.begin(); k != kernels.end(); ++k ) { if ( (**k).canHandle(cand->index()) ) { Energy scale = evolutionOrdering()->hardScale(cand->emitter(),cand->spectator(), cand->emitterX(),cand->spectatorX(), **k,cand->index()); maxScale = max(maxScale,scale); } } if ( cand->emitter()->vetoScale() >= ZERO ) { maxScale = min(maxScale,sqrt(cand->emitter()->vetoScale())); if ( minVetoScale >= ZERO ) minVetoScale = min(minVetoScale,sqrt(cand->emitter()->vetoScale())); else minVetoScale = sqrt(cand->emitter()->vetoScale()); } maxScale = min(maxPt,maxScale); cand->scale(maxScale); } if ( !evolutionOrdering()->independentDipoles() && chainOrderVetoScales && minVetoScale >= ZERO ) { for ( list::iterator cand = candidates.begin(); cand != candidates.end(); ++cand ) { cand->scale(min(cand->scale(),minVetoScale)); } } } void DipoleShowerHandler::addCandidates(PPair particles, list& clist) const { DipoleSplittingInfo candidate; Energy2 scale = ZERO; pair is(particles.first == eventRecord().incoming().first, particles.second == eventRecord().incoming().second); if ( (is.first && !is.second) || (!is.first && is.second) ) { scale = -(particles.first->momentum() - particles.second->momentum()).m2(); } else { scale = (particles.first->momentum() + particles.second->momentum()).m2(); } DipoleIndex index(particles.first->dataPtr(),particles.second->dataPtr(), is.first ? eventRecord().pdfs().first : PDF(), is.second ? eventRecord().pdfs().second : PDF()); candidate.scale(sqrt(scale)); candidate.index(index); candidate.configuration(make_pair(true,false)); candidate.emitter(particles.first); candidate.emitterX(is.first ? eventRecord().fractions().first : 1.0); candidate.spectator(particles.second); candidate.spectatorX(is.second ? eventRecord().fractions().second : 1.0); clist.push_back(candidate); index.swap(); candidate.index(index); candidate.configuration(make_pair(false,true)); candidate.emitter(particles.second); candidate.emitterX(is.second ? eventRecord().fractions().second : 1.0); candidate.spectator(particles.first); candidate.spectatorX(is.first ? eventRecord().fractions().first : 1.0); clist.push_back(candidate); } void DipoleShowerHandler::getCandidates(list& clist) const { clist.clear(); for ( PList::const_iterator i = eventRecord().outgoing().begin(); i != eventRecord().outgoing().end(); ++i ) { PList::const_iterator j = i; ++j; for ( ; j != eventRecord().outgoing().end(); ++j ) { addCandidates(make_pair(*i,*j),clist); } // Changed order of *i and inc().first if ( eventRecord().incoming().first->coloured() ) addCandidates(make_pair(eventRecord().incoming().first,*i),clist); if ( eventRecord().incoming().second->coloured() ) addCandidates(make_pair(*i,eventRecord().incoming().second),clist); } if ( eventRecord().incoming().first->coloured() && eventRecord().incoming().second->coloured() ) { addCandidates(eventRecord().incoming(),clist); } } void DipoleShowerHandler::performSplitting(DipoleSplittingInfo& split) const { Ptr::tptr kinematics = split.splittingKinematics(); kinematics->generateKinematics(split.emitter()->momentum(), split.spectator()->momentum(), split); split.splitEmitter(split.emitterData()->produceParticle(kinematics->lastEmitterMomentum())); split.splitSpectator(split.spectatorData()->produceParticle(kinematics->lastSpectatorMomentum())); split.emission(split.emissionData()->produceParticle(kinematics->lastEmissionMomentum())); // Setting resolution scales for the particles split.emission()->scale(sqr(split.lastPt())); split.splitEmitter()->scale(sqr(split.lastPt())); split.splitSpectator()->scale(split.spectator()->scale()); PVector neighbours; if ( DipolePartonSplitter::colourConnected(split.emitter(), eventRecord().incoming().first) && split.emitter() != eventRecord().incoming().first ) neighbours.push_back(eventRecord().incoming().first); if ( DipolePartonSplitter::colourConnected(split.emitter(), eventRecord().incoming().second) && split.emitter() != eventRecord().incoming().second ) neighbours.push_back(eventRecord().incoming().second); for ( PList::const_iterator p = eventRecord().outgoing().begin(); p != eventRecord().outgoing().end(); ++p ) { if ( *p == split.emitter() ) continue; if ( DipolePartonSplitter::colourConnected(split.emitter(),*p) ) neighbours.push_back(*p); } assert(neighbours.size() == 1 || neighbours.size() == 2 ); if ( neighbours.size() == 2 ) { if ( UseRandom::rnd() < 0.5 ) swap(neighbours[0],neighbours[1]); } DipolePartonSplitter::split(split.emitter(),split.splitEmitter(),split.emission(), neighbours.front(),split.index().initialStateEmitter(),false); DipolePartonSplitter::change(split.spectator(),split.splitSpectator(), split.index().initialStateSpectator(),false); } Energy DipoleShowerHandler::nextSubleadingSplitting(Energy hardPt, Energy optHardPt, Energy optCutoff, const bool decay) { list candidates; getCandidates(candidates); hardScalesSubleading(candidates,hardPt); for ( list::iterator cand = candidates.begin(); cand != candidates.end(); cand++ ) { cand->scale(hardPt); } list::iterator split = candidates.end(); // Winner of all dipoles DipoleSplittingInfo winner; // Winner for the current iteration of the for loop DipoleSplittingInfo candWinner; Energy winnerScale = 0.0*GeV; Energy nextScale = 0.0*GeV; for ( list::iterator cand = candidates.begin(); cand != candidates.end(); cand++ ) { nextScale = getWinner(candWinner, cand->index(), cand->emitterX(),cand->spectatorX(), make_pair(true,false), cand->emitter(),cand->spectator(), hardPt, optHardPt, optCutoff); if ( nextScale > winnerScale ) { winnerScale = nextScale; winner = candWinner; split = cand; winnerIndex = winningKernelIndex;//check } } if ( split == candidates.end() ) return ZERO; if ( decay ) winner.isDecayProc( true ); split->fill(winner); performSplitting(*split); eventRecord().update(*split); for ( list::iterator dip = candidates.begin(); dip != candidates.end(); ++dip ) { if ( dip == split ) continue; dip->emission(split->emission()); if ( dip->emitter() == split->emitter() ) { dip->splitEmitter(split->splitEmitter()); } else { dip->splitEmitter(dip->emitter()); } if ( dip->spectator() == split->spectator() ) { dip->splitSpectator(split->splitSpectator()); } else { dip->splitSpectator(dip->spectator()); } } // Update the ShowerHandler of the splitting reweight. if ( doSubleadingNc ) { theSplittingReweight->updateCurrentHandler(); } return split->lastPt(); } Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner, const Dipole& dip, pair 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 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; } if ( index.incomingDecaySpectator() && !doFSR() ) { winner.didStopEvolving(); return 0.0*GeV; } // Currently do not split IF dipoles so // don't evaluate them in order to avoid // exceptions in the log if ( index.incomingDecayEmitter() ) { winner.didStopEvolving(); return 0.0*GeV; } DipoleSplittingInfo candidate; candidate.index(index); candidate.configuration(conf); candidate.emitterX(emitterX); candidate.spectatorX(spectatorX); candidate.emitter(emitter); candidate.spectator(spectator); if ( generators().find(candidate.index()) == generators().end() ) getGenerators(candidate.index(),theSplittingReweight); // // 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. // // SW - Update 04/01/2016: Note - This caused a bug for me as I did not // include equality checks on the decay booleans in the == definition pair 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 ) { if ( doPartialUnweighting ) gen->second->doPartialUnweighting(referenceWeight); // (*) 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 ( std::isnan( double(dScale/MeV) ) ) throw RedoShower(); candidate.scale(dScale); // Calculate the mass of the recoil system // for decay dipoles if ( candidate.index().incomingDecaySpectator() || candidate.index().incomingDecayEmitter() ) { Energy recoilMass = gen->second->splittingKinematics()->recoilMassKin(emitter->momentum(), spectator->momentum()); candidate.recoilMass(recoilMass); } // Store emitter and spectator masses, needed in kinematics if ( candidate.index().emitterData()->mass() != ZERO ) { if ( !candidate.index().offShellEmitter() ) candidate.emitterMass( emitter->nominalMass() ); else candidate.emitterMass( emitter->mass() ); } if ( candidate.index().spectatorData()->mass() != ZERO ) { if ( !candidate.index().offShellSpectator() ) candidate.spectatorMass( spectator->nominalMass() ); else candidate.spectatorMass( spectator->mass() ); } candidate.continuesEvolving(); Energy hardScale = evolutionOrdering()->maxPt(startScale,candidate,*(gen->second->splittingKernel())); Energy maxPossible = gen->second->splittingKinematics()->ptMax(candidate.scale(), candidate.emitterX(), candidate.spectatorX(), candidate, *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; if ( continueSubleadingNc() ) winningKernelIndex = kernelIndex+1;//check } if ( continueSubleadingNc() ) { kernelIndex++;//check scales.push_back(nextScale);//check theWeightsVector.push_back(gen->second->splittingWeightVector()); } reweight(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, const bool decay) { if ( nEmissions ) if ( emDone == nEmissions ) return; if ( doSubleadingNc ) { unsigned int subEmDone = 0; // Set the starting scale Energy hardPt = muPt; double wref = referenceWeight; while ( subEmDone < subleadingNcEmissionsLimit && hardPt != ZERO && continueSubleadingNc() ) { // Clear out the weights from the earlier step theWeightsVector.clear(); kernelIndex = 0;//check scales.clear();//check hardPt = nextSubleadingSplitting( hardPt, optHardPt, optCutoff, decay ); // Partial unweighting if ( doPartialUnweightingAtEmission ) { const double w = reweight(); if ( abs(w) < wref ) { if ( abs(w)/wref < UseRandom::rnd() ) { // Set weight to zero and end this event reweight(0.0); return; } else reweight( wref*w/abs(w) ); } // Update the reference weight after emission wref *= referenceWeight; } // When the winning scale is larger than the cutoff // remove the added weights that are under the winning scale if ( hardPt != ZERO ) { Energy maxq = 0.0*GeV; #ifndef NDEBUG size_t iwinner = theWeightsVector.size();//check #endif for ( size_t i = 0; i < theWeightsVector.size(); i++ ) { if ( theWeightsVector[i].size() > 0 ) { // get<2> is true for an accept step. if ( std::get<2>(theWeightsVector[i].back()) && std::get<0>(theWeightsVector[i].back()) > maxq) { maxq = std::get<0>(theWeightsVector[i].back()); #ifndef NDEBUG iwinner = i;//check #endif } } } assert(winnerIndex-1 == iwinner);//check double correctionWeight = 1.0; for ( size_t i = 0; i < theWeightsVector.size(); i++ ) { for ( size_t j = 0; j < theWeightsVector[i].size(); j++ ) { if ( std::get<0>(theWeightsVector[i][j]) < maxq ) correctionWeight *= std::get<1>(theWeightsVector[i][j]); } } reweight(reweight()/correctionWeight); } // Increment the number of subleading Nc emissions done subEmDone++; // Stop if the limit of emissions is reached if ( nEmissions ) if ( ++emDone == nEmissions ) return; } // Subleading shower done, prepare chains for the standard // dipole shower eventRecord().prepareChainsSubleading( decay ); // Set scales for ( list::iterator ch = eventRecord().chains().begin(); ch != eventRecord().chains().end(); ch++ ) { for ( list::iterator dp = ch->dipoles().begin(); dp != ch->dipoles().end(); dp++ ) { dp->emitterScale(make_pair(true,false),hardPt); dp->emitterScale(make_pair(false,true),hardPt); } } } DipoleSplittingInfo winner; DipoleSplittingInfo dipoleWinner; while ( eventRecord().haveChain() ) { if ( verbosity > 2 ) { generator()->log() << "DipoleShowerHandler selecting splittings for the chain:\n" << eventRecord().currentChain() << flush; } list::iterator winnerDip = eventRecord().currentChain().dipoles().end(); Energy winnerScale = 0.0*GeV; Energy nextLeftScale = 0.0*GeV; Energy nextRightScale = 0.0*GeV; for ( list::iterator dip = eventRecord().currentChain().dipoles().begin(); dip != eventRecord().currentChain().dipoles().end(); ++dip ) { nextLeftScale = getWinner(dipoleWinner,*dip,{true,false},optHardPt,optCutoff); if ( nextLeftScale > winnerScale ) { winnerScale = nextLeftScale; winner = dipoleWinner; winnerDip = dip; } nextRightScale = getWinner(dipoleWinner,*dip,{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(reweight()*w); } continue; } // Check if the produced splitting would be part // of a matrix element region in a multi jet merging. // If so, the optHardPt is set to the current winner scale and the slitting // is vetoed. Note: It is possible that the current scale is larger than the // merging scale but another shower configuration shows a scale that is // below the required scale. if(firstInteraction() && !decay){ if ( isMERegion( winnerScale , winner , winnerDip) ){ optHardPt=winnerScale; // Vetoed shower. continue; }else if( theMergingHelper ){ optHardPt=ZERO; } } // otherwise perform the splitting didRadiate = true; eventRecord().isMCatNLOSEvent(false); eventRecord().isMCatNLOHEvent(false); pair::iterator,list::iterator> children; DipoleChain* firstChain = nullptr; DipoleChain* secondChain = nullptr; // Generate the azimuthal angle if ( spinCorrelations() ) vertexRecord().generatePhi(winner,*winnerDip); if ( decay ) winner.isDecayProc( true ); // Note: the dipoles are updated in eventRecord().split(....) after the splitting, // hence the entire cascade is handled in doCascade // The dipole scales are updated in dip->split(....) if ( decay ) winner.isDecayProc( true ); eventRecord().split(winnerDip,winner,children,firstChain,secondChain); // Update the vertex record following the splitting if ( spinCorrelations() ) vertexRecord().update(winner); 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(reweight()*w); } if ( nEmissions ) if ( ++emDone == nEmissions ) return; } } bool DipoleShowerHandler::isMERegion(const Energy winnerScale, const DipoleSplittingInfo & winner, list::iterator winnerDip ){ // First check if we have a merging setup adn additional conditions. if(!theMergingHelper)return false; if(!eventHandler()->currentCollision())return false; if(theMergingHelper->maxLegs()<=eventRecord().outgoing().size()+ eventRecord().hard().size() +2)//incoming return false; if( theMergingHelper->mergingScale() > winnerScale ) return false; // Now produce a temporary splitting to check if the final configuration is // part of the matrix element region pair::iterator,list::iterator> tmpchildren; DipoleSplittingInfo tmpwinner=winner; DipoleChain* tmpfirstChain = nullptr; DipoleChain* tmpsecondChain = nullptr; auto New=eventRecord().tmpsplit(winnerDip,tmpwinner, tmpchildren,tmpfirstChain, tmpsecondChain); // This is the same function that is used in the ME calculations of the // multi jet merging. if (theMergingHelper->matrixElementRegion(New.first, New.second, winnerScale, theMergingHelper->mergingScale())) { return true; }else return false; } 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 inMomenta (eventRecord().incoming().first->momentum(), eventRecord().incoming().second->momentum()); LorentzRotation 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 masses(eventRecord().incoming().first->mass(), eventRecord().incoming().second->mass()); pair 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::tptr as) { for ( auto & k : kernels) { if ( !k->alphaS() ) 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::tptr rw) { for ( auto & g : generators() ) g.second->splittingReweight(rw); } void DipoleShowerHandler::getGenerators(const DipoleIndex& ind, Ptr::tptr rw) { bool gotone = false; for ( auto & k : kernels ) { 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::ptr nGenerator = new_ptr(DipoleSplittingGenerator()); nGenerator->doCompensate(theDoCompensate); nGenerator->splittingKernel(k); if ( renormalizationScaleFactor() != 1. ) nGenerator->splittingKernel()->renormalizationScaleFactor(renormalizationScaleFactor()); if ( factorizationScaleFactor() != 1. ) nGenerator->splittingKernel()->factorizationScaleFactor(factorizationScaleFactor()); if ( !nGenerator->splittingReweight() ) nGenerator->splittingReweight(rw); 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->prepare(dummy); generators().insert({ind,nGenerator}); } } if ( !gotone ) { throw 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::runerror; } } // 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); // copy off-shell particle ids before showering from input vector to the // set used in the simulation if ( theColouredOffShellInShower.empty() ) { for(unsigned int ix=0;ixsplittingKinematics()->openZBoundaries() == 0 ) zChoice0 = true; else if ( k->splittingKinematics()->openZBoundaries() == 1 ) zChoice1 = true; else zChoiceOther = true; // either inconsistent or other option which cannot be handled by the matching if ( zChoice0 && zChoice1 ) { zChoiceOther = true; break; } } if ( zChoiceOther ) theZBoundaries = 2; else if ( zChoice1 ) theZBoundaries = 1; else if ( zChoice0 ) theZBoundaries = 0; } 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 << thePowhegDecayEmission //<< theAnalyseSpinCorrelations << doSubleadingNc << subleadingNcEmissionsLimit << densityOperatorEvolution << ounit(densityOperatorCutoff,GeV2) << doPartialUnweightingAtEmission << doPartialUnweighting << referenceWeight << cmecReweightFactor << negCMECScaling << realignmentScheme << verbosity << printEvent << ounit(theRenormalizationScaleFreeze,GeV) << ounit(theFactorizationScaleFreeze,GeV) << theShowerApproximation << theDoCompensate << theFreezeGrid << theDetuning << theEventReweight << theSplittingReweight << ounit(maxPt,GeV) << ounit(muPt,GeV)<< theMergingHelper << theColouredOffShellInShower << theInputColouredOffShellInShower << theZBoundaries; } void DipoleShowerHandler::persistentInput(PersistentIStream & is, int) { is >> kernels >> theEvolutionOrdering >> constituentReshuffler >> intrinsicPtGenerator >> theGlobalAlphaS >> chainOrderVetoScales >> nEmissions >> discardNoEmissions >> firstMCatNLOEmission >> thePowhegDecayEmission //>> theAnalyseSpinCorrelations >> doSubleadingNc >> subleadingNcEmissionsLimit >> densityOperatorEvolution >> iunit(densityOperatorCutoff,GeV2) >> doPartialUnweightingAtEmission >> doPartialUnweighting >> referenceWeight >> cmecReweightFactor >> negCMECScaling >> realignmentScheme >> verbosity >> printEvent >> iunit(theRenormalizationScaleFreeze,GeV) >> iunit(theFactorizationScaleFreeze,GeV) >> theShowerApproximation >> theDoCompensate >> theFreezeGrid >> theDetuning >> theEventReweight >> theSplittingReweight >> iunit(maxPt,GeV) >> iunit(muPt,GeV)>>theMergingHelper >> theColouredOffShellInShower >> theInputColouredOffShellInShower >> theZBoundaries; } ClassDescription DipoleShowerHandler::initDipoleShowerHandler; // Definition of the static class description member. void DipoleShowerHandler::Init() { static ClassDocumentation 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 interfaceKernels ("Kernels", "Set the splitting kernels to be used by the dipole shower.", &DipoleShowerHandler::kernels, -1, false, false, true, false, false); static Reference interfaceEvolutionOrdering ("EvolutionOrdering", "Set the evolution ordering to be used.", &DipoleShowerHandler::theEvolutionOrdering, false, false, true, false, false); static Reference interfaceConstituentReshuffler ("ConstituentReshuffler", "The object to be used to reshuffle partons to their constitutent mass shells.", &DipoleShowerHandler::constituentReshuffler, false, false, true, true, false); static Reference interfaceIntrinsicPtGenerator ("IntrinsicPtGenerator", "Set the object in charge to generate intrinsic pt for incoming partons.", &DipoleShowerHandler::intrinsicPtGenerator, false, false, true, true, false); static Reference interfaceGlobalAlphaS ("GlobalAlphaS", "Set a global strong coupling for all splitting kernels.", &DipoleShowerHandler::theGlobalAlphaS, false, false, true, true, false); // Start: Trying to add interface for the subleading Nc static Switch interfaceDoSubleadingNc ("DoSubleadingNc", "Switch on or off subleading Nc corrections.", &DipoleShowerHandler::doSubleadingNc, true, false, false); static SwitchOption interfaceDoSubleadingNcOn (interfaceDoSubleadingNc, "On", "Switch on subleading Nc corrections.", true); static SwitchOption interfaceDoSubleadingNcOff (interfaceDoSubleadingNc, "Off", "Switch off subleading Nc corrections.", false); // Limit for how many subleading Nc emissions should be calculated static Parameter interfaceSubleadingNcEmissionsLimit ("SubleadingNcEmissionsLimit", "Number of emissions to calculate subleading Nc corrections for.", &DipoleShowerHandler::subleadingNcEmissionsLimit,0,0,0, false, false, Interface::lowerlim); static Parameter interfaceDensityOperatorEvolution ("DensityOperatorEvolution", "Scheme for evolving the density operator.", &DipoleShowerHandler::densityOperatorEvolution,0,0,0, false, false, Interface::lowerlim); static Parameter interfaceDensityOperatorCutoff ("DensityOperatorCutoff", "Cutoff for momentum invariants for the density operator evolution.", &DipoleShowerHandler::densityOperatorCutoff,GeV2,1.0*GeV2,0.0*GeV2,0*GeV2, false, false, Interface::lowerlim); static Switch interfaceDoPartialUnweightingAtEmission ("DoPartialUnweightingAtEmission", "Switch on or off partial unweighting at the emission level.", &DipoleShowerHandler::doPartialUnweightingAtEmission,true,false,false); static SwitchOption interfaceDoPartialUnweightingAtEmissionOn (interfaceDoPartialUnweightingAtEmission, "On", "Switch on partial unweighting.", true); static SwitchOption interfaceDoPartialUnweightingAtEmissionOff (interfaceDoPartialUnweightingAtEmission, "Off", "Switch off partial unweighting.", false); static Switch interfaceDoPartialUnweighting ("DoPartialUnweighting", "Switch on or off partial unweighting at the dipole splitting level.", &DipoleShowerHandler::doPartialUnweighting,true,false,false); static SwitchOption interfaceDoPartialUnweightingOn (interfaceDoPartialUnweighting, "On", "Switch on partial unweighting.", true); static SwitchOption interfaceDoPartialUnweightingOff (interfaceDoPartialUnweighting, "Off", "Switch off partial unweighting.", false); static Parameter interfaceReferenceWeight ("ReferenceWeight", "Reference weight for the partial unweighting.", &DipoleShowerHandler::referenceWeight,0.1,0.0,0, false, false, Interface::lowerlim); static Parameter interfaceCMECReweightFactor ("CMECReweightFactor", "Factor used in the reweighting algorithm.", &DipoleShowerHandler::cmecReweightFactor,1.0,0.0,0, false, false, Interface::lowerlim); static Parameter interfaceNegCMECScaling ("NegCMECScaling", "Scaling factor for the negative colour matrix element corrections (CMECs).", &DipoleShowerHandler::negCMECScaling,0.0,0.0,0, false, false, Interface::lowerlim); static Switch 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 interfaceChainOrderVetoScales ("ChainOrderVetoScales", "[experimental] Switch the chain ordering for veto scales on or off.", &DipoleShowerHandler::chainOrderVetoScales, true, false, false); static SwitchOption interfaceChainOrderVetoScalesYes (interfaceChainOrderVetoScales, "Yes", "Switch on chain ordering for veto scales.", true); static SwitchOption interfaceChainOrderVetoScalesNo (interfaceChainOrderVetoScales, "No", "Switch off chain ordering for veto scales.", false); interfaceChainOrderVetoScales.rank(-1); static Parameter 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 interfaceDiscardNoEmissions ("DiscardNoEmissions", "[debug option] Discard events without radiation.", &DipoleShowerHandler::discardNoEmissions, false, false, false); static SwitchOption interfaceDiscardNoEmissionsYes (interfaceDiscardNoEmissions, "Yes", "Discard events without radiation.", true); static SwitchOption interfaceDiscardNoEmissionsNo (interfaceDiscardNoEmissions, "No", "Do not discard events without radiation.", false); interfaceDiscardNoEmissions.rank(-1); static Switch interfaceFirstMCatNLOEmission ("FirstMCatNLOEmission", "[debug option] Only perform the first MC@NLO emission.", &DipoleShowerHandler::firstMCatNLOEmission, false, false, false); static SwitchOption interfaceFirstMCatNLOEmissionYes (interfaceFirstMCatNLOEmission, "Yes", "Perform only the first MC@NLO emission.", true); static SwitchOption interfaceFirstMCatNLOEmissionNo (interfaceFirstMCatNLOEmission, "No", "Produce all emissions.", false); interfaceFirstMCatNLOEmission.rank(-1); static Parameter 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 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 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 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 interfaceDoCompensate ("DoCompensate", "", &DipoleShowerHandler::theDoCompensate, false, false, false); static SwitchOption interfaceDoCompensateYes (interfaceDoCompensate, "Yes", "", true); static SwitchOption interfaceDoCompensateNo (interfaceDoCompensate, "No", "", false); static Parameter interfaceFreezeGrid ("FreezeGrid", "", &DipoleShowerHandler::theFreezeGrid, 500000, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceDetuning ("Detuning", "A value to detune the overestimate kernel.", &DipoleShowerHandler::theDetuning, 1.0, 1.0, 0, false, false, Interface::lowerlim); static Reference interfaceEventReweight ("EventReweight", "", &DipoleShowerHandler::theEventReweight, false, false, true, true, false); static Reference interfaceSplittingReweight ("SplittingReweight", "Set the splitting reweight.", &DipoleShowerHandler::theSplittingReweight, false, false, true, true, false); static Switch interfacePowhegDecayEmission ("PowhegDecayEmission", "Use Powheg style emission for the decays", &DipoleShowerHandler::thePowhegDecayEmission, true, false, false); static SwitchOption interfacePowhegDecayEmissionYes (interfacePowhegDecayEmission,"Yes","Powheg decay emission on", true); static SwitchOption interfacePowhegDecayEmissionNo (interfacePowhegDecayEmission,"No","Powheg decay emission off", false); static ParVector interfaceOffShellInShower ("OffShellInShower", "PDG codes of the coloured particles that can be off-shell in the process.", &DipoleShowerHandler::theInputColouredOffShellInShower, -1, 0l, -10000000l, 10000000l, false, false, Interface::limited); /* static Switch interfaceAnalyseSpinCorrelations ("AnalyseSpinCorrelations", "Record the information required for the spin correlation analyis.", &DipoleShowerHandler::theAnalyseSpinCorrelations, false, false, false); static SwitchOption interfaceAnalyseSpinCorrelationsYes (interfaceAnalyseSpinCorrelations,"Yes","Record the information for analysing the spin correlations.", true); static SwitchOption interfaceAnalyseSpinCorrelationsNo (interfaceAnalyseSpinCorrelations,"No","Do not record extra information.", false); */ } diff --git a/Shower/Dipole/DipoleShowerHandler.h b/Shower/Dipole/DipoleShowerHandler.h --- a/Shower/Dipole/DipoleShowerHandler.h +++ b/Shower/Dipole/DipoleShowerHandler.h @@ -1,764 +1,756 @@ // -*- C++ -*- // // DipoleShowerHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_DipoleShowerHandler_H #define HERWIG_DipoleShowerHandler_H // // This is the declaration of the DipoleShowerHandler class. // #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/Shower/Dipole/DipoleShowerHandler.fh" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingReweight.h" #include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleEventRecord.h" #include "Herwig/Shower/Dipole/Base/DipoleEvolutionOrdering.h" #include "Herwig/Shower/Dipole/Base/DipoleEventReweight.h" #include "Herwig/Shower/Dipole/Utility/ConstituentReshuffler.h" #include "Herwig/Shower/Dipole/Utility/IntrinsicPtGenerator.h" #include "Herwig/MatrixElement/Matchbox/Base/MergerBase.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" #include "Herwig/Shower/Dipole/SpinCorrelations/DipoleVertexRecord.h" #include "Herwig/MatrixElement/Matchbox/Utility/DensityOperator.h" #include namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Stephen Webster * * \brief The DipoleShowerHandler class manages the showering using * the dipole shower algorithm. * * @see \ref DipoleShowerHandlerInterfaces "The interfaces" * defined for DipoleShowerHandler. */ class DipoleShowerHandler: public ShowerHandler { friend class Merger; public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ DipoleShowerHandler(); - /** - * The destructor. - */ - virtual ~DipoleShowerHandler(); - //@} - public: inline void colourPrint(); /** * Indicate a problem in the shower. */ struct RedoShower {}; /** * Insert an additional splitting kernel. */ void addSplitting(Ptr::ptr sp) { kernels.push_back(sp); } /** * Reset the alpha_s for all splitting kernels. */ void resetAlphaS(Ptr::tptr); virtual void cascade(tPVector); /** * Reset the splitting reweight for all splitting kernels. */ void resetReweight(Ptr::tptr); /** * Return true, if the shower handler can generate a truncated * shower for POWHEG style events generated using Matchbox */ virtual bool canHandleMatchboxTrunc() const { return false; } /** * Return true, if this cascade handler will perform reshuffling from hard * process masses. */ virtual bool isReshuffling() const { return false; } /** * Return the relevant hard scale to be used in the profile scales */ virtual Energy hardScale() const { return muPt; } /** * Calculate the alpha_s value the shower uses for Q. */ double as(Energy Q)const{return theGlobalAlphaS->value(sqr(Q));} /** * Return the number of scale dependent active flavours from * the alpha_s object. */ double Nf(Energy Q)const{return theGlobalAlphaS->Nf(sqr(Q));} /* * Access the vertex record */ DipoleVertexRecord& vertexRecord() { return theVertexRecord; } /** * Return the event record */ const DipoleVertexRecord& vertexRecord() const { return theVertexRecord; } /** * Set the pointer to the Merging Helper. * Used by the merging factory. */ void setMerger(Ptr::ptr mh){theMergingHelper=mh;} public: /** * Return the dictionary for the incoming particles and outgoing partons * in the event, will be empty if subleading Nc is turned off. */ const map& particleIndices() const { return eventRecord().particleIndices(); } /** * Return the particle data vector of the particles in the event, will * be empty if subleading Nc is turned off. */ const cPDVector& particlesAfter() const { return eventRecord().particlesAfter(); } /** * Return the density operator from the event record. */ DensityOperator& densityOperator() { return eventRecord().densityOperator(); } /** * Return the colour matrix element correction map, will be empty if * subleading Nc is turned off. NOT USED, REMOVE */ const map,pair >,double>& correlatorMap() const { return eventRecord().densityOperator().correlatorMap(); } /** * Return the colour basis used in the density operator. NOT USED, REMOVE */ Ptr::tptr colourBasis() { return eventRecord().densityOperator().colourBasis(); } /** * Return the continue subleading Nc flag from the event record. */ bool continueSubleadingNc() const { return eventRecord().getContinueSubleadingNc(); } protected: /** * Add the possible splitting candidates given a pair of emitting particles */ void addCandidates(PPair particles, list& clist) const; /** * Get all possible radiating dipoles */ void getCandidates(list& clist) const; /** * Perform a splitting independent of any chains */ void performSplitting(DipoleSplittingInfo&) const; /** * Generate the next subleading Nc improved splitting and return the scale */ Energy nextSubleadingSplitting(Energy hardPt, Energy optHardPt, Energy optCutoff, const bool decay); protected: typedef multimap::ptr> GeneratorMap; /** * The main method which manages the showering of a subprocess. */ virtual tPPair cascade(tSubProPtr sub, XCombPtr xcomb) { return cascade(sub,xcomb,ZERO,ZERO); } /** * The main method which manages the showering of a subprocess. */ tPPair cascade(tSubProPtr sub, XCombPtr xcomb, Energy optHardPt, Energy optCutoff); /** * Build splitting generators for the given * dipole index. */ void getGenerators(const DipoleIndex&, Ptr::tptr rw = Ptr::tptr()); /** * Setup the hard scales. */ void hardScales(Energy2 scale); /** * Setup the hard scales of the dipoles after subleading emissions.//debug */ void hardScalesSubleading(list candidates,Energy hardPt); /** * Return the evolution ordering */ Ptr::tptr evolutionOrdering() const { return theEvolutionOrdering; } /** * Reshuffle to constituent mass shells */ void constituentReshuffle(); /** * Reshuffle to constituent mass shells */ void decayConstituentReshuffle( PerturbativeProcessPtr decayProc); /** * Access the generator map */ GeneratorMap& generators() { return theGenerators; } /** * Access the event record */ DipoleEventRecord& eventRecord() { return theEventRecord; } /** * Return the event record */ const DipoleEventRecord& eventRecord() const { return theEventRecord; } /** * Return the splitting kernels. */ const vector::ptr>& splittingKernels() const { return kernels; } /** * Return the set of offshell parton ids. **/ const set& offShellPartons() { return theColouredOffShellInShower; } /** * In a merging setup this function checks if the next shower * configuration is part of the matrix element region. */ bool isMERegion(const Energy winnerScale, const DipoleSplittingInfo & winner, const list::iterator winnerDip); /** * Realign the event such as to have the incoming partons along thre * beam axes. */ bool realign(); /** * The choice of z boundaries; 0 = restricted, 1 = open, 2 = mixed/other */ virtual int showerPhaseSpaceOption() const { return theZBoundaries; } protected: /** * Perform the cascade. */ void doCascade(unsigned int& emDone, Energy optHardPt = ZERO, Energy optCutoff = ZERO, const bool decay = false); /** * Set the number of emissions **/ void setNEmissions(unsigned int n){nEmissions=n;} /** * Get the winning splitting for the * given dipole and configuration. */ Energy getWinner(DipoleSplittingInfo& winner, const Dipole& dip, pair conf, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Get the winning splitting for the * given dipole and configuration. */ Energy getWinner(DipoleSplittingInfo& winner, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Get the winning splitting for the * given dipole and configuration. */ Energy getWinner(SubleadingSplittingInfo& winner, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Get the winning splitting for the * given dipole and configuration. */ Energy getWinner(DipoleSplittingInfo& winner, const DipoleIndex& index, double emitterX, double spectatorX, pair conf, tPPtr emitter, tPPtr spectator, Energy startScale, Energy optHardPt = ZERO, Energy optCutoff = ZERO); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The splitting kernels to be used. */ vector::ptr> kernels; /** * The evolution ordering considered */ Ptr::ptr theEvolutionOrdering; /** * The ConstituentReshuffler to be used */ Ptr::ptr constituentReshuffler; /** * The intrinsic pt generator to be used. */ Ptr::ptr intrinsicPtGenerator; /** * A global alpha_s to be used for all splitting kernels. */ Ptr::ptr theGlobalAlphaS; /** * Apply chain ordering to events from matrix * element corrections. */ bool chainOrderVetoScales; /** * Limit the number of emissions. * Limit applied if > 0. */ unsigned int nEmissions; /** * Discard events which did not radiate. */ bool discardNoEmissions; /** * Perform the first MC@NLO emission only. */ bool firstMCatNLOEmission; /** * True if powheg style emissions are to be used in the decays */ bool thePowhegDecayEmission; /** * Switch to record information required for the * nearest neighbour analysis. */ //bool theAnalyseSpinCorrelations; /** * The realignment scheme */ int realignmentScheme; /** * Switch on or off subleading Nc corrections */ bool doSubleadingNc; /** * Number of emissions to do subleading Nc corrections to. */ size_t subleadingNcEmissionsLimit; /** * Current reference weight used for partial unweighting of the * subleading colour shower (updated each emission). */ int currentReferenceWeight; /** * Integer used to set which method of evolving the density operator * to use: * 0 - Vijk is Eikonal but there is a cutoff. * 1 - Vijk is Eikonal. * 2 - Vijk=1 for all i,j,k. * 3 - Semi-leading Nc, Vijk=0 for all */ int densityOperatorEvolution; /** * Cutoff scale for the invariants (e.g. pEmitter*pEmission) in the * Eikonal dipole kernel, Vijk. */ Energy2 densityOperatorCutoff; /** * Switch on or off partial unweighting in after each subleading emission. */ bool doPartialUnweightingAtEmission; /** * Switch on or off partial unweighting in the splitting generator. */ bool doPartialUnweighting; /** * Reference weight for the partial unweighting. */ double referenceWeight; /** * Factor changing the acceptance probability for the veto algorithm. */ double cmecReweightFactor; /** * Scaling factor for the negative colour matrix element corrections. */ double negCMECScaling; private: /** * The verbosity level. * 0 - print no info * 1 - print diagnostic information on setting up * splitting generators etc. * 2 - print detailed event information for up to * printEvent events. * 3 - print dipole chains after each splitting. */ int verbosity; /** * See verbosity. */ int printEvent; private: /** * The splitting generators indexed by the dipole * indices they can work on. */ GeneratorMap theGenerators; /** * The evnt record used. */ DipoleEventRecord theEventRecord; /** * The vertex record. **/ DipoleVertexRecord theVertexRecord; /** * The number of shoer tries so far. */ unsigned int nTries; /** * Whether or not we did radiate anything */ bool didRadiate; /** * Whether or not we did realign the event */ bool didRealign; /** * Vector of candidate splittings containing a vector of the * weights, scale and a bool for every step in the reweighted * veto algorithm. The bool is true for an accept step. */ vector > > theWeightsVector; /** * Winning candidate index. */ size_t winnerIndex;//debug size_t kernelIndex;//debug size_t winningKernelIndex;//debug vector scales;//debug private: /** * A freezing value for the renormalization scale */ Energy theRenormalizationScaleFreeze; /** * A freezing value for the factorization scale */ Energy theFactorizationScaleFreeze; /** * The matching subtraction, if appropriate */ Ptr::tptr theShowerApproximation; /** * True, if sampler should apply compensation */ bool theDoCompensate; /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long theFreezeGrid; /** * The detuning factor applied to the sampling overestimate kernel */ double theDetuning; /** * A pointer to the dipole event reweight object */ Ptr::ptr theEventReweight; /** * A pointer to a global dipole splitting reweight */ Ptr::ptr theSplittingReweight; /** * True if no warnings have been issued yet */ static bool firstWarn; /** * The shower starting scale for the last event encountered */ Energy maxPt; /** * The shower hard scale for the last event encountered */ Energy muPt; /** * The merging helper takes care of merging multiple LO and NLO * cross sections. Here we need to check if an emission would * radiate in the matrix element region of an other multipicity. * If so, the emission is vetoed. */ Ptr::ptr theMergingHelper; /** * PDG codes of the partons which can have an off-shell mass, * this is fast storage for use during running */ set theColouredOffShellInShower; /** * PDG codes of the partons which can have an off-shell mass, * this is a vector that is interfaced so they can be changed */ vector theInputColouredOffShellInShower; /** * The choice of z boundaries; 0 = restricted, 1 = open, 2 = mixed/other */ int theZBoundaries; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initDipoleShowerHandler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleShowerHandler & operator=(const DipoleShowerHandler &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleShowerHandler. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleShowerHandler. */ typedef Herwig::ShowerHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleShowerHandler class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleShowerHandler"; } /** * The name of a file containing the dynamic library where the class * DipoleShowerHandler is implemented. It may also include several, space-separated, * libraries if the class DipoleShowerHandler 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_DipoleShowerHandler_H */ diff --git a/Shower/Dipole/Kernels/ColourMatrixElementCorrection.cc b/Shower/Dipole/Kernels/ColourMatrixElementCorrection.cc --- a/Shower/Dipole/Kernels/ColourMatrixElementCorrection.cc +++ b/Shower/Dipole/Kernels/ColourMatrixElementCorrection.cc @@ -1,91 +1,89 @@ // -*- C++ -*- // // ColourMatrixElementCorrection.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 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 ColourMatrixElementCorrection class. // #include "ColourMatrixElementCorrection.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 "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Shower/Dipole/DipoleShowerHandler.h" using namespace Herwig; ColourMatrixElementCorrection::ColourMatrixElementCorrection():lambda(1.0),negCMECScaling(1.0) {} -ColourMatrixElementCorrection::~ColourMatrixElementCorrection() {} - IBPtr ColourMatrixElementCorrection::clone() const { return new_ptr(*this); } IBPtr ColourMatrixElementCorrection::fullclone() const { return new_ptr(*this); } double ColourMatrixElementCorrection::cmec(const DipoleSplittingInfo& dsplit) const { // Do not calculate CMECs if the subleading Nc shower has stopped if ( !(currentHandler()->continueSubleadingNc()) ) { return 1.; } const PPtr em = dsplit.emitter(); const PPtr sp = dsplit.spectator(); const tcPDPtr emis = dsplit.emissionData(); // Get the dictionary from particle pointers to herwig particle numbers const map& theDictionary = currentHandler()->particleIndices(); const cPDVector& theParticles = currentHandler()->particlesAfter(); // Use the dictionary to find // - emitter index // - spectator index // - emission ParticleID const std::tuple ikemission = std::make_tuple(theDictionary.at(em), theDictionary.at(sp), emis->id()); double factor = currentHandler()->densityOperator().colourMatrixElementCorrection(ikemission,theParticles); return factor > 0.0 ? factor : negCMECScaling*factor; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ColourMatrixElementCorrection::persistentOutput(PersistentOStream &) const { // *** ATTENTION *** os << ; // Add all member variable which should be written persistently here. } void ColourMatrixElementCorrection::persistentInput(PersistentIStream &, int) { // *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here. } // *** 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 describeHerwigColourMatrixElementCorrection("Herwig::ColourMatrixElementCorrection", "HwDipoleShower.so"); void ColourMatrixElementCorrection::Init() { static ClassDocumentation documentation ("There is no documentation for the ColourMatrixElementCorrection class"); } diff --git a/Shower/Dipole/Kernels/ColourMatrixElementCorrection.h b/Shower/Dipole/Kernels/ColourMatrixElementCorrection.h --- a/Shower/Dipole/Kernels/ColourMatrixElementCorrection.h +++ b/Shower/Dipole/Kernels/ColourMatrixElementCorrection.h @@ -1,171 +1,163 @@ // -*- C++ -*- // // ColourMatrixElementCorrection.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 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_ColourMatrixElementCorrection_H #define Herwig_ColourMatrixElementCorrection_H // // This is the declaration of the ColourMatrixElementCorrection class. // #include "Herwig/Shower/Dipole/Base/DipoleSplittingReweight.h" #include namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Johan Thoren, Simon Platzer * * \brief ColourMatrixElementCorrection is implementing colour matrix element * corrections through the weighted Sudakov algorithm * * @see \ref ColourMatrixElementCorrectionInterfaces "The interfaces" * defined for ColourMatrixElementCorrection. */ class ColourMatrixElementCorrection: public DipoleSplittingReweight { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ ColourMatrixElementCorrection(); - /** - * The destructor. - */ - virtual ~ColourMatrixElementCorrection(); - //@} - public: /** * Calculate and cache the colour matrix element correction factor * for the given splitting type. */ double cmec(const DipoleSplittingInfo&) const; /** * Return the reweighting factor for the given splitting type. */ virtual double evaluate(const DipoleSplittingInfo& s) const { return cmec(s); } /** * Return the absolute value of the colour matrix element correction * as an enhancement hint for the sampling of the un-reweighted * splitting kernel. */ virtual double hint(const DipoleSplittingInfo& s) const { if ( hintOnly(s) ) return cmec(s); return abs(cmec(s))*lambda; } /** * Return true, if the reweight can be entirely absorbed into the hint. A * possible detuning will be switched off. */ virtual bool hintOnly(const DipoleSplittingInfo& s) const { return cmec(s) > 0.; } /** * Set the factor in front of enhance used by the veto algorithm. */ virtual void reweightFactor(const double c) { assert(c > 0.0); lambda = c; } /** * Set the factor in front of enhance used by the veto algorithm. */ virtual void negativeScaling(const double c) { assert(c >= 0.0); negCMECScaling = c; } 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: /** * Factor to shuffle the magnitude of the CMEC between the splitting kernel * and the weight in the reweighted veto algorithm. */ double lambda; /** * Scaling factor multiplying all of the negative colour matrix element * corrections. The physically sensible value is 1.0, but this factor can * be used to examine the effects of the negative contributions. */ double negCMECScaling; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ColourMatrixElementCorrection & operator=(const ColourMatrixElementCorrection &) = delete; }; } #endif /* Herwig_ColourMatrixElementCorrection_H */ diff --git a/Shower/Dipole/Kernels/DipoleSplittingKernel.cc b/Shower/Dipole/Kernels/DipoleSplittingKernel.cc --- a/Shower/Dipole/Kernels/DipoleSplittingKernel.cc +++ b/Shower/Dipole/Kernels/DipoleSplittingKernel.cc @@ -1,411 +1,408 @@ // -*- C++ -*- // // DipoleSplittingKernel.cc is a part of Herwig - // A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleSplittingKernel class. // #include "DipoleSplittingKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Shower/ShowerHandler.h" using namespace Herwig; DipoleSplittingKernel::DipoleSplittingKernel() : HandlerBase(), theScreeningScale(0.0*GeV), thePresamplingPoints(2000), theMaxtry(100000), theFreezeGrid(500000), theDetuning(1.0), theStrictLargeN(false), theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0), theRenormalizationScaleFreeze(1.*GeV), theFactorizationScaleFreeze(1.*GeV), theVirtualitySplittingScale(false), theCMWScheme(0), presampling(false) {} -DipoleSplittingKernel::~DipoleSplittingKernel() {} - - // initialize static variable out of line double DipoleSplittingKernel::theMaxPDFRatio = 1000000.; // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleSplittingKernel::persistentOutput(PersistentOStream & os) const { os << theAlphaS << ounit(theScreeningScale,GeV) << theSplittingKinematics << thePDFRatio << thePresamplingPoints << theMaxtry << theFreezeGrid << theDetuning << theFlavour << theMCCheck << theStrictLargeN << theFactorizationScaleFactor << theRenormalizationScaleFactor << ounit(theRenormalizationScaleFreeze,GeV) << ounit(theFactorizationScaleFreeze,GeV) << theVirtualitySplittingScale<> theAlphaS >> iunit(theScreeningScale,GeV) >> theSplittingKinematics >> thePDFRatio >> thePresamplingPoints >> theMaxtry >> theFreezeGrid >> theDetuning >> theFlavour >> theMCCheck >> theStrictLargeN >> theFactorizationScaleFactor >> theRenormalizationScaleFactor >> iunit(theRenormalizationScaleFreeze,GeV) >> iunit(theFactorizationScaleFreeze,GeV) >> theVirtualitySplittingScale>>theCMWScheme>>theUseThisKernel; } double DipoleSplittingKernel::alphaPDF(const DipoleSplittingInfo& split, Energy optScale, double rScaleFactor, double fScaleFactor) const { Energy pt = optScale == ZERO ? split.lastPt() : optScale; Energy2 scale = ZERO; if ( !virtualitySplittingScale() ) { scale = sqr(pt) + sqr(theScreeningScale); } else { scale = sqr(splittingKinematics()->QFromPt(pt,split)) + sqr(theScreeningScale); } Energy2 fScale = sqr(theFactorizationScaleFactor*fScaleFactor)*scale; fScale = max( fScale , sqr(factorizationScaleFreeze()) ); Energy2 rScale = sqr(theRenormalizationScaleFactor*rScaleFactor)*scale; rScale = max( rScale , sqr(renormalizationScaleFreeze()) ); if(split.calcFixedExpansion()){ fScale = max( sqr(split.fixedScale()) , sqr(factorizationScaleFreeze()) ); rScale = max( sqr(split.fixedScale()) , sqr(renormalizationScaleFreeze()) ); } double alphas = 1.0; double pdf = 1.0; // check if we are potentially reweighting and cache evaluations bool evaluatePDF = true; bool evaluateAlphaS = true; bool variations = !ShowerHandler::currentHandler()->showerVariations().empty() && !presampling; if ( variations ) { map::const_iterator pit = thePDFCache.find(fScaleFactor); evaluatePDF = (pit == thePDFCache.end()); if ( !evaluatePDF ) { pdf = pit->second; } map::const_iterator ait = theAlphaSCache.find(rScaleFactor); evaluateAlphaS = (ait == theAlphaSCache.end()); if ( !evaluateAlphaS ) { alphas = ait->second; } } if ( evaluateAlphaS ){ if (theCMWScheme==0||split.calcFixedExpansion()) { alphas = alphaS()->value(rScale); }else if(theCMWScheme==1){ alphas = alphaS()->value(rScale); alphas *=1.+(3.*(67./18.-1./6.*sqr(Constants::pi)) -5./9.*alphaS()->Nf(rScale))* alphas/2./Constants::pi; }else if(theCMWScheme==2){ double kg=exp(-(67.-3.*sqr(Constants::pi)-10/3*alphaS()->Nf(rScale)) /(33.-2.*alphaS()->Nf(rScale))); Energy2 cmwscale2=max(kg*rScale, sqr(renormalizationScaleFreeze()) ); alphas = alphaS()->value(cmwscale2); }else{ throw Exception() << "This CMW-Scheme is not implemented." << Exception::abortnow; } } if ( evaluatePDF ) { if ( split.index().initialStateEmitter() ) { assert(pdfRatio()); pdf *= split.lastEmitterZ() * (*pdfRatio())(split.index().emitterPDF(), fScale, split.index().emitterData(),split.emitterData(), split.emitterX(),split.lastEmitterZ()); } if ( split.index().initialStateSpectator() ) { assert(pdfRatio()); pdf *= split.lastSpectatorZ() * (*pdfRatio())(split.index().spectatorPDF(), fScale, split.index().spectatorData(),split.spectatorData(), split.spectatorX(),split.lastSpectatorZ()); } } if ( evaluatePDF && variations ) { thePDFCache[fScaleFactor] = min(pdf,theMaxPDFRatio); } if ( evaluateAlphaS && variations ) { theAlphaSCache[rScaleFactor] = alphas; } double ret = min(pdf,theMaxPDFRatio)* (split.calcFixedExpansion()? 1.:(alphas / (2.*Constants::pi))); if ( ret < 0. ) ret = 0.; return ret; } void DipoleSplittingKernel::accept(const DipoleSplittingInfo& split, double, double, map& weights) const { if ( ShowerHandler::currentHandler()->showerVariations().empty() ) return; double reference = alphaPDF(split); assert(reference > 0.); for ( map::const_iterator var = ShowerHandler::currentHandler()->showerVariations().begin(); var != ShowerHandler::currentHandler()->showerVariations().end(); ++var ) { if ( ( ShowerHandler::currentHandler()->firstInteraction() && var->second.firstInteraction ) || ( !ShowerHandler::currentHandler()->firstInteraction() && var->second.secondaryInteractions ) ) { double varied = alphaPDF(split,ZERO, var->second.renormalizationScaleFactor, var->second.factorizationScaleFactor); if ( varied != reference ) { map::iterator wi = weights.find(var->first); if ( wi != weights.end() ) wi->second *= varied/reference; else weights[var->first] = varied/reference; } } } } void DipoleSplittingKernel::veto(const DipoleSplittingInfo& split, double p, double r, map& weights) const { if ( ShowerHandler::currentHandler()->showerVariations().empty() ) return; double reference = alphaPDF(split); // this is dangerous, but we have no other choice currently -- need to // carefully check for the effects; the assumption is that if the central // one ius zero, then so will be the variations. if ( reference == 0.0 ) return; for ( map::const_iterator var = ShowerHandler::currentHandler()->showerVariations().begin(); var != ShowerHandler::currentHandler()->showerVariations().end(); ++var ) { if ( ( ShowerHandler::currentHandler()->firstInteraction() && var->second.firstInteraction ) || ( !ShowerHandler::currentHandler()->firstInteraction() && var->second.secondaryInteractions ) ) { double varied = alphaPDF(split,ZERO, var->second.renormalizationScaleFactor, var->second.factorizationScaleFactor); if ( varied != reference ) { map::iterator wi = weights.find(var->first); if ( wi != weights.end() ) wi->second *= (r - varied*p/reference) / (r-p); else weights[var->first] = (r - varied*p/reference) / (r-p); } } } } AbstractClassDescription DipoleSplittingKernel::initDipoleSplittingKernel; // Definition of the static class description member. void DipoleSplittingKernel::Init() { static ClassDocumentation documentation ("DipoleSplittingKernel is the base class for all kernels " "used within the dipole shower."); static Reference interfaceAlphaS ("AlphaS", "The strong coupling to be used by this splitting kernel.", &DipoleSplittingKernel::theAlphaS, false, false, true, true, false); static Parameter interfaceScreeningScale ("ScreeningScale", "A colour screening scale", &DipoleSplittingKernel::theScreeningScale, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Reference interfaceSplittingKinematics ("SplittingKinematics", "The splitting kinematics to be used by this splitting kernel.", &DipoleSplittingKernel::theSplittingKinematics, false, false, true, false, false); static Reference interfacePDFRatio ("PDFRatio", "Set the optional PDF ratio object to evaluate this kernel", &DipoleSplittingKernel::thePDFRatio, false, false, true, true, false); static Parameter interfacePresamplingPoints ("PresamplingPoints", "The number of points used to presample this kernel.", &DipoleSplittingKernel::thePresamplingPoints, 2000, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceMaxtry ("Maxtry", "The maximum number of attempts to generate a splitting.", &DipoleSplittingKernel::theMaxtry, 10000, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceFreezeGrid ("FreezeGrid", "", &DipoleSplittingKernel::theFreezeGrid, 500000, 1, 0, false, false, Interface::lowerlim); static Reference interfaceFlavour ("Flavour", "Set the flavour to be produced if ambiguous.", &DipoleSplittingKernel::theFlavour, false, false, true, true, false); static Reference interfaceMCCheck ("MCCheck", "[debug option] MCCheck", &DipoleSplittingKernel::theMCCheck, false, false, true, true, false); interfaceMCCheck.rank(-1); static Switch interfaceStrictLargeN ("StrictLargeN", "Work in a strict large-N limit.", &DipoleSplittingKernel::theStrictLargeN, false, false, false); static SwitchOption interfaceStrictLargeNYes (interfaceStrictLargeN, "Yes", "Replace C_F -> C_A/2 where present", true); static SwitchOption interfaceStrictLargeNNo (interfaceStrictLargeN, "No", "Keep C_F=4/3", false); interfaceStrictLargeN.rank(-2); static Switch interfaceCMWScheme ("CMWScheme", "Use the CMW Scheme related Kg expression to the splitting", &DipoleSplittingKernel::theCMWScheme, 0, false, false); static SwitchOption interfaceCMWSchemeNo (interfaceCMWScheme,"No","No CMW-Scheme", 0); static SwitchOption interfaceCMWSchemeLinear (interfaceCMWScheme,"Linear", "Linear CMW multiplication: alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi )",1); static SwitchOption interfaceCMWSchemeFactor (interfaceCMWScheme,"Factor", "Use factor in alpha_s argument: alpha_s(q) -> alpha_s(k_g*q) with kfac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) ",2); static Parameter interfaceFactorizationScaleFactor ("FactorizationScaleFactor", "The factorization scale factor.", &DipoleSplittingKernel::theFactorizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); interfaceFactorizationScaleFactor.rank(-2); static Parameter interfaceRenormalizationScaleFactor ("RenormalizationScaleFactor", "The renormalization scale factor.", &DipoleSplittingKernel::theRenormalizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); interfaceRenormalizationScaleFactor.rank(-2); static Parameter interfaceRenormalizationScaleFreeze ("RenormalizationScaleFreeze", "The freezing scale for the renormalization scale.", &DipoleSplittingKernel::theRenormalizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceFactorizationScaleFreeze ("FactorizationScaleFreeze", "The freezing scale for the factorization scale.", &DipoleSplittingKernel::theFactorizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Switch interfaceVirtualitySplittingScale ("VirtualitySplittingScale", "Use the virtuality as the splitting scale.", &DipoleSplittingKernel::theVirtualitySplittingScale, false, false, false); static SwitchOption interfaceVirtualitySplittingScaleYes (interfaceVirtualitySplittingScale, "Yes", "Use vrituality.", true); static SwitchOption interfaceVirtualitySplittingScaleNo (interfaceVirtualitySplittingScale, "No", "Use transverse momentum.", false); static Parameter interfaceDetuning ("Detuning", "A value to detune the overestimate kernel.", &DipoleSplittingKernel::theDetuning, 1.0, 1.0, 0, false, false, Interface::lowerlim); static Switch interfaceUseThisKernel ("UseKernel", "Turn On and of the Kernel.", &DipoleSplittingKernel::theUseThisKernel, true, false, false); static SwitchOption interfaceUseThisKernelYes (interfaceUseThisKernel, "Yes", "Use this Kernel.", true); static SwitchOption interfaceUseThisKernelNo (interfaceUseThisKernel, "No", "Dont use this Kernel.", false); } diff --git a/Shower/Dipole/Kernels/DipoleSplittingKernel.h b/Shower/Dipole/Kernels/DipoleSplittingKernel.h --- a/Shower/Dipole/Kernels/DipoleSplittingKernel.h +++ b/Shower/Dipole/Kernels/DipoleSplittingKernel.h @@ -1,546 +1,538 @@ // -*- C++ -*- // // DipoleSplittingKernel.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_DipoleSplittingKernel_H #define HERWIG_DipoleSplittingKernel_H // // This is the declaration of the DipoleSplittingKernel class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/StandardModel/AlphaSBase.h" #include "ThePEG/PDF/PDF.h" #include "Herwig/Shower/Dipole/Utility/PDFRatio.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h" #include "ThePEG/EventRecord/RhoDMatrix.h" #include "Herwig/Decay/DecayMatrixElement.h" #include "Herwig/Decay/TwoBodyDecayMatrixElement.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleSplittingKernel is the base class for all kernels * used within the dipole shower. * * @see \ref DipoleSplittingKernelInterfaces "The interfaces" * defined for DipoleSplittingKernel. */ class DipoleSplittingKernel: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ DipoleSplittingKernel(); - /** - * The destructor. - */ - virtual ~DipoleSplittingKernel(); - //@} - public: /** * Return the alpha_s to be used */ Ptr::tptr alphaS() const { return theAlphaS; } /** * Set the alpha_s to be used */ void alphaS(Ptr::tptr ap) { theAlphaS = ap; } /** * Return the splitting kinematics object */ Ptr::tptr splittingKinematics() const { return theSplittingKinematics; } /** * Return the mc check object */ Ptr::ptr mcCheck() const { return theMCCheck; } /** * Set the splitting kinematics object */ void splittingKinematics(Ptr::tptr sp) { theSplittingKinematics = sp; } /** * Return the PDFRatio object */ Ptr::tptr pdfRatio() const { return thePDFRatio; } /** * Set the PDFRatio object */ void pdfRatio(Ptr::tptr sp) { thePDFRatio = sp; } /** * Return the number of additional parameter * random variables needed to evaluate this kernel * except the momentum fractions of incoming partons. * These will be accessible through the * lastSplittingParameters() container of the splitting * info object. */ virtual int nDimAdditional() const { return 0; } /** * Set the freezing value for the renormalization scale */ void renormalizationScaleFreeze(Energy s) { theRenormalizationScaleFreeze = s; } /** * Set the freezing value for the factorization scale */ void factorizationScaleFreeze(Energy s) { theFactorizationScaleFreeze = s; } /** * Get the freezing value for the renormalization scale */ Energy renormalizationScaleFreeze() const { return theRenormalizationScaleFreeze; } /** * Get the freezing value for the factorization scale */ Energy factorizationScaleFreeze() const { return theFactorizationScaleFreeze; } public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const = 0; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const = 0; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const = 0; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const = 0; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const = 0; /** * Return the flavour produced, if this cannot * be determined from the dipole. */ PDPtr flavour() const { return theFlavour; } /** * Return true, if this splitting kernel is supposed to work in a * strict large-N limit, i.e. replacing C_F by C_A/2 */ bool strictLargeN() const { return theStrictLargeN; } public: /** * Inform this splitting kernel, that it is being * presampled until a call to stopPresampling */ virtual void startPresampling(const DipoleIndex&) { presampling = true; } /** * Inform this splitting kernel, that it is not being * presampled until a call to startPresampling */ virtual void stopPresampling(const DipoleIndex&) { presampling = false; } /** * Return the number of points to presample this * splitting generator. */ unsigned long presamplingPoints() const { return thePresamplingPoints; } /** * Return the maximum number of trials * to generate a splitting. */ unsigned long maxtry() const { return theMaxtry; } /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long freezeGrid() const { return theFreezeGrid; } /** * Set the number of accepted points after which the grid should * be frozen */ void freezeGrid(unsigned long n) { theFreezeGrid = n; } /** * Set a detuning factor to be applied to the sampling overestimate kernel */ void detuning(double d) { theDetuning = d; } /** * Return the detuning factor applied to the sampling overestimate kernel */ double detuning() const { return theDetuning; } /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const = 0; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const = 0; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const = 0; /** * Clear the alphaPDF cache */ void clearAlphaPDFCache() const { theAlphaSCache.clear(); thePDFCache.clear(); } /** * Update the variations vector at the given splitting using the indicated * kernel and overestimate values. */ virtual void accept(const DipoleSplittingInfo&, double, double, map&) const; /** * Update the variations vector at the given splitting using the indicated * kernel and overestimate values. */ virtual void veto(const DipoleSplittingInfo&, double, double, map&) const; /** * Return true, if this kernel is capable of * delivering an overestimate to the kernel, and * of inverting the integral over the overestimate * w.r.t. the phasepsace provided by the given * DipoleSplittingInfo object. */ virtual bool haveOverestimate(const DipoleSplittingInfo&) const { return false; } /** * Return the overestimate to this splitting kernel * for the given dipole splitting. */ virtual double overestimate(const DipoleSplittingInfo&) const { return -1.; } /** * Invert the integral over the overestimate * w.r.t. the phasepsace provided by the given * DipoleSplittingInfo object to equal * the given value. */ virtual double invertOverestimateIntegral(const DipoleSplittingInfo&, double) const { return -1.; } /** * . */ bool useThisKernel() const { return theUseThisKernel; } 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; } /** * Return the CMW sheme used by the kernel */ unsigned int cmwScheme() const {return theCMWScheme;} protected: /** * Return the common factor of (alphas/2pi)*(pdf ratio) */ double alphaPDF(const DipoleSplittingInfo&, Energy optScale = ZERO, double rScaleFactor = 1.0, double fScaleFactor = 1.0) const; /** * Return true, if the virtuality of the splitting should be used as the * argument of alphas rather than the pt */ bool virtualitySplittingScale() const { return theVirtualitySplittingScale; } 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 alpha_s to be used. */ Ptr::ptr theAlphaS; /** * An optional 'colour screening' scale * for alternative intrinsic pt generation. */ Energy theScreeningScale; /** * The splitting kinematics to be used. */ Ptr::ptr theSplittingKinematics; /** * An optional PDF ratio object to be used * when evaluating this kernel. */ Ptr::ptr thePDFRatio; /** * The number of points to presample this * splitting generator. */ unsigned long thePresamplingPoints; /** * The maximum number of trials * to generate a splitting. */ unsigned long theMaxtry; /** * The maximum value for any pdf ratio. * TODO: JB:Should this be an interfaced value? Is there a reasobable case where it should be allowed to be bigger than 1000000.? */ static double theMaxPDFRatio; /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long theFreezeGrid; /** * The detuning factor applied to the sampling overestimate kernel */ double theDetuning; /** * The flavour produced, if this cannot * be determined from the dipole. */ PDPtr theFlavour; /** * Pointer to a check histogram object */ Ptr::ptr theMCCheck; /** * True, if this splitting kernel is supposed to work in a * strict large-N limit, i.e. replacing C_F by C_A/2 */ bool theStrictLargeN; /** * The factorization scale factor. */ double theFactorizationScaleFactor; /** * The renormalization scale factor. */ double theRenormalizationScaleFactor; /** * A freezing value for the renormalization scale */ Energy theRenormalizationScaleFreeze; /** * A freezing value for the factorization scale */ Energy theFactorizationScaleFreeze; /** * True, if the virtuality of the splitting should be used as the * argument of alphas rather than the pt */ bool theVirtualitySplittingScale; /** * Implementing CMW in the kernels. **/ unsigned int theCMWScheme=0; /** * Cache for alphas evaluations */ mutable map theAlphaSCache; /** * Cache for PDF evaluations */ mutable map thePDFCache; /** * True, if we are presampling */ bool presampling; /** * True, if the kernel should be used */ bool theUseThisKernel = true; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initDipoleSplittingKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleSplittingKernel & operator=(const DipoleSplittingKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleSplittingKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleSplittingKernel. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleSplittingKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleSplittingKernel"; } /** * The name of a file containing the dynamic library where the class * DipoleSplittingKernel is implemented. It may also include several, space-separated, * libraries if the class DipoleSplittingKernel 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_DipoleSplittingKernel_H */ diff --git a/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc @@ -1,196 +1,194 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FFMgx2ggxDipoleKernel class. // #include "FFMgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FFMgx2ggxDipoleKernel::FFMgx2ggxDipoleKernel() : DipoleSplittingKernel(){} -FFMgx2ggxDipoleKernel::~FFMgx2ggxDipoleKernel() {} - IBPtr FFMgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FFMgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FFMgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() != ZERO && !ind.initialStateEmitter() && !ind.initialStateSpectator() && !ind.incomingDecayEmitter() && !ind.incomingDecaySpectator(); } bool FFMgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g && abs(spectator(a)->mass()) == abs(sk.spectator(b)->mass()); } tcPDPtr FFMgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFMgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFMgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FFMgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // Sudakov parameterisation variables, // needed to calculate y. double z = split.lastZ(); Energy pt = split.lastPt(); // Construct mass squared variables Energy2 Qijk = sqr(split.scale()); Energy2 mk2 = sqr(split.spectatorMass()); Energy2 sbar = Qijk - mk2; // Calculate y double y = sqr(pt) / sbar / z / (1.-z); double vijk = sqrt( sqr(2.*mk2 + sbar*(1.-y)) - 4.*mk2*Qijk ) / sbar / (1.-y); double viji = 1.; // zi, used in dipole splitting kernel double zi = split.lastSplittingParameters()[0]; double zip = 0.5*(1.+viji*vijk); double zim = 0.5*(1.-viji*vijk); // how to choose kappa? double kappa = 0.; double S1=1./(1.-zi*(1.-y)); double S2=1./(1.-(1.-zi)*(1.-y)); double NS=(zi*(1.-zi)-(1.-kappa)*zip*zim-2.)/vijk; if( theAsymmetryOption == 0 ){ ret *= 3.*( S1 + 0.5 * NS); }else if ( theAsymmetryOption == 1 ){ ret *= 3.*zi*( S1 +S2 + NS ); }else{ ret *= 3.*0.5*( S1 + S2 + NS ); } return ret > 0. ? ret : 0.; } vector< pair > FFMgx2ggxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { // Need variables for the AP kernels double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_pmp = (1.-z)*sqrt( (1.-z)/z ); //double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp)) - 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp))/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FFMgx2ggxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { // Need variables for the AP kernels double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_pmp = (1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(2,2,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(2,2,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,2) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,2) = 0; (*kernelPhiDep)(2,0,0) = 0; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFMgx2ggxDipoleKernel::persistentOutput(PersistentOStream & os) const { os << theAsymmetryOption; } void FFMgx2ggxDipoleKernel::persistentInput(PersistentIStream & is, int) { is >> theAsymmetryOption; } ClassDescription FFMgx2ggxDipoleKernel::initFFMgx2ggxDipoleKernel; // Definition of the static class description member. void FFMgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("FFMgx2ggxDipoleKernel"); static Parameter interfacetheAsymmetryOption ("AsymmetryOption", "The asymmetry option for final state gluon spliitings.", &FFMgx2ggxDipoleKernel::theAsymmetryOption, 1, 0, 0, false, false, Interface::lowerlim); } diff --git a/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h @@ -1,198 +1,190 @@ // -*- C++ -*- #ifndef HERWIG_FFMgx2ggxDipoleKernel_H #define HERWIG_FFMgx2ggxDipoleKernel_H // // This is the declaration of the FFMgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll, Stephen Webster * * \brief FFMgx2ggxDipoleKernel implements the g -> gg * splitting off a final-final dipole * */ class FFMgx2ggxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFMgx2ggxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FFMgx2ggxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * Asymmetry option for final state gluon splittings. */ int theAsymmetryOption=1; /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFMgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMgx2ggxDipoleKernel & operator=(const FFMgx2ggxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFMgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFMgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FFMgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFMgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FFMgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FFMgx2ggxDipoleKernel 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_FFMgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.cc @@ -1,195 +1,193 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FFMgx2qqxDipoleKernel class. // #include "FFMgx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FFMgx2qqxDipoleKernel::FFMgx2qqxDipoleKernel() : DipoleSplittingKernel() {} -FFMgx2qqxDipoleKernel::~FFMgx2qqxDipoleKernel() {} - IBPtr FFMgx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FFMgx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FFMgx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && !( ind.spectatorData()->mass() == ZERO && flavour()->mass() == ZERO ) && !ind.initialStateEmitter() && !ind.initialStateSpectator() && !ind.incomingDecayEmitter() && !ind.incomingDecaySpectator(); } bool FFMgx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() + sk.emission(b)->id() == 0 && abs(sk.emitter(b)->id()) < 6 && emitter(a)->id() == sk.emitter(b)->id() && abs(sk.spectator(b)->mass()) == abs(spectator(a)->mass()); } tcPDPtr FFMgx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6); return flavour(); } tcPDPtr FFMgx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6); return flavour()->CC(); } tcPDPtr FFMgx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FFMgx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // Sudakov parameterisation variables, // needed to calculate y. double z = split.lastZ(); Energy pt = split.lastPt(); // Construct mass squared variables Energy2 Qijk = sqr(split.scale()); Energy2 mi2 = sqr(split.emitterData()->mass()); Energy2 mj2 = mi2; Energy2 mk2 = sqr(split.spectatorMass()); Energy2 sbar = Qijk - mi2 - mj2 - mk2; // Calculate y double y = (sqr(pt) + sqr(1.-z)*mi2 + sqr(z)*mj2) / sbar / z / (1.-z); // zi, used in dipole splitting kernel double zi = split.lastSplittingParameters()[0]; double vijk = sqrt( sqr(2.*mk2 + sbar*(1.-y)) - 4.*mk2*Qijk ) / sbar / (1.-y); double viji = sqrt( sqr(sbar*y) - 4.*sqr(mi2) ) / (sbar*y + 2.*mi2); double zip = 0.5*(1.+viji*vijk); double zim = 0.5*(1.-viji*vijk); // how to choose kappa?? double kappa = 0.; ret *= 0.25 / vijk * ( 1. - 2.*( zi*(1.-zi) - (1.-kappa)*zip*zim - kappa*mi2 / ( 2.*mi2 + (Qijk - 2.*mi2 - mk2)*y) ) ); return ret > 0. ? ret : 0.; } vector< pair > FFMgx2qqxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { // Need variables for the AP kernels double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy2 mi2 = sqr(dInfo.emitterData()->mass()); // Altarelli-Parisi spin-indexed kernels: double ratio = mi2 / ( mi2 + sqr(pt) ); double root = sqrt(1.-ratio); double v_AP_ppp = sqrt(ratio); double v_AP_ppm = z*root; double v_AP_pmp = -(1.-z)*root; //double v_AP_mmm = v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp)) + 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp) )/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FFMgx2qqxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { // Need variables for the AP kernels double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy2 mi2 = sqr(dInfo.emitterData()->mass()); // Altarelli-Parisi spin-indexed kernels: double ratio = mi2 / ( mi2 + sqr(pt) ); double root = sqrt(1.-ratio); double v_AP_ppp = sqrt(ratio); double v_AP_ppm = z*root; double v_AP_pmp = -(1.-z)*root; double v_AP_mmm = v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm; (*kernelPhiDep)(2,1,1) = v_AP_ppp; (*kernelPhiDep)(0,0,1) = v_AP_mmp/phase; (*kernelPhiDep)(2,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,1,1) = 0.; (*kernelPhiDep)(2,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFMgx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FFMgx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FFMgx2qqxDipoleKernel::initFFMgx2qqxDipoleKernel; // Definition of the static class description member. void FFMgx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("FFMgx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.h --- a/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FFMgx2qqxDipoleKernel_H #define HERWIG_FFMgx2qqxDipoleKernel_H // // This is the declaration of the FFMgx2qqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll, Stephen Webster * * \brief FFMgx2qqxDipoleKernel implements the g -> qqbar * splitting off a final-final dipole * */ class FFMgx2qqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFMgx2qqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FFMgx2qqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFMgx2qqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMgx2qqxDipoleKernel & operator=(const FFMgx2qqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFMgx2qqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFMgx2qqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FFMgx2qqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFMgx2qqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FFMgx2qqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FFMgx2qqxDipoleKernel 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_FFMgx2qqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.cc @@ -1,169 +1,167 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FFMqx2qgxDipoleKernel class. // #include "FFMqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FFMqx2qgxDipoleKernel::FFMqx2qgxDipoleKernel() : DipoleSplittingKernel() {} -FFMqx2qgxDipoleKernel::~FFMqx2qgxDipoleKernel() {} - IBPtr FFMqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FFMqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FFMqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 7 && // 2012-05-01 abs(ind.emitterData()->id()) == abs(flavour()->id()) && !( ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() == ZERO ) && !ind.initialStateEmitter() && !ind.initialStateSpectator() && !ind.incomingDecayEmitter() && !ind.incomingDecaySpectator(); } bool FFMqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emission(b)->id() == ParticleID::g && abs(sk.emitter(b)->id()) < 7 && abs(sk.emitter(b)->mass()) == abs(emitter(a)->mass()) && abs(sk.spectator(b)->mass()) == abs(spectator(a)->mass()); } // 2012-05-01 tcPDPtr FFMqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { assert(flavour()); assert(abs(flavour()->id())<7); return ind.emitterData()->id() > 0 ? (tcPDPtr) flavour() : (tcPDPtr) flavour()->CC(); } tcPDPtr FFMqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFMqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FFMqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // Sudakov parameterisation variables, // needed to calculate y. double z = split.lastZ(); Energy pt = split.lastPt(); // Construct mass squared variables // Note for q->qg can use the emitterMass // (i.e. mass of emitter before splitting = mass of emitter after) Energy2 Qijk = sqr(split.scale()); Energy2 mi2 = sqr(split.emitterMass()); Energy2 mk2 = sqr(split.spectatorMass()); Energy2 sbar = Qijk - mi2 - mk2; // Calculate y double y = (sqr(pt) + sqr(1.-z)*mi2) / sbar / z / (1.-z); // zi, used in dipole splitting kernel double zi = split.lastSplittingParameters()[0]; double vijk = sqrt( sqr(2.*mk2 + sbar*(1.-y)) - 4.*mk2*Qijk ) / sbar / (1.-y); double vtilde = sqrt( sqr(Qijk) + sqr(mi2) + sqr(mk2) - 2.*(mi2*Qijk + mk2*Qijk + mi2*mk2) ) / sbar; ret *= (!strictLargeN() ? 4./3. : 3./2.)* ( 2./(1.-zi*(1.-y)) - vtilde/vijk*( 1. + zi + 2.*mi2/sbar/y ) ); return ret > 0. ? ret : 0.; } vector< pair > FFMqx2qgxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr FFMqx2qgxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { // Need variables for the AP kernels double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy mi = dInfo.emitterMass(); // Altarelli-Parisi spin-indexed kernels: Energy den = sqrt(sqr(mi)*sqr(1.-z) + sqr(pt)); double v_AP_ppp = pt / den / sqrt(1.-z); double v_AP_ppm = - z * v_AP_ppp ; double v_AP_pmp = mi*(1.-z)*sqrt(1.-z) / den ; double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -1 or -1/2, 1=+1/2, 2 = +1 (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,1,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(1,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm; (*kernelPhiDep)(1,0,2) = v_AP_pmp; (*kernelPhiDep)(0,1,2) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFMqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FFMqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FFMqx2qgxDipoleKernel::initFFMqx2qgxDipoleKernel; // Definition of the static class description member. void FFMqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("FFMqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.h --- a/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FFMqx2qgxDipoleKernel_H #define HERWIG_FFMqx2qgxDipoleKernel_H // // This is the declaration of the FFMqx2qgxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll, Stephen Webster * * \brief FFMqx2qgxDipoleKernel implements the q -> qg * splitting off a final-final dipole * */ class FFMqx2qgxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFMqx2qgxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FFMqx2qgxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFMqx2qgxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMqx2qgxDipoleKernel & operator=(const FFMqx2qgxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFMqx2qgxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFMqx2qgxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FFMqx2qgxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFMqx2qgxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FFMqx2qgxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FFMqx2qgxDipoleKernel 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_FFMqx2qgxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc @@ -1,173 +1,171 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FFgx2ggxDipoleKernel class. // #include "FFgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FFgx2ggxDipoleKernel::FFgx2ggxDipoleKernel() : DipoleSplittingKernel(){} -FFgx2ggxDipoleKernel::~FFgx2ggxDipoleKernel() {} - IBPtr FFgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FFgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FFgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && !ind.initialStateEmitter() && !ind.initialStateSpectator(); } #ifndef NDEBUG bool FFgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, #else bool FFgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& , #endif const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g; } tcPDPtr FFgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FFgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double y = sqr(split.lastPt() / split.scale()) / (z*(1.-z)); double S1=1./(1.-z*(1.-y)); double S2=1./(1.-(1.-z)*(1.-y)); double NS=(-2 + z*(1.-z)); if( theAsymmetryOption == 0 ){ ret *= 3.*( S1 + 0.5 * NS); }else if ( theAsymmetryOption == 1 ){ ret *= 3.*z*( S1 +S2 + NS ); }else{ ret *= 3.*0.5*( S1 + S2 + NS ); } return ret > 0. ? ret : 0.; } vector< pair > FFgx2ggxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_pmp = (1.-z)*sqrt( (1.-z)/z ); //double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp)) - 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp))/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FFgx2ggxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_pmp = (1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(2,2,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(2,2,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,2) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,2) = 0; (*kernelPhiDep)(2,0,0) = 0; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFgx2ggxDipoleKernel::persistentOutput(PersistentOStream & os) const { os << theAsymmetryOption; } void FFgx2ggxDipoleKernel::persistentInput(PersistentIStream & is, int) { is >> theAsymmetryOption; } ClassDescription FFgx2ggxDipoleKernel::initFFgx2ggxDipoleKernel; // Definition of the static class description member. void FFgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("FFgx2ggxDipoleKernel"); static Parameter interfacetheAsymmetryOption ("AsymmetryOption", "The asymmetry option for final state gluon spliitings.", &FFgx2ggxDipoleKernel::theAsymmetryOption, 1, 0, 0, false, false, Interface::lowerlim); } diff --git a/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h @@ -1,198 +1,190 @@ // -*- C++ -*- #ifndef HERWIG_FFgx2ggxDipoleKernel_H #define HERWIG_FFgx2ggxDipoleKernel_H // // This is the declaration of the FFgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FFgx2ggxDipoleKernel implements the g -> gg * splitting off a final-final dipole * */ class FFgx2ggxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFgx2ggxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FFgx2ggxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFgx2ggxDipoleKernel & operator=(const FFgx2ggxDipoleKernel &) = delete; /** * Asymmetry option for final state gluon splittings. */ int theAsymmetryOption=1; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FFgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FFgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FFgx2ggxDipoleKernel 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_FFgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.cc @@ -1,158 +1,156 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FFgx2qqxDipoleKernel class. // #include "FFgx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FFgx2qqxDipoleKernel::FFgx2qqxDipoleKernel() : DipoleSplittingKernel() {} -FFgx2qqxDipoleKernel::~FFgx2qqxDipoleKernel() {} - IBPtr FFgx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FFgx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FFgx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && flavour()->mass() == ZERO && !ind.initialStateEmitter() && !ind.initialStateSpectator(); } #ifndef NDEBUG bool FFgx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, #else bool FFgx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& , #endif const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() + sk.emission(b)->id() == 0 && abs(sk.emitter(b)->id()) < 6 && sk.emitter(b)->mass() == ZERO; } tcPDPtr FFgx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour(); } tcPDPtr FFgx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour()->CC(); } tcPDPtr FFgx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FFgx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); ret *= .25 * ( 1. - 2.*z*(1.-z) ); return ret > 0. ? ret : 0.; } vector< pair > FFgx2qqxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppm = z; double v_AP_pmp = -(1.-z); double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppm) + sqr(v_AP_pmp)) + 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*( sqr(v_AP_ppm) + sqr(v_AP_pmp) )/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FFgx2qqxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppm = z; double v_AP_pmp = -(1.-z); double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = 0.; (*kernelPhiDep)(2,1,1) = 0.; (*kernelPhiDep)(0,0,1) = v_AP_mmp/phase; (*kernelPhiDep)(2,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,1,1) = 0.; (*kernelPhiDep)(2,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFgx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FFgx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FFgx2qqxDipoleKernel::initFFgx2qqxDipoleKernel; // Definition of the static class description member. void FFgx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("FFgx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.h --- a/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FFgx2qqxDipoleKernel_H #define HERWIG_FFgx2qqxDipoleKernel_H // // This is the declaration of the FFgx2qqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FFgx2qqxDipoleKernel implements the g -> qqbar * splitting off a final-final dipole * */ class FFgx2qqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFgx2qqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FFgx2qqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFgx2qqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFgx2qqxDipoleKernel & operator=(const FFgx2qqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFgx2qqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFgx2qqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FFgx2qqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFgx2qqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FFgx2qqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FFgx2qqxDipoleKernel 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_FFgx2qqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.cc @@ -1,139 +1,137 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FFqx2qgxDipoleKernel class. // #include "FFqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FFqx2qgxDipoleKernel::FFqx2qgxDipoleKernel() : DipoleSplittingKernel() {} -FFqx2qgxDipoleKernel::~FFqx2qgxDipoleKernel() {} - IBPtr FFqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FFqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FFqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 6 && ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() == ZERO && !ind.initialStateEmitter() && !ind.initialStateSpectator(); } #ifndef NDEBUG bool FFqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, #else bool FFqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& , #endif const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emission(b)->id() == ParticleID::g && abs(sk.emitter(b)->id()) < 6 && sk.emitter(b)->mass() == ZERO; } tcPDPtr FFqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { return ind.emitterData(); } tcPDPtr FFqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FFqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FFqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double y = sqr(split.lastPt() / split.scale()) / (z*(1.-z)); ret *= (!strictLargeN() ? 4./3. : 3./2.)*( 2./(1.-z*(1.-y)) - (1.+z) ); return ret > 0. ? ret : 0.; } vector< pair > FFqx2qgxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr FFqx2qgxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt( 1./(1.-z) ); double v_AP_ppm = -z/sqrt(1.-z); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -1 or -1/2, 1=+1/2, 2 = +1 (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,1,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(1,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = 0.; (*kernelPhiDep)(1,0,2) = 0.; (*kernelPhiDep)(0,1,2) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FFqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FFqx2qgxDipoleKernel::initFFqx2qgxDipoleKernel; // Definition of the static class description member. void FFqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("FFqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.h --- a/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FFqx2qgxDipoleKernel_H #define HERWIG_FFqx2qgxDipoleKernel_H // // This is the declaration of the FFqx2qgxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FFqx2qgxDipoleKernel implements the q -> qg * splitting off a final-final dipole * */ class FFqx2qgxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFqx2qgxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FFqx2qgxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFqx2qgxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFqx2qgxDipoleKernel & operator=(const FFqx2qgxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFqx2qgxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFqx2qgxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FFqx2qgxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFqx2qgxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FFqx2qgxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FFqx2qgxDipoleKernel 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_FFqx2qgxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.cc @@ -1,220 +1,218 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIMDecaygx2ggxDipoleKernel class. // #include "FIMDecaygx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIMDecaygx2ggxDipoleKernel::FIMDecaygx2ggxDipoleKernel() : DipoleSplittingKernel(){} -FIMDecaygx2ggxDipoleKernel::~FIMDecaygx2ggxDipoleKernel() {} - IBPtr FIMDecaygx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIMDecaygx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIMDecaygx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.incomingDecaySpectator() && !ind.incomingDecayEmitter() && ind.emitterData()->id() == ParticleID::g && !(ind.spectatorData()->mass() == ZERO) && // Initial state here refers to the entire event !ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool FIMDecaygx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emission(b)->id() == ParticleID::g && sk.emitter(b)->id() == ParticleID::g && abs(sk.spectator(b)->mass()) == abs(spectator(a)->mass()); } tcPDPtr FIMDecaygx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIMDecaygx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIMDecaygx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIMDecaygx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // Sudakov parameterisation variables, // needed to calculate y. double z = split.lastZ(); Energy pt = split.lastPt(); // Construct mass squared variables // Note for q->qg can use the emitterMass // (i.e. mass of emitter before splitting = mass of emitter after) Energy2 Qijk = sqr(split.scale()); Energy2 mk2 = sqr(split.recoilMass()); Energy2 sbar = Qijk - mk2; // Note this should be the same as Qijk Energy2 ma2 = sqr(split.spectatorMass()); // Calculate y double y = sqr(pt) / sbar / z / (1.-z); if( sqr(2.*mk2+sbar*(1.-y)) - 4.*mk2*Qijk < ZERO ){ generator()->logWarning( Exception() << "error in FIMDecayqx2qgxDipoleKernel::evaluate -- " << "mk2 " << mk2/GeV2 << " y " << y << Exception::warning ); return 0.0; } // zi, used in dipole splitting kernel double zi = split.lastSplittingParameters()[0]; double vijk = sqrt( sqr(2.*mk2 + sbar*(1.-y)) - 4.*mk2*Qijk ) / sbar / (1.-y); double vtilde = 1.; double viji = 1.; double zip = 0.5*(1.+viji*vijk); double zim = 0.5*(1.-viji*vijk); // how to choose kappa? double kappa = 0.; double S1 = 0.5*3.*(2.*y + 1.)/((1.+y)-zi*(1.-y)) + (!strictLargeN() ? 4./3. : 3./2.)* y/(1.-zi*(1.-y)) * ( 2.*(2.*y + 1.)/((1.+y)-zi*(1.-y)) - (vtilde/vijk)*(2. + 2.*ma2/((1.-zi*(1.-y))*sbar)) ); double S2 = 0.5*3.*(2.*y + 1.)/((1.+y)-(1.-zi)*(1.-y)) + (!strictLargeN() ? 4./3. : 3./2.)* y/(1.-(1.-zi)*(1.-y)) * ( 2.*(2.*y + 1.)/((1.+y)-(1.-zi)*(1.-y)) - (vtilde/vijk)*(2. + 2.*ma2/((1.-(1.-zi)*(1.-y))*sbar)) ); double NS = 0.5*3.*(zi*(1.-zi)-(1.-kappa)*zip*zim - 2.)/vijk; if( theAsymmetryOption == 0 ){ ret *= 2.*S1 + NS; }else if ( theAsymmetryOption == 1 ){ ret *= 2.*zi*( S1 + S2 + NS ); }else{ ret *= S1 + S2 + NS; } return ret > 0. ? ret : 0.; } vector< pair > FIMDecaygx2ggxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { // Need variables for the AP kernels double z = dInfo.lastSplittingParameters()[0]; // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_pmp = (1.-z)*sqrt( (1.-z)/z ); //double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp)) - 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp))/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FIMDecaygx2ggxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { // Need variables for the AP kernels double z = dInfo.lastSplittingParameters()[0]; // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_pmp = (1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(2,2,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(2,2,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,2) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,2) = 0; (*kernelPhiDep)(2,0,0) = 0; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMDecaygx2ggxDipoleKernel::persistentOutput(PersistentOStream & os) const { os<>theAsymmetryOption; } ClassDescription FIMDecaygx2ggxDipoleKernel::initFIMDecaygx2ggxDipoleKernel; // Definition of the static class description member. void FIMDecaygx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("FIMDecaygx2ggxDipoleKernel"); static Parameter interfacetheAsymmetryOption ("AsymmetryOption", "The asymmetry option for final state gluon spliitings.", &FIMDecaygx2ggxDipoleKernel::theAsymmetryOption, 0, 0, 0, false, false, Interface::lowerlim); } diff --git a/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIMDecaygx2ggxDipoleKernel.h @@ -1,197 +1,189 @@ // -*- C++ -*- #ifndef HERWIG_FIMDecaygx2ggxDipoleKernel_H #define HERWIG_FIMDecaygx2ggxDipoleKernel_H // // This is the declaration of the FIMDecaygx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Stephen Webster * * \brief FIMDecaygx2ggxDipoleKernel implements the g -> gg * splitting off a final-initial decay dipole and includes the * contribution from the splitting of the intial / decay particle * */ class FIMDecaygx2ggxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMDecaygx2ggxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FIMDecaygx2ggxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMDecaygx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMDecaygx2ggxDipoleKernel & operator=(const FIMDecaygx2ggxDipoleKernel &) = delete; /** * Asymmetry option for final state gluon splittings. */ int theAsymmetryOption=0; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMDecaygx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMDecaygx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMDecaygx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMDecaygx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIMDecaygx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIMDecaygx2ggxDipoleKernel 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_FIMDecaygx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.cc @@ -1,207 +1,205 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIMDecaygx2qqxDipoleKernel class. // #include "FIMDecaygx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIMDecaygx2qqxDipoleKernel::FIMDecaygx2qqxDipoleKernel() : DipoleSplittingKernel() {} -FIMDecaygx2qqxDipoleKernel::~FIMDecaygx2qqxDipoleKernel() {} - IBPtr FIMDecaygx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIMDecaygx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIMDecaygx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.incomingDecaySpectator() && !ind.incomingDecayEmitter() && ind.emitterData()->id() == ParticleID::g && !(ind.spectatorData()->mass() == ZERO) && // Initial state here refers to the entire event !ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool FIMDecaygx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() + sk.emission(b)->id() == 0 && abs(sk.emitter(b)->id()) < 6 && emitter(a)->id() == sk.emitter(b)->id() && abs(sk.spectator(b)->mass()) == abs(spectator(a)->mass()); } tcPDPtr FIMDecaygx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6); return flavour(); } tcPDPtr FIMDecaygx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6); return flavour()->CC(); } tcPDPtr FIMDecaygx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIMDecaygx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // Sudakov parameterisation variables, // needed to calculate y. double z = split.lastZ(); Energy pt = split.lastPt(); // Construct mass squared variables // Note for q->qg can use the emitterMass // (i.e. mass of emitter before splitting = mass of emitter after) Energy2 Qijk = sqr(split.scale()); Energy2 mi2 = sqr(split.emitterData()->mass()); Energy2 mj2 = mi2; Energy2 mk2 = sqr(split.recoilMass()); Energy2 sbar = Qijk - mi2 - mj2 - mk2; // Calculate y double y = (sqr(pt) + sqr(1.-z)*mi2 + sqr(z)*mj2) / sbar / z / (1.-z); if( sqr(2.*mk2+sbar*(1.-y)) - 4.*mk2*Qijk < ZERO ){ generator()->logWarning( Exception() << "error in FIMDecayqx2qgxDipoleKernel::evaluate -- " << "mk2 " << mk2/GeV2 << " mi2 " << mi2/GeV2 << " y " << y << Exception::warning ); return 0.0; } // zi, used in dipole splitting kernel double zi = split.lastSplittingParameters()[0]; double vijk = sqrt( sqr(2.*mk2 + sbar*(1.-y)) - 4.*mk2*Qijk ) / sbar / (1.-y); double viji = sqrt( sqr(sbar*y) - 4.*sqr(mi2) ) / (sbar*y + 2.*mi2); double zip = 0.5*(1.+viji*vijk); double zim = 0.5*(1.-viji*vijk); // how to choose kappa? double kappa = 0.; ret *= 0.25 / vijk * ( 1. - 2.*( zi*(1.-zi) - (1.-kappa)*zip*zim - kappa*mi2/(2.*mi2 + sbar*y) ) ); return ret > 0. ? ret : 0.; } vector< pair > FIMDecaygx2qqxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { // Need variables for the AP kernels double z = dInfo.lastSplittingParameters()[0]; Energy pt = dInfo.lastPt(); Energy2 mi2 = sqr(dInfo.emitterData()->mass()); // Altarelli-Parisi spin-indexed kernels: double ratio = mi2 / ( mi2 + sqr(pt) ); double root = sqrt(1.-ratio); double v_AP_ppp = sqrt(ratio); double v_AP_ppm = z*root; double v_AP_pmp = -(1.-z)*root; // double v_AP_mmm = v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp)) + 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp) )/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FIMDecaygx2qqxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { // Need variables for the AP kernels double z = dInfo.lastSplittingParameters()[0]; Energy pt = dInfo.lastPt(); Energy2 mi2 = sqr(dInfo.emitterData()->mass()); // Altarelli-Parisi spin-indexed kernels: double ratio = mi2 / ( mi2 + sqr(pt) ); double root = sqrt(1.-ratio); double v_AP_ppp = sqrt(ratio); double v_AP_ppm = z*root; double v_AP_pmp = -(1.-z)*root; double v_AP_mmm = v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm; (*kernelPhiDep)(2,1,1) = v_AP_ppp;; (*kernelPhiDep)(0,0,1) = v_AP_mmp/phase; (*kernelPhiDep)(2,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,1,1) = 0.; (*kernelPhiDep)(2,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMDecaygx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FIMDecaygx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FIMDecaygx2qqxDipoleKernel::initFIMDecaygx2qqxDipoleKernel; // Definition of the static class description member. void FIMDecaygx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("FIMDecaygx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIMDecaygx2qqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FIMDecaygx2qqxDipoleKernel_H #define HERWIG_FIMDecaygx2qqxDipoleKernel_H // // This is the declaration of the FIMDecaygx2qqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Stephen Webster * * \brief FIMDecaygx2qqxDipoleKernel implements the g -> qq * splitting off a final-initial decay dipole * */ class FIMDecaygx2qqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMDecaygx2qqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FIMDecaygx2qqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMDecaygx2qqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMDecaygx2qqxDipoleKernel & operator=(const FIMDecaygx2qqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMDecaygx2qqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMDecaygx2qqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMDecaygx2qqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMDecaygx2qqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIMDecaygx2qqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIMDecaygx2qqxDipoleKernel 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_FIMDecaygx2qqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.cc @@ -1,187 +1,185 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIMDecayqx2qgxDipoleKernel class. // #include "FIMDecayqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIMDecayqx2qgxDipoleKernel::FIMDecayqx2qgxDipoleKernel() : DipoleSplittingKernel() {} -FIMDecayqx2qgxDipoleKernel::~FIMDecayqx2qgxDipoleKernel() {} - IBPtr FIMDecayqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIMDecayqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIMDecayqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.incomingDecaySpectator() && !ind.incomingDecayEmitter() && abs(ind.emitterData()->id()) < 7 && // This line matches to the kernel declared in a .in file for the given emitter flavour abs(ind.emitterData()->id()) == abs(flavour()->id()) && !(ind.spectatorData()->mass() == ZERO) && // Initial state here refers to the entire event !ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool FIMDecayqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emission(b)->id() == ParticleID::g && abs(sk.emitter(b)->id()) < 7 && abs(sk.emitter(b)->mass()) == abs(emitter(a)->mass()) && abs(sk.spectator(b)->mass()) == abs(spectator(a)->mass()); } tcPDPtr FIMDecayqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { assert(flavour()); assert(abs(flavour()->id()) < 7); return ind.emitterData()->id() > 0 ? (tcPDPtr) flavour() : (tcPDPtr) flavour()->CC(); } tcPDPtr FIMDecayqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIMDecayqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIMDecayqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // Sudakov parameterisation variables, // needed to calculate y. double z = split.lastZ(); Energy pt = split.lastPt(); // Construct mass squared variables // Note for q->qg can use the emitterMass // (i.e. mass of emitter before splitting = mass of emitter after) Energy2 Qijk = sqr(split.scale()); Energy2 mi2 = sqr(split.emitterMass()); Energy2 mk2 = sqr(split.recoilMass()); Energy2 sbar = Qijk - mi2 - mk2; // Note this should be the same as Qijk Energy2 ma2 = sqr(split.spectatorMass()); // Calculate y double y = (sqr(pt) + sqr(1.-z)*mi2) / sbar / z / (1.-z); if( sqr(2.*mk2+sbar*(1.-y)) - 4.*mk2*Qijk < ZERO ){ generator()->logWarning( Exception() << "error in FIMDecayqx2qgxDipoleKernel::evaluate -- " << "mk2 " << mk2/GeV2 << " mi2 " << mi2/GeV2 << " y " << y << Exception::warning ); return 0.0; } // zi, used in dipole splitting kernel double zi = split.lastSplittingParameters()[0]; double vijk = sqrt( sqr(2.*mk2 + sbar*(1.-y)) - 4.*mk2*Qijk ) / sbar / (1.-y); double vtilde = sqrt( sqr(Qijk) + sqr(mi2) + sqr(mk2) - 2.*(mi2*Qijk + mk2*Qijk + mi2*mk2) ) / sbar; ret *= (!strictLargeN() ? 4./3. : 3./2.) * ( ( 2.*( 2.*mi2/sbar + 2.*y + 1. ) / ((1.+y) - zi*(1.-y)) - (vtilde/vijk) * ( (1.+zi) + 2.*mi2/y/sbar ) ) + y/(1. - zi*(1.-y)) * ( 2.*(2.*mi2/sbar + 2.*y + 1. ) / ((1.+y) - zi*(1.-y)) - (vtilde/vijk) * ( 2. + 2.*ma2/((1. - zi*(1.-y))*sbar) ) ) ); return ret > 0. ? ret : 0.; } vector< pair > FIMDecayqx2qgxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr FIMDecayqx2qgxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { // Need variables for the AP kernels double z = dInfo.lastSplittingParameters()[0]; Energy pt = dInfo.lastPt(); Energy mi = dInfo.emitterMass(); // Altarelli-Parisi spin-indexed kernels: Energy den = sqrt(sqr(mi)*sqr(1.-z) + sqr(pt)); double v_AP_ppp = pt / den / sqrt(1.-z); double v_AP_ppm = - z * v_AP_ppp ; double v_AP_pmp = mi*(1.-z)*sqrt(1.-z) / den ; double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -1 or -1/2, 1=+1/2, 2 = +1 (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,1,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(1,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm; (*kernelPhiDep)(1,0,2) = v_AP_pmp; (*kernelPhiDep)(0,1,2) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMDecayqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FIMDecayqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FIMDecayqx2qgxDipoleKernel::initFIMDecayqx2qgxDipoleKernel; // Definition of the static class description member. void FIMDecayqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("FIMDecayqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIMDecayqx2qgxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FIMDecayqx2qgxDipoleKernel_H #define HERWIG_FIMDecayqx2qgxDipoleKernel_H // // This is the declaration of the FIMDecayqx2qgxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Stephen Webster * * \brief FIMDecayqx2qgxDipoleKernel implements the q -> qg * splitting off a final-initial decay dipole and includes the * contribution from the splitting of the intial / decay particle * */ class FIMDecayqx2qgxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMDecayqx2qgxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FIMDecayqx2qgxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex& ind) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex& ind) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo& split) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMDecayqx2qgxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMDecayqx2qgxDipoleKernel & operator=(const FIMDecayqx2qgxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMDecayqx2qgxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMDecayqx2qgxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMDecayqx2qgxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMDecayqx2qgxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIMDecayqx2qgxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIMDecayqx2qgxDipoleKernel 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_FIMDecayqx2qgxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.cc @@ -1,180 +1,178 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIMgx2qqxDipoleKernel class. // #include "FIMgx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIMgx2qqxDipoleKernel::FIMgx2qqxDipoleKernel() : DipoleSplittingKernel() {} -FIMgx2qqxDipoleKernel::~FIMgx2qqxDipoleKernel() {} - IBPtr FIMgx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIMgx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIMgx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && flavour()->mass() != ZERO && !ind.initialStateEmitter() && ind.initialStateSpectator(); } bool FIMgx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() + sk.emission(b)->id() == 0 && abs(sk.emitter(b)->id()) < 6 && emitter(a)->mass() == sk.emitter(b)->mass() && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr FIMgx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() != ZERO); return flavour(); } tcPDPtr FIMgx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() != ZERO); return flavour()->CC(); } tcPDPtr FIMgx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } // TODO // assure split.scale() is sqrt(sbar) double FIMgx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // mi=m=mQ, Mi=0, mj=Mj=0 Energy2 mQ2 = sqr(split.emitterData()->mass()); double z = split.lastZ(); double x = 1./ ( 1. + ( sqr(split.lastPt()) + mQ2 ) / ( z*(1.-z) * sqr(split.scale()) ) ); double muQ2 = x * mQ2/sqr(split.scale()); double zm = .5 * ( 1. - sqrt( 1. - 4.*muQ2/(1.-x) ) ); double zp = .5 * ( 1. + sqrt( 1. - 4.*muQ2/(1.-x) ) ); ret *= .25 * (1.-2.*(zp-z)*(z-zm)); return ret > 0. ? ret : 0.; } vector< pair > FIMgx2qqxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy2 mi2 = sqr(dInfo.emitterData()->mass()); // Altarelli-Parisi spin-indexed kernels: double ratio = mi2 / ( mi2 + sqr(pt) ); double root = sqrt(1.-ratio); double v_AP_ppp = sqrt(ratio); double v_AP_ppm = z*root; double v_AP_pmp = -(1.-z)*root; //double v_AP_mmm = v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp)) + 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp) )/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FIMgx2qqxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy2 mi2 = sqr(dInfo.emitterData()->mass()); // Altarelli-Parisi spin-indexed kernels: double ratio = mi2 / ( mi2 + sqr(pt) ); double root = sqrt(1.-ratio); double v_AP_ppp = sqrt(ratio); double v_AP_ppm = z*root; double v_AP_pmp = -(1.-z)*root; double v_AP_mmm = v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm; (*kernelPhiDep)(2,1,1) = v_AP_ppp; (*kernelPhiDep)(0,0,1) = v_AP_mmp/phase; (*kernelPhiDep)(2,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,1,1) = 0.; (*kernelPhiDep)(2,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMgx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FIMgx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FIMgx2qqxDipoleKernel::initFIMgx2qqxDipoleKernel; // Definition of the static class description member. void FIMgx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("FIMgx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FIMgx2qqxDipoleKernel_H #define HERWIG_FIMgx2qqxDipoleKernel_H // // This is the declaration of the FIMgx2qqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll * * \brief FIMgx2qqxDipoleKernel implements the g -> qqbar * splitting off a final-initial dipole * */ class FIMgx2qqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMgx2qqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FIMgx2qqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMgx2qqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMgx2qqxDipoleKernel & operator=(const FIMgx2qqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMgx2qqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMgx2qqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMgx2qqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMgx2qqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIMgx2qqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIMgx2qqxDipoleKernel 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_FIMgx2qqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.cc @@ -1,155 +1,153 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIMqx2qgxDipoleKernel class. // #include "FIMqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIMqx2qgxDipoleKernel::FIMqx2qgxDipoleKernel() : DipoleSplittingKernel() {} -FIMqx2qgxDipoleKernel::~FIMqx2qgxDipoleKernel() {} - IBPtr FIMqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIMqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIMqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 7 && abs(ind.emitterData()->id())==abs(flavour()->id()) && ind.emitterData()->mass() != ZERO && ind.spectatorData()->mass() == ZERO && !ind.initialStateEmitter() && ind.initialStateSpectator(); } bool FIMqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emission(b)->id() == ParticleID::g && abs(sk.emitter(b)->id()) < 7 && sk.emitter(b)->mass() == emitter(a)->mass() && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr FIMqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { assert(flavour()); assert(abs(flavour()->id())<7 && flavour()->mass() != ZERO); return ind.emitterData()->id() > 0 ? (tcPDPtr) flavour() : (tcPDPtr) flavour()->CC(); } tcPDPtr FIMqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIMqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } // TODO // split.scale() should be sqrt(sbar) = sqrt( Mi2 - Q2 ) !!! double FIMqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); // Mi=mi=mQ, m=0, Mj=mj=0 Energy2 mQ2 = sqr(split.emitterMass()); double z = split.lastZ(); double x = 1. / ( 1. + ( sqr(split.lastPt()) + sqr(1.-z)*mQ2 ) / ( z*(1.-z) * sqr(split.scale()) ) ); // Simon has extra terms ret *= (!strictLargeN() ? 4./3. : 3./2.) * ( 2./(1.-z+(1.-x)) -(1.+z) - mQ2/sqr(split.scale()) * 2.*x/(1.-x) ); return ret > 0. ? ret : 0.; } vector< pair > FIMqx2qgxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr FIMqx2qgxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy mi = dInfo.emitterMass(); // Altarelli-Parisi spin-indexed kernels: Energy den = sqrt(sqr(mi)*sqr(1.-z) + sqr(pt)); double v_AP_ppp = pt / den / sqrt(1.-z); double v_AP_ppm = - z * v_AP_ppp ; double v_AP_pmp = mi*(1.-z)*sqrt(1.-z) / den ; double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -1 or -1/2, 1=+1/2, 2 = +1 (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,1,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(1,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm; (*kernelPhiDep)(1,0,2) = v_AP_pmp; (*kernelPhiDep)(0,1,2) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FIMqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FIMqx2qgxDipoleKernel::initFIMqx2qgxDipoleKernel; // Definition of the static class description member. void FIMqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("FIMqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FIMqx2qgxDipoleKernel_H #define HERWIG_FIMqx2qgxDipoleKernel_H // // This is the declaration of the FIMqx2qgxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll * * \brief FIMqx2qgxDipoleKernel implements the q -> qg * splitting off a final-initial dipole * */ class FIMqx2qgxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMqx2qgxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FIMqx2qgxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMqx2qgxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMqx2qgxDipoleKernel & operator=(const FIMqx2qgxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMqx2qgxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMqx2qgxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMqx2qgxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMqx2qgxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIMqx2qgxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIMqx2qgxDipoleKernel 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_FIMqx2qgxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc @@ -1,172 +1,170 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIgx2ggxDipoleKernel class. // #include "FIgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIgx2ggxDipoleKernel::FIgx2ggxDipoleKernel() : DipoleSplittingKernel() {} -FIgx2ggxDipoleKernel::~FIgx2ggxDipoleKernel() {} - IBPtr FIgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && !ind.initialStateEmitter() && ind.initialStateSpectator(); } bool FIgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr FIgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double x = 1. / ( 1. + sqr(split.lastPt()/split.scale()) / (z*(1.-z)) ); double S1=1./(1.-z+(1.-x)); double S2=1./(1.-(1.-z)+(1.-x)); double NS=(-2 + z*(1.-z)+(1.-x)*(1.+x*z*(1.-z))); if( theAsymmetryOption == 0 ){ ret *= 3.*( S1 + 0.5 * NS); }else if ( theAsymmetryOption == 1 ){ ret *= 3.*z*( S1 +S2 + NS ); }else{ ret *= 3.*0.5*( S1 + S2 + NS ); } return ret > 0. ? ret : 0.; } vector< pair > FIgx2ggxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_pmp = (1.-z)*sqrt( (1.-z)/z ); //double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp)) - 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_pmp))/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FIgx2ggxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_pmp = (1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(2,2,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(2,2,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,2) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,2) = 0; (*kernelPhiDep)(2,0,0) = 0; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIgx2ggxDipoleKernel::persistentOutput(PersistentOStream & os) const { os << theAsymmetryOption; } void FIgx2ggxDipoleKernel::persistentInput(PersistentIStream & is, int) { is >> theAsymmetryOption; } ClassDescription FIgx2ggxDipoleKernel::initFIgx2ggxDipoleKernel; // Definition of the static class description member. void FIgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("FIgx2ggxDipoleKernel"); static Parameter interfacetheAsymmetryOption ("AsymmetryOption", "The asymmetry option for final state gluon spliitings.", &FIgx2ggxDipoleKernel::theAsymmetryOption, 1, 0, 0, false, false, Interface::lowerlim); } diff --git a/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h @@ -1,197 +1,189 @@ // -*- C++ -*- #ifndef HERWIG_FIgx2ggxDipoleKernel_H #define HERWIG_FIgx2ggxDipoleKernel_H // // This is the declaration of the FIgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FIgx2ggxDipoleKernel implements the g -> gg * splitting off a final-initial dipole * */ class FIgx2ggxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIgx2ggxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FIgx2ggxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * Asymmetry option for final state gluon splittings. */ int theAsymmetryOption=1; /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIgx2ggxDipoleKernel & operator=(const FIgx2ggxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIgx2ggxDipoleKernel 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_FIgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.cc @@ -1,155 +1,153 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIgx2qqxDipoleKernel class. // #include "FIgx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIgx2qqxDipoleKernel::FIgx2qqxDipoleKernel() : DipoleSplittingKernel() {} -FIgx2qqxDipoleKernel::~FIgx2qqxDipoleKernel() {} - IBPtr FIgx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIgx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIgx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && flavour()->mass() == ZERO && !ind.initialStateEmitter() && ind.initialStateSpectator(); } bool FIgx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() + sk.emission(b)->id() == 0 && abs(sk.emitter(b)->id()) < 6 && // sk.emitter(b)->mass() == ZERO && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr FIgx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour(); } tcPDPtr FIgx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour()->CC(); } tcPDPtr FIgx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIgx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); ret *= .25 * (1.-2.*z*(1.-z)); return ret > 0. ? ret : 0.; } vector< pair > FIgx2qqxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppm = z; double v_AP_pmp = -(1.-z); double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppm) + sqr(v_AP_pmp)) + 2.*abs(rho(0,2))*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*( sqr(v_AP_ppm) + sqr(v_AP_pmp) )/max ) ); distPhiDep.push_back( make_pair(-2, rho(0,2)*(v_AP_mpm*v_AP_ppm + v_AP_mmp*v_AP_pmp)/max ) ); distPhiDep.push_back( make_pair(2, rho(2,0)*(v_AP_ppm*v_AP_mpm + v_AP_pmp*v_AP_mmp)/max) ); return distPhiDep; } DecayMEPtr FIgx2qqxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppm = z; double v_AP_pmp = -(1.-z); double v_AP_mmp = -v_AP_ppm; double v_AP_mpm = -v_AP_pmp; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = 0.; (*kernelPhiDep)(2,1,1) = 0.; (*kernelPhiDep)(0,0,1) = v_AP_mmp/phase; (*kernelPhiDep)(2,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,1,1) = 0.; (*kernelPhiDep)(2,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIgx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FIgx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FIgx2qqxDipoleKernel::initFIgx2qqxDipoleKernel; // Definition of the static class description member. void FIgx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("FIgx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FIgx2qqxDipoleKernel_H #define HERWIG_FIgx2qqxDipoleKernel_H // // This is the declaration of the FIgx2qqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FIgx2qqxDipoleKernel implements the g -> qqbar * splitting off a final-initial dipole * */ class FIgx2qqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIgx2qqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FIgx2qqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIgx2qqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIgx2qqxDipoleKernel & operator=(const FIgx2qqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIgx2qqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIgx2qqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIgx2qqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIgx2qqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIgx2qqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIgx2qqxDipoleKernel 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_FIgx2qqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.cc @@ -1,138 +1,136 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the FIqx2qgxDipoleKernel class. // #include "FIqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; FIqx2qgxDipoleKernel::FIqx2qgxDipoleKernel() : DipoleSplittingKernel() {} -FIqx2qgxDipoleKernel::~FIqx2qgxDipoleKernel() {} - IBPtr FIqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr FIqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool FIqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 6 && ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() == ZERO && !ind.initialStateEmitter() && ind.initialStateSpectator(); } bool FIqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emission(b)->id() == ParticleID::g && abs(sk.emitter(b)->id()) < 6 && sk.emitter(b)->mass() == ZERO && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr FIqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { return ind.emitterData(); } tcPDPtr FIqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr FIqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double FIqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double x = 1. / ( 1. + sqr(split.lastPt()/split.scale()) / (z*(1.-z)) ); ret *= (!strictLargeN() ? 4./3. : 3./2.) * ( 2./(1.-z+(1.-x)) -(1.+z) + (1.-x)*(1.+3.*x*z) ); return ret > 0. ? ret : 0.; } vector< pair > FIqx2qgxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr FIqx2qgxDipoleKernel::matrixElement( const DipoleSplittingInfo& dInfo ) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt( 1./(1.-z) ); double v_AP_ppm = -z/sqrt(1.-z); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -1 or -1/2, 1=+1/2, 2 = +1 (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,1,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(1,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = 0.; (*kernelPhiDep)(1,0,2) = 0.; (*kernelPhiDep)(0,1,2) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void FIqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription FIqx2qgxDipoleKernel::initFIqx2qgxDipoleKernel; // Definition of the static class description member. void FIqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("FIqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.h --- a/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.h +++ b/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_FIqx2qgxDipoleKernel_H #define HERWIG_FIqx2qgxDipoleKernel_H // // This is the declaration of the FIqx2qgxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FIqx2qgxDipoleKernel implements the q -> qg * splitting off a final-initial dipole * */ class FIqx2qgxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIqx2qgxDipoleKernel(); - /** - * The destructor. - */ - virtual ~FIqx2qgxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIqx2qgxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIqx2qgxDipoleKernel & operator=(const FIqx2qgxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIqx2qgxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIqx2qgxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the FIqx2qgxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIqx2qgxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * FIqx2qgxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class FIqx2qgxDipoleKernel 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_FIqx2qgxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.cc @@ -1,165 +1,163 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IFMgx2ggxDipoleKernel class. // #include "IFMgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IFMgx2ggxDipoleKernel::IFMgx2ggxDipoleKernel() : DipoleSplittingKernel() {} -IFMgx2ggxDipoleKernel::~IFMgx2ggxDipoleKernel() {} - IBPtr IFMgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IFMgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IFMgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() != ZERO && ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool IFMgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g && a.emitterPDF() == b.emitterPDF() && sk.spectator(b)->mass() == spectator(a)->mass(); } tcPDPtr IFMgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IFMgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IFMgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IFMgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); Energy pt = split.lastPt(); double ratio = sqr(pt/split.scale()); double muk2 = sqr(split.spectatorMass()/split.scale()); // Calculate x and u double rho = 1. - 4.*ratio*(1.-muk2)*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/(ratio*(1.-muk2))) * (1. - sqrt(rho)); double u = x*ratio / (1.-z); // NOTE - The definition of muk used in the kinematics differs from that in CS double muk2CS = x*muk2; ret *= 3. * ( 1./(1.-x+u) - 1. + x*(1.-x) + (1.-x)/x - muk2CS*u/(x*(1.-u)) ); return ret > 0. ? ret : 0.; } vector< pair > IFMgx2ggxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_mpm = -(1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; //double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_mpm)) - 2.*abs(rho(0,2))*(v_AP_ppp*v_AP_pmp + v_AP_mmm*v_AP_mpm); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_mpm))/max ) ); distPhiDep.push_back( make_pair(2, rho(0,2)*(v_AP_mmm*v_AP_mpm + v_AP_pmp*v_AP_ppp)/max ) ); distPhiDep.push_back( make_pair(-2, rho(2,0)*(v_AP_ppp*v_AP_pmp + v_AP_mpm*v_AP_mmm)/max) ); return distPhiDep; } DecayMEPtr IFMgx2ggxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_mpm = -(1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1, PDT::Spin1, PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(2,2,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(2,2,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,2) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,2) = 0; (*kernelPhiDep)(2,0,0) = 0; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFMgx2ggxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IFMgx2ggxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IFMgx2ggxDipoleKernel::initIFMgx2ggxDipoleKernel; // Definition of the static class description member. void IFMgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("IFMgx2ggxDipoleKernelv"); } diff --git a/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IFMgx2ggxDipoleKernel_H #define HERWIG_IFMgx2ggxDipoleKernel_H // // This is the declaration of the IFMgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll * * \brief IFMgx2ggxDipoleKernel implements the g -> gg * splitting off an initial-final dipole * */ class IFMgx2ggxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMgx2ggxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IFMgx2ggxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFMgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMgx2ggxDipoleKernel & operator=(const IFMgx2ggxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFMgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFMgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IFMgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFMgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IFMgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IFMgx2ggxDipoleKernel 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_IFMgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.cc @@ -1,168 +1,166 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IFMgx2qqxDipoleKernel class. // #include "IFMgx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IFMgx2qqxDipoleKernel::IFMgx2qqxDipoleKernel() : DipoleSplittingKernel() {} -IFMgx2qqxDipoleKernel::~IFMgx2qqxDipoleKernel() {} - IBPtr IFMgx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IFMgx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IFMgx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() != ZERO && flavour()->mass() == ZERO && ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool IFMgx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return flavour() == sk.flavour() && abs(flavour()->id()) < 6 && flavour()->mass() == ZERO && spectator(a)->mass() == sk.spectator(b)->mass() && a.emitterPDF() == b.emitterPDF(); } tcPDPtr IFMgx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour(); } tcPDPtr IFMgx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour(); } tcPDPtr IFMgx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IFMgx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); Energy pt = split.lastPt(); double ratio = sqr(pt/split.scale()); double muk2 = sqr(split.spectatorMass()/split.scale()); // Calculate x and u double rho = 1. - 4.*ratio*(1.-muk2)*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/(ratio*(1.-muk2))) * (1. - sqrt(rho)); double u = x*ratio / (1.-z); // NOTE - The definition of muk used in the kinematics differs from that in CS double muk2CS = x*muk2; ret *= 0.5 * (!strictLargeN() ? 4./3. : 3./2.) * ( x + 2.*(1.-x)/x - 2.*muk2CS/x*u/(1.-u) ); return ret > 0. ? ret : 0.; } vector< pair > IFMgx2qqxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt(1./z); double v_AP_mpm = (1.-z)/sqrt(z); double v_AP_mmm = -v_AP_ppp; double v_AP_pmp = -v_AP_mpm; // Initialise variables for the distributions vector< pair > distPhiDep; double max = sqr(v_AP_ppp) + sqr(v_AP_mpm) - 2.*abs(rho(0,2))*(v_AP_pmp*v_AP_ppp + v_AP_mmm*v_AP_mpm); distPhiDep.push_back(make_pair( 0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_mpm))/max ) ); distPhiDep.push_back(make_pair( 2, rho(0,2)*(v_AP_pmp*v_AP_ppp + v_AP_mmm*v_AP_mpm )/max ) ); distPhiDep.push_back(make_pair( -2, rho(2,0)*(v_AP_ppp*v_AP_pmp + v_AP_mpm*v_AP_mmm )/max ) ); return distPhiDep; } DecayMEPtr IFMgx2qqxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt(1./z); double v_AP_mpm = (1.-z)/sqrt(z); double v_AP_mmm = -v_AP_ppp; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half, PDT::Spin1, PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -1 or -1/2, 1=+1/2, 2 = +1 (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,2,1) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,1) = 0.; (*kernelPhiDep)(1,2,0) = 0.; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(1,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,1) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFMgx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IFMgx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IFMgx2qqxDipoleKernel::initIFMgx2qqxDipoleKernel; // Definition of the static class description member. void IFMgx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("IFMgx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h --- a/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IFMgx2qqxDipoleKernel_H #define HERWIG_IFMgx2qqxDipoleKernel_H // // This is the declaration of the IFgx2qqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll * * \brief IFMgx2qqxDipoleKernel implements the g -> qq * splitting off an initial-final dipole * */ class IFMgx2qqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMgx2qqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IFMgx2qqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFMgx2qqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMgx2qqxDipoleKernel & operator=(const IFMgx2qqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFMgx2qqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFMgx2qqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IFMgx2qqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFMgx2qqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IFMgx2qqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IFMgx2qqxDipoleKernel 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_IFMgx2qqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.cc b/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.cc @@ -1,144 +1,142 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IFMqx2gqxDipoleKernel class. // #include "IFMqx2gqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IFMqx2gqxDipoleKernel::IFMqx2gqxDipoleKernel() : DipoleSplittingKernel() {} -IFMqx2gqxDipoleKernel::~IFMqx2gqxDipoleKernel() {} - IBPtr IFMqx2gqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IFMqx2gqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IFMqx2gqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 6 && ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() != ZERO && ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool IFMqx2gqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return a.emitterData() == b.emitterData() && emitter(a) == sk.emitter(b) && spectator(a)->mass() == sk.spectator(b)->mass() && a.emitterPDF() == b.emitterPDF(); } tcPDPtr IFMqx2gqxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IFMqx2gqxDipoleKernel::emission(const DipoleIndex& ind) const { return ind.emitterData()->CC(); } tcPDPtr IFMqx2gqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IFMqx2gqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); Energy pt = split.lastPt(); double ratio = sqr(pt/split.scale()); double muk2 = sqr(split.spectatorMass()/split.scale()); // Calculate x double rho = 1. - 4.*ratio*(1.-muk2)*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/(ratio*(1.-muk2))) * (1. - sqrt(rho)); ret *= .5 * ( 1.-2.*x*(1.-x) ); return ret > 0. ? ret : 0.; } vector< pair > IFMqx2gqxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr IFMqx2gqxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppm = z; double v_AP_mpm = (1.-z); double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1, PDT::Spin1Half, PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = 0.; (*kernelPhiDep)(2,1,1) = 0.; (*kernelPhiDep)(0,0,1) = v_AP_mmp/phase; (*kernelPhiDep)(2,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,1,1) = 0.; (*kernelPhiDep)(2,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFMqx2gqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IFMqx2gqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IFMqx2gqxDipoleKernel::initIFMqx2gqxDipoleKernel; // Definition of the static class description member. void IFMqx2gqxDipoleKernel::Init() { static ClassDocumentation documentation ("IFMqx2gqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h b/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h --- a/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IFMqx2gqxDipoleKernel_H #define HERWIG_IFMqx2gqxDipoleKernel_H // // This is the declaration of the IFqx2gqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll * * \brief IFMqx2gqxDipoleKernel implements the q -> gqbar * splitting off an initial-final dipole * */ class IFMqx2gqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMqx2gqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IFMqx2gqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFMqx2gqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMqx2gqxDipoleKernel & operator=(const IFMqx2gqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFMqx2gqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFMqx2gqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IFMqx2gqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFMqx2gqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IFMqx2gqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IFMqx2gqxDipoleKernel 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_IFMqx2gqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.cc @@ -1,147 +1,145 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IFMqx2qgxDipoleKernel class. // #include "IFMqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IFMqx2qgxDipoleKernel::IFMqx2qgxDipoleKernel() : DipoleSplittingKernel() {} -IFMqx2qgxDipoleKernel::~IFMqx2qgxDipoleKernel() {} - IBPtr IFMqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IFMqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IFMqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 6 && ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() != ZERO && ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool IFMqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return emitter(a) == sk.emitter(b) && emission(a) == sk.emission(b) && spectator(a)->mass() == sk.spectator(b)->mass() && a.emitterPDF() == b.emitterPDF(); } tcPDPtr IFMqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { return ind.emitterData(); } tcPDPtr IFMqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IFMqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IFMqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); Energy pt = split.lastPt(); double ratio = sqr(pt/split.scale()); double muk2 = sqr(split.spectatorMass()/split.scale()); // Calculate x and u double rho = 1. - 4.*ratio*(1.-muk2)*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/(ratio*(1.-muk2))) * (1. - sqrt(rho)); double u = x*ratio / (1.-z); // 19/01/2017 - SW: Removed finite term as its effect on // the ratio of -ve/+ve kernels is small ret *= (!strictLargeN() ? 4./3. : 3./2.) * ( 2./(1.-x+u) - (1.+x) ); return ret > 0. ? ret : 0.; } vector< pair > IFMqx2qgxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr IFMqx2qgxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt( 1./(1.-z) ); double v_AP_ppm = -z/sqrt(1.-z); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,1,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(1,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = 0.; (*kernelPhiDep)(1,0,2) = 0.; (*kernelPhiDep)(0,1,2) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFMqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IFMqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IFMqx2qgxDipoleKernel::initIFMqx2qgxDipoleKernel; // Definition of the static class description member. void IFMqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("IFMqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h --- a/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IFMqx2qgxDipoleKernel_H #define HERWIG_IFMqx2qgxDipoleKernel_H // // This is the declaration of the IFqx2qgxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll * * \brief IFMqx2qgxDipoleKernel implements the q -> qg * splitting off an initial-final dipole * */ class IFMqx2qgxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMqx2qgxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IFMqx2qgxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFMqx2qgxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMqx2qgxDipoleKernel & operator=(const IFMqx2qgxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFMqx2qgxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFMqx2qgxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IFMqx2qgxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFMqx2qgxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IFMqx2qgxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IFMqx2qgxDipoleKernel 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_IFMqx2qgxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.cc @@ -1,158 +1,156 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IFgx2ggxDipoleKernel class. // #include "IFgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IFgx2ggxDipoleKernel::IFgx2ggxDipoleKernel() : DipoleSplittingKernel() {} -IFgx2ggxDipoleKernel::~IFgx2ggxDipoleKernel() {} - IBPtr IFgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IFgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IFgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool IFgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g && a.emitterPDF() == b.emitterPDF(); } tcPDPtr IFgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IFgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IFgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IFgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double ratio = sqr(split.lastPt()/split.scale()); 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)); ret *= 3. * ( 1./(1.-x+u) + (1.-x)/x - 1. + x*(1.-x) ); return ret > 0. ? ret : 0.; } vector< pair > IFgx2ggxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_mpm = -(1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; //double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_mpm)) - 2.*abs(rho(0,2))*(v_AP_ppp*v_AP_pmp + v_AP_mmm*v_AP_mpm); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_mpm))/max ) ); distPhiDep.push_back( make_pair(2, rho(0,2)*(v_AP_mmm*v_AP_mpm + v_AP_pmp*v_AP_ppp)/max ) ); distPhiDep.push_back( make_pair(-2, rho(2,0)*(v_AP_ppp*v_AP_pmp + v_AP_mpm*v_AP_mmm)/max) ); return distPhiDep; } DecayMEPtr IFgx2ggxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_mpm = -(1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1, PDT::Spin1, PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(2,2,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(2,2,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,2) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,2) = 0; (*kernelPhiDep)(2,0,0) = 0; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFgx2ggxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IFgx2ggxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IFgx2ggxDipoleKernel::initIFgx2ggxDipoleKernel; // Definition of the static class description member. void IFgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("IFgx2ggxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IFgx2ggxDipoleKernel_H #define HERWIG_IFgx2ggxDipoleKernel_H // // This is the declaration of the IFgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IFgx2ggxDipoleKernel implements the g -> gg * splitting off an initial-final dipole * */ class IFgx2ggxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFgx2ggxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IFgx2ggxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFgx2ggxDipoleKernel & operator=(const IFgx2ggxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IFgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IFgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IFgx2ggxDipoleKernel 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_IFgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.cc @@ -1,160 +1,158 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IFgx2qqxDipoleKernel class. // #include "IFgx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IFgx2qqxDipoleKernel::IFgx2qqxDipoleKernel() : DipoleSplittingKernel() {} -IFgx2qqxDipoleKernel::~IFgx2qqxDipoleKernel() {} - IBPtr IFgx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IFgx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IFgx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && flavour()->mass() == ZERO && ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool IFgx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return flavour() == sk.flavour() && abs(flavour()->id()) < 6 && flavour()->mass() == ZERO && a.emitterPDF() == b.emitterPDF(); } tcPDPtr IFgx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour(); } tcPDPtr IFgx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour(); } tcPDPtr IFgx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IFgx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double ratio = sqr(split.lastPt()/split.scale()); double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); ret *= 0.5 * (!strictLargeN() ? 4./3. : 3./2.) * ( x + 2.*(1.-x)/x ); return ret > 0. ? ret : 0.; } vector< pair > IFgx2qqxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt(1./z); double v_AP_mpm = (1.-z)/sqrt(z); double v_AP_mmm = -v_AP_ppp; double v_AP_pmp = -v_AP_mpm; // Initialise variables for the distributions vector< pair > distPhiDep; double max = sqr(v_AP_ppp) + sqr(v_AP_mpm) - 2.*abs(rho(0,2))*(v_AP_pmp*v_AP_ppp + v_AP_mmm*v_AP_mpm); distPhiDep.push_back(make_pair( 0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_mpm))/max ) ); distPhiDep.push_back(make_pair( 2, rho(0,2)*(v_AP_pmp*v_AP_ppp + v_AP_mmm*v_AP_mpm )/max ) ); distPhiDep.push_back(make_pair( -2, rho(2,0)*(v_AP_ppp*v_AP_pmp + v_AP_mpm*v_AP_mmm )/max ) ); return distPhiDep; } DecayMEPtr IFgx2qqxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt(1./z); double v_AP_mpm = (1.-z)/sqrt(z); double v_AP_mmm = -v_AP_ppp; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half, PDT::Spin1, PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -1 or -1/2, 1=+1/2, 2 = +1 (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,2,1) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,1) = 0.; (*kernelPhiDep)(1,2,0) = 0.; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(1,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,1) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFgx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IFgx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IFgx2qqxDipoleKernel::initIFgx2qqxDipoleKernel; // Definition of the static class description member. void IFgx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("IFgx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.h --- a/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IFgx2qqxDipoleKernel_H #define HERWIG_IFgx2qqxDipoleKernel_H // // This is the declaration of the IFgx2qqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IFgx2qqxDipoleKernel implements the g -> qq * splitting off an initial-final dipole * */ class IFgx2qqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFgx2qqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IFgx2qqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFgx2qqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFgx2qqxDipoleKernel & operator=(const IFgx2qqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFgx2qqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFgx2qqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IFgx2qqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFgx2qqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IFgx2qqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IFgx2qqxDipoleKernel 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_IFgx2qqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.cc b/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.cc @@ -1,139 +1,137 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IFqx2gqxDipoleKernel class. // #include "IFqx2gqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IFqx2gqxDipoleKernel::IFqx2gqxDipoleKernel() : DipoleSplittingKernel() {} -IFqx2gqxDipoleKernel::~IFqx2gqxDipoleKernel() {} - IBPtr IFqx2gqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IFqx2gqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IFqx2gqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 6 && ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() == ZERO && ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool IFqx2gqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return a.emitterData() == b.emitterData() && emitter(a) == sk.emitter(b) && a.emitterPDF() == b.emitterPDF(); } tcPDPtr IFqx2gqxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IFqx2gqxDipoleKernel::emission(const DipoleIndex& ind) const { return ind.emitterData()->CC(); } tcPDPtr IFqx2gqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IFqx2gqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double ratio = sqr(split.lastPt()/split.scale()); double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); ret *= .5 * ( 1.-2.*x*(1.-x) ); return ret > 0. ? ret : 0.; } vector< pair > IFqx2gqxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr IFqx2gqxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppm = z; double v_AP_mpm = (1.-z); double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1, PDT::Spin1Half, PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = 0.; (*kernelPhiDep)(2,1,1) = 0.; (*kernelPhiDep)(0,0,1) = v_AP_mmp/phase; (*kernelPhiDep)(2,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,1,1) = 0.; (*kernelPhiDep)(2,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFqx2gqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IFqx2gqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IFqx2gqxDipoleKernel::initIFqx2gqxDipoleKernel; // Definition of the static class description member. void IFqx2gqxDipoleKernel::Init() { static ClassDocumentation documentation ("IFqx2gqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.h b/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.h --- a/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IFqx2gqxDipoleKernel_H #define HERWIG_IFqx2gqxDipoleKernel_H // // This is the declaration of the IFqx2gqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IFqx2gqxDipoleKernel implements the q -> gqbar * splitting off an initial-final dipole * */ class IFqx2gqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFqx2gqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IFqx2gqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFqx2gqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFqx2gqxDipoleKernel & operator=(const IFqx2gqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFqx2gqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFqx2gqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IFqx2gqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFqx2gqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IFqx2gqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IFqx2gqxDipoleKernel 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_IFqx2gqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.cc @@ -1,140 +1,138 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IFqx2qgxDipoleKernel class. // #include "IFqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IFqx2qgxDipoleKernel::IFqx2qgxDipoleKernel() : DipoleSplittingKernel() {} -IFqx2qgxDipoleKernel::~IFqx2qgxDipoleKernel() {} - IBPtr IFqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IFqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IFqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 6 && ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() == ZERO && ind.initialStateEmitter() && !ind.initialStateSpectator(); } bool IFqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return emitter(a) == sk.emitter(b) && emission(a) == sk.emission(b) && a.emitterPDF() == b.emitterPDF(); } tcPDPtr IFqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { return ind.emitterData(); } tcPDPtr IFqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IFqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IFqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double ratio = sqr(split.lastPt()/split.scale()); 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)); ret *= (!strictLargeN() ? 4./3. : 3./2.) * ( 2./(1.-x+u) - (1.+x) + u*(1.+3.*x*(1.-u) ) ); return ret > 0. ? ret : 0.; } vector< pair > IFqx2qgxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr IFqx2qgxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt( 1./(1.-z) ); double v_AP_ppm = -z/sqrt(1.-z); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,1,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(1,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = 0.; (*kernelPhiDep)(1,0,2) = 0.; (*kernelPhiDep)(0,1,2) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IFqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IFqx2qgxDipoleKernel::initIFqx2qgxDipoleKernel; // Definition of the static class description member. void IFqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("IFqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.h --- a/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IFqx2qgxDipoleKernel_H #define HERWIG_IFqx2qgxDipoleKernel_H // // This is the declaration of the IFqx2qgxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IFqx2qgxDipoleKernel implements the q -> qg * splitting off an initial-final dipole * */ class IFqx2qgxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFqx2qgxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IFqx2qgxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFqx2qgxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFqx2qgxDipoleKernel & operator=(const IFqx2qgxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFqx2qgxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFqx2qgxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IFqx2qgxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFqx2qgxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IFqx2qgxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IFqx2qgxDipoleKernel 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_IFqx2qgxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.cc @@ -1,160 +1,158 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IIgx2ggxDipoleKernel class. // #include "IIgx2ggxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IIgx2ggxDipoleKernel::IIgx2ggxDipoleKernel() : DipoleSplittingKernel() {} -IIgx2ggxDipoleKernel::~IIgx2ggxDipoleKernel() {} - IBPtr IIgx2ggxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IIgx2ggxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IIgx2ggxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && ind.initialStateEmitter() && ind.initialStateSpectator(); } bool IIgx2ggxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return sk.emitter(b)->id() == ParticleID::g && sk.emission(b)->id() == ParticleID::g && a.emitterPDF() == b.emitterPDF() && a.spectatorData() == b.spectatorData() && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr IIgx2ggxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IIgx2ggxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IIgx2ggxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IIgx2ggxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double ratio = sqr(split.lastPt()/split.scale()); double x = z*(1.-z)/(1.-z+ratio); ret *= 3. * ( x/(1.-x) + (1.-x)/x +x*(1.-x) ); return ret > 0. ? ret : 0.; } vector< pair > IIgx2ggxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_mpm = -(1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; //double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Initialise variables for the distributions vector< pair > distPhiDep; double max = (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_mpm)) - 2.*abs(rho(0,2))*(v_AP_ppp*v_AP_pmp + v_AP_mmm*v_AP_mpm); distPhiDep.push_back( make_pair(0, (rho(0,0)+rho(2,2))* (sqr(v_AP_ppp) + sqr(v_AP_ppm) + sqr(v_AP_mpm))/max ) ); distPhiDep.push_back( make_pair(2, rho(0,2)*(v_AP_mmm*v_AP_mpm + v_AP_pmp*v_AP_ppp)/max ) ); distPhiDep.push_back( make_pair(-2, rho(2,0)*(v_AP_ppp*v_AP_pmp + v_AP_mpm*v_AP_mmm)/max) ); return distPhiDep; } DecayMEPtr IIgx2ggxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = -sqrt( 1./(z*(1.-z)) ); double v_AP_ppm = z*sqrt( z / (1.-z) ); double v_AP_mpm = -(1.-z)*sqrt( (1.-z)/z ); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1, PDT::Spin1, PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(2,2,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(2,2,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,2) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,2) = 0; (*kernelPhiDep)(2,0,0) = 0; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IIgx2ggxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IIgx2ggxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IIgx2ggxDipoleKernel::initIIgx2ggxDipoleKernel; // Definition of the static class description member. void IIgx2ggxDipoleKernel::Init() { static ClassDocumentation documentation ("IIgx2ggxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.h --- a/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IIgx2ggxDipoleKernel_H #define HERWIG_IIgx2ggxDipoleKernel_H // // This is the declaration of the IIgx2ggxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IIgx2ggxDipoleKernel implements the g -> gg * splitting off an initial-initial dipole * */ class IIgx2ggxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IIgx2ggxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IIgx2ggxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIIgx2ggxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IIgx2ggxDipoleKernel & operator=(const IIgx2ggxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IIgx2ggxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IIgx2ggxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IIgx2ggxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IIgx2ggxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IIgx2ggxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IIgx2ggxDipoleKernel 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_IIgx2ggxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.cc @@ -1,161 +1,159 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IIgx2qqxDipoleKernel class. // #include "IIgx2qqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IIgx2qqxDipoleKernel::IIgx2qqxDipoleKernel() : DipoleSplittingKernel() {} -IIgx2qqxDipoleKernel::~IIgx2qqxDipoleKernel() {} - IBPtr IIgx2qqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IIgx2qqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IIgx2qqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && ind.emitterData()->id() == ParticleID::g && ind.spectatorData()->mass() == ZERO && flavour()->mass() == ZERO && ind.initialStateEmitter() && ind.initialStateSpectator(); } bool IIgx2qqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return flavour() == sk.flavour() && abs(flavour()->id()) < 6 && flavour()->mass() == ZERO && a.emitterPDF() == b.emitterPDF() && a.spectatorData() == b.spectatorData() && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr IIgx2qqxDipoleKernel::emitter(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour(); } tcPDPtr IIgx2qqxDipoleKernel::emission(const DipoleIndex&) const { assert(flavour()); assert(abs(flavour()->id()) < 6 && flavour()->mass() == ZERO); return flavour(); } tcPDPtr IIgx2qqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IIgx2qqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double ratio = sqr(split.lastPt()/split.scale()); double x = z*(1.-z)/(1.-z+ratio); ret *= 0.5 * (!strictLargeN() ? 4./3. : 3./2.) * ( 1./x +sqr(1.-x)/x ); return ret > 0. ? ret : 0.; } vector< pair > IIgx2qqxDipoleKernel::generatePhi(const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt(1./z); double v_AP_mpm = (1.-z)/sqrt(z); double v_AP_mmm = -v_AP_ppp; double v_AP_pmp = -v_AP_mpm; // Initialise variables for the distributions vector< pair > distPhiDep; double max = sqr(v_AP_ppp) + sqr(v_AP_mpm) - 2.*abs(rho(0,2))*(v_AP_pmp*v_AP_ppp + v_AP_mmm*v_AP_mpm); distPhiDep.push_back(make_pair( 0, (rho(0,0)+rho(2,2))*(sqr(v_AP_ppp) + sqr(v_AP_mpm))/max ) ); distPhiDep.push_back(make_pair( 2, rho(0,2)*(v_AP_pmp*v_AP_ppp + v_AP_mmm*v_AP_mpm )/max ) ); distPhiDep.push_back(make_pair( -2, rho(2,0)*(v_AP_ppp*v_AP_pmp + v_AP_mpm*v_AP_mmm )/max ) ); return distPhiDep; } DecayMEPtr IIgx2qqxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt(1./z); double v_AP_mpm = (1.-z)/sqrt(z); double v_AP_mmm = -v_AP_ppp; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half, PDT::Spin1, PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -1 or -1/2, 1=+1/2, 2 = +1 (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,2,1) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,1) = 0.; (*kernelPhiDep)(1,2,0) = 0.; (*kernelPhiDep)(0,2,0) = v_AP_mpm/phase; (*kernelPhiDep)(1,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,2,1) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IIgx2qqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IIgx2qqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IIgx2qqxDipoleKernel::initIIgx2qqxDipoleKernel; // Definition of the static class description member. void IIgx2qqxDipoleKernel::Init() { static ClassDocumentation documentation ("IIgx2qqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.h --- a/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IIgx2qqxDipoleKernel_H #define HERWIG_IIgx2qqxDipoleKernel_H // // This is the declaration of the IIgx2qqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IIgx2qqxDipoleKernel implements the g -> qq * splitting off an initial-initial dipole * */ class IIgx2qqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IIgx2qqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IIgx2qqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIIgx2qqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IIgx2qqxDipoleKernel & operator=(const IIgx2qqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IIgx2qqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IIgx2qqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IIgx2qqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IIgx2qqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IIgx2qqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IIgx2qqxDipoleKernel 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_IIgx2qqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.cc b/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.cc @@ -1,140 +1,138 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IIqx2gqxDipoleKernel class. // #include "IIqx2gqxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IIqx2gqxDipoleKernel::IIqx2gqxDipoleKernel() : DipoleSplittingKernel() {} -IIqx2gqxDipoleKernel::~IIqx2gqxDipoleKernel() {} - IBPtr IIqx2gqxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IIqx2gqxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IIqx2gqxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 6 && ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() == ZERO && ind.initialStateEmitter() && ind.initialStateSpectator(); } bool IIqx2gqxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return a.emitterData() == b.emitterData() && emitter(a) == sk.emitter(b) && a.emitterPDF() == b.emitterPDF() && a.spectatorData() == b.spectatorData() && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr IIqx2gqxDipoleKernel::emitter(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IIqx2gqxDipoleKernel::emission(const DipoleIndex& ind) const { return ind.emitterData()->CC(); } tcPDPtr IIqx2gqxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IIqx2gqxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double ratio = sqr(split.lastPt()/split.scale()); double x = z*(1.-z)/(1.-z+ratio); ret *= .5 * ( 1.-2.*x*(1.-x) ); return ret > 0. ? ret : 0.; } vector< pair > IIqx2gqxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr IIqx2gqxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppm = z; double v_AP_mpm = (1.-z); double v_AP_mmp = -v_AP_ppm; double v_AP_pmp = -v_AP_mpm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1, PDT::Spin1Half, PDT::Spin1Half))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = 0.; (*kernelPhiDep)(2,1,1) = 0.; (*kernelPhiDep)(0,0,1) = v_AP_mmp/phase; (*kernelPhiDep)(2,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = v_AP_mpm/phase; (*kernelPhiDep)(2,0,1) = v_AP_pmp*phase; (*kernelPhiDep)(0,1,1) = 0.; (*kernelPhiDep)(2,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IIqx2gqxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IIqx2gqxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IIqx2gqxDipoleKernel::initIIqx2gqxDipoleKernel; // Definition of the static class description member. void IIqx2gqxDipoleKernel::Init() { static ClassDocumentation documentation ("IIqx2gqxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.h b/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.h --- a/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IIqx2gqxDipoleKernel_H #define HERWIG_IIqx2gqxDipoleKernel_H // // This is the declaration of the IIqx2gqxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IIqx2gqxDipoleKernel implements the q -> gqbar * splitting off an initial-initial dipole * */ class IIqx2gqxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IIqx2gqxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IIqx2gqxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIIqx2gqxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IIqx2gqxDipoleKernel & operator=(const IIqx2gqxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IIqx2gqxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IIqx2gqxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IIqx2gqxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IIqx2gqxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IIqx2gqxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IIqx2gqxDipoleKernel 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_IIqx2gqxDipoleKernel_H */ diff --git a/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.cc --- a/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.cc +++ b/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.cc @@ -1,139 +1,137 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the IIqx2qgxDipoleKernel class. // #include "IIqx2qgxDipoleKernel.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; IIqx2qgxDipoleKernel::IIqx2qgxDipoleKernel() : DipoleSplittingKernel() {} -IIqx2qgxDipoleKernel::~IIqx2qgxDipoleKernel() {} - IBPtr IIqx2qgxDipoleKernel::clone() const { return new_ptr(*this); } IBPtr IIqx2qgxDipoleKernel::fullclone() const { return new_ptr(*this); } bool IIqx2qgxDipoleKernel::canHandle(const DipoleIndex& ind) const { return useThisKernel() && abs(ind.emitterData()->id()) < 6 && ind.emitterData()->mass() == ZERO && ind.spectatorData()->mass() == ZERO && ind.initialStateEmitter() && ind.initialStateSpectator(); } bool IIqx2qgxDipoleKernel::canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const { assert(canHandle(a)); if ( !canHandle(b) ) return false; return emitter(a) == sk.emitter(b) && emission(a) == sk.emission(b) && a.emitterPDF() == b.emitterPDF() && a.spectatorData() == b.spectatorData() && a.spectatorPDF() == b.spectatorPDF(); } tcPDPtr IIqx2qgxDipoleKernel::emitter(const DipoleIndex& ind) const { return ind.emitterData(); } tcPDPtr IIqx2qgxDipoleKernel::emission(const DipoleIndex&) const { return getParticleData(ParticleID::g); } tcPDPtr IIqx2qgxDipoleKernel::spectator(const DipoleIndex& ind) const { return ind.spectatorData(); } double IIqx2qgxDipoleKernel::evaluate(const DipoleSplittingInfo& split) const { double ret = alphaPDF(split); double z = split.lastZ(); double ratio = sqr(split.lastPt()/split.scale()); double x = z*(1.-z)/(1.-z+ratio); ret *= (!strictLargeN() ? 4./3. : 3./2.) * ( (1.+sqr(x))/(1.-x) ); return ret > 0. ? ret : 0.; } vector< pair > IIqx2qgxDipoleKernel::generatePhi(const DipoleSplittingInfo&, const RhoDMatrix&) const { // No dependence on the spin density matrix, // dependence on off-diagonal terms cancels. return {{ {0, 1.} }}; } DecayMEPtr IIqx2qgxDipoleKernel::matrixElement(const DipoleSplittingInfo& dInfo) const { double z = dInfo.lastZ(); // Altarelli-Parisi spin-indexed kernels: double v_AP_ppp = sqrt( 1./(1.-z) ); double v_AP_ppm = -z/sqrt(1.-z); double v_AP_mmm = -v_AP_ppp; double v_AP_mmp = -v_AP_ppm; // Construct the (phi-dependent) spin-unaveraged splitting kernel DecayMEPtr kernelPhiDep (new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1))); Complex phase = exp(Complex(0.,1.)*dInfo.lastPhi()); // 0 = -, 2 = + (*kernelPhiDep)(0,0,0) = v_AP_mmm*phase; (*kernelPhiDep)(1,1,2) = v_AP_ppp/phase; (*kernelPhiDep)(0,0,2) = v_AP_mmp/phase; (*kernelPhiDep)(1,1,0) = v_AP_ppm*phase; (*kernelPhiDep)(0,1,0) = 0.; (*kernelPhiDep)(1,0,2) = 0.; (*kernelPhiDep)(0,1,2) = 0.; (*kernelPhiDep)(1,0,0) = 0.; return kernelPhiDep; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IIqx2qgxDipoleKernel::persistentOutput(PersistentOStream & ) const { } void IIqx2qgxDipoleKernel::persistentInput(PersistentIStream & , int) { } ClassDescription IIqx2qgxDipoleKernel::initIIqx2qgxDipoleKernel; // Definition of the static class description member. void IIqx2qgxDipoleKernel::Init() { static ClassDocumentation documentation ("IIqx2qgxDipoleKernel"); } diff --git a/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.h --- a/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.h +++ b/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.h @@ -1,192 +1,184 @@ // -*- C++ -*- #ifndef HERWIG_IIqx2qgxDipoleKernel_H #define HERWIG_IIqx2qgxDipoleKernel_H // // This is the declaration of the IIqx2qgxDipoleKernel class. // #include "DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IIqx2qgxDipoleKernel implements the q -> qg * splitting off an initial-initial dipole * */ class IIqx2qgxDipoleKernel: public DipoleSplittingKernel { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IIqx2qgxDipoleKernel(); - /** - * The destructor. - */ - virtual ~IIqx2qgxDipoleKernel(); - //@} - public: /** * Return true, if this splitting kernel * applies to the given dipole index. */ virtual bool canHandle(const DipoleIndex&) const; /** * Return true, if this splitting kernel is * the same for the given index a, as the given * splitting kernel for index b. */ virtual bool canHandleEquivalent(const DipoleIndex& a, const DipoleSplittingKernel& sk, const DipoleIndex& b) const; /** * Return the emitter data after splitting, given * a dipole index. */ virtual tcPDPtr emitter(const DipoleIndex&) const; /** * Return the emission data after splitting, given * a dipole index. */ virtual tcPDPtr emission(const DipoleIndex&) const; /** * Return the spectator data after splitting, given * a dipole index. */ virtual tcPDPtr spectator(const DipoleIndex&) const; /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const; /** * Evaluate rho_ii' V_ijk V*_i'jk / equivalent for initial-state splitting, * required for generating spin-correlated azimuthal angles. **/ virtual vector< pair > generatePhi( const DipoleSplittingInfo& dInfo, const RhoDMatrix& rho) const; /** * Return the completely spin-unaveraged (i.e. spin-indexed) splitting kernel. **/ virtual DecayMEPtr matrixElement(const DipoleSplittingInfo& dInfo) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIIqx2qgxDipoleKernel; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IIqx2qgxDipoleKernel & operator=(const IIqx2qgxDipoleKernel &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IIqx2qgxDipoleKernel. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IIqx2qgxDipoleKernel. */ typedef Herwig::DipoleSplittingKernel NthBase; }; /** This template specialization informs ThePEG about the name of * the IIqx2qgxDipoleKernel class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IIqx2qgxDipoleKernel"; } /** * The name of a file containing the dynamic library where the class * IIqx2qgxDipoleKernel is implemented. It may also include several, space-separated, * libraries if the class IIqx2qgxDipoleKernel 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_IIqx2qgxDipoleKernel_H */ diff --git a/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc --- a/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc +++ b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc @@ -1,389 +1,387 @@ // -*- C++ -*- // // DipoleSplittingKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleSplittingKinematics class. // #include "DipoleSplittingKinematics.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/RandomHelpers.h" #include using namespace Herwig; DipoleSplittingKinematics::DipoleSplittingKinematics() : HandlerBase(), theIRCutoff(1.0*GeV), theXMin(1.e-5), theJacobian(0.0), theLastPt(0.0*GeV), theLastZ(0.0), theLastPhi(0.0), theLastEmitterZ(1.0), theLastSpectatorZ(1.0), theLastSplittingParameters(),theOpenZBoundaries(1) {} -DipoleSplittingKinematics::~DipoleSplittingKinematics() {} - void DipoleSplittingKinematics::persistentOutput(PersistentOStream & os) const { os << ounit(theIRCutoff,GeV) << theXMin << theMCCheck<> iunit(theIRCutoff,GeV) >> theXMin >> theMCCheck>>theOpenZBoundaries; } void DipoleSplittingKinematics::prepareSplitting(DipoleSplittingInfo& dInfo) { dInfo.splittingKinematics(this); if ( lastPt() > IRCutoff() ) dInfo.lastPt(lastPt()); else { dInfo.lastPt(0.0*GeV); dInfo.didStopEvolving(); } dInfo.lastZ(lastZ()); dInfo.lastPhi(lastPhi()); dInfo.lastEmitterZ(lastEmitterZ()); dInfo.lastSpectatorZ(lastSpectatorZ()); dInfo.splittingParameters().resize(lastSplittingParameters().size()); copy(lastSplittingParameters().begin(),lastSplittingParameters().end(), dInfo.splittingParameters().begin()); } Energy DipoleSplittingKinematics::ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { return ptMax(dScale, emX, specX, dInfo.index(), split); } Energy DipoleSplittingKinematics::ptMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr, tPPtr) const { return ptMax(dScale, emX, specX, dIndex, split); } Energy DipoleSplittingKinematics::QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { return QMax(dScale, emX, specX, dInfo.index(), split); } Energy DipoleSplittingKinematics::QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr, tPPtr) const { return QMax(dScale, emX, specX, dIndex, split); } Energy DipoleSplittingKinematics::generatePt(double r, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, double& weight) const { Energy maxPt = ptMax(dScale,emX,specX,dIndex,split); if ( maxPt <= IRCutoff() ) { weight = 0.0; return ZERO; } weight *= log(sqr(maxPt/IRCutoff())); return IRCutoff()*pow(maxPt/IRCutoff(),r); } double DipoleSplittingKinematics::ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const { Energy maxPt = ptMax(dScale,emX,specX,dIndex,split); assert(pt >= IRCutoff() && pt <= maxPt); return log(pt/IRCutoff())/log(maxPt/IRCutoff()); } double DipoleSplittingKinematics::generateZ(double r, Energy pt, int sampling, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split, double& weight) const { pair zLims = zBoundaries(pt,dInfo,split); if(zLims.first==zLims.second){ weight = 0.0; return 0.0; } using namespace RandomHelpers; if ( sampling == FlatZ ) { pair kw = generate(flat(zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverZ ) { pair kw = generate(inverse(0.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverOneMinusZ ) { pair kw = generate(inverse(1.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverZOneMinusZ ) { pair kw = generate(inverse(0.0,zLims.first,zLims.second) + inverse(1.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } weight = 0.0; return 0.0; } Lorentz5Momentum DipoleSplittingKinematics::getKt(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2, Energy pt, double phi, bool spacelike) const { Lorentz5Momentum P; // CoM frame if ( !spacelike ) P = p1 + p2; // Breit frame else P = p1 - p2; Energy mag = sqrt(abs(P.m2())); // Define Q. The 'boost' part of this transforms from the current // frame into a frame (') in which P' = Q Lorentz5Momentum Q = !spacelike ? Lorentz5Momentum(ZERO,ZERO,ZERO,mag,mag) : Lorentz5Momentum(ZERO,ZERO,mag,ZERO,-mag); // This is required to make the boost parameter // gamma positive (construct the 00 term of the // transformtion below to see this) //if ( spacelike && P.z() < -mag ) //Q.setZ(-Q.z()); // Below is safer than above as it avoids // cases of very small positive (P*Q + Q2) if ( spacelike && P.z() < ZERO ) Q.setZ(-Q.z()); Energy2 Q2 = Q.m2(); // Establish if we need to boost bool boost = abs((P-Q).vect().mag2()/GeV2) > 1e-10 || abs((P-Q).t()/GeV) > 1e-5; // Initialise copy of p1 to transform in the following Lorentz5Momentum inFrame1(p1); if ( boost ) inFrame1 = inFrame1 - ((P*inFrame1+Q*inFrame1)/(Q2+P*Q))*(P+Q) + 2.*((P*inFrame1)/Q2)*Q; // Compute components of kt double cPhi = cos(phi); double sPhi = sqrt(1.-sqr(cPhi)); if ( phi > Constants::pi ) sPhi = -sPhi; // Initialise kt Lorentz5Momentum kt; // By 'timelike' case we mean we work in the centre-of-momentum frame // The boost to the com frame is defined upto some rotation, // here we do the rotation to/from the frame with boosted p1 along the +ve z-axis if ( !spacelike ) { Axis inFrame1Unit = inFrame1.vect().unit(); if ( inFrame1Unit.perp2() > 1e-12 ) { // 'n' indicates normalised momenta components double pxn = inFrame1Unit.x(); double pyn = inFrame1Unit.y(); double pzn = inFrame1Unit.z(); double den = 1./(1.+pzn); kt.setT(ZERO); kt.setX( pt * ( (sqr(pyn)*den + pzn)*cPhi - pxn*pyn*den*sPhi ) ); kt.setY( pt * ( -pxn*pyn*den*cPhi + (sqr(pxn)*den + pzn)*sPhi) ); kt.setZ( -pt * ( pxn*cPhi + pyn*sPhi ) ); } // If boosted p1 already lies along the z-axis, construct the pt // in this frame, rotating to put boosted p1 along the *+ve* z-axis // if required else { // Note pzn will simply be +1 or -1 in this case double pzn = inFrame1Unit.z(); // Multiply y component by pzn: // In the case of pzn = -1, this corresponds to a rotation // about the x-axis as done in boostToSplitting kt.setT(ZERO); kt.setX( pt * cPhi ); kt.setY( pt * pzn*sPhi ); kt.setZ(ZERO); } } // By 'spacelike' we mean we work in the Breit frame. // The transformation to the breit frame above is // defined up to boosts in the x- and y-directions, // here we do the boosts to put the momenta along the z-axis else { Energy ptx = inFrame1.x(); Energy pty = inFrame1.y(); // q/2 = energy component of inFrame1 AFTER applying // boosts to eliminate the x and y components. Therefore // we calculate q from the mass and the z-component as // these will not change due to these boosts. Energy q = 2.*sqrt(sqr(inFrame1) + sqr(inFrame1.z())); Energy Qp = sqrt(4.*(sqr(ptx)+sqr(pty))+sqr(q)); Energy Qy = sqrt(4.*sqr(pty)+sqr(q)); // Most straightforward way to construct kt in frame // where p1 lies along the positive z-axis double pzn = inFrame1.z()/abs(inFrame1.z()); kt.setT(2.*pt*(ptx*q*cPhi+pty*Qp*pzn*sPhi)/(q*Qy)); kt.setX(pt*(Qp*q*cPhi+4.*ptx*pty*pzn*sPhi)/(q*Qy)); kt.setY(pt*Qy*pzn*sPhi/q); kt.setZ(ZERO); } // Transform back to the lab frame // Note Q*kt = 0 if ( boost ) kt = kt - ((P*kt+Q*kt)/(Q2+P*Q))*(P+Q);// + 2.*((Q*kt)/Q2)*P; kt.setMass(-pt); kt.rescaleRho(); return kt; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). AbstractClassDescription DipoleSplittingKinematics::initDipoleSplittingKinematics; // Definition of the static class description member. void DipoleSplittingKinematics::Init() { static ClassDocumentation documentation ("DipoleSplittingKinematics is the base class for dipole splittings " "as performed in the dipole shower."); static Parameter interfaceIRCutoff ("IRCutoff", "The IR cutoff to be used by this splitting kinematics.", &DipoleSplittingKinematics::theIRCutoff, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceXMin ("XMin", "The minimum momentum fraction for incoming partons", &DipoleSplittingKinematics::theXMin, 1.0e-5, 0.0, 1.0, false, false, Interface::limited); static Reference interfaceMCCheck ("MCCheck", "[debug option] MCCheck", &DipoleSplittingKinematics::theMCCheck, false, false, true, true, false); interfaceMCCheck.rank(-1); static Switch interfaceOpenZBoundaries ("OpenZBoundaries", "", &DipoleSplittingKinematics::theOpenZBoundaries, 0, false, false); static SwitchOption interfaceOpenZBoundarieshardScale (interfaceOpenZBoundaries, "Hard", "", 0); static SwitchOption interfaceOpenZBoundariesfull (interfaceOpenZBoundaries, "Full", "", 1); static SwitchOption interfaceOpenZBoundariesDipoleScale (interfaceOpenZBoundaries, "DipoleScale", "", 2); } diff --git a/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h --- a/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h +++ b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h @@ -1,672 +1,664 @@ // -*- C++ -*- // // DipoleSplittingKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_DipoleSplittingKinematics_H #define HERWIG_DipoleSplittingKinematics_H // // This is the declaration of the DipoleSplittingKinematics class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/UtilityBase.h" #include "Herwig/Shower/Dipole/Utility/DipoleMCCheck.h" namespace Herwig { using namespace ThePEG; class DipoleIndex; class DipoleSplittingInfo; class DipoleSplittingKernel; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleSplittingKinematics is the base class for dipole splittings * as performed in the dipole shower. * * @see \ref DipoleSplittingKinematicsInterfaces "The interfaces" * defined for DipoleSplittingKinematics. */ class DipoleSplittingKinematics: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ DipoleSplittingKinematics(); - /** - * The destructor. - */ - virtual ~DipoleSplittingKinematics(); - //@} - public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { // MEMinBias produces non-zero zeros. if(abs(pEmitter*pSpectator)<0.0000001*GeV2)return ZERO; assert(pEmitter*pSpectator >= ZERO); return sqrt(2.*pEmitter*pSpectator); } /** * Return the mass of the system absorbing * the recoil in the dipole splitting. * This is overloaded in the decay dipoles. */ virtual Energy recoilMassKin(const Lorentz5Momentum&, const Lorentz5Momentum& pSpectator) const { return pSpectator.m(); } /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const =0; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const =0; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const; /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const = 0; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const = 0; /** * Return the infrared cutoff. */ virtual Energy IRCutoff() const { return theIRCutoff; } /** * Return the minimum momentum fraction for * incoming partons */ double xMin() const { return theXMin; } /** * Generate a pt */ Energy generatePt(double r, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, double& weight) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const = 0; /** * Enumerate the variants of sampling z */ enum ZSamplingOptions { FlatZ = 0, OneOverZ, OneOverOneMinusZ, OneOverZOneMinusZ }; /** * Generate a z value flat */ double generateZ(double r, Energy pt, int sampling, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split, double& weight) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) = 0; /** * Get the splitting phasespace weight associated to * the last call to generateSplitting. This is taken to * be the single particle phasespace times 16 \pi^2 divided * by the relevant propagator invariant. */ double jacobian() const { return theJacobian; } /** * Return true, if this splitting kinematics * class is capable of delivering an overestimate * to the jacobian. */ virtual bool haveOverestimate() const { return false; } /** * Return the overestimated jacobian for the * last generated parameters. */ virtual double jacobianOverestimate() const { return -1.; } /** * Return the last generated pt */ Energy lastPt() const { return theLastPt; } /** * Return the last generated momentum fraction. */ double lastZ() const { return theLastZ; } /** * Return the last calculated zPrime for massive FF and decay dipoles. */ // Do not need in current implementation, // using lastSplittingParameters instead. //double lastZPrime() const { return theLastZPrime; } /** * Return the last generated azimuthal angle. */ double lastPhi() const { return theLastPhi; } /** * Return the momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ double lastEmitterZ() const { return theLastEmitterZ; } /** * Return the momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ double lastSpectatorZ() const { return theLastSpectatorZ; } /** * Return any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ const vector& lastSplittingParameters() const { return theLastSplittingParameters; } /** * Complete a DipoleSplittingInfo object with * the parameters generated by the last call to * generateSplitting() */ void prepareSplitting(DipoleSplittingInfo& dInfo); public: /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) = 0; /** * Return the emitter's momentum after the splitting. */ const Lorentz5Momentum& lastEmitterMomentum() const { return theEmitterMomentum; } /** * Return the spectator's momentum after the splitting. */ const Lorentz5Momentum& lastSpectatorMomentum() const { return theSpectatorMomentum; } /** * Return the emission's momentum. */ const Lorentz5Momentum& lastEmissionMomentum() const { return theEmissionMomentum; } /* * Return true, if there is a transformation which should * be applied to all other final state particles except the ones * involved in the splitting after having performed the splitting. */ virtual bool doesTransform () const { return false; } /** * Calculate and store a required Lorentz transformation **/ virtual void setTransformation () {}; /* * Use the Dipole scale instead of hardpt for z-boundaries. */ int openZBoundaries() const { return theOpenZBoundaries; } /* * perform the transformation if required. */ virtual void transform (PPtr&) {}; /* * SW 30/01/2019: Test feature only, not for release. * Return true to only apply the transformation to non-coloured particles. * Note this requires careful handling in DipoleEventRecord */ //virtual bool transformHardOnly() const { return false; } /** * SW 30/01/2019: Test feature only, not for release. * In II case use colourless particles only to absorb recoil */ //virtual void transformHard ( PPtr& ) {}; /** * SW 30/01/2019: Used in DipoleEventRecord to prepare for * transformHard, test feature only, not for release. * Add to splitRecoilMomentum for transformation */ // void addToRecoilMom( const Lorentz5Momentum& mom ) { // Lorentz5Momentum newRecoilMom = splitRecoilMomentum() + mom; // splitRecoilMomentum(newRecoilMom); // } /* * Return true if this splitting is of a dipole which contains * a decayed parton and requires the remnant to absorb the recoil. */ virtual bool isDecay() const { return false; } /** * Perform the recoil in the case of a decayed parton */ //virtual Lorentz5Momentum decayRecoil ( const Lorentz5Momentum& p, const int) { return p; } /** * Perform the recoil in the case of a decayed parton */ virtual void decayRecoil ( PList& ) {}; /** * Return the pVector, required for spin correlations. */ virtual Lorentz5Momentum pVector(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum&, const DipoleSplittingInfo&) const { return pEmitter; } /** * Return the nVector, required for spin correlations. */ virtual Lorentz5Momentum nVector(const Lorentz5Momentum&, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo&) const { return pSpectator; } // {;} protected: /** * Calculate a transverse momentum for the given momenta, * invariant pt and azimuth. */ Lorentz5Momentum getKt(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2, Energy pt, double phi, bool spacelike = false) const; /** * Set the splitting phasespace weight associated to * the last call to generateSplitting. This is taken to * be the single particle phasespace times 16 \pi^2 divided * by the relevant propagator invariant. */ void jacobian(double w) { theJacobian = w; } /** * Set the last generated pt */ void lastPt(Energy p) { theLastPt = p; } /** * Set the last generated momentum fraction. */ void lastZ(double z) { theLastZ = z; } /** * Set the last calculated zPrime for massive FF and decay dipoles. */ // Do not need in current implementation, // using lastSplittingParameters instead. //void lastZPrime(double zPrime) { theLastZPrime = zPrime; } /** * Set the last generated azimuthal angle. */ void lastPhi(double p) { theLastPhi = p; } /** * Set the momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ void lastEmitterZ(double z) { theLastEmitterZ = z; } /** * Set the momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ void lastSpectatorZ(double z) { theLastSpectatorZ = z; } /** * Access any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ vector& splittingParameters() { return theLastSplittingParameters; } /** * Set the emitter's momentum after the splitting. */ void emitterMomentum(const Lorentz5Momentum& p) { theEmitterMomentum = p; } /** * Set the spectator's momentum after the splitting. */ void spectatorMomentum(const Lorentz5Momentum& p) { theSpectatorMomentum = p; } /** * Set the emission's momentum. */ void emissionMomentum(const Lorentz5Momentum& p) { theEmissionMomentum = p; } /** * Set the momentum of the recoil system after the splitting. */ void splitRecoilMomentum( const Lorentz5Momentum& mom ) { theSplitRecoilMomentum = mom; } /** * Return the momentum of the recoil system after splitting. */ const Lorentz5Momentum& splitRecoilMomentum() const { return theSplitRecoilMomentum; } public: /** * 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(); 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); //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The infrared cutoff associated to this * splitting kinematics. */ Energy theIRCutoff; /** * The minimum momentum fraction for * incoming partons */ double theXMin; /** * The last calculated splitting phase space weight. */ double theJacobian; /** * The last generated pt */ Energy theLastPt; /** * The last generated momentum fraction. */ double theLastZ; /** * The last calculated zPrime required for massive FF * and decay kinematics dipoles. * zPrime := qi.nk / (qi+qj).nk (qj = emission momentum) */ // Do not need in current implementation, // using lastSplittingParameters instead. //double theLastZPrime; /** * The last generated azimuthal angle. */ double theLastPhi; /** * The momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ double theLastEmitterZ; /** * The momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ double theLastSpectatorZ; /** * Any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ vector theLastSplittingParameters; /** * The emitter's momentum after the splitting. */ Lorentz5Momentum theEmitterMomentum; /** * The emission's momentum after the splitting. */ Lorentz5Momentum theEmissionMomentum; /** * The spectator's momentum after the splitting. */ Lorentz5Momentum theSpectatorMomentum; /** * The momentum of the recoil system after the splitting, * used in decay dipole kinematics. */ Lorentz5Momentum theSplitRecoilMomentum; int theOpenZBoundaries; protected: /** * Pointer to a check histogram object */ Ptr::ptr theMCCheck; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class. */ static AbstractClassDescription initDipoleSplittingKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleSplittingKinematics & operator=(const DipoleSplittingKinematics &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleSplittingKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleSplittingKinematics. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleSplittingKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleSplittingKinematics"; } /** * The name of a file containing the dynamic library where the class * DipoleSplittingKinematics is implemented. It may also include several, space-separated, * libraries if the class DipoleSplittingKinematics 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_DipoleSplittingKinematics_H */ diff --git a/Shower/Dipole/Kinematics/FFLightKinematics.cc b/Shower/Dipole/Kinematics/FFLightKinematics.cc --- a/Shower/Dipole/Kinematics/FFLightKinematics.cc +++ b/Shower/Dipole/Kinematics/FFLightKinematics.cc @@ -1,175 +1,173 @@ // -*- C++ -*- // // FFLightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFLightKinematics class. // #include "FFLightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" using namespace Herwig; FFLightKinematics::FFLightKinematics() : DipoleSplittingKinematics() {} -FFLightKinematics::~FFLightKinematics() {} - IBPtr FFLightKinematics::clone() const { return new_ptr(*this); } IBPtr FFLightKinematics::fullclone() const { return new_ptr(*this); } Energy FFLightKinematics::ptMax(Energy dScale, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale/2.; } Energy FFLightKinematics::QMax(Energy dScale, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale; } Energy FFLightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale*sqrt(z*(1.-z)); } Energy FFLightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale/sqrt(z*(1.-z)); } pair FFLightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { Energy hard=dInfo.hardPt(); if(openZBoundaries()>0)hard=dInfo.scale()/2.; const double s = sqrt(1.-sqr(pt/hard)); return {0.5*(1.-s),0.5*(1.+s)}; } bool FFLightKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split) { 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.emissionData()->id() != ParticleID::g ) { z = generateZ(xi,pt,FlatZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } } else { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } double y = sqr(pt/info.scale())/(z*(1.-z)); if ( z < 0.0 || z > 1.0 || y < 0.0 || y > 1.0 ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian(weight*(1.-y)); lastPt(pt); lastZ(z); lastPhi(phi); if ( theMCCheck ) theMCCheck->book(1.,1.,info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void FFLightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); double y = sqr(pt / (pEmitter+pSpectator).m()) / (z*(1.-z)); Lorentz5Momentum kt = getKt(pEmitter, pSpectator, pt, dInfo.lastPhi()); Lorentz5Momentum em = z*pEmitter + y*(1.-z)*pSpectator + kt; Lorentz5Momentum emm = (1.-z)*pEmitter + z*y*pSpectator - kt; Lorentz5Momentum spe = (1.-y)*pSpectator; em.setMass(ZERO); em.rescaleEnergy(); emm.setMass(ZERO); emm.rescaleEnergy(); spe.setMass(ZERO); 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 FFLightKinematics::persistentOutput(PersistentOStream & ) const { } void FFLightKinematics::persistentInput(PersistentIStream & , int) { } ClassDescription FFLightKinematics::initFFLightKinematics; // Definition of the static class description member. void FFLightKinematics::Init() { static ClassDocumentation documentation ("FFLightKinematics implements massless splittings " "off a final-final dipole."); } diff --git a/Shower/Dipole/Kinematics/FFLightKinematics.h b/Shower/Dipole/Kinematics/FFLightKinematics.h --- a/Shower/Dipole/Kinematics/FFLightKinematics.h +++ b/Shower/Dipole/Kinematics/FFLightKinematics.h @@ -1,200 +1,192 @@ // -*- C++ -*- // // FFLightKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFLightKinematics_H #define HERWIG_FFLightKinematics_H // // This is the declaration of the FFLightKinematics class. // #include "DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FFLightKinematics implements massless splittings * off a final-final dipole. * */ class FFLightKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFLightKinematics(); - /** - * The destructor. - */ - virtual ~FFLightKinematics(); - //@} - public: /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel&) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel&) const; /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel&); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFLightKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFLightKinematics & operator=(const FFLightKinematics &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFLightKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFLightKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the FFLightKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFLightKinematics"; } /** * The name of a file containing the dynamic library where the class * FFLightKinematics is implemented. It may also include several, space-separated, * libraries if the class FFLightKinematics 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_FFLightKinematics_H */ diff --git a/Shower/Dipole/Kinematics/FFMassiveKinematics.cc b/Shower/Dipole/Kinematics/FFMassiveKinematics.cc --- a/Shower/Dipole/Kinematics/FFMassiveKinematics.cc +++ b/Shower/Dipole/Kinematics/FFMassiveKinematics.cc @@ -1,436 +1,434 @@ // -*- C++ -*- // // FFMassiveKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFMassiveKinematics class. // #include "FFMassiveKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" #include "ThePEG/Interface/Switch.h" // TODO: remove after verification // only for checking for NaN or inf #include using namespace Herwig; FFMassiveKinematics::FFMassiveKinematics() : DipoleSplittingKinematics() {} -FFMassiveKinematics::~FFMassiveKinematics() {} - IBPtr FFMassiveKinematics::clone() const { return new_ptr(*this); } IBPtr FFMassiveKinematics::fullclone() const { return new_ptr(*this); } pair FFMassiveKinematics::kappaSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } pair FFMassiveKinematics::xiSupport(const DipoleSplittingInfo& split) const { double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); if ( split.index().emitterData()->id() == ParticleID::g ) { if ( split.emissionData()->id() != ParticleID::g ) return {0.5*(1.-c),0.5*(1.+c)}; double b = log((1.+c)/(1.-c)); return {-b,b}; } return {-log(0.5*(1.+c)),-log(0.5*(1.-c))}; } Energy FFMassiveKinematics::dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { return (pEmitter+pSpectator).m(); } Energy FFMassiveKinematics::ptMax(Energy dScale, double, double, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { DipoleIndex ind = dInfo.index(); double mui2 = 0.; // g->gg and g->qqbar if ( abs(split.emitter(ind)->id()) == abs(split.emission(ind)->id()) ) { mui2 = sqr(split.emitter(ind)->mass() / dScale); } // Otherwise have X->Xg (should work for SUSY) else { mui2 = sqr(dInfo.emitterMass()/dScale); } double muj2 = sqr(split.emission(ind)->mass() / dScale); double muk = dInfo.spectatorMass()/dScale; return rootOfKallen(mui2, muj2, sqr(1.-muk)) / ( 2.-2.*muk ) * dScale; } Energy FFMassiveKinematics::ptMax(Energy dScale, double, double, const DipoleIndex& ind, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const { double mui2 = 0.; // g->gg and g->qqbar if ( abs(split.emitter(ind)->id()) == abs(split.emission(ind)->id()) ) { mui2 = sqr(split.emitter(ind)->mass() / dScale); } // Otherwise have X->Xg (should work for SUSY) else { mui2 = sqr(emitter->mass()/dScale); } double muj2 = sqr(split.emission(ind)->mass() / dScale); double muk = spectator->mass()/dScale; return rootOfKallen(mui2, muj2, sqr(1.-muk)) / ( 2.-2.*muk ) * dScale; } Energy FFMassiveKinematics::QMax(Energy dScale, double, double, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { assert(false && "implementation missing"); double Muk = dInfo.spectatorMass() / dScale; return dScale * ( 1.-2.*Muk+sqr(Muk) ); } // The name of this function is misleading // scale here is defined as sqr(scale) = sqr(qi+qj) // Here, scale is Q Energy FFMassiveKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z=split.lastSplittingParameters()[0]; // masses Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(split.emitterData()->id()) == abs(split.emissionData()->id()) ) { mi2 = sqr(split.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = sqr(split.emitterMass()); } Energy2 m2 = sqr(split.emissionData()->mass()); Energy2 pt2 = z*(1.-z)*sqr(scale) - (1.-z)*mi2 - z*m2; assert(pt2 >= ZERO); return sqrt(pt2); } // This is simply the inverse of PtFromQ Energy FFMassiveKinematics::QFromPt(Energy pt, const DipoleSplittingInfo& split) const { double z=split.lastSplittingParameters()[0]; // masses Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(split.emitterData()->id()) == abs(split.emissionData()->id()) ) { mi2 = sqr( split.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = sqr(split.emitterMass()); } Energy2 m2 = sqr(split.emissionData()->mass()); Energy2 Q2 = (sqr(pt) + (1.-z)*mi2 + z*m2)/(z*(1.-z)); return sqrt(Q2); } double FFMassiveKinematics::ptToRandom(Energy pt, Energy, double,double, const DipoleIndex&, const DipoleSplittingKernel&) const { return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); } // SW, 14/02/2019: Tidied to match thesis bool FFMassiveKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) { // Scale 's' and masses Energy2 Qijk = sqr(info.scale()); Energy2 mij2 = sqr(info.emitterMass()); Energy2 Mk2 = sqr(info.spectatorMass()); // To solve issue with scale during presampling // need to enforce that Qijk-mij2-mk2 = 2*pij.pk > 0. // Combine checks by comparing against square root if ( Qijk-mij2-Mk2 < sqrt(4.*mij2*Mk2) ) { jacobian(0.0); return false; } Energy2 mk2 = Mk2; Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(info.emitterData()->id()) == abs(info.emissionData()->id()) ) { mi2 = sqr(info.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = mij2; } Energy2 mj2 = sqr(info.emissionData()->mass()); // Calculate pt Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); Energy2 pt2 = sqr(pt); if ( pt > info.hardPt() || pt < IRCutoff() ) { jacobian(0.0); return false; } // Generate z double z; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { z = xi; } else { z = exp(xi)/(1.+exp(xi)); } } else { z = 1.-exp(-xi); } // new: 2011-08-31 // 2011-11-08: this does happen if( (sqrt(mi2)+sqrt(mj2)+sqrt(mk2))/ sqrt(Qijk) > 1. ){ jacobian(0.0); return false; } // Limits on z. // Phasespace constraint to incorporate ptMax. Energy hard = info.hardPt(); Energy2 sqrRootQijkMk = sqr(sqrt(Qijk)-sqrt(mk2)); if(openZBoundaries()>0){ // From ptMax(..) hard = rootOfKallen(mi2, mj2, sqrRootQijkMk) / ( 2.*sqrt(sqrRootQijkMk) ); assert(pt<=hard); } double ptRatio = sqrt(1.-sqr(pt/hard)); double zp1 = ( mi2 - mj2 + sqrRootQijkMk + rootOfKallen(mi2,mj2,sqrRootQijkMk) * ptRatio ) / 2. / sqrRootQijkMk ; double zm1 = ( mi2 - mj2 + sqrRootQijkMk - rootOfKallen(mi2,mj2,sqrRootQijkMk) * ptRatio ) / 2. / sqrRootQijkMk ; if ( z > zp1 || z < zm1 ) { jacobian(0.0); return false; } // Calculate y Energy2 sbar = Qijk - mi2 - mj2 - mk2; double y = (pt2 + sqr(1.-z)*mi2 + sqr(z)*mj2) / sbar / z / (1.-z); // Kinematic phasespace boundaries for y. // Same as in Dittmaier hep-ph/9904440v2 (equivalent to CS). double ym = 2.*sqrt(mi2)*sqrt(mj2)/sbar; double yp = 1. - 2.*sqrt(mk2)*sqrt(sqrRootQijkMk) / sbar; if ( y < ym || y > yp ) { jacobian(0.0); return false; } // Virtuality of emitted pair and other invariant scale Energy2 Qij2 = (pt2 + (1.-z)*mi2 + z*mj2) / z / (1.-z); Energy2 sijk = 0.5*( Qijk - mij2 - Mk2 + rootOfKallen(Qijk,mij2,mk2) ); // Calculate xk and xij double lambdaIJ = 1. + (mij2/sijk); double lambdaK = 1. + (mk2/sijk); double fac1 = lambdaIJ*lambdaK + (mk2 - Qij2)/sijk; double xk = ( fac1 + sqrt( sqr(fac1) - 4.*lambdaIJ*lambdaK*mk2/sijk ) ) / 2. / lambdaK ; double xij = 1. - mk2*(1.-xk) / xk / sijk; // Calculate zi double zi = ( z*xij*xk*sijk + mk2*(pt2+mi2) / (z*xij*xk*sijk) ) / (1.-y) / sbar; // Limits on zi double facA = (2.*mi2 + sbar*y) / 2. / (mi2 + mj2 + sbar*y); // viji*vijk double facB = sqrt( (sqr(2.*mk2 + sbar*(1.-y)) - 4.*mk2*Qijk) * (sqr(sbar)*sqr(y) - 4.*mi2*mj2)) / sbar / (1.-y) / (sbar*y + 2.*mi2); double zim = facA * (1. - facB); double zip = facA * (1. + facB); if ( zi < zim || zi > zip ) { jacobian(0.0); return false; } double mapZJacobian; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { mapZJacobian = 1.; } else { mapZJacobian = z*(1.-z); } } else { mapZJacobian = 1.-z; } // Compute and store the jacobian double jac = 0.0; jac = sbar / rootOfKallen(Qijk,mij2,mk2) * (1.-y) / ( 1. + (mi2 + mj2 - mij2)/sbar/y ) * (pt2 / (pt2 + sqr(1.-z)*mi2+sqr(z)*mj2)) * abs(1. - 2.*mk2*Qij2 / (sbar*(1.-y)*xij*xk*sijk)); jacobian(jac * mapZJacobian * 2. * log(0.5 * generator()->maximumCMEnergy()/IRCutoff()) ); // Record the physical variables, as used by the CS kernel definitions double phi = 2.*Constants::pi*rphi; lastPt(pt); lastZ(z); lastPhi(phi); // Record zi for use in kinematics generation and kernel evaluation splittingParameters().clear(); splittingParameters().push_back(zi); if ( theMCCheck ) { theMCCheck->book(1.,1.,info.scale(),info.hardPt(),pt,z,jacobian()); } return true; } // revised 2011-08-22 // revised 2011-11-06 // revised with new FF kinematics in 2016 - SW // SW, 14/02/2019: Tidied to match thesis void FFMassiveKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy2 pt2 = sqr(pt); // Masses Energy2 mij2 = sqr(dInfo.emitterMass()); Energy2 Mk2 = sqr(dInfo.spectatorMass()); Energy2 mk2 = Mk2; Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(dInfo.emitterData()->id()) == abs(dInfo.emissionData()->id()) ) { mi2 = sqr(dInfo.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = mij2; } Energy2 mj2 = sqr(dInfo.emissionData()->mass()); // Scales Energy2 Qijk = sqr(dInfo.scale()); Energy2 Qij2 = (pt2 + (1.-z)*mi2 + z*mj2) / z / (1.-z); Energy2 sijk = 0.5*( Qijk - mij2 - Mk2 + rootOfKallen(Qijk,mij2,Mk2) ); Energy4 sijk2 = sqr(sijk); // Calculate xk and xij double lambdaIJ = 1. + (mij2/sijk); double lambdaK = 1. + (mk2/sijk); double fac1 = lambdaIJ*lambdaK + (mk2 - Qij2)/sijk; double xk = ( fac1 + sqrt( sqr(fac1) - 4.*lambdaIJ*lambdaK*mk2/sijk ) ) / 2. / lambdaK ; double xij = 1. - mk2*(1.-xk) / xk / sijk; // Construct reference momenta nk and nij Lorentz5Momentum nij = ( sijk2 / (sijk2-mij2*Mk2) ) * (pEmitter - (mij2/sijk)*pSpectator); Lorentz5Momentum nk = ( sijk2 / (sijk2-mij2*Mk2) ) * (pSpectator - (Mk2/sijk)*pEmitter); // Construct qij, qk, qi and qj Lorentz5Momentum qij = xij*nij + (mij2/(xij*sijk))*nk; Lorentz5Momentum qk = xk*nk + (Mk2/(xk*sijk))*nij; Lorentz5Momentum qt = getKt(pEmitter, pSpectator, pt, dInfo.lastPhi()); // For clarity, following notation in notes: Lorentz5Momentum qi = z*qij + ((pt2 + mi2 - z*z*mij2)/(xij*sijk*z))*nk + qt; Lorentz5Momentum qj = (1.-z)*qij + ((pt2 + mj2 - sqr(1.-z)*mij2)/(xij*sijk*(1.-z)))*nk - qt; qi.setMass(sqrt(mi2)); qi.rescaleEnergy(); qj.setMass(sqrt(mj2)); qj.rescaleEnergy(); qk.setMass(sqrt(mk2)); qk.rescaleEnergy(); emitterMomentum(qi); emissionMomentum(qj); spectatorMomentum(qk); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FFMassiveKinematics::persistentOutput(PersistentOStream &) const { //os << ; } void FFMassiveKinematics::persistentInput(PersistentIStream &, int) { //is >> ; } ClassDescription FFMassiveKinematics::initFFMassiveKinematics; // Definition of the static class description member. void FFMassiveKinematics::Init() { static ClassDocumentation documentation ("FFMassiveKinematics implements massive splittings " "off a final-final dipole."); } diff --git a/Shower/Dipole/Kinematics/FFMassiveKinematics.h b/Shower/Dipole/Kinematics/FFMassiveKinematics.h --- a/Shower/Dipole/Kinematics/FFMassiveKinematics.h +++ b/Shower/Dipole/Kinematics/FFMassiveKinematics.h @@ -1,299 +1,291 @@ // -*- C++ -*- // // FFMassiveKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FFMassiveKinematics_H #define HERWIG_FFMassiveKinematics_H // // This is the declaration of the FFMassiveKinematics class. // #include "DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Stephen Webster * * \brief FFMassiveKinematics implements massive splittings * off a final-final dipole. * */ class FFMassiveKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FFMassiveKinematics(); - /** - * The destructor. - */ - virtual ~FFMassiveKinematics(); - //@} - public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { return {0.0,1.0}; } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double, double, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for massive // dipoles, for now anyway. assert(false); return ZERO; } /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for massive // dipoles, for now anyway. assert(false); return ZERO; } /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel& split); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { if ( a*a + b*b + c*c - 2.*(a*b + a*c + b*c) > ZERO ) return sqrt(a*a + b*b + c*c - 2.*(a*b + a*c + b*c) ) ; else return ZERO; } /** * Perform a rotation on both momenta such that the first one will * point along the (positive) z axis. Rotate back to the original * reference frame by applying rotateUz(returnedVector) to each momentum. */ ThreeVector rotateToZ (Lorentz5Momentum& pTarget, Lorentz5Momentum& p1){ ThreeVector oldAxis = pTarget.vect().unit(); double ct = oldAxis.z(); double st = sqrt( 1.-sqr(ct) ); // cos,sin(theta) double cp = oldAxis.x()/st; double sp = oldAxis.y()/st; // cos,sin(phi) pTarget.setZ( pTarget.vect().mag() ); pTarget.setX( 0.*GeV ); pTarget.setY( 0.*GeV ); Lorentz5Momentum p1old = p1; p1.setX( sp*p1old.x() - cp*p1old.y() ); p1.setY( ct*cp*p1old.x() + ct*sp*p1old.y() - st*p1old.z() ); p1.setZ( st*cp*p1old.x() + st*sp*p1old.y() + ct*p1old.z() ); return oldAxis; } 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFMassiveKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMassiveKinematics & operator=(const FFMassiveKinematics &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFMassiveKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFMassiveKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the FFMassiveKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFMassiveKinematics"; } /** * The name of a file containing the dynamic library where the class * FFMassiveKinematics is implemented. It may also include several, space-separated, * libraries if the class FFMassiveKinematics 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_FFMassiveKinematics_H */ diff --git a/Shower/Dipole/Kinematics/FILightKinematics.cc b/Shower/Dipole/Kinematics/FILightKinematics.cc --- a/Shower/Dipole/Kinematics/FILightKinematics.cc +++ b/Shower/Dipole/Kinematics/FILightKinematics.cc @@ -1,187 +1,185 @@ // -*- C++ -*- // // FILightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FILightKinematics class. // #include "FILightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" using namespace Herwig; FILightKinematics::FILightKinematics() : DipoleSplittingKinematics() {} -FILightKinematics::~FILightKinematics() {} - IBPtr FILightKinematics::clone() const { return new_ptr(*this); } IBPtr FILightKinematics::fullclone() const { return new_ptr(*this); } Energy FILightKinematics::ptMax(Energy dScale, double, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale * sqrt((1.-specX)/specX) /2.; } Energy FILightKinematics::QMax(Energy dScale, double, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale * sqrt((1.-specX)/specX); } Energy FILightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale*sqrt(z*(1.-z)); } Energy FILightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale/sqrt(z*(1.-z)); } pair FILightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { Energy hard=dInfo.hardPt(); if(openZBoundaries()==1) hard=dInfo.scale()*sqrt((1.-dInfo.spectatorX())/dInfo.spectatorX())/2.; if(openZBoundaries()==2) hard=dInfo.scale()*min(1.,sqrt((1.-dInfo.spectatorX())/dInfo.spectatorX())/2.); if(hard info.hardPt() ) { jacobian(0.0); return false; } double z = 0.0; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { z = generateZ(xi,pt,FlatZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } } else { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } double x = 1./(1.+sqr(pt/info.scale())/(z*(1.-z))); if ( z < 0.0 || z > 1.0 || x < info.spectatorX() || x > 1.0 ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian(weight); lastPt(pt); lastZ(z); lastPhi(phi); lastSpectatorZ(x); if ( theMCCheck ) theMCCheck->book(1.,info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void FILightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); double x = 1./(1.+sqr(pt/dInfo.scale())/(z*(1.-z))); Lorentz5Momentum kt = getKt(pEmitter, pSpectator, pt, dInfo.lastPhi(), true); Lorentz5Momentum em = z*pEmitter + (1.-z)*((1.-x)/x)*pSpectator + kt; Lorentz5Momentum emm = (1.-z)*pEmitter + z*((1.-x)/x)*pSpectator - kt; Lorentz5Momentum spe = (1./x)*pSpectator; em.setMass(ZERO); em.rescaleEnergy(); emm.setMass(ZERO); emm.rescaleEnergy(); spe.setMass(ZERO); 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 FILightKinematics::persistentOutput(PersistentOStream & ) const { } void FILightKinematics::persistentInput(PersistentIStream & , int) { } ClassDescription FILightKinematics::initFILightKinematics; // Definition of the static class description member. void FILightKinematics::Init() { static ClassDocumentation documentation ("FILightKinematics implements massless splittings " "off a final-initial dipole."); } diff --git a/Shower/Dipole/Kinematics/FILightKinematics.h b/Shower/Dipole/Kinematics/FILightKinematics.h --- a/Shower/Dipole/Kinematics/FILightKinematics.h +++ b/Shower/Dipole/Kinematics/FILightKinematics.h @@ -1,200 +1,192 @@ // -*- C++ -*- // // FILightKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FILightKinematics_H #define HERWIG_FILightKinematics_H // // This is the declaration of the FILightKinematics class. // #include "DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief FILightKinematics implements massless splittings * off a final-initial dipole. * */ class FILightKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FILightKinematics(); - /** - * The destructor. - */ - virtual ~FILightKinematics(); - //@} - public: /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel&) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel&) const; /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel&); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFILightKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FILightKinematics & operator=(const FILightKinematics &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FILightKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FILightKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the FILightKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FILightKinematics"; } /** * The name of a file containing the dynamic library where the class * FILightKinematics is implemented. It may also include several, space-separated, * libraries if the class FILightKinematics 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_FILightKinematics_H */ diff --git a/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.cc b/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.cc --- a/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.cc +++ b/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.cc @@ -1,452 +1,450 @@ // -*- C++ -*- // // FIMassiveDecayKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIMassiveDecayKinematics class. // #include "FIMassiveDecayKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" #include "ThePEG/Interface/Switch.h" using namespace Herwig; FIMassiveDecayKinematics::FIMassiveDecayKinematics() : DipoleSplittingKinematics() {} -FIMassiveDecayKinematics::~FIMassiveDecayKinematics() {} - IBPtr FIMassiveDecayKinematics::clone() const { return new_ptr(*this); } IBPtr FIMassiveDecayKinematics::fullclone() const { return new_ptr(*this); } pair FIMassiveDecayKinematics::kappaSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } pair FIMassiveDecayKinematics::xiSupport(const DipoleSplittingInfo& split) const { double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); if ( split.index().emitterData()->id() == ParticleID::g ) { if ( split.emissionData()->id() != ParticleID::g ){ return {0.5*(1.-c),0.5*(1.+c)}; } double b = log((1.+c)/(1.-c)); return {-b,b}; } return {-log(0.5*(1.+c)),-log(0.5*(1.-c))}; } Energy FIMassiveDecayKinematics::dipoleScale(const Lorentz5Momentum&, const Lorentz5Momentum& pSpectator) const { return pSpectator.m(); } Energy FIMassiveDecayKinematics::recoilMassKin(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { Lorentz5Momentum pk = pSpectator - pEmitter; Energy pkmass = pk.m(); return pkmass; } Energy FIMassiveDecayKinematics::ptMax(Energy dScale, double, double, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { DipoleIndex ind = dInfo.index(); double mui2 = 0.; // g->gg and g->qqbar if ( abs(split.emitter(ind)->id()) == abs(split.emission(ind)->id()) ) { mui2 = sqr(split.emitter(ind)->mass() / dScale); } // Otherwise have X->Xg (should work for SUSY) else { mui2 = sqr(dInfo.emitterMass()/dScale); } double muj2 = sqr( split.emission(ind)->mass() / dScale ); // Mass of recoil system double muk = dInfo.recoilMass() / dScale; return rootOfKallen( mui2, muj2, sqr(1.-muk) ) / ( 2.-2.*muk ) * dScale; } Energy FIMassiveDecayKinematics::ptMax(Energy dScale, double, double, const DipoleIndex& ind, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const { double mui2 = 0.; // g->gg and g->qqbar if ( abs(split.emitter(ind)->id()) == abs(split.emission(ind)->id()) ) { mui2 = sqr(split.emitter(ind)->mass() / dScale); } // Otherwise have X->Xg (should work for SUSY) else { mui2 = sqr(emitter->mass()/dScale); } double muj2 = sqr(split.emission(ind)->mass() / dScale); // Mass of recoil system double muk = recoilMassKin(emitter->momentum(),spectator->momentum()) / dScale; return rootOfKallen( mui2, muj2, sqr(1.-muk) ) / ( 2.-2.*muk ) * dScale; } Energy FIMassiveDecayKinematics::QMax(Energy dScale, double, double, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { assert(false && "implementation missing"); // Mass of recoil system double Muk2 = sqr( dInfo.recoilMass() / dScale ); double Muk = sqrt( Muk2 ); return dScale * ( 1.-2.*Muk+Muk2 ); } // The name of this function is misleading // scale here is defined as sqr(scale) = sqr(qi+qj) // Here, scale is Q Energy FIMassiveDecayKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double zPrime = split.lastSplittingParameters()[0]; // masses Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(split.emitterData()->id()) == abs(split.emissionData()->id()) ) { mi2 = sqr( split.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = sqr(split.emitterMass()); } Energy2 m2 = sqr(split.emissionData()->mass()); Energy2 pt2 = zPrime*(1.-zPrime)*sqr(scale) - (1-zPrime)*mi2 - zPrime*m2; assert(pt2 >= ZERO); return sqrt(pt2); } // This is simply the inverse of PtFromQ Energy FIMassiveDecayKinematics::QFromPt(Energy pt, const DipoleSplittingInfo& split) const { double zPrime = split.lastSplittingParameters()[0]; // masses Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(split.emitterData()->id()) == abs(split.emissionData()->id()) ) { mi2 = sqr( split.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = sqr(split.emitterMass()); } Energy2 m2 = sqr(split.emissionData()->mass()); Energy2 Q2 = (sqr(pt) + (1-zPrime)*mi2 + zPrime*m2)/(zPrime*(1.-zPrime)); return sqrt(Q2); } double FIMassiveDecayKinematics::ptToRandom(Energy pt, Energy, double,double, const DipoleIndex&, const DipoleSplittingKernel&) const { return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); } // SW, 14/02/2019: Tidied to match thesis bool FIMassiveDecayKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) { // Scale 's' and masses Energy2 Qijk = sqr(info.scale()); Energy2 mij2 = sqr(info.emitterMass()); Energy2 Mk2 = sqr(info.recoilMass()); // To solve issue with scale during presampling // need to enforce that Qijk-mij2-mk2 = 2*pij.pk > 0. // Combine checks by comparing against square root if ( Qijk-mij2-Mk2 < sqrt(4.*mij2*Mk2) ) { jacobian(0.0); return false; } Energy2 mk2 = Mk2; Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(info.emitterData()->id()) == abs(info.emissionData()->id()) ) { mi2 = sqr(info.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = mij2; } Energy2 mj2 = sqr(info.emissionData()->mass()); // Calculate pt Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); Energy2 pt2 = sqr(pt); if ( pt > info.hardPt() || pt < IRCutoff() ) { jacobian(0.0); return false; } // Generate z double z; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { z = xi; } else { z = exp(xi)/(1.+exp(xi)); } } else { z = 1.-exp(-xi); } // new: 2011-08-31 // 2011-11-08: this does happen if( (sqrt(mi2)+sqrt(mj2)+sqrt(mk2))/ sqrt(Qijk) > 1. ){ jacobian(0.0); return false; } // Limits on z. // Phasespace constraint to incorporate ptMax. Energy hard = info.hardPt(); Energy2 sqrRootQijkMk = sqr(sqrt(Qijk)-sqrt(mk2)); if(openZBoundaries()>0){ // From ptMax(..) hard = rootOfKallen(mi2, mj2, sqrRootQijkMk) / ( 2.*sqrt(sqrRootQijkMk) ); assert(pt<=hard); } double ptRatio = sqrt(1.-sqr(pt/hard)); double zp1 = ( mi2 - mj2 + sqrRootQijkMk + rootOfKallen(mi2,mj2,sqrRootQijkMk) * ptRatio ) / 2. / sqrRootQijkMk ; double zm1 = ( mi2 - mj2 + sqrRootQijkMk - rootOfKallen(mi2,mj2,sqrRootQijkMk) * ptRatio ) / 2. / sqrRootQijkMk ; if ( z > zp1 || z < zm1 ) { jacobian(0.0); return false; } // Calculate y Energy2 sbar = Qijk - mi2 - mj2 - mk2; double y = (pt2 + sqr(1.-z)*mi2 + sqr(z)*mj2) / sbar / z / (1.-z); // Kinematic phasespace boundaries for y. // Same as in Dittmaier hep-ph/9904440v2 (equivalent to CS). double ym = 2.*sqrt(mi2)*sqrt(mj2)/sbar; double yp = 1. - 2.*sqrt(mk2)*sqrt(sqrRootQijkMk) / sbar; if ( y < ym || y > yp ) { jacobian(0.0); return false; } // Virtuality of emitted pair and other invariant scale Energy2 Qij2 = (pt2 + (1.-z)*mi2 + z*mj2) / z / (1.-z); Energy2 sijk = 0.5*( Qijk - mij2 - Mk2 + rootOfKallen(Qijk,mij2,mk2) ); // Calculate xk and xij double lambdaIJ = 1. + (mij2/sijk); double lambdaK = 1. + (mk2/sijk); double fac1 = lambdaIJ*lambdaK + (mk2 - Qij2)/sijk; double xk = ( fac1 + sqrt( sqr(fac1) - 4.*lambdaIJ*lambdaK*mk2/sijk ) ) / 2. / lambdaK ; double xij = 1. - mk2*(1.-xk) / xk / sijk; // Calculate zi double zi = ( z*xij*xk*sijk + mk2*(pt2+mi2) / (z*xij*xk*sijk) ) / (1.-y) / sbar; // Limits on zi double facA = (2.*mi2 + sbar*y) / 2. / (mi2 + mj2 + sbar*y); // viji*vijk double facB = sqrt( (sqr(2.*mk2 + sbar*(1.-y)) - 4.*mk2*Qijk) * (sqr(sbar)*sqr(y) - 4.*mi2*mj2)) / sbar / (1.-y) / (sbar*y + 2.*mi2); double zim = facA * (1. - facB); double zip = facA * (1. + facB); if ( zi < zim || zi > zip ) { jacobian(0.0); return false; } double mapZJacobian; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { mapZJacobian = 1.; } else { mapZJacobian = z*(1.-z); } } else { mapZJacobian = 1.-z; } // Compute and store the jacobian double jac = 0.0; jac = sbar / rootOfKallen(Qijk,mij2,mk2) * (1.-y) / ( 1. + (mi2 + mj2 - mij2)/sbar/y ) * (pt2 / (pt2 + sqr(1.-z)*mi2+sqr(z)*mj2)) * abs(1. - 2.*mk2*Qij2 / (sbar*(1.-y)*xij*xk*sijk)); jacobian(jac * mapZJacobian * 2. * log(0.5 * generator()->maximumCMEnergy()/IRCutoff()) ); // Record the physical variables, as used by the CS kernel definitions double phi = 2.*Constants::pi*rphi; lastPt(pt); lastZ(z); lastPhi(phi); // Record zi for use in kinematics generation and kernel evaluation splittingParameters().clear(); splittingParameters().push_back(zi); if ( theMCCheck ) { theMCCheck->book(1.,1.,info.scale(),info.hardPt(),pt,z,jacobian()); } return true; } // SW, 14/02/2019: Tidied to match thesis void FIMassiveDecayKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy2 pt2 = sqr(pt); // Momentum of the recoil system Lorentz5Momentum pk = pSpectator - pEmitter; Lorentz5Momentum pij = pEmitter; // scaled masses Energy2 mij2 = sqr(dInfo.emitterMass()); Energy2 Mk2 = sqr(dInfo.recoilMass()); Energy2 mk2 = Mk2; Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(dInfo.emitterData()->id()) == abs(dInfo.emissionData()->id()) ) { mi2 = sqr(dInfo.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = mij2; } Energy2 mj2 = sqr(dInfo.emissionData()->mass()); // Scales Energy2 Qijk = sqr(dInfo.scale()); Energy2 Qij2 = (pt2 + (1.-z)*mi2 + z*mj2) / z / (1.-z); Energy2 sijk = 0.5*( Qijk - mij2 - mk2 + rootOfKallen(Qijk,mij2,mk2) ); Energy4 sijk2 = sqr(sijk); // Calculate xk and xij double lambdaIJ = 1. + (mij2/sijk); double lambdaK = 1. + (mk2/sijk); double fac1 = lambdaIJ*lambdaK + (mk2 - Qij2)/sijk; double xk = ( fac1 + sqrt( sqr(fac1) - 4.*lambdaIJ*lambdaK*mk2/sijk ) ) / 2. / lambdaK ; double xij = 1. - mk2*(1.-xk) / xk / sijk; // Construct reference momenta nk and nij Lorentz5Momentum nij = ( sijk2 / (sijk2-mij2*Mk2) ) * (pij - (mij2/sijk)*pk); Lorentz5Momentum nk = ( sijk2 / (sijk2-mij2*Mk2) ) * (pk - (Mk2/sijk)*pij); // Construct qij, qk, qi and qj Lorentz5Momentum qij = xij*nij + (mij2/(xij*sijk))*nk; Lorentz5Momentum qk = xk*nk + (Mk2/(xk*sijk))*nij; Lorentz5Momentum qt = getKt(pij, pk, pt, dInfo.lastPhi()); // No need to actually calculate nt and wt: Lorentz5Momentum qi = z*qij + ((pt2 + mi2 - z*z*mij2)/(xij*sijk*z))*nk + qt; Lorentz5Momentum qj = (1.-z)*qij + ((pt2 + mj2 - sqr(1.-z)*mij2)/(xij*sijk*(1.-z)))*nk - qt; qi.setMass(sqrt(mi2)); qi.rescaleEnergy(); qj.setMass(sqrt(mj2)); qj.rescaleEnergy(); emitterMomentum(qi); emissionMomentum(qj); spectatorMomentum(pSpectator); // Required for absorbing recoil in DipoleEventRecord::update splitRecoilMomentum(qk); } Lorentz5Momentum FIMassiveDecayKinematics::nVector(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo&) const { return (pSpectator-pEmitter); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMassiveDecayKinematics::persistentOutput(PersistentOStream &) const { //os << ; } void FIMassiveDecayKinematics::persistentInput(PersistentIStream &, int) { //is >> ; } ClassDescription FIMassiveDecayKinematics::initFIMassiveDecayKinematics; // Definition of the static class description member. void FIMassiveDecayKinematics::Init() { static ClassDocumentation documentation ("FIMassiveDecayKinematics implements implements massive splittings " "off a final-initial decay dipole."); } diff --git a/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.h b/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.h --- a/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.h +++ b/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.h @@ -1,327 +1,319 @@ // -*- C++ -*- // // FIMassiveDecayKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FIMassiveDecayKinematics_H #define HERWIG_FIMassiveDecayKinematics_H // // This is the declaration of the FIMassiveDecayKinematics class. // #include "DipoleSplittingKinematics.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/UtilityBase.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Stephen Webster * * \brief FIMassiveDecayKinematics implements massive splittings * off a final-initial decay dipole. * */ class FIMassiveDecayKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMassiveDecayKinematics(); - /** - * The destructor. - */ - virtual ~FIMassiveDecayKinematics(); - //@} - public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { return {0.0,1.0}; } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the mass of the system absorbing * the recoil in the dipole splitting. * This is only used in decay dipoles. */ virtual Energy recoilMassKin(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double, double, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for the decays. assert(false); return ZERO; } /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for the decays. assert(false); return ZERO; } /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); /** * Return the nVector as required for spin correlations. */ virtual Lorentz5Momentum nVector(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) const; /* * Return true if this splitting is of a dipole which contains * a decayed parton and requires the remnant to absorb the recoil. */ virtual bool isDecay() const { return true; } /** * Perform the recoil in the case of a decayed parton */ virtual void decayRecoil ( PList& recoilSystem ) { PList::iterator beginRecoil = recoilSystem.begin(); PList::iterator endRecoil = recoilSystem.end(); // This is the final momentum that we must transform the system to const Momentum3 transformMom = splitRecoilMomentum().vect(); // Calculate required Lorentz rotation Lorentz5Momentum sum = ThePEG::UtilityBase::sumMomentum(beginRecoil, endRecoil); LorentzRotation rot = ThePEG::UtilityBase::transformToCMS(sum); rot = ThePEG::UtilityBase::transformFromCMS (Lorentz5Momentum(transformMom, sqrt(transformMom.mag2() + sum.m2()))) * rot; // Transform the particle spinInfo if required for ( const auto& p : recoilSystem ) { if ( p->spinInfo() ) p->spinInfo()->transform(p->momentum(),rot); } ThePEG::UtilityBase::transform(beginRecoil, endRecoil, rot ); } public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { if ( a*a + b*b + c*c - 2.*(a*b + a*c + b*c) > ZERO ) return sqrt(a*a + b*b + c*c - 2.*(a*b + a*c + b*c) ) ; else return ZERO; } 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMassiveDecayKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMassiveDecayKinematics & operator=(const FIMassiveDecayKinematics &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMassiveDecayKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMassiveDecayKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMassiveDecayKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMassiveDecayKinematics"; } /** * The name of a file containing the dynamic library where the class * FIMassiveDecayKinematics is implemented. It may also include several, space-separated, * libraries if the class FIMassiveDecayKinematics 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_FIMassiveDecayKinematics_H */ diff --git a/Shower/Dipole/Kinematics/FIMassiveKinematics.cc b/Shower/Dipole/Kinematics/FIMassiveKinematics.cc --- a/Shower/Dipole/Kinematics/FIMassiveKinematics.cc +++ b/Shower/Dipole/Kinematics/FIMassiveKinematics.cc @@ -1,385 +1,383 @@ // -*- C++ -*- // // FIMassiveKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FIMassiveKinematics class. // #include "FIMassiveKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" using namespace Herwig; FIMassiveKinematics::FIMassiveKinematics() : DipoleSplittingKinematics() {} -FIMassiveKinematics::~FIMassiveKinematics() {} - IBPtr FIMassiveKinematics::clone() const { return new_ptr(*this); } IBPtr FIMassiveKinematics::fullclone() const { return new_ptr(*this); } pair FIMassiveKinematics::kappaSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } pair FIMassiveKinematics::xiSupport(const DipoleSplittingInfo& split) const { double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); if ( split.index().emitterData()->id() == ParticleID::g ) { if ( split.emissionData()->id() != ParticleID::g ) return {0.5*(1.-c),0.5*(1.+c)}; double b = log((1.+c)/(1.-c)); return {-b,b}; } return {-log(0.5*(1.+c)),-log(0.5*(1.-c))}; } // sbar Energy FIMassiveKinematics::dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { return sqrt(2.*(pEmitter*pSpectator)); } Energy FIMassiveKinematics::ptMax(Energy dScale, double, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { DipoleIndex ind = dInfo.index(); Energy2 mij2 = sqr(dInfo.emitterMass()); Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(split.emitter(ind)->id()) == abs(split.emission(ind)->id()) ) { mi2 = sqr(split.emitter(ind)->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = mij2; } Energy2 mj2 = sqr(split.emission(ind)->mass()); Energy2 sPrime = sqr(dScale) * (1.-specX)/specX + mij2; return .5 * sqrt(sPrime) * rootOfKallen( sPrime/sPrime, mi2/sPrime, mj2/sPrime ); } Energy FIMassiveKinematics::ptMax(Energy dScale, double, double specX, const DipoleIndex& ind, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr) const { Energy2 mij2 = sqr(emitter->mass()); Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(split.emitter(ind)->id()) == abs(split.emission(ind)->id()) ) { mi2 = sqr(split.emitter(ind)->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = mij2; } Energy2 mj2 = sqr(split.emission(ind)->mass()); Energy2 sPrime = sqr(dScale) * (1.-specX)/specX + mij2; return .5 * sqrt(sPrime) * rootOfKallen( sPrime/sPrime, mi2/sPrime, mj2/sPrime ); } Energy FIMassiveKinematics::QMax(Energy dScale, double, double specX, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { generator()->log() << "FIMassiveKinematics::QMax called.\n" << flush; assert(false && "implementation missing"); // this is sqrt( 2qi*q ) -> max; return dScale * sqrt((1.-specX)/specX); } Energy FIMassiveKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { // from Martin's thesis double z = split.lastZ(); // masses Energy2 mi2 = ZERO;; if ( abs(split.emitterData()->id()) == abs(split.emissionData()->id()) ) { mi2 = sqr(split.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = sqr(split.emitterMass()); } Energy2 mj2 = sqr(split.emissionData()->mass()); Energy2 pt2 = z*(1.-z)*sqr(scale) - (1.-z)*mi2 - z*mj2; assert(pt2 >= ZERO); return sqrt(pt2); } Energy FIMassiveKinematics::QFromPt(Energy pt, const DipoleSplittingInfo& split) const { // from Martin's thesis double z = split.lastZ(); // masses Energy2 mi2 = ZERO;; if ( abs(split.emitterData()->id()) == abs(split.emissionData()->id()) ) { mi2 = sqr(split.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = sqr(split.emitterMass()); } Energy2 mj2 = sqr(split.emissionData()->mass()); Energy2 Q2 = (sqr(pt) + (1.-z)*mi2 + z*mj2)/(z*(1.-z)); return sqrt(Q2); } double FIMassiveKinematics::ptToRandom(Energy pt, Energy, double,double, const DipoleIndex&, const DipoleSplittingKernel&) const { return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); } bool FIMassiveKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) { if ( info.spectatorX() < xMin() ) { jacobian(0.0); return false; } Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); if ( pt > info.hardPt() || pt < IRCutoff() ) { jacobian(0.0); return false; } double z; double mapZJacobian; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { z = xi; mapZJacobian = 1.; } else { z = exp(xi)/(1.+exp(xi)); mapZJacobian = z*(1.-z); } } else { z = 1.-exp(-xi); mapZJacobian = 1.-z; } // Construct mass squared variables Energy2 mij2 = sqr(info.emitterMass()); Energy2 mi2 = ZERO; // g->gg and g->qqbar if ( abs(info.emitterData()->id()) == abs(info.emissionData()->id()) ) { mi2 = sqr(info.emitterData()->mass()); } // Otherwise have X->Xg (should work for SUSY) else { mi2 = mij2; } Energy2 mj2 = sqr(info.emissionData()->mass()); Energy2 pt2 = sqr(pt); // 2 pij.pb Energy2 sbar = sqr(info.scale()); // Compute x double x = 1. / ( 1. + ( pt2 + (1.-z)*mi2 + z*mj2 - z*(1.-z)*mij2 ) / ( z*(1.-z)*sbar ) ); // Check the limit on x double xs = info.spectatorX(); if ( x < xs ) { jacobian(0.0); return false; } // Compute and check the z limits Energy2 sPrime = sbar * (1.-xs)/xs + mij2; Energy hard=info.hardPt(); if(openZBoundaries()==1){ hard=.5 * sqrt(sPrime) * rootOfKallen( sPrime/sPrime, mi2/sPrime, mj2/sPrime ); } if(openZBoundaries()==2){ Energy2 s = mij2 - sbar; hard=min(0.5*sqrt(sPrime) * rootOfKallen( sPrime/sPrime, mi2/sPrime, mj2/sPrime ) , 0.5*sqrt(s) * rootOfKallen( s/s, mi2/s, mj2/s )); } double ptRatio = sqrt(1.-sqr(pt/hard)); double zm1 = .5*( 1.+(mi2-mj2)/sPrime - rootOfKallen(sPrime/sPrime,mi2/sPrime,mj2/sPrime) * ptRatio); double zp1 = .5*( 1.+(mi2-mj2)/sPrime + rootOfKallen(sPrime/sPrime,mi2/sPrime,mj2/sPrime) * ptRatio); if ( z > zp1 || z < zm1 ) { jacobian(0.0); return false; } // additional purely kinematic constraints from // the integration limits in Catani-Seymour double mui2CS = x*mi2/sbar; double muj2CS = x*mj2/sbar; double muij2CS = x*mij2/sbar; // Limit on x double xp = 1. + muij2CS - sqr(sqrt(mui2CS)+sqrt(muj2CS)); if (x > xp ) { jacobian(0.0); return false; } // Limit on z double root = sqr(1.-x+muij2CS-mui2CS-muj2CS)-4.*mui2CS*muj2CS; if( root < 0. && root>-1e-10 ) { // assert(false); root = 0.; } else if (root <0. ) { jacobian(0.0); return false; } root = sqrt(root); double zm2 = .5*( 1.-x+muij2CS+mui2CS-muj2CS - root ) / (1.-x+muij2CS); double zp2 = .5*( 1.-x+muij2CS+mui2CS-muj2CS + root ) / (1.-x+muij2CS); if ( z > zp2 || z < zm2 ) { jacobian(0.0); return false; } // Store the splitting variables double phi = 2.*Constants::pi*rphi; // Compute and store the jacobian double jacPt2 = 1. / ( 1. + (1.-z)*mi2/pt2 + z*mj2/pt2 - z*(1.-z)*mij2/pt2 ); jacobian( jacPt2 * mapZJacobian * 2.*log(0.5 * generator()->maximumCMEnergy()/IRCutoff())); lastPt(pt); lastZ(z); lastPhi(phi); lastSpectatorZ(x); if ( theMCCheck ) theMCCheck->book(1.,info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void FIMassiveKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { // Get splitting variables Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); // Compute sqr scales Energy2 pt2 = sqr(pt); Energy2 sbar = sqr(dInfo.scale()); // Construct mass squared variables Energy2 mij2 = sqr(dInfo.emitterMass()); Energy mi = ZERO; // g->gg and g->qqbar if ( abs(dInfo.emitterData()->id()) == abs(dInfo.emissionData()->id()) ) { mi = dInfo.emitterData()->mass(); } // Otherwise have X->Xg (should work for SUSY) else { mi = dInfo.emitterMass(); } Energy2 mi2 = sqr(mi); Energy2 mj2 = sqr(dInfo.emissionData()->mass()); double xInv = ( 1. + (pt2+(1.-z)*mi2+z*mj2-z*(1.-z)*mij2) / (z*(1.-z)*sbar) ); Lorentz5Momentum kt = getKt(pEmitter, pSpectator, pt, dInfo.lastPhi(), true); Lorentz5Momentum em = z*pEmitter + (pt2+mi2-z*z*mij2)/(z*sbar)*pSpectator + kt; Lorentz5Momentum emm = (1.-z)*pEmitter + (pt2+mj2-sqr(1.-z)*mij2)/((1.-z)*sbar)*pSpectator - kt; Lorentz5Momentum spe = xInv*pSpectator; em.setMass(mi); em.rescaleEnergy(); emm.setMass(dInfo.emissionData()->mass()); emm.rescaleEnergy(); spe.setMass(ZERO); 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 FIMassiveKinematics::persistentOutput(PersistentOStream & ) const { } void FIMassiveKinematics::persistentInput(PersistentIStream & , int) { } ClassDescription FIMassiveKinematics::initFIMassiveKinematics; // Definition of the static class description member. void FIMassiveKinematics::Init() { static ClassDocumentation documentation ("FIMassiveKinematics implements massless splittings " "off a final-initial dipole."); } diff --git a/Shower/Dipole/Kinematics/FIMassiveKinematics.h b/Shower/Dipole/Kinematics/FIMassiveKinematics.h --- a/Shower/Dipole/Kinematics/FIMassiveKinematics.h +++ b/Shower/Dipole/Kinematics/FIMassiveKinematics.h @@ -1,281 +1,273 @@ // -*- C++ -*- // // FILightKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_FILightKinematics_H #define HERWIG_FILightKinematics_H // // This is the declaration of the FILightKinematics class. // #include "DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll * * \brief FIMassiveKinematics implements massless splittings * off a final-initial dipole. * */ class FIMassiveKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ FIMassiveKinematics(); - /** - * The destructor. - */ - virtual ~FIMassiveKinematics(); - //@} - public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { return {0.0,1.0}; } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double, double, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for massive // dipoles, for now anyway. assert(false); return ZERO; } /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for massive // dipoles, for now anyway. assert(false); return ZERO; } /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel&) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel&); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); public: /** * Triangular / Kallen function */ template inline double rootOfKallen (T a, T b, T c) const { double sres=a*a + b*b + c*c - 2.*( a*b+a*c+b*c ); return sres>0.?sqrt( sres ):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 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMassiveKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMassiveKinematics & operator=(const FIMassiveKinematics &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMassiveKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMassiveKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMassiveKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMassiveKinematics"; } /** * The name of a file containing the dynamic library where the class * FIMassiveKinematics is implemented. It may also include several, space-separated, * libraries if the class FIMassiveKinematics 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_FIMassiveKinematics_H */ diff --git a/Shower/Dipole/Kinematics/IFLightKinematics.cc b/Shower/Dipole/Kinematics/IFLightKinematics.cc --- a/Shower/Dipole/Kinematics/IFLightKinematics.cc +++ b/Shower/Dipole/Kinematics/IFLightKinematics.cc @@ -1,255 +1,253 @@ // -*- C++ -*- // // IFLightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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/Shower/Dipole/Base/DipoleSplittingInfo.h" using namespace Herwig; IFLightKinematics::IFLightKinematics() : 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 IFLightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { double x = dInfo.emitterX(); Energy hard=dInfo.hardPt(); if(openZBoundaries()==1)hard=dInfo.scale() * sqrt((1.-x)/x) /2.; if(openZBoundaries()==2)hard=dInfo.scale() * min(1.,sqrt((1.-x)/x) /2.); if(hard 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./(u+x-2.*u*x))); 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); // Initialise the momenta 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); emm = ((1.-x)/(x-u))*pEmitter + ((u/x)*(1.-u)/(x-u))*pSpectator - kt/(x-u); spe = (1.-u/x)*pSpectator; } else { em = (1./x)*pEmitter; emm = ((1.-x)*(1.-u)/x)*pEmitter + u*pSpectator + kt; spe = ((1.-x)*u/x)*pEmitter + (1.-u)*pSpectator - kt; } em.setMass(ZERO); em.rescaleEnergy(); emm.setMass(ZERO); emm.rescaleEnergy(); spe.setMass(ZERO); 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 &) const { //os << theCollinearScheme; } void IFLightKinematics::persistentInput(PersistentIStream &, int) { //is >> theCollinearScheme; } ClassDescription IFLightKinematics::initIFLightKinematics; // Definition of the static class description member. void IFLightKinematics::Init() { static ClassDocumentation documentation ("IFLightKinematics implements massless splittings " "off a initial-final dipole."); /* static Switch interfaceCollinearScheme ("CollinearScheme", "[experimental] Switch on or off the collinear scheme", &IFLightKinematics::theCollinearScheme, false, false, false); static SwitchOption interfaceCollinearSchemeYes (interfaceCollinearScheme, "Yes", "Switch on the collinear scheme.", true); static SwitchOption interfaceCollinearSchemeNo (interfaceCollinearScheme, "No", "Switch off the collinear scheme", false); interfaceCollinearScheme.rank(-1); */ } diff --git a/Shower/Dipole/Kinematics/IFLightKinematics.h b/Shower/Dipole/Kinematics/IFLightKinematics.h --- a/Shower/Dipole/Kinematics/IFLightKinematics.h +++ b/Shower/Dipole/Kinematics/IFLightKinematics.h @@ -1,209 +1,201 @@ // -*- C++ -*- // // IFLightKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFLightKinematics_H #define HERWIG_IFLightKinematics_H // // This is the declaration of the IFLightKinematics class. // #include "DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IFLightKinematics implements massless splittings * off an initial-final dipole. * * @see \ref IFLightKinematicsInterfaces "The interfaces" * defined for IFLightKinematics. */ class IFLightKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFLightKinematics(); - /** - * The destructor. - */ - virtual ~IFLightKinematics(); - //@} - public: /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel&) const; /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel&); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFLightKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFLightKinematics & operator=(const IFLightKinematics &) = delete; private: /** * Wether or not to choose the `collinear' scheme */ bool theCollinearScheme; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFLightKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFLightKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the IFLightKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFLightKinematics"; } /** * The name of a file containing the dynamic library where the class * IFLightKinematics is implemented. It may also include several, space-separated, * libraries if the class IFLightKinematics 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_IFLightKinematics_H */ diff --git a/Shower/Dipole/Kinematics/IFMassiveDecayKinematics.cc b/Shower/Dipole/Kinematics/IFMassiveDecayKinematics.cc --- a/Shower/Dipole/Kinematics/IFMassiveDecayKinematics.cc +++ b/Shower/Dipole/Kinematics/IFMassiveDecayKinematics.cc @@ -1,392 +1,390 @@ // -*- C++ -*- // // IFMassiveDecayKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFMassiveDecayKinematics class. // #include "IFMassiveDecayKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" using namespace Herwig; IFMassiveDecayKinematics::IFMassiveDecayKinematics() : DipoleSplittingKinematics() {} -IFMassiveDecayKinematics::~IFMassiveDecayKinematics() {} - IBPtr IFMassiveDecayKinematics::clone() const { return new_ptr(*this); } IBPtr IFMassiveDecayKinematics::fullclone() const { return new_ptr(*this); } pair IFMassiveDecayKinematics::kappaSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } pair IFMassiveDecayKinematics::xiSupport(const DipoleSplittingInfo& split) const { double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); if ( split.index().emitterData()->id() == ParticleID::g ) { if ( split.emissionData()->id() != ParticleID::g ){ return {0.5*(1.-c),0.5*(1.+c)};} double b = log((1.+c)/(1.-c)); return {-b,b}; } return {-log(0.5*(1.+c)),-log(0.5*(1.-c))}; } Energy IFMassiveDecayKinematics::dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum&) const { return pEmitter.m(); } Energy IFMassiveDecayKinematics::recoilMassKin(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { Lorentz5Momentum pk = pEmitter - pSpectator; double pkmass = pk.m(); return pkmass; } Energy IFMassiveDecayKinematics::ptMax(Energy dScale, double, double, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const { DipoleIndex ind = dInfo.index(); double mui = split.spectator(ind)->mass() / dScale; double mu = split.emission(ind)->mass() / dScale; // Mass of recoil system // Use abs() due to generation of negative // recoilMass during sampling. double muj = abs(dInfo.recoilMass() / dScale); double mui2 = sqr( mui ), mu2 = sqr( mu ); return rootOfKallen( mui2, mu2, sqr(1.-muj) ) / ( 2.-2.*muj ) * dScale; } Energy IFMassiveDecayKinematics::QMax(Energy dScale, double, double, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { assert(false && "implementation missing"); // Mass of recoil system double Muj = abs(dInfo.recoilMass() / dScale); return dScale * ( 1.-2.*Muj+sqr(Muj) ); } Energy IFMassiveDecayKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { // from Martin's thesis double zPrime = split.lastSplittingParameters()[0]; Energy mi = split.spectatorData()->mass(); Energy m = split.emissionData()->mass(); Energy2 pt2 = zPrime*(1.-zPrime)*sqr(scale) - (1-zPrime)*sqr(mi) - zPrime*sqr(m); assert(pt2 >= ZERO); return sqrt(pt2); } Energy IFMassiveDecayKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { // from Martin's thesis double zPrime = split.lastSplittingParameters()[0]; Energy mi = split.spectatorData()->mass(); Energy m = split.emissionData()->mass(); Energy2 Q2 = (sqr(scale) + (1-zPrime)*sqr(mi) + zPrime*sqr(m))/(zPrime*(1.-zPrime)); return sqrt(Q2); } double IFMassiveDecayKinematics::ptToRandom(Energy pt, Energy, double,double, const DipoleIndex&, const DipoleSplittingKernel&) const { return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); } bool IFMassiveDecayKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) { // Construct mass squared variables Energy2 mi2 = sqr( info.spectatorData()->mass() ); Energy2 mj2 = sqr( info.emissionData()->mass() ); // Specific to the IFDecay kinematics Energy2 mij2 = mi2; Energy2 mk2 = sqr( info.recoilMass() ); Energy2 Qijk = sqr( info.scale()); // To solve issue with scale during presampling // need to enforce that Qijk-mij2-mk2 = 2*pij.pk > 0, // so combine checks by comparing against square root. if ( Qijk-mij2-mk2 < sqrt(4.*mij2*mk2) ) { jacobian(0.0); return false; } Energy2 sijk = 0.5*( Qijk - mij2 - mk2 + sqrt( sqr(Qijk-mij2-mk2) - 4.*mij2*mk2 ) ); // Calculate pt Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); Energy2 pt2 = sqr(pt); if ( pt > info.hardPt() || pt < IRCutoff() ) { jacobian(0.0); return false; } // Generate zPrime (i.e. the new definition of z specific to massive FF and decays) double zPrime; // TODO: This may need to change along with the emitter and spectator usage, if IFDecays are implemented again if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { zPrime = xi; } else { zPrime = exp(xi)/(1.+exp(xi)); } } else { zPrime = 1.-exp(-xi); } // scaled masses *** TODO: rewrite above in terms of mu to avoid this calculation ***, and mix up of notation double mui2 = mi2 / Qijk; double mu2 = mj2 / Qijk; double muj2 = mk2 / Qijk; double Mui2 = mui2; double Muj2 = muj2; // Check limit on pt Energy ptmax1 = rootOfKallen( mui2, mu2, sqr(1.-sqrt(muj2)) ) / ( 2.-2.*sqrt(muj2) ) * info.scale(); Energy auxHardPt = ptmax1 > info.hardPt() ? info.hardPt() : ptmax1; // 24/05/2015: Moved this check from the zPrime limit checks if ( pt > auxHardPt ){ jacobian(0.0); return false; } // 2011-11-09 //assert(ptmax1>info.hardPt()); // 24/05/2015: // The simple >= assert above is triggered // during sampling due to precision. // Have added a tolerance to deal with this. assert( abs(ptmax1 - info.hardPt()) <= 1e-8 || ptmax1>=info.hardPt() ); // new: 2011-08-31 // 2011-11-08: this does happen if( sqrt(mui2)+sqrt(mu2)+sqrt(muj2) > 1. ){ jacobian(0.0); return false; } // I have derived and checked the equations for zp1 and zm1, these apply to zPrime!!! // phasespace constraint to incorporate ptMax double zp1 = ( 1.+mui2-mu2+muj2-2.*sqrt(muj2) + rootOfKallen(mui2,mu2,sqr(1-sqrt(muj2))) * sqrt( 1.-sqr(pt/auxHardPt) ) ) / ( 2.*sqr(1.-sqrt(muj2)) ); double zm1 = ( 1.+mui2-mu2+muj2-2.*sqrt(muj2) - rootOfKallen(mui2,mu2,sqr(1-sqrt(muj2))) * sqrt( 1.-sqr(pt/auxHardPt) ) ) / ( 2.*sqr(1.-sqrt(muj2)) ); if ( zPrime > zp1 || zPrime < zm1 ) { jacobian(0.0); return false; } // Calculate A:=xij*w double A = (1./(sijk*zPrime*(1.-zPrime))) * ( pt2 + zPrime*mj2 + (1.-zPrime)*mi2 - zPrime*(1.-zPrime)*mij2 ); // Calculate y from A (can also write explicitly in terms of qt, zPrime and masses however we need A anyway) Energy2 sbar = Qijk - mi2 - mj2 - mk2; double y = (1./sbar) * (A*sijk + mij2 - mi2 - mj2); // kinematic phasespace boundaries for y // same as in Dittmaier hep-ph/9904440v2 (equivalent to CS) double bar = 1.-mui2-mu2-muj2; double ym = 2.*sqrt(mui2)*sqrt(mu2)/bar; double yp = 1. - 2.*sqrt(muj2)*(1.-sqrt(muj2))/bar; if ( y < ym || y > yp ) { jacobian(0.0); return false; } // Calculate xk and xij double lambdaK = 1. + (mk2/sijk); double lambdaIJ = 1. + (mij2/sijk); double xk = (1./(2.*lambdaK)) * ( (lambdaK + (mk2/sijk)*lambdaIJ - A) + sqrt( sqr(lambdaK + (mk2/sijk)*lambdaIJ - A) - 4.*lambdaK*lambdaIJ*mk2/sijk) ); double xij = 1. - ( (mk2/sijk) * (1.-xk) / xk ); // Transform to standard z definition as used in the kernels (i.e. that used in CS and standard sudakov parametrisations) double z = ( (zPrime*xij*xk*sijk/2.) + (mk2/ ( 2.*xk*xij*sijk*zPrime))*(pt2 + mi2) ) / ( (xij*xk*sijk/2.) + (mk2*mij2/(2.*xk*xij*sijk)) + (mk2/(2.*xk*xij))*A ); // I think these apply to z but need to double check double zm = ( (2.*mui2+bar*y)*(1.-y) - sqrt(y*y-ym*ym)*sqrt(sqr(2.*muj2+bar-bar*y)-4.*muj2) ) / ( 2.*(1.-y)*(mui2+mu2+bar*y) ); double zp = ( (2.*mui2+bar*y)*(1.-y) + sqrt(y*y-ym*ym)*sqrt(sqr(2.*muj2+bar-bar*y)-4.*muj2) ) / ( 2.*(1.-y)*(mui2+mu2+bar*y) ); if ( z < zm || z > zp ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; // TODO: This may need changing due to different definitions of z double mapZJacobian; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { mapZJacobian = 1.; } else { mapZJacobian = z*(1.-z); } } else { mapZJacobian = 1.-z; } // TODO: May need a redefinition due to different definitions of z jacobian( 2. * mapZJacobian * (1.-y) * log(0.5 * generator()->maximumCMEnergy()/IRCutoff()) * bar / rootOfKallen(1.,Mui2,Muj2) ); // Record the physical variables, as used by the CS kernel definitions lastPt(pt); lastZ(z); lastPhi(phi); // Record zPrime for use in kinematics generation and kernel evaluation splittingParameters().clear(); splittingParameters().push_back(zPrime); if ( theMCCheck ) { theMCCheck->book(1.,1.,info.scale(),info.hardPt(),pt,z,jacobian()); } return true; } // Check use of const void IFMassiveDecayKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { // There is no plan to implement IF-type decays, // therefore these kinematics have not been kept up-to-date, // have not had any bug fixes and have not been kept up-to-date // with other developments since their creation. assert(false && "The should be no initial-final type decay dipoles being showered, something is wrong."); // The only value stored in dInfo.lastSplittingParameters() should be zPrime assert(dInfo.lastSplittingParameters().size() == 1 ); double zPrime = dInfo.lastSplittingParameters()[0]; Energy pt = dInfo.lastPt(); Energy2 pt2 = sqr(pt); // Momentum of the recoil system Lorentz5Momentum pk = pEmitter-pSpectator; Lorentz5Momentum pij = pSpectator; // Masses - Currently not using the mu-ratio formalism and using a different notation to Simon Energy2 mi2 = sqr( dInfo.spectatorData()->mass() ); Energy2 mj2 = sqr( dInfo.emissionData()->mass() ); Energy2 mij2 = mi2; Energy2 mk2 = sqr(dInfo.recoilMass()); Energy2 Qijk = sqr(dInfo.scale()); Energy2 sijk = 0.5*( Qijk - mij2 - mk2 + sqrt( sqr(Qijk-mij2-mk2) - 4.*mij2*mk2 ) ); Energy4 sijk2 = sqr(sijk); // Calculate A:=xij*w double A = (1./(sijk*zPrime*(1.-zPrime))) * ( pt2 + zPrime*mj2 + (1.-zPrime)*mi2 - zPrime*(1.-zPrime)*mij2 ); // Calculate xk and xij double lambdaK = 1. + (mk2/sijk); double lambdaIJ = 1. + (mij2/sijk); double xk = (1./(2.*lambdaK)) * ( (lambdaK + (mk2/sijk)*lambdaIJ - A) + sqrt( sqr(lambdaK + (mk2/sijk)*lambdaIJ - A) - 4.*lambdaK*lambdaIJ*mk2/sijk) ); double xij = 1. - ( (mk2/sijk) * (1.-xk) / xk ); // Construct reference momenta nk, nij, nt Lorentz5Momentum nij = ( sijk2 / (sijk2-mij2*mk2) ) * (pij - (mij2/sijk)*pk); Lorentz5Momentum nk = ( sijk2 / (sijk2-mij2*mk2) ) * (pk - (mk2/sijk)*pij); // Following notation in notes, qt = sqrt(wt)*nt Lorentz5Momentum qt = getKt(nij, nk, pt, dInfo.lastPhi()); // Construct qij, qk, qi and qj Lorentz5Momentum qij = xij*nij + (mij2/(xij*sijk))*nk; Lorentz5Momentum qk = xk*nk + (mk2/(xk*sijk))*nij; // No need to actually calculate nt and wt: Lorentz5Momentum qi = zPrime*qij + ((pt2 + mi2 - zPrime*zPrime*mij2)/(xij*sijk*zPrime))*nk + qt; Lorentz5Momentum qj = (1.-zPrime)*qij + ((pt2 + mj2 - sqr(1.-zPrime)*mij2)/(xij*sijk*(1.-zPrime)))*nk - qt; // book spectatorMomentum(qi); emissionMomentum(qj); emitterMomentum(pEmitter); //recoilMomentum is not currently used //recoilMomentum(pk); splitRecoilMomentum(qk); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFMassiveDecayKinematics::persistentOutput(PersistentOStream & ) const { } void IFMassiveDecayKinematics::persistentInput(PersistentIStream & , int) { } ClassDescription IFMassiveDecayKinematics::initIFMassiveDecayKinematics; // Definition of the static class description member. void IFMassiveDecayKinematics::Init() { static ClassDocumentation documentation ("IFMassiveDecayKinematics implements implements massive splittings " "off an initial-final decay dipole."); } diff --git a/Shower/Dipole/Kinematics/IFMassiveDecayKinematics.h b/Shower/Dipole/Kinematics/IFMassiveDecayKinematics.h --- a/Shower/Dipole/Kinematics/IFMassiveDecayKinematics.h +++ b/Shower/Dipole/Kinematics/IFMassiveDecayKinematics.h @@ -1,297 +1,289 @@ // -*- C++ -*- // // IFMassiveDecayKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFMassiveDecayKinematics_H #define HERWIG_IFMassiveDecayKinematics_H // // This is the declaration of the IFMassiveDecayKinematics class. // #include "DipoleSplittingKinematics.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/UtilityBase.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Stephen Webster * * \brief IFMassiveDecayKinematics implements massive splittings * off an initial-final decay dipole. * */ class IFMassiveDecayKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMassiveDecayKinematics(); - /** - * The destructor. - */ - virtual ~IFMassiveDecayKinematics(); - //@} - public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { return {0.0,1.0}; } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the mass of the system absorbing * the recoil in the dipole splitting. * This is only used in decay dipoles. */ virtual Energy recoilMassKin(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for the decays. assert(false); return 0.0; } /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for the decays. assert(false); return 0.0; } /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); /* * Return true if this splitting is of a dipole which contains * a decayed parton and requires the remnant to absorb the recoil. */ virtual bool isDecay() const { return true; } /** * Perform the recoil in the case of a decayed parton */ virtual void decayRecoil ( PList& recoilSystem ) { PList::iterator beginRecoil = recoilSystem.begin(); PList::iterator endRecoil = recoilSystem.end(); const ThreeVector transformMom = splitRecoilMomentum().vect(); ThePEG::UtilityBase::setMomentum(beginRecoil, endRecoil, transformMom ); } public: /** * Triangular / Kallen function */ template inline double rootOfKallen (T a, T b, T c) const { double sres=a*a + b*b + c*c - 2.*( a*b+a*c+b*c ); return sres>0.?sqrt( sres ):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 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFMassiveDecayKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMassiveDecayKinematics & operator=(const IFMassiveDecayKinematics &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFMassiveDecayKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFMassiveDecayKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the IFMassiveDecayKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFMassiveDecayKinematics"; } /** * The name of a file containing the dynamic library where the class * IFMassiveDecayKinematics is implemented. It may also include several, space-separated, * libraries if the class IFMassiveDecayKinematics 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_IFMassiveDecayKinematics_H */ diff --git a/Shower/Dipole/Kinematics/IFMassiveKinematics.cc b/Shower/Dipole/Kinematics/IFMassiveKinematics.cc --- a/Shower/Dipole/Kinematics/IFMassiveKinematics.cc +++ b/Shower/Dipole/Kinematics/IFMassiveKinematics.cc @@ -1,373 +1,371 @@ // -*- C++ -*- // // IFMassiveKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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/Shower/Dipole/Base/DipoleSplittingInfo.h" #include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.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 IFMassiveKinematics::kappaSupport(const DipoleSplittingInfo&) const { return {0.0,1.0}; } pair 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 {-b,b}; } else { return {log(0.5*(1.-c)),log(0.5*(1.+c))}; } } if ( split.index().emitterData()->id() != ParticleID::g && split.emitterData()->id() != ParticleID::g ) { return {-log(0.5*(1.+c)),-log(0.5*(1.-c))}; } return {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 DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { Energy2 A = sqr(dScale) * (1.-emX)/emX; Energy2 mk2 = sqr(dInfo.spectatorMass()); Energy ptMax = 0.5*A/sqrt(mk2+A); return ptMax; } Energy IFMassiveKinematics::ptMax(Energy dScale, double emX, double, const DipoleIndex&, const DipoleSplittingKernel&, tPPtr, tPPtr spectator) const { Energy2 A = sqr(dScale) * (1.-emX)/emX; Energy2 mk2 = sqr(spectator->mass()); Energy ptMax = 0.5*A/sqrt(mk2+A); return ptMax; } Energy IFMassiveKinematics::QMax(Energy, double, double, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { assert(false && "add this"); return 0.0*GeV; } Energy IFMassiveKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale*sqrt(1.-z); } Energy IFMassiveKinematics::QFromPt(Energy pt, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return pt/sqrt(1.-z); } 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&) { // Check emitter x against xmin if ( info.emitterX() < xMin() ) { jacobian(0.0); return false; } // Generate pt and check it against max allowed Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); if ( pt < IRCutoff() || pt > info.hardPt() ) { jacobian(0.0); return false; } // Compute scales required Energy2 pt2 = sqr(pt); Energy2 saj = sqr(info.scale()); Energy2 mk2 = sqr(info.spectatorMass()); // Generate z 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.; } } // Check limits on z double xe = info.emitterX(); Energy hard = info.hardPt(); if(openZBoundaries()==1){ Energy2 A = saj*(1.-xe)/xe; hard = 0.5*A/sqrt(mk2+A); } if(openZBoundaries()==2){ Energy2 A = saj*min(1.,(1.-xe)/xe); hard= 0.5*A/sqrt(mk2+A); assert(pt2<=sqr(hard)); } double ptRatio = sqrt(1. - pt2/sqr(hard) ); double zp = 0.5*(1.+xe + (1.-xe)*ptRatio); double zm = 0.5*(1.+xe - (1.-xe)*ptRatio); if ( z < zm || z > zp ) { jacobian(0.0); return false; } // Calculate x and u in terms of z and pt double r = pt2/saj; double muk2 = mk2/saj; double rho = 1. - 4.*r*(1.-muk2)*z*(1.-z)/sqr(1.-z+r); if ( rho < 0.0 ) { // This has never happened jacobian(0.0); return false; } double x = 0.5*((1.-z+r)/(r*(1.-muk2))) * (1. - sqrt(rho)); double u = x*r / (1.-z); // Check limits on x and u // Following Catani-Seymour paper double muk2CS = x*muk2; double up = (1.-x) / ( 1.-x + muk2CS ); if ( x < xe || x > 1. || u < 0. || u > up ) { jacobian(0.0); return false; } // Compute the Jacobian double jac = 1./(u + x - 2.*u*x*(1.-muk2)); jacobian( jac * mapZJacobian * 2. * log(0.5 * generator()->maximumCMEnergy()/IRCutoff())); // Log results double phi = 2.*Constants::pi*rphi; 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) { // Initialise the momenta Lorentz5Momentum em; Lorentz5Momentum emm; Lorentz5Momentum spe; if (!theCollinearScheme) { assert(false); 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.spectatorMass())); Lorentz5Momentum kt = getKt (pSpectator, pEmitter, magKt, dInfo.lastPhi(),true); Energy2 mj2 = sqr(dInfo.spectatorMass()); double alpha = 1. - 2.*mj2/sbar; if ( 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; // 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; // 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; } } else { // Get z, pt and the relevant scales double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); Energy2 pt2 = sqr(pt); Energy2 saj = 2.*pEmitter*pSpectator; double muk2 = sqr(dInfo.spectatorMass())/saj; double r = pt2/saj; // Calculate x and u double rho = 1. - 4.*r*(1.-muk2)*z*(1.-z)/sqr(1.-z+r); double x = 0.5*((1.-z+r)/(r*(1.-muk2))) * (1. - sqrt(rho)); double u = x*r / (1.-z); // Generate kt Lorentz5Momentum kt = getKt(pEmitter, pSpectator, pt, dInfo.lastPhi(), true); // Set the momenta em = (1./x)*pEmitter; emm = ((1.-x)*(1.-u)/x - 2.*u*muk2)*pEmitter + u*pSpectator + kt; spe = ((1.-x)*u/x + 2.*u*muk2)*pEmitter + (1.-u)*pSpectator - kt; } em.setMass(ZERO); em.rescaleEnergy(); emm.setMass(ZERO); emm.rescaleEnergy(); spe.setMass(dInfo.spectatorMass()); 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 &) const { //os << theCollinearScheme; } void IFMassiveKinematics::persistentInput(PersistentIStream &, int) { //is >> theCollinearScheme; } ClassDescription IFMassiveKinematics::initIFMassiveKinematics; // Definition of the static class description member. void IFMassiveKinematics::Init() { static ClassDocumentation documentation ("IFMassiveKinematics implements massless splittings " "off a initial-final dipole."); /* static Switch interfaceCollinearScheme ("CollinearScheme", "[experimental] Switch on or off the collinear scheme", &IFMassiveKinematics::theCollinearScheme, false, false, false); static SwitchOption interfaceCollinearSchemeYes (interfaceCollinearScheme, "Yes", "Switch on the collinear scheme.", true); static SwitchOption interfaceCollinearSchemeNo (interfaceCollinearScheme, "No", "Switch off the collinear scheme", false); interfaceCollinearScheme.rank(-1); */ } diff --git a/Shower/Dipole/Kinematics/IFMassiveKinematics.h b/Shower/Dipole/Kinematics/IFMassiveKinematics.h --- a/Shower/Dipole/Kinematics/IFMassiveKinematics.h +++ b/Shower/Dipole/Kinematics/IFMassiveKinematics.h @@ -1,279 +1,271 @@ // -*- C++ -*- // // IFLightKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IFLightKinematics_H #define HERWIG_IFLightKinematics_H // // This is the declaration of the IFLightKinematics class. // #include "DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Martin Stoll * * \brief IFMassiveKinematics implements massless splittings * off an initial-final dipole. * * @see \ref IFMassiveKinematicsInterfaces "The interfaces" * defined for IFMassiveKinematics. */ class IFMassiveKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IFMassiveKinematics(); - /** - * The destructor. - */ - virtual ~IFMassiveKinematics(); - //@} - public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { return {0.0,1.0}; } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double, double, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for massive // dipoles, for now anyway. assert(false); return ZERO; } /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for massive // dipoles, for now anyway. assert(false); return ZERO; } /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel&) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel&); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIFMassiveKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFMassiveKinematics & operator=(const IFMassiveKinematics &) = delete; private: /** * Wether or not to choose the `collinear' scheme */ bool theCollinearScheme; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IFMassiveKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IFMassiveKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the IFMassiveKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IFMassiveKinematics"; } /** * The name of a file containing the dynamic library where the class * IFMassiveKinematics is implemented. It may also include several, space-separated, * libraries if the class IFMassiveKinematics 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_IFMassiveKinematics_H */ diff --git a/Shower/Dipole/Kinematics/IILightKinematics.cc b/Shower/Dipole/Kinematics/IILightKinematics.cc --- a/Shower/Dipole/Kinematics/IILightKinematics.cc +++ b/Shower/Dipole/Kinematics/IILightKinematics.cc @@ -1,358 +1,356 @@ // -*- C++ -*- // // IILightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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/Shower/Dipole/Base/DipoleSplittingInfo.h" using namespace Herwig; IILightKinematics::IILightKinematics() : DipoleSplittingKinematics(), theCollinearScheme(true), didCollinear(false), theTransformationCalculated(false) {} //theTransformHardOnly(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 IILightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { double x = !theCollinearScheme ? dInfo.emitterX()*dInfo.spectatorX() : dInfo.emitterX(); Energy hard=dInfo.hardPt(); if(openZBoundaries()==1)hard=(1.-x) *dInfo.scale()/(2.*sqrt(x)); if(openZBoundaries()==2)hard=min(dInfo.scale(),(1.-x) *dInfo.scale()/(2.*sqrt(x))); if(hard 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()); // Initialise the momenta Lorentz5Momentum em; Lorentz5Momentum emm; Lorentz5Momentum spe; if ( !theCollinearScheme && (1.-v-x)/(v+x) < 1. ) { assert(false); em = (1./(v+x))*pEmitter+(v*(1.-v-x)/(x*(x+v)))*pSpectator+kt/(x+v); emm = ((1.-v-x)/(v+x))*pEmitter+(v/(x*(x+v)))*pSpectator+kt/(x+v); spe = (1.+v/x)*pSpectator; didCollinear = false; } else { em = (1./x)*pEmitter; emm = ((1.-x-v)/x)*pEmitter+v*pSpectator+kt; spe = pSpectator; K = em + spe - emm; K2 = K.m2(); Ktilde = pEmitter + pSpectator; KplusKtilde = K + Ktilde; KplusKtilde2 = KplusKtilde.m2(); didCollinear = true; // Set indicator that the transformation, // required for spin correlations, hasn't // been calculated. theTransformationCalculated = false; } em.setMass(ZERO); em.rescaleEnergy(); emm.setMass(ZERO); emm.rescaleEnergy(); spe.setMass(ZERO); spe.rescaleEnergy(); emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); } void IILightKinematics::setTransformation () { // Construct transformation for spin correlations // Clear the rotation theRecoilTransformation = LorentzRotation(); // Construct boost part Energy KplusKtildeT = KplusKtilde.t(); Energy KT = K.t(); double tt = 1. - 2.*sqr(KplusKtildeT)/KplusKtilde2 + 2.*KT*Ktilde.t()/K2; double tx = 2.*KplusKtildeT*KplusKtilde.x()/KplusKtilde2 - 2.*KT*Ktilde.x()/K2; double ty = 2.*KplusKtildeT*KplusKtilde.y()/KplusKtilde2 - 2.*KT*Ktilde.y()/K2; double tz = 2.*KplusKtildeT*KplusKtilde.z()/KplusKtilde2 - 2.*KT*Ktilde.z()/K2; theRecoilTransformation.boost(tx/tt, ty/tt, tz/tt, tt); // Rotate KtildeSpinCorrTrans to z-axis Lorentz5Momentum KtildeSpinCorrTrans = theRecoilTransformation*Lorentz5Momentum(Ktilde); Axis axis(KtildeSpinCorrTrans.vect().unit()); if( axis.perp2() > 1e-12 ) { double sinth(sqrt(1.-sqr(axis.z()))); theRecoilTransformation.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if( axis.z() < 0. ) { theRecoilTransformation.rotate(Constants::pi,Axis(1.,0.,0.)); } // Rotate from z-axis to K Axis axis2(K.vect().unit()); if( axis2.perp2() > 1e-12 ) { double sinth(sqrt(1.-sqr(axis2.z()))); theRecoilTransformation.rotate(acos(axis2.z()),Axis(-axis2.y()/sinth,axis2.x()/sinth,0.)); } else if( axis2.z() < 0. ) { theRecoilTransformation.rotate(Constants::pi,Axis(1.,0.,0.)); } // SW 30/01/2019: Test feature only, not for release. // Required for absorbing recoil in hard particles only //splitRecoilMomentum(K); // Set indicator that the transformation, // has been calculated theTransformationCalculated = true; } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IILightKinematics::persistentOutput(PersistentOStream &) const { //os << theTransformHardOnly; //os << theCollinearScheme; } void IILightKinematics::persistentInput(PersistentIStream &, int) { //is >> theTransformHardOnly; //is >> theCollinearScheme; } ClassDescription IILightKinematics::initIILightKinematics; // Definition of the static class description member. void IILightKinematics::Init() { static ClassDocumentation documentation ("IILightKinematics implements massless splittings " "off an initial-initial dipole."); /* static Switch interfaceTransformHardOnly ("TransformHardOnly", "[Dev only] Apply recoil transformation to colourless particles only.", &IILightKinematics::theTransformHardOnly, false, false, false); static SwitchOption interfaceTransformHardOnlyYes (interfaceTransformHardOnly, "Yes", "Transform only colourless particles.", true); static SwitchOption interfaceTransformHardOnlyNo (interfaceTransformHardOnly, "No", "Transform all particles.", false); interfaceTransformHardOnly.rank(-1); */ /* static Switch interfaceCollinearScheme ("CollinearScheme", "[experimental] Switch on or off the collinear scheme", &IILightKinematics::theCollinearScheme, false, false, false); static SwitchOption interfaceCollinearSchemeYes (interfaceCollinearScheme, "Yes", "Switch on the collinear scheme.", true); static SwitchOption interfaceCollinearSchemeNo (interfaceCollinearScheme, "No", "Switch off the collinear scheme", false); interfaceCollinearScheme.rank(-1); */ } diff --git a/Shower/Dipole/Kinematics/IILightKinematics.h b/Shower/Dipole/Kinematics/IILightKinematics.h --- a/Shower/Dipole/Kinematics/IILightKinematics.h +++ b/Shower/Dipole/Kinematics/IILightKinematics.h @@ -1,295 +1,287 @@ // -*- C++ -*- // // IILightKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IILightKinematics_H #define HERWIG_IILightKinematics_H // // This is the declaration of the IILightKinematics class. // #include "DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IILightKinematics implements massless splittings * off an initial-initial dipole. * * @see \ref IILightKinematicsInterfaces "The interfaces" * defined for IILightKinematics. */ class IILightKinematics: public DipoleSplittingKinematics { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IILightKinematics(); - /** - * The destructor. - */ - virtual ~IILightKinematics(); - //@} - public: /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel&) const; /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel&); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); /** * Return true, if there is a transformation which should * be applied to all other final state particles except the ones * involved in the splitting after having performed the splitting */ virtual bool doesTransform () const { return theCollinearScheme || didCollinear; } /** * Calculate and store a required Lorentz transformation **/ virtual void setTransformation () ; /* * perform the transformation, if existing */ virtual void transform (PPtr& part) { if ( !theCollinearScheme && !didCollinear ) return; Lorentz5Momentum mom = part->momentum(); // If particle has SpinInfo check that we're // not dealing with an intermediate spectator. if ( part->spinInfo() && !(part->spinInfo()->timelike() && part->children().size() == 1 ) && !(!part->spinInfo()->timelike() && part->parents()[0]->children().size() == 1 ) ) { if ( !theTransformationCalculated ) setTransformation(); part->spinInfo()->transform(mom,theRecoilTransformation); } part->set5Momentum(mom-(2.*(KplusKtilde*mom)/KplusKtilde2)*KplusKtilde+(2.*(Ktilde*mom)/K2)*K); } /* * SW 30/01/2019: Test feature only, not for release. * Return true to only apply the transformation to non-coloured particles. * Note this requires careful handling in DipoleEventRecord */ //virtual bool transformHardOnly() const { return theTransformHardOnly; } /** * SW 30/01/2019: Test feature only, not for release. * Perform the recoil in the case of a decayed parton */ // virtual void transformHard ( PPtr& hard ) { // if ( !theTransformationCalculated ) { // setTransformation(); // theTransformationCalculated = true; // } // hard->setMomentum(splitRecoilMomentum()); // hard->rescaleMass(); // } 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIILightKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IILightKinematics & operator=(const IILightKinematics &) = delete; private: /** * Wether or not to choose the `collinear' scheme */ bool theCollinearScheme; bool didCollinear; /** * SW 30/01/2019: Test feature only, not for release. * Whether to transform only hard (i.e. non-coloured) particles. */ //bool theTransformHardOnly; Lorentz5Momentum K; Energy2 K2; Lorentz5Momentum Ktilde; Lorentz5Momentum KplusKtilde; Energy2 KplusKtilde2; /** * Store the LorentzRotation object equivalent to the * transformation applied to the outgoing particles. * Need this to apply to the particle SpinInfo if spin * correlations are included. */ LorentzRotation theRecoilTransformation; /** * Bool to avoid unecessary recalculation of the * Lorentz transformation. */ bool theTransformationCalculated; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IILightKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IILightKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the IILightKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IILightKinematics"; } /** * The name of a file containing the dynamic library where the class * IILightKinematics is implemented. It may also include several, space-separated, * libraries if the class IILightKinematics 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_IILightKinematics_H */ diff --git a/Shower/Dipole/Merging/MergingFactory.cc b/Shower/Dipole/Merging/MergingFactory.cc --- a/Shower/Dipole/Merging/MergingFactory.cc +++ b/Shower/Dipole/Merging/MergingFactory.cc @@ -1,679 +1,679 @@ // -*- C++ -*- // // MergeboxFactory.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MergeboxFactory class. // #include "MergingFactory.h" #include "Node.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Utilities/ColourOutput.h" using namespace Herwig; using std::ostream_iterator; IBPtr MergingFactory::clone() const { return new_ptr(*this); } IBPtr MergingFactory::fullclone() const { return new_ptr(*this); } void MergingFactory::doinit(){ MatchboxFactory::doinit(); if (subProcessGroups()) { throw InitException() << "There are no subprocess groups in merging!"; } } void MergingFactory::productionMode() { if(M()<0) for ( vector::ptr>::iterator amp = amplitudes().begin(); amp != amplitudes().end(); ++amp ) { Repository::clog() << "One-loop contributions from '" << (**amp).name() << "' are not required and will be disabled.\n" << flush; (**amp).disableOneLoop(); } MatchboxFactory::productionMode(); } void MergingFactory::fillMEsMap() { olpProcesses().clear(); assert( getProcesses().size() == 1 ); processMap[0] = getProcesses()[0]; if ( MH()->M() >= 0 ) setHighestVirt(processMap[0].size()+MH()->M()); MH()->N0(processMap[0].size()); for ( int i = 1 ; i <= MH()->N() ; ++i ) { processMap[i] = processMap[i - 1]; processMap[i].push_back("j"); } for ( int i = 0 ; i <= MH()->N() ; ++i ) { const bool below_maxNLO = i < MH()->M() + 1; vector ames = makeMEs(processMap[i], orderInAlphaS() + i, below_maxNLO ); copy(ames.begin(), ames.end(), back_inserter(pureMEsMap()[i])); } } #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" void MergingFactory::prepare_BV(int i) { // check if we have virtual contributions bool haveVirtuals = true; for ( auto born : pureMEsMap()[i]) { prepareME(born); if ( born->isOLPTree() ) { int id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::treeME2); born->olpProcess(ProcessType::treeME2,id); id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::colourCorrelatedME2); born->olpProcess(ProcessType::colourCorrelatedME2,id); bool haveGluon = false; for ( const auto & p : born->subProcess().legs ) if ( p->id() == 21 ) { haveGluon = true; break; } if ( haveGluon ) { id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::spinColourCorrelatedME2); born->olpProcess(ProcessType::spinColourCorrelatedME2,id); } } if ( born->isOLPLoop() && i <= MH()->M() ) { int id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::oneLoopInterference); born->olpProcess(ProcessType::oneLoopInterference,id); if ( !born->onlyOneLoop() && born->needsOLPCorrelators() ) { id = orderOLPProcess(born->subProcess(), born->matchboxAmplitude(), ProcessType::colourCorrelatedME2); born->olpProcess(ProcessType::colourCorrelatedME2,id); } } haveVirtuals &= born->haveOneLoop(); } // check for consistent conventions on virtuals, if we are to include MH()->M() if (!(i > MH()->M()||haveVirtuals)) throw InitException() << MH()->M() << " NLO corrections requested,\n" << "but no virtual contributions are found."; } void MergingFactory::prepare_R(int i) { for ( auto real : pureMEsMap()[i]) prepareME(real); } #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" void MergingFactory::getVirtuals(MatchboxMEBasePtr nlo, bool clone){ const auto & partons = nlo->diagrams().front()->partons(); for ( auto I : DipoleRepository::insertionIOperators(dipoleSet()) ) if ( I->apply(partons) ){ auto myI = I; if ( clone ) myI = I->cloneMe(); nlo->virtuals().push_back(myI); } for ( auto PK : DipoleRepository::insertionPKOperators(dipoleSet()) ) if ( PK->apply(partons) ){ auto myPK = PK; if ( clone ) myPK = PK->cloneMe(); nlo->virtuals().push_back(myPK); } } void MergingFactory::pushB(MatchboxMEBasePtr born, int i) { MatchboxMEBasePtr bornme = born->cloneMe(); bornme->maxMultCKKW(1); bornme->minMultCKKW(0); string pname = fullName() + "/" + bornme->name() + ".Born"; if ( !(generator()->preinitRegister(bornme, pname)) ) throw InitException() << "Born ME "<< pname << " already existing."; NodePtr clusternode = new_ptr(Node(bornme, 0, MH())); clusternode->deepHead(clusternode); MH()->firstNodeMap(bornme,clusternode); bornme->merger(MH()); vector current = {{clusternode}}; vector children; unsigned int k = 1; while ( ! thePureMEsMap[i - k].empty() ) { for ( auto tmp : current ){//j tmp->birth(thePureMEsMap[i - k]); for ( auto tmpchild : tmp->children() ) {//m children.push_back(tmpchild); } } current = children; children.clear(); ++k; } if ( MH()->N() > i ) bornme->needsCorrelations(); else bornme->needsNoCorrelations(); bornme->cloneDependencies(); MEs().push_back(bornme); } void MergingFactory::pushV(MatchboxMEBasePtr born, int i) { MatchboxMEBasePtr nlo = born->cloneMe(); string pname = fullName() + "/" + nlo->name() + ".Virtual"; if ( !(generator()->preinitRegister(nlo, pname)) ) throw InitException() << "Virtual ME "<< pname << " already existing."; ////////////////////////////////////NLO/////////////////////////// nlo->virtuals().clear(); getVirtuals(nlo , false); if ( nlo->virtuals().empty() ) throw InitException() << "No insertion operators have been found for " << born->name() << ".\n"; nlo->doOneLoopNoBorn(); ////////////////////////////////////NLO/////////////////////////// NodePtr clusternode = new_ptr(Node(nlo, 0,MH())); clusternode->deepHead(clusternode); clusternode->virtualContribution(true); MH()->firstNodeMap(nlo,clusternode); nlo->merger(MH()); vector current = {{clusternode}}; vector children; unsigned int k = 1; while ( ! thePureMEsMap[i - k].empty() ) { for ( auto tmp : current ){ tmp->birth(thePureMEsMap[i - k]); for ( auto tmpchild : tmp->children()) children.push_back(tmpchild); } current = children; children.clear(); ++k; } 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(); MEs().push_back(nlo); } void MergingFactory::pushR(MatchboxMEBasePtr born, int i) { MatchboxMEBasePtr bornme = born->cloneMe(); string pname = fullName() + "/" + bornme->name() + ".Real"; if ( !(generator()->preinitRegister(bornme, pname)) ) throw InitException() << "Subtracted ME " << pname << " already existing."; NodePtr clusternode = new_ptr(Node(bornme, 1, MH())); clusternode->deepHead(clusternode); clusternode->subtractedReal(true); MH()->firstNodeMap(bornme,clusternode); bornme->merger(MH()); vector current = {{clusternode}}; vector children; unsigned int k = 1; while ( ! thePureMEsMap[i - k].empty() ) { for ( auto tmp : current ){ tmp->birth(thePureMEsMap[i - k]); for ( auto tmpchild : tmp->children()) children.push_back(tmpchild); } current = children; children.clear(); ++k; } if(clusternode->children().empty()){ // This is a finite real contribution. // This process is included in the LO merging. return; } if ( MH()->N() > i ) bornme->needsCorrelations(); else bornme->needsNoCorrelations(); bornme->cloneDependencies(pname); MEs().push_back(bornme); } // MergingFactory should never order OLPs here, // they're done elsewhere. void MergingFactory::orderOLPs() {} #include "ThePEG/Utilities/StringUtils.h" vector MergingFactory::parseProcess(string in) { vector process = StringUtils::split(in); if ( process.size() < 3 ) throw Exception() << "MatchboxFactory: Invalid process."<< Exception::runerror; for ( string & p : process) { p = StringUtils::stripws(p); } theN = 0; bool prodprocess = true; vector result; for ( const string & p : process ) { if ( p == "->" ) continue; if (p=="[") { prodprocess = false; } else if (p=="]") { prodprocess = false; // TODO what if there's stuff after the bracket? assert( p == process.back() ); break; } else if (p=="[j") { prodprocess = false; ++theN; } else if (p=="j" && !prodprocess) { ++theN; prodprocess = false; } else if (p=="j]") { ++theN; prodprocess = false; // TODO what if there's stuff after the bracket? assert( p == process.back() ); break; } else if ( prodprocess ) { result.push_back(p); } else { throw InitException() << "Unknown particle class \"" << p << '"' << " in the process definition merging bracket.\n" << "Only jets (\"j\") are supported at the moment."; } } return result; } #include "Herwig/Utilities/Progress.h" void MergingFactory::setup() { useMe(); DipoleShowerHandlerPtr dsh=dynamic_ptr_cast(this->CKKWHandler()); if(! dsh )throw InitException() << "The showerhandler for the MergingFactory must be the DipoleShower. "; dsh->setMerger(MH()); MH()->setFactory(this); MH()->setDipoleShower(dsh); if(!ransetup){ generator()->log() <<"\nStarting merging setup.\n\n"; olpProcesses().clear(); externalAmplitudes().clear(); // We set the couplings in the ME to be fixed // and reweight in the history weight for this. setFixedCouplings(true); setFixedQEDCouplings(true); // rebind the particle data objects, can't use rebind() function for ( auto & g : particleGroups()) { for ( auto & p : g.second) { p = getParticleData(p->id()); } } const PDVector& partons = particleGroups()["j"]; unsigned int nl = 0; - for ( const auto p : partons ) { + for ( const auto & p : partons ) { const Energy mass = p->hardProcessMass(); const long pid = p->id(); if ( abs(pid) < 7 && mass == ZERO ) ++nl; if ( pid > 0 && pid < 7 && mass == ZERO ) nLightJetVec( pid ); if ( pid > 0 && pid < 7 && mass != ZERO ) nHeavyJetVec( pid ); } nLight(nl/2); const PDVector& partonsInP = particleGroups()["p"]; - for ( const auto pip : partonsInP ) + for ( const auto & pip : partonsInP ) if ( pip->id() > 0 && pip->id() < 7 && pip->hardProcessMass() == ZERO ) nLightProtonVec( pip->id() ); // fill the amplitudes if ( !amplitudes().empty() ) fillMEsMap(); // Use the colour basis of the first element of amplitudes // to set the large N colour basis for the MergingHelper assert(!amplitudes().empty() ); if ( amplitudes()[0]->colourBasis() ) { auto largeNBasis = amplitudes()[0]->colourBasis()->cloneMe(); largeNBasis->clear(); largeNBasis->doLargeN(); MH()->largeNBasis(largeNBasis); } // prepare the Born and virtual matrix elements for ( int i = 0 ; i <= max(0, MH()->N()) ; ++i ) prepare_BV(i); // prepare the real emission matrix elements for ( int i = 0 ; i <= MH()->N() ; ++i ) prepare_R(i); if (MH()->N()<=MH()->M()) { throw InitException() << "Merging: The number of NLOs need to be" << "\nsmaller than the number of LO processes.\n"; } // Order the external Amplitudes. orderOLPs(); // start creating matrix elements MEs().clear(); // count the subprocesses size_t numb = 0; size_t numv = 0; size_t numr = 0; for (int i = 0; i <= max(0, MH()->N()) ; ++i ) { for ( auto born : thePureMEsMap[i] ) { if (bornContributions() ) { numb++; } } } for (int i = 0 ; i <=max(0, MH()->N()); ++i ) for ( auto virt : thePureMEsMap[i] ) if ( virtualContributions() && i <= MH()->M()) { numv++; } for (int i = 1; i <= max(0, MH()->N()) ; ++i ) for ( auto real : thePureMEsMap[i] ) if (realContributions() && i <= MH()->M() + 1 ){ numr++; } if(int(numb+numv+numr) < theChunk){ throw InitException() << "You try to chunk (Chunk="< 0 && theChunkPart == 0 ) throw InitException() <<" Set the ChunkPart ( = "<log() << ANSI::yellow << "\n\nWarning: \nYou split up the runs into theChunks. This is no standard feature." << "\nYou are now responsible to make sure to run all theChunk parts." << "\nThis setup run is for: " << theChunkPart << "/" << theChunk<<"\n\n "; generator()->log() << ANSI::red << "Preparing Merging: "; generator()->log() << ANSI::green << numb << " x Born " << ANSI::red; if (MH()->M()>-1) { generator()->log() << ANSI::yellow << numv << " x Virtual "; generator()->log() << ANSI::blue << numr << " x Real " << ANSI::red << flush; } int countchunk=0; progress_display progressBar{ numb+numv+numr, generator()->log() }; // insert the born contributions to ME vector for (int i = 0; i <= max(0, MH()->N()) ; ++i ) for ( auto born : thePureMEsMap[i]) if (bornContributions() ){ countchunk++; // theChunkPart is in [1,...,theChunk] if ( theChunk == 0 || theChunkPart == countchunk ) pushB( born , i ); if ( countchunk == theChunk ) countchunk=0; generator()->log() << ANSI::green; ++progressBar; generator()->log() << ANSI::reset; } // insert the virtual contributions to ME vector for (int i = 0 ; i <=max(0, MH()->N()); ++i ) for ( auto virt : thePureMEsMap[i]) if ( virtualContributions() && i <= MH()->M()){ countchunk++;// theChunkPart is in [1,...,theChunk] if ( theChunk == 0 || theChunkPart == countchunk ) pushV(virt, i); if ( countchunk == theChunk ) countchunk=0; generator()->log() << ANSI::yellow; ++progressBar; } // insert the real contributions to ME vector for (int i = 1; i <= max(0, MH()->N()) ; ++i ) for ( auto real : thePureMEsMap[i] ) if (realContributions()&& i <= MH()->M() + 1 ){ countchunk++;// theChunkPart is in [1,...,theChunk] if ( theChunk == 0 || theChunkPart == countchunk ) pushR(real, i); if ( countchunk == theChunk ) countchunk=0; generator()->log() << ANSI::blue; ++progressBar; } generator()->log() << ANSI::reset; if ( !externalAmplitudes().empty() ) { generator()->log() << "Initializing external amplitudes." << endl; progress_display progressBar{ externalAmplitudes().size(), generator()->log() }; - for ( const auto ext : externalAmplitudes() ) { + for ( const auto & ext : externalAmplitudes() ) { if ( ! ext->initializeExternal() ) { throw InitException() << "error: failed to initialize amplitude '" << ext->name() << "'\n"; } ++progressBar; } generator()->log() << "---------------------------------------------------" << endl; } if ( !olpProcesses().empty() ) { generator()->log() << "Initializing one-loop provider(s)." << endl; map::tptr, map, int> > olps; - for (const auto oit : olpProcesses()) { + for (const auto & oit : olpProcesses()) { olps[oit.first] = oit.second; } progress_display progressBar{ olps.size(), generator()->log() }; - for ( const auto olpit : olps ) { + for ( const auto & olpit : olps ) { if ( !olpit.first->startOLP(olpit.second) ) { throw InitException() << "error: failed to start OLP for amplitude '" << olpit.first->name() << "'\n"; } ++progressBar; } generator()->log() << "---------------------------------------------------\n" << flush; } generator()->log() <<"\nGenerated "<log() << "---------------------------------------------------\n" << flush; generator()->log() <<"\n\n" << ANSI::red <<"Note: Due to the unitarization of the higher " <<"\nmultiplicities, the individual cross sections " <<"\ngiven in the integration and run step are not" <<"\nmeaningful without merging." << ANSI::reset << endl; ransetup=true; } } #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" void MergingFactory::persistentOutput(PersistentOStream & os) const { os << theonlymulti << ransetup << processMap << theMergingHelper <> theonlymulti >> ransetup >> processMap >> theMergingHelper >>theM>>theN>>theNonQCDCuts>>theChunk>>theChunkPart; } #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" void MergingFactory::Init() { static Parameter interfaceonlymulti("onlymulti", "Calculate only the ME with k additional partons.", &MergingFactory::theonlymulti, -1, -1, 0, false, false, Interface::lowerlim); static Switch interface_Unitarized("Unitarized", "Unitarize the cross section (default is unitarised. NLO merging must be unitarised).", &MergingFactory::unitarized, true, false, false); static SwitchOption interface_UnitarizedYes(interface_Unitarized, "Yes", "Switch on the unitarized cross section.", true); static SwitchOption interface_UnitarizedNo(interface_Unitarized, "No", "Switch off the unitarized cross section.", false); static Reference interfaceMergingHelper("MergingHelper", "Pointer to the Merging Helper.", &MergingFactory::theMergingHelper, false, false, true, true, false); static Parameter interfaceaddNLOLegs("NLOProcesses", "Set the number of virtual corrections to consider. 0 is default for no virtual correction.", &MergingFactory::theM, 0, 0, 0, false, false, Interface::lowerlim); static Reference interfaceNonQcdCuts("NonQCDCuts", "Cut on non-QCD modified observables. Be carefull!", &MergingFactory::theNonQCDCuts, false, false, true, true, false); static Parameter interfacetheChunk("Chunk", "Cut the number of subprocesses into n theChunks.", &MergingFactory::theChunk, -1, -1, 0, false, false, Interface::lowerlim); static Parameter interfacetheChunkPart("ChunkPart", "If theChunk is larger then 0, set this parameter to the n'th part. Make sure to add the ChunksParts afterwards.", &MergingFactory::theChunkPart, -1, -1, 0, false, false, Interface::lowerlim); } // *** 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 describeHerwigMergingFactory("Herwig::MergingFactory", "HwDipoleShower.so"); diff --git a/Shower/Dipole/Merging/Node.cc b/Shower/Dipole/Merging/Node.cc --- a/Shower/Dipole/Merging/Node.cc +++ b/Shower/Dipole/Merging/Node.cc @@ -1,458 +1,456 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the Node class. // #include "Node.h" #include "MergingFactory.h" #include "Merger.h" using namespace Herwig; Node::Node(MatchboxMEBasePtr nodeME, int cutstage, MergerPtr mh) :Interfaced(), thenodeMEPtr(nodeME), thedipol(), theparent(), theCutStage(cutstage), theSubtractedReal(false), theVirtualContribution(false), theMergingHelper(mh) { nodeME->maxMultCKKW(1); nodeME->minMultCKKW(0); } Node::Node(NodePtr deephead, NodePtr head, SubtractionDipolePtr dipol, MatchboxMEBasePtr nodeME, int cutstage) :Interfaced(), thenodeMEPtr(nodeME), thedipol(dipol), theparent(head), theDeepHead(deephead), theCutStage(cutstage), theSubtractedReal(false), theVirtualContribution(false), theMergingHelper() //The subnodes have no merging helper { } -Node::~Node() { } - SubtractionDipolePtr Node::dipole() const { return thedipol; } /** returns the matrix element pointer */ const MatchboxMEBasePtr Node::nodeME() const { return thenodeMEPtr; } /** access the matrix element pointer */ MatchboxMEBasePtr Node::nodeME() { return thenodeMEPtr; } pair Node::getInOut( ){ PVector in; const auto me= nodeME(); const auto pd=me->mePartonData(); for( auto i : {0 , 1} ) in.push_back(pd[i]->produceParticle( me->lastMEMomenta()[i] ) ); PVector out; for ( size_t i = 2;i< pd.size();i++ ){ PPtr p = pd[i]->produceParticle( me->lastMEMomenta()[i] ); out.push_back( p ); } return { in , out }; } int Node::legsize() const {return nodeME()->legsize();} NodePtr Node::randomChild() { return thechildren[UseRandom::irnd(thechildren.size())]; } bool Node::allAbove(Energy pt) { for (NodePtr child : thechildren) if ( child->pT() < pt ) return false; return true; } Energy Node::maxChildPt(){ Energy maxi=-1*GeV; for (NodePtr child : thechildren)maxi=max(child->pT(),maxi); return maxi; } bool Node::isInHistoryOf(NodePtr other) { while (other->parent()) { if (other == this) return true; other = other->parent(); } return false; } void Node::flushCaches() { if (didflush) return; didflush=true; for ( auto const & ch: thechildren) { ch->xcomb()->clean(); ch->nodeME()->flushCaches(); ch->flushCaches(); } } void Node::setKinematics() { for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); ch->dipole()->setKinematics(); ch->nodeME()->setKinematics(); ch->setKinematics(); } } void Node::clearKinematics() { for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); ch->nodeME()->clearKinematics(); ch->dipole()->clearKinematics(); ch->clearKinematics(); } } bool Node::generateKinematics(const double *r, bool directCut) { didflush=false; // If there are no children to the child process we are done. if(children().empty()) return true; assert(parent()); if ( ! directCut && pT() < deepHead()->MH()->mergePt()) { // Real emission: // If there are children to the child process, // we now require that all subsequent children // with pt < merging scale are in their ME region. // Since the possible children of the real emission // contribution are now in their ME region, // it is clear that a second clustering is possible // -- modulo phase space restrictions. // Therefore the real emission contribution // are unitarised and the cross section is // hardly modified. auto inOutPair = getInOut(); NodePtr rc = randomChild(); rc->dipole()->setXComb(rc->xcomb()); if(!rc->dipole()->generateKinematics(r))assert(false); // If not in ME -> return false if(!deepHead()->MH()->matrixElementRegion( inOutPair.first , inOutPair.second , rc->pT() , deepHead()->MH()->mergePt() ) )return false; } for (auto & ch : children() ) { ch->dipole()->setXComb(ch->xcomb()); if ( !ch->dipole()->generateKinematics(r) ) { assert(false); } ch->generateKinematics( r, true); } return true; } bool Node::firstgenerateKinematics(const double *r, bool directCut) { didflush=false; // This is called form the merging helper for the first node. So: assert(!parent()); assert(xcomb()); if(MH()->treefactory()->nonQCDCuts()){ tcPDVector outdata(xcomb()->mePartonData().begin()+2, xcomb()->mePartonData().end()); vector outmomenta(xcomb()->meMomenta().begin()+2, xcomb()->meMomenta().end()); if ( !MH()->treefactory()->nonQCDCuts()->passCuts(outdata,outmomenta, xcomb()->mePartonData()[0], xcomb()->mePartonData()[1]) ) return false; } ///// This should not be needed!!! ///// ( Warning inMerger::matrixElementRegion gets triggered.) flushCaches(); //Set here the new merge Pt for the next phase space point.( Smearing!!!) MH()->smearMergePt(); // If there are no children to this node, we are done here: if (children().empty()) return true; // directCut is for born and for virtual contributions. // if directCut is true, then cut on the first ME region. // call recursiv generate kinematics for subsequent nodes. if ( directCut ){ auto inOutPair = getInOut(); NodePtr rc = randomChild(); rc->dipole()->setXComb(rc->xcomb()); if ( !rc->dipole()->generateKinematics(r) ) { return false; } rc->nodeME()->setXComb(rc->xcomb()); if(!MH()->matrixElementRegion( inOutPair.first , inOutPair.second , rc->pT() , MH()->mergePt() ) ){ return false; } } for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); if ( !ch->dipole()->generateKinematics(r) ) { cout<<"\nCould not generate dipole kinematics";;return false; } if( ! ch->generateKinematics(r,directCut) )return false; } return true; } StdXCombPtr Node::xcomb() const { assert(thexcomb); return thexcomb; } StdXCombPtr Node::xcomb(){ if(thexcomb)return thexcomb; assert(parent()); thexcomb=dipole()->makeBornXComb(parent()->xcomb()); xcomb()->head(parent()->xcomb()); dipole()->setXComb(thexcomb); return thexcomb; } void Node::setXComb(tStdXCombPtr xc) { assert ( !parent() ); thexcomb=xc; assert(thexcomb->lastParticles().first); } #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" void Node::birth(const vector & vec) { // produce the children vector dipoles = nodeME()->getDipoles(DipoleRepository::dipoles( nodeME()->factory()->dipoleSet()), vec, true); for ( auto const & dip : dipoles ) { dip->doSubtraction(); NodePtr node = new_ptr(Node(theDeepHead, this, dip, dip->underlyingBornME(), theDeepHead->cutStage())); thechildren.push_back(node); } } vector Node::getNextOrderedNodes(bool normal, double hardScaleFactor) const { vector temp = children(); vector res; for (NodePtr const & child : children()) { if(deepHead()->MH()->mergePt()>child->pT()) { res.clear(); return res; } } for (NodePtr const & child: children()) { if (parent()&& normal) { if ( child->pT() < pT() ) { continue; } } if ( child->children().size() != 0 ) { for (NodePtr itChild: child->children()) { if( itChild->pT() > child->pT()&&child->inShowerPS(itChild->pT()) ) { res.push_back(child); break; } } } else { const auto sc=child->nodeME()->factory()->scaleChoice(); sc->setXComb(child->xcomb()); if ( sqr(hardScaleFactor)* sc->renormalizationScale() >= sqr(child->pT()) && child->inShowerPS(hardScaleFactor*sqrt(sc->renormalizationScale()))) { res.push_back(child); } } } return res; } bool Node::inShowerPS(Energy hardpT)const { // Here we decide if the current phase space // point can be reached from the underlying Node. // Full phase space available -> Tilde Kinematic is always fine. if(deepHead()->MH()->openZBoundaries()==1) return true; double z_ = dipole()->lastZ(); // restrict according to hard scale if(deepHead()->MH()->openZBoundaries()==0){ pair zbounds = dipole()->tildeKinematics()->zBounds(pT(), hardpT); return (zbounds.first temp = getNextOrderedNodes(normal, hardScaleFactor); Energy minpt = Constants::MaxEnergy; Selector subprosel; while (temp.size() != 0) { minpt = Constants::MaxEnergy; subprosel.clear(); for (NodePtr const & child : temp) { // colour basis is not strictly needed for evaluating the colour correlator //assert(deepHead()->MH()->largeNBasis()); if( child->dipole()->underlyingBornME()->largeNColourCorrelatedME2( {child->dipole()->bornEmitter(), child->dipole()->bornSpectator()}, deepHead()->MH()->largeNBasis()) != 0. ) { double weight = 1.; if ( deepHead()->MH()->chooseHistory() == 0 ) weight = abs(child->dipole()->dSigHatDR()/nanobarn); else if ( deepHead()->MH()->chooseHistory() == 1 ) weight = abs(child->dipole()->dSigHatDR()/child->nodeME()->dSigHatDRB()); else if ( deepHead()->MH()->chooseHistory() == 2 ) weight = 1.; else if ( deepHead()->MH()->chooseHistory() == 3 ) weight = 1_GeV/child->pT(); else assert(false); if(weight != 0.) { subprosel.insert(weight , child); minpt = min(minpt, child->pT()); } } } if (subprosel.empty()) return res; res = subprosel.select(UseRandom::rnd()); temp = res->getNextOrderedNodes(true, hardScaleFactor); } return res; } pair Node::calcDipandPS(Energy scale)const { return dipole()->dipandPs(sqr(scale), deepHead()->MH()->largeNBasis()); } CrossSection Node::calcPs(Energy scale)const { return dipole()->ps(sqr(scale), deepHead()->MH()->largeNBasis()); } CrossSection Node::calcDip(Energy scale)const { return dipole()->dip(sqr(scale)); } IBPtr Node::clone() const { return new_ptr(*this); } IBPtr Node::fullclone() const { return new_ptr(*this); } #include "ThePEG/Persistency/PersistentOStream.h" void Node::persistentOutput(PersistentOStream & os) const { os << thexcomb<< thenodeMEPtr<< thedipol<< thechildren<< theparent<< theProjector<< theDeepHead<< theCutStage<< ounit(theRunningPt, GeV)<< theSubtractedReal<< theVirtualContribution<< theMergingHelper; } #include "ThePEG/Persistency/PersistentIStream.h" void Node::persistentInput(PersistentIStream & is, int) { is >> thexcomb>> thenodeMEPtr>> thedipol>> thechildren>> theparent>> theProjector>> theDeepHead>> theCutStage>> iunit(theRunningPt, GeV)>> theSubtractedReal>> theVirtualContribution>> theMergingHelper; } // *** 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). #include "ThePEG/Utilities/DescribeClass.h" DescribeClass describeHerwigNode("Herwig::Node", "HwDipoleShower.so"); void Node::Init() { static ClassDocumentation documentation("There is no documentation for the Node class"); } diff --git a/Shower/Dipole/Merging/Node.h b/Shower/Dipole/Merging/Node.h --- a/Shower/Dipole/Merging/Node.h +++ b/Shower/Dipole/Merging/Node.h @@ -1,242 +1,240 @@ // -*- C++ -*- #ifndef Herwig_Node_H #define Herwig_Node_H // // This is the declaration of the Node class. // #include "Node.fh" #include "MergingFactory.fh" #include "Merger.h" #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Config/std.h" #include "ThePEG/Interface/Interfaced.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.fh" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh" #include "Herwig/Shower/Dipole/Base/DipoleEventRecord.h" #include "ThePEG/MatrixElement/MEBase.h" #include namespace Herwig { using namespace ThePEG; /** * The Node class represents a part of the shower history * in the merging procedure. * Each node can search for its "childen" in the "birth" step. * The children processes that can be created by clustering two legs * with a given spectator -- just like in the shower. * To perform the "birth" a vector of processes is given to the node * and the possible dipoles are given by the factory object. * * * @see \ref NodeInterfaces "The interfaces" * defined for Node. */ class Node : public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ Node (){}; // constructor for first nodes Node(MatchboxMEBasePtr nodeME , int cutstage , MergerPtr mh ); // another constructor for underlying nodes Node(NodePtr deephead, NodePtr head, SubtractionDipolePtr dipol, MatchboxMEBasePtr nodeME, int cutstage); - /// The destructor. - virtual ~Node(); //@} public: // get children from vector void birth(const vector & vec); /// recursive setXComb. proStage is the number of clusterings /// before the projectors get filled. void setXComb(tStdXCombPtr xc); /// calculate the dipole and ps approximation pair calcDipandPS(Energy scale)const; /// calculate the ps approximation CrossSection calcPs(Energy scale)const; /// calculate the dipole CrossSection calcDip(Energy scale)const; /// recursive flush caches and clean up XCombs. void flushCaches(); /// recursive clearKinematics void clearKinematics(); /// recursive setKinematics void setKinematics(); /// recursive generateKinematics using tilde kinematics of the dipoles bool generateKinematics(const double *r, bool directCut); /// generate the kinamatics of the first node bool firstgenerateKinematics(const double *r, bool directCut); //return the ME const MatchboxMEBasePtr nodeME() const; //return the node ME MatchboxMEBasePtr nodeME(); //return the parent Node NodePtr parent() const {return theparent;} /// vector of children nodes created in birth vector< NodePtr > children() const {return thechildren;} //pick a random child (flat) NodePtr randomChild(); /// true if all children show scales above pt bool allAbove(Energy pt); /// return maximum of all child pts. Energy maxChildPt(); /// true if the node is in the history of other. bool isInHistoryOf(NodePtr other); /// legsize of the node ME int legsize() const; /// set the first node (first men). only use in factory void deepHead(NodePtr deephead) {theDeepHead = deephead;} /// return the first node NodePtr deepHead() const {return theDeepHead;} /// returns the dipol of the node. SubtractionDipolePtr dipole() const; /// return the xcomb StdXCombPtr xcomb() const; /// return the xcomb (if not created, create one from head) StdXCombPtr xcomb() ; /// return the current running pt Energy runningPt() const { return theRunningPt; } /// set the current running pt void runningPt(Energy x) { theRunningPt=x; } /// return the cut stage to cut on merging pt in generate kinematics int cutStage() const { return theCutStage; } /// get a vector of the next nodes, ordered in pt (and in parton shower phace space) vector getNextOrderedNodes(bool normal=true, double hardscalefactor=1.) const; //true if the node is in shower history for a given pt bool inShowerPS(Energy hardpt)const; //get the history NodePtr getHistory(bool normal=true, double hardscalefactor=1.); //true if node correspond to a subtracted real. bool subtractedReal() const {return theSubtractedReal;} /// set if node correspont to a subtracted real. void subtractedReal(bool x) { theSubtractedReal = x;} //true if node correspond to a virtual contribution. bool virtualContribution() const { return theVirtualContribution ;} /// set if node correspont to a virtual contribution. void virtualContribution(bool x) {theVirtualContribution = x;} //pointer to the merging helper MergerPtr MH()const{return theMergingHelper;} /// set the merging helper void MH(MergerPtr a){theMergingHelper=a;} /// pT of the dipole Energy pT()const{return dipole()->lastPt();} /// get incoming and outgoing particles (TODO: expensive) pair getInOut(); private: /// the Matrixelement representing this node. MatchboxMEBasePtr thenodeMEPtr; /// the dipol used to substract /// and generate kinematics using tilde kinematics SubtractionDipolePtr thedipol; /// the parent node NodePtr theparent; /// The godfather node of whole tree.(Firstnode) NodePtr theDeepHead; /** * The CutStage is number of clusterings which are possible without * introducing a merging scale to cut away singularities. * -> subtracted MEs have the CutStage 1. * -> virtual and normal tree level ME get 0. */ int theCutStage; /// flag to tell if node is subtracted real bool theSubtractedReal; /// flag to tell if node is virtual contribution bool theVirtualContribution; /// the merging helper (should be static) MergerPtr theMergingHelper; //the xcomb of the node StdXCombPtr thexcomb; /// vector of the children node vector< NodePtr > thechildren; /// the current running pt Energy theRunningPt; /// The nodes of the projection stage. NodePtr theProjector; /// flag not to enter infinite loop. (There should be a better solution...) bool didflush=false; 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Node & operator=(const Node &) = delete; }; } #endif /* Herwig_Node_H */ diff --git a/Shower/Dipole/Utility/ConstituentReshuffler.cc b/Shower/Dipole/Utility/ConstituentReshuffler.cc --- a/Shower/Dipole/Utility/ConstituentReshuffler.cc +++ b/Shower/Dipole/Utility/ConstituentReshuffler.cc @@ -1,622 +1,617 @@ // -*- C++ -*- // // ConstituentReshuffler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ConstituentReshuffler class. // #include #include "ConstituentReshuffler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "DipolePartonSplitter.h" #include "Herwig/Utilities/GSLBisection.h" #include "Herwig/Shower/Dipole/DipoleShowerHandler.h" #include "Herwig/Shower/ShowerHandler.h" using namespace Herwig; -ConstituentReshuffler::ConstituentReshuffler() - : HandlerBase() {} - -ConstituentReshuffler::~ConstituentReshuffler() {} - IBPtr ConstituentReshuffler::clone() const { return new_ptr(*this); } IBPtr ConstituentReshuffler::fullclone() const { return new_ptr(*this); } void ConstituentReshuffler::reshuffle(PList& out, PPair& in, PList& intermediates, const bool decay, PList& decayPartons, PList& decayRecoilers) { assert(ShowerHandler::currentHandler()->retConstituentMasses()); if ( !decay ) { if (out.size() == 0) return; if (out.size() == 1) { PPtr recoiler; PPtr parton = out.front(); if (DipolePartonSplitter::colourConnected(parton,in.first) && DipolePartonSplitter::colourConnected(parton,in.second)) { if (UseRandom::rnd() < .5) recoiler = in.first; else recoiler = in.second; } else if (DipolePartonSplitter::colourConnected(parton,in.first)) { recoiler = in.first; } else if (DipolePartonSplitter::colourConnected(parton,in.second)) { recoiler = in.second; } else assert(false); assert(abs(recoiler->momentum().vect().perp2()/GeV2) < 1e-6); double sign = recoiler->momentum().z() < 0.*GeV ? -1. : 1.; Energy2 qperp2 = parton->momentum().perp2(); if (qperp2/GeV2 < Constants::epsilon) { // no emission off a 2 -> singlet process which // needed a single forced splitting: should never happen (?) assert(false); throw Veto(); } Energy2 m2 = sqr(parton->dataPtr()->constituentMass()); Energy abs_q = parton->momentum().vect().mag(); Energy qz = parton->momentum().z(); Energy abs_pz = recoiler->momentum().t(); assert(abs_pz > 0.*GeV); Energy xi_pz = sign*(2.*qperp2*abs_pz + m2*(abs_q + sign*qz))/(2.*qperp2); Energy x_qz = (2.*qperp2*qz + m2*(qz+sign*abs_q))/(2.*qperp2); Lorentz5Momentum recoiler_momentum (0.*GeV,0.*GeV,xi_pz,xi_pz < 0.*GeV ? - xi_pz : xi_pz); recoiler_momentum.rescaleMass(); Lorentz5Momentum parton_momentum (parton->momentum().x(),parton->momentum().y(),x_qz,sqrt(m2+qperp2+x_qz*x_qz)); parton_momentum.rescaleMass(); PPtr n_parton = new_ptr(Particle(parton->dataPtr())); n_parton->set5Momentum(parton_momentum); DipolePartonSplitter::change(parton,n_parton,false); out.pop_front(); intermediates.push_back(parton); out.push_back(n_parton); PPtr n_recoiler = new_ptr(Particle(recoiler->dataPtr())); n_recoiler->set5Momentum(recoiler_momentum); DipolePartonSplitter::change(recoiler,n_recoiler,true); intermediates.push_back(recoiler); if (recoiler == in.first) { in.first = n_recoiler; } if (recoiler == in.second) { in.second = n_recoiler; } return; } } Energy zero (0.*GeV); Lorentz5Momentum Q (zero,zero,zero,zero); for (PList::iterator p = out.begin(); p != out.end(); ++p) { Q += (**p).momentum(); } Boost beta = Q.findBoostToCM(); list mbackup; bool need_boost = (beta.mag2() > Constants::epsilon); if (need_boost) { for (PList::iterator p = out.begin(); p != out.end(); ++p) { Lorentz5Momentum mom = (**p).momentum(); mbackup.push_back(mom); (**p).set5Momentum(mom.boost(beta)); } } double xi; // Only partons if ( decayRecoilers.size()==0 ) { list masses; for ( auto p : out ) masses.push_back(p->dataPtr()->constituentMass()); ReshuffleEquation::const_iterator> solve (Q.m(),out.begin(),out.end(), masses.begin(),masses.end()); GSLBisection solver(1e-10,1e-8,10000); try { xi = solver.value(solve,0.0,1.1); } catch (GSLBisection::GSLerror) { throw DipoleShowerHandler::RedoShower(); } catch (GSLBisection::IntervalError) { throw DipoleShowerHandler::RedoShower(); } } // Partons and decaying recoilers else { DecayReshuffleEquation solve (Q.m(),decayPartons.begin(),decayPartons.end(),decayRecoilers.begin(),decayRecoilers.end()); GSLBisection solver(1e-10,1e-8,10000); try { xi = solver.value(solve,0.0,1.1); } catch (GSLBisection::GSLerror) { throw DipoleShowerHandler::RedoShower(); } catch (GSLBisection::IntervalError) { throw DipoleShowerHandler::RedoShower(); } } PList reshuffled; list::const_iterator backup_it; if (need_boost) backup_it = mbackup.begin(); // Reshuffling of non-decaying partons only if ( decayRecoilers.size()==0 ) { for (PList::iterator p = out.begin(); p != out.end(); ++p) { PPtr rp = new_ptr(Particle((**p).dataPtr())); DipolePartonSplitter::change(*p,rp,false); Lorentz5Momentum rm; rm = Lorentz5Momentum (xi*(**p).momentum().x(), xi*(**p).momentum().y(), xi*(**p).momentum().z(), sqrt(sqr((**p).dataPtr()->constituentMass()) + xi*xi*(sqr((**p).momentum().t())-sqr((**p).dataPtr()->mass())))); rm.rescaleMass(); if (need_boost) { (**p).set5Momentum(*backup_it); ++backup_it; rm.boost(-beta); } rp->set5Momentum(rm); intermediates.push_back(*p); reshuffled.push_back(rp); } } // For the case of a decay process with non-partonic recoilers else { assert ( decay ); for (PList::iterator p = out.begin(); p != out.end(); ++p) { // Flag to update spinInfo bool updateSpin = false; PPtr rp = new_ptr(Particle((**p).dataPtr())); DipolePartonSplitter::change(*p,rp,false); Lorentz5Momentum rm; // If the particle is a parton and not a recoiler if ( find( decayRecoilers.begin(), decayRecoilers.end(), *p ) == decayRecoilers.end() ) { rm = Lorentz5Momentum (xi*(**p).momentum().x(), xi*(**p).momentum().y(), xi*(**p).momentum().z(), sqrt(sqr((**p).dataPtr()->constituentMass()) + xi*xi*(sqr((**p).momentum().t())-sqr((**p).dataPtr()->mass())))); } // Otherwise the parton is a recoiler // and its invariant mass must be preserved else { if ( (*p)-> spinInfo() ) updateSpin = true; rm = Lorentz5Momentum (xi*(**p).momentum().x(), xi*(**p).momentum().y(), xi*(**p).momentum().z(), sqrt(sqr((**p).momentum().m()) + xi*xi*(sqr((**p).momentum().t())-sqr((**p).momentum().m())))); } rm.rescaleMass(); if (need_boost) { (**p).set5Momentum(*backup_it); ++backup_it; rm.boost(-beta); } rp->set5Momentum(rm); // Update SpinInfo if required if ( updateSpin ) updateSpinInfo(*p, rp); intermediates.push_back(*p); reshuffled.push_back(rp); } } out.clear(); out.splice(out.end(),reshuffled); } void ConstituentReshuffler::hardProcDecayReshuffle(PList& decaying, PList& eventOutgoing, PList& eventHard, PPair& eventIncoming, PList& eventIntermediates) { // Note, when this function is called, the particle pointers // in theDecays/decaying are those prior to the showering. // Here we find the newest pointers in the outgoing. // The update of the PPtrs in theDecays is done in DipoleShowerHandler::constituentReshuffle() // as this needs to be done if ConstituentReshuffling is switched off. //Make sure the shower should return constituent masses: assert(ShowerHandler::currentHandler()->retConstituentMasses()); // Find the outgoing decaying particles PList recoilers; for ( PList::iterator decIt = decaying.begin(); decIt != decaying.end(); ++decIt) { // First find the particles in the intermediates PList::iterator pos = find(eventIntermediates.begin(),eventIntermediates.end(), *decIt); // Colourless particle or coloured particle that did not radiate. if(pos==eventIntermediates.end()) { // Check that this is not a particle from a subsequent decay. // e.g. the W from a top decay from an LHE file. if ( find( eventHard.begin(), eventHard.end(), *decIt ) == eventHard.end() && find( eventOutgoing.begin(), eventOutgoing.end(), *decIt ) == eventOutgoing.end() ) continue; else recoilers.push_back( *decIt ); } // Coloured decaying particle that radiated else { PPtr unstable = *pos; while(!unstable->children().empty()) { unstable = unstable->children()[0]; } assert( find( eventOutgoing.begin(),eventOutgoing.end(), unstable ) != eventOutgoing.end() ); recoilers.push_back( unstable ); } } // Make a list of partons PList partons; for ( PList::iterator outPos = eventOutgoing.begin(); outPos != eventOutgoing.end(); ++outPos ) { if ( find (recoilers.begin(), recoilers.end(), *outPos ) == recoilers.end() ) { partons.push_back( *outPos ); } } // If no outgoing partons, do nothing if ( partons.size() == 0 ){ return; } // Otherwise reshuffling needs to be done. // If there is only one parton, attempt to reshuffle with // the incoming to be consistent with the reshuffle for a // hard process with no decays. else if ( partons.size() == 1 && ( DipolePartonSplitter::colourConnected(partons.front(),eventIncoming.first) || DipolePartonSplitter::colourConnected(partons.front(),eventIncoming.second) ) ) { // Erase the parton from the event outgoing eventOutgoing.erase( find( eventOutgoing.begin(), eventOutgoing.end(), partons.front() ) ); // Perform the reshuffle, this update the intermediates and the incoming reshuffle(partons, eventIncoming, eventIntermediates); // Update the outgoing eventOutgoing.push_back(partons.front()); return; } // If reshuffling amongst the incoming is not possible // or if we have multiple outgoing partons. else { // Create a complete list of the outgoing from the process PList out; // Make an empty list for storing the new intermediates PList intermediates; // Empty incoming particles pair PPair in; // A single parton which cannot be reshuffled // with the incoming. if ( partons.size() == 1 ) { // Populate the out for the reshuffling out.insert(out.end(),partons.begin(),partons.end()); out.insert(out.end(),recoilers.begin(),recoilers.end()); assert( out.size() > 1 ); // Perform the reshuffle with the temporary particle lists reshuffle(out, in, intermediates, true, partons, recoilers); } // If there is more than one parton, reshuffle only // amongst the partons else { assert(partons.size() > 1); // Populate the out for the reshuffling out.insert(out.end(),partons.begin(),partons.end()); assert( out.size() > 1 ); // Perform the reshuffle with the temporary particle lists reshuffle(out, in, intermediates, true); } // Update the dipole event record updateEvent(intermediates, eventIntermediates, out, eventOutgoing, eventHard ); return; } } void ConstituentReshuffler::decayReshuffle(PerturbativeProcessPtr& decayProc, PList& eventOutgoing, PList& eventHard, PList& eventIntermediates ) { // Separate particles into those to be assigned constituent masses // i.e. non-decaying coloured partons // and those which must only absorb recoil // i.e. non-coloured and decaying particles PList partons; PList recoilers; //Make sure the shower should return constituent masses: assert(ShowerHandler::currentHandler()->retConstituentMasses()); // Populate the particle lists from the outgoing of the decay process for( unsigned int ix = 0; ixoutgoing().size(); ++ix) { // Identify recoilers if ( !decayProc->outgoing()[ix].first->coloured() || ShowerHandler::currentHandler()->decaysInShower(decayProc->outgoing()[ix].first->id() ) ) recoilers.push_back(decayProc->outgoing()[ix].first); else partons.push_back(decayProc->outgoing()[ix].first); } // If there are no outgoing partons, then no reshuffling // needs to be done if ( partons.size() == 0 ) return; // Reshuffling needs to be done: else { // Create a complete list of the outgoing from the process PList out; // Make an empty list for storing the new intermediates PList intermediates; // Empty incoming particles pair PPair in; // SW - 15/06/2018, 31/01/2019 - Always include 'recoilers' in // reshuffling, regardless of the number of partons to be put on their // constituent mass shell. This is because reshuffling between 2 partons // frequently leads to a redoShower exception. This treatment is // consistent with the AO shower // Populate the out for the reshuffling out.insert(out.end(),partons.begin(),partons.end()); out.insert(out.end(),recoilers.begin(),recoilers.end()); assert( out.size() > 1 ); // Perform the reshuffle with the temporary particle lists reshuffle(out, in, intermediates, true, partons, recoilers); // Update the dipole event record and the decay process updateEvent(intermediates, eventIntermediates, out, eventOutgoing, eventHard, decayProc ); return; } } void ConstituentReshuffler::updateEvent( PList& intermediates, PList& eventIntermediates, #ifndef NDEBUG PList& out, #else PList&, #endif PList& eventOutgoing, PList& eventHard, PerturbativeProcessPtr decayProc ) { // Loop over the new intermediates following the reshuffling for (PList::iterator p = intermediates.begin(); p != intermediates.end(); ++p) { // Update the event record intermediates eventIntermediates.push_back(*p); // Identify the reshuffled particle assert( (*p)->children().size()==1 ); PPtr reshuffled = (*p)->children()[0]; assert( find(out.begin(), out.end(), reshuffled) != out.end() ); // Update the event record outgoing PList::iterator posOut = find(eventOutgoing.begin(), eventOutgoing.end(), *p); if ( posOut != eventOutgoing.end() ) { eventOutgoing.erase(posOut); eventOutgoing.push_back(reshuffled); } else { PList::iterator posHard = find(eventHard.begin(), eventHard.end(), *p); assert( posHard != eventHard.end() ); eventHard.erase(posHard); eventHard.push_back(reshuffled); } // Replace the particle in the the decay process outgoing if ( decayProc ) { vector >::iterator decayOutIt = decayProc->outgoing().end(); for ( decayOutIt = decayProc->outgoing().begin(); decayOutIt!= decayProc->outgoing().end(); ++decayOutIt ) { if ( decayOutIt->first == *p ){ break; } } assert( decayOutIt != decayProc->outgoing().end() ); decayOutIt->first = reshuffled; } } } void ConstituentReshuffler::updateSpinInfo( PPtr& oldPart, PPtr& newPart ) { const Lorentz5Momentum& oldMom = oldPart->momentum(); const Lorentz5Momentum& newMom = newPart->momentum(); // Rotation from old momentum to +ve z-axis LorentzRotation oldToZAxis; Axis axisOld(oldMom.vect().unit()); if( axisOld.perp2() > 1e-12 ) { double sinth(sqrt(1.-sqr(axisOld.z()))); oldToZAxis.rotate( -acos(axisOld.z()),Axis(-axisOld.y()/sinth,axisOld.x()/sinth,0.)); } // Rotation from new momentum to +ve z-axis LorentzRotation newToZAxis; Axis axisNew(newMom.vect().unit()); if( axisNew.perp2() > 1e-12 ) { double sinth(sqrt(1.-sqr(axisNew.z()))); newToZAxis.rotate( -acos(axisNew.z()),Axis(-axisNew.y()/sinth,axisNew.x()/sinth,0.)); } // Boost from old momentum to new momentum along z-axis Lorentz5Momentum momOldRotated = oldToZAxis*Lorentz5Momentum(oldMom); Lorentz5Momentum momNewRotated = newToZAxis*Lorentz5Momentum(newMom); Energy2 a = sqr(momOldRotated.z()) + sqr(momNewRotated.t()); Energy2 b = 2.*momOldRotated.t()*momOldRotated.z(); Energy2 c = sqr(momOldRotated.t()) - sqr(momNewRotated.t()); double beta; // The rotated momentum should always lie along the +ve z-axis if ( momOldRotated.z() > ZERO ) beta = (-b + sqrt(sqr(b)-4.*a*c)) / 2. / a; else beta = (-b - sqrt(sqr(b)-4.*a*c)) / 2. / a; LorentzRotation boostOldToNew(0., 0., beta); // Total transform LorentzRotation transform = (newToZAxis.inverse())*boostOldToNew*oldToZAxis; // Assign the same spin info to the old and new particles newPart->spinInfo(oldPart->spinInfo()); newPart->spinInfo()->transform(oldMom, transform); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ConstituentReshuffler::persistentOutput(PersistentOStream &) const { } void ConstituentReshuffler::persistentInput(PersistentIStream &, int) { } ClassDescription ConstituentReshuffler::initConstituentReshuffler; // Definition of the static class description member. void ConstituentReshuffler::Init() { static ClassDocumentation documentation ("The ConstituentReshuffler class implements reshuffling " "of partons on their nominal mass shell to their constituent " "mass shells."); } diff --git a/Shower/Dipole/Utility/ConstituentReshuffler.h b/Shower/Dipole/Utility/ConstituentReshuffler.h --- a/Shower/Dipole/Utility/ConstituentReshuffler.h +++ b/Shower/Dipole/Utility/ConstituentReshuffler.h @@ -1,274 +1,259 @@ // -*- C++ -*- // // ConstituentReshuffler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ConstituentReshuffler_H #define HERWIG_ConstituentReshuffler_H // // This is the declaration of the ConstituentReshuffler class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Utilities/Exception.h" #include "Herwig/Shower/PerturbativeProcess.h" #include "Herwig/Utilities/Reshuffler.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Stephen Webster * * \brief The ConstituentReshuffler class implements reshuffling * of partons on their nominal mass shell to their constituent * mass shells. * */ class ConstituentReshuffler: public HandlerBase, public Reshuffler { public: - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - ConstituentReshuffler(); - - /** - * The destructor. - */ - virtual ~ConstituentReshuffler(); - //@} - -public: - /** * Reshuffle the outgoing partons to constituent * masses. Optionally, incoming partons are given * to absorb recoils. Add the non-reshuffled partons * to the intermediates list. Throw ConstituentReshufflerProblem * if a numerical problem prevents the solution of * the reshuffling equation. */ void reshuffle(PList& out, PPair& in, PList& intermediates, const bool decay, PList& decayPartons, PList& decayRecoilers); /** * Reshuffle the outgoing partons to constituent * masses. Optionally, incoming partons are given * to absorb recoils. Add the non-reshuffled partons * to the intermediates list. Throw ConstituentReshufflerProblem * if a numerical problem prevents the solution of * the reshuffling equation. */ void reshuffle(PList& out, PPair& in, PList& intermediates, const bool decay=false) { PList decayPartons; PList decayRecoilers; reshuffle(out, in, intermediates, decay, decayPartons, decayRecoilers); } /** * Reshuffle the outgoing partons following the showering * of the initial hard interaction to constituent masses, * for the case of outgoing decaying particles. * Throw ConstituentReshufflerProblem * if a numerical problem prevents the solution of * the reshuffling equation. */ void hardProcDecayReshuffle(PList& decaying, PList& eventOutgoing, PList& eventHard, PPair& eventIncoming, PList& eventIntermediates) ; /** * Reshuffle the outgoing partons following the showering * of a particle decay to constituent masses. * Throw ConstituentReshufflerProblem * if a numerical problem prevents the solution of * the reshuffling equation. */ void decayReshuffle(PerturbativeProcessPtr& decayProc, PList& eventOutgoing, PList& eventHard, PList& eventIntermediates) ; /** * Update the dipole event record and, if appropriate, * the relevant decay process. **/ void updateEvent( PList& intermediates, PList& eventIntermediates, PList& out, PList& eventOutgoing, PList& eventHard, PerturbativeProcessPtr decayProc = PerturbativeProcessPtr() ) ; /** * Update the spinInfo of a particle following reshuffling * to take account of the change in momentum. * Used only for unstable particles that need to be dealt with. **/ void updateSpinInfo( PPtr& oldPart, PPtr& newPart ) ; protected: /** * The function object defining the equation * to be solved in the case of separate recoilers * TODO - refine the whole implementation of separate partons and recoilers */ struct DecayReshuffleEquation { DecayReshuffleEquation (Energy q, PList::iterator m_begin, PList::iterator m_end, PList::iterator n_begin, PList::iterator n_end) : w(q), p_begin(m_begin), p_end(m_end), r_begin(n_begin), r_end(n_end) {} typedef double ArgType; typedef double ValType; static double aUnit(); static double vUnit(); double operator() (double xi) const; Energy w; PList::iterator p_begin; PList::iterator p_end; PList::iterator r_begin; PList::iterator r_end; }; 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: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initConstituentReshuffler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ConstituentReshuffler & operator=(const ConstituentReshuffler &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of ConstituentReshuffler. */ template <> struct BaseClassTrait { /** Typedef of the first base class of ConstituentReshuffler. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the ConstituentReshuffler class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::ConstituentReshuffler"; } /** * The name of a file containing the dynamic library where the class * ConstituentReshuffler is implemented. It may also include several, space-separated, * libraries if the class ConstituentReshuffler 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_ConstituentReshuffler_H */ diff --git a/Shower/Dipole/Utility/DipoleMCCheck.cc b/Shower/Dipole/Utility/DipoleMCCheck.cc --- a/Shower/Dipole/Utility/DipoleMCCheck.cc +++ b/Shower/Dipole/Utility/DipoleMCCheck.cc @@ -1,283 +1,281 @@ // -*- C++ -*- // // DipoleMCCheck.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleMCCheck class. // #include "DipoleMCCheck.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; DipoleMCCheck::DipoleMCCheck() : HandlerBase(), theHardPtBins(10), theEmitterXBins(5), theSpectatorXBins(5), thePtBins(100), theZBins(100) { } -DipoleMCCheck::~DipoleMCCheck() {} - IBPtr DipoleMCCheck::clone() const { return new_ptr(*this); } IBPtr DipoleMCCheck::fullclone() const { return new_ptr(*this); } vector DipoleMCCheck::makeLogBins(double xlow, double xup, unsigned int n) const { vector res; double c = log10(xup/xlow) / (n-1.); for ( unsigned int k = 0; k < n; ++k ) res.push_back(xlow*pow(10.0,k*c)); return res; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleMCCheck::doinitrun() { HandlerBase::doinitrun(); vector ptbins; double w = 0.5/theHardPtBins; for ( unsigned int k = 1; k <= theHardPtBins; ++k ) ptbins.push_back(k*w); vector xebins; if ( theEmitterXBins > 1 ) xebins = makeLogBins(1e-7,1.0,theEmitterXBins); else xebins.push_back(1.0); vector xsbins; if ( theSpectatorXBins > 1 ) xsbins = makeLogBins(1e-7,1.0,theSpectatorXBins); else xsbins.push_back(1.0); for ( vector::const_iterator xeit = xebins.begin(); xeit != xebins.end(); ++xeit ) { map::ptr,Ptr::ptr> > > xebin; for ( vector::const_iterator xsit = xsbins.begin(); xsit != xsbins.end(); ++xsit ) { map::ptr,Ptr::ptr> > xsbin; for ( vector::const_iterator ptit = ptbins.begin(); ptit != ptbins.end(); ++ptit ) { pair::ptr,Ptr::ptr> ptbin (new_ptr(Histogram(0.0,0.5,thePtBins)), new_ptr(Histogram(0.0,1.0,theZBins))); xsbin[*ptit] = ptbin; } xebin[*xsit] = xsbin; } histoMap[*xeit] = xebin; } } void DipoleMCCheck::dofinish() { HandlerBase::dofinish(); map::ptr,Ptr::ptr> > > >::iterator xeit; map::ptr,Ptr::ptr> > >::iterator xsit; map::ptr,Ptr::ptr> >::iterator ptit; double xelow = 0.0; double xeup = 0.0; for ( xeit = histoMap.begin(); xeit != histoMap.end(); ++xeit ) { xeup = xelow + xeit->first; double xslow = 0.0; double xsup = 0.0; for ( xsit = xeit->second.begin(); xsit != xeit->second.end(); ++xsit ) { xsup = xslow + xsit->first; // open files here ostringstream ptFileName; ptFileName << name() << "_pt_" << xelow << "_" << xeup << "_" << xslow << "_" << xsup << ".dat"; ofstream ptFile(ptFileName.str().c_str()); ostringstream zFileName; zFileName << name() << "_z_" << xelow << "_" << xeup << "_" << xslow << "_" << xsup << ".dat"; ofstream zFile(zFileName.str().c_str()); double ptlow = 0.0; double ptup = 0.0; for ( ptit = xsit->second.begin(); ptit != xsit->second.end(); ++ptit ) { ptup = ptlow + ptit->first; // dump histos here ptFile << "#\n# " << ptlow << " < \\kappa < " << ptup << "\n#\n"; zFile << "#\n# " << ptlow << " < \\kappa < " << ptup << "\n#\n"; ptit->second.first->simpleOutput(ptFile,false); ptit->second.second->simpleOutput(zFile,false); ptFile << "\n\n\n"; zFile << "\n\n\n"; ptlow = ptup; } xslow = xsup; } xelow = xeup; } } void DipoleMCCheck::book(double xe,double xs, Energy dScale, Energy hardPt, Energy pt, double z, double weight) { map::ptr,Ptr::ptr> > > >::iterator xeit; map::ptr,Ptr::ptr> > >::iterator xsit; map::ptr,Ptr::ptr> >::iterator ptit; if ( theEmitterXBins == 1 || xe >= 1. ) xeit = --histoMap.end(); else xeit = histoMap.upper_bound(xe); if ( theSpectatorXBins == 1 || xs >= 1. ) xsit = --(xeit->second.end()); else xsit = xeit->second.upper_bound(xs); if ( theHardPtBins == 1 || hardPt/dScale >= 0.5 ) ptit = --(xsit->second.end()); else ptit = xsit->second.upper_bound(hardPt/dScale); ptit->second.first->addWeighted(pt/dScale,weight); ptit->second.second->addWeighted(z,weight); } void DipoleMCCheck::persistentOutput(PersistentOStream & os) const { os << theHardPtBins << theEmitterXBins << theSpectatorXBins << thePtBins << theZBins; } void DipoleMCCheck::persistentInput(PersistentIStream & is, int) { is >> theHardPtBins >> theEmitterXBins >> theSpectatorXBins >> thePtBins >> theZBins; } ClassDescription DipoleMCCheck::initDipoleMCCheck; // Definition of the static class description member. void DipoleMCCheck::Init() { static ClassDocumentation documentation ("DipoleMCCheck is used to perform checks for " "the dipole shower."); static Parameter interfaceHardPtBins ("HardPtBins", "HardPtBins", &DipoleMCCheck::theHardPtBins, 10, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceEmitterXBins ("EmitterXBins", "EmitterXBins", &DipoleMCCheck::theEmitterXBins, 5, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceSpectatorXBins ("SpectatorXBins", "SpectatorXBins", &DipoleMCCheck::theSpectatorXBins, 5, 1, 0, false, false, Interface::lowerlim); static Parameter interfacePtBins ("PtBins", "PtBins", &DipoleMCCheck::thePtBins, 100, 1, 0, false, false, Interface::lowerlim); static Parameter interfaceZBins ("ZBins", "ZBins", &DipoleMCCheck::theZBins, 100, 1, 0, false, false, Interface::lowerlim); } diff --git a/Shower/Dipole/Utility/DipoleMCCheck.h b/Shower/Dipole/Utility/DipoleMCCheck.h --- a/Shower/Dipole/Utility/DipoleMCCheck.h +++ b/Shower/Dipole/Utility/DipoleMCCheck.h @@ -1,231 +1,223 @@ // -*- C++ -*- // // DipoleMCCheck.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_DipoleMCCheck_H #define HERWIG_DipoleMCCheck_H // // This is the declaration of the DipoleMCCheck class. // #include "ThePEG/Handlers/HandlerBase.h" #include "Herwig/Utilities/Histogram.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleMCCheck is used to perform checks for * the dipole shower. * * @see \ref DipoleMCCheckInterfaces "The interfaces" * defined for DipoleMCCheck. */ class DipoleMCCheck: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ DipoleMCCheck(); - /** - * The destructor. - */ - virtual ~DipoleMCCheck(); - //@} - public: /** * Book a point. */ void book(double xe,double xs, Energy dScale, Energy hardPt, Energy pt, double z, double weight); 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: /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The number of bins in the starting scale * divided by the dipole scale, the upper bound * is 1/2. */ unsigned int theHardPtBins; /** * The number of bins in the emitter fraction. * The lenght of the zero bin is taken to be * 10^(-7). */ unsigned int theEmitterXBins; /** * The number of bins in the spectator fraction. * The lenght of the zero bin is taken to be * 10^(-7). */ unsigned int theSpectatorXBins; /** * The number of bins in pt dicided by the * dipole scale; the upper bound is 1/2 */ unsigned int thePtBins; /** * The number of bins in z */ unsigned int theZBins; /** * The recursive map structure: xe, xs, hard pt / GeV * to histograms for pt and z; * output is done such that there's one file for each * xe,xs bin, including all histograms for the * hard pt bins. */ map::ptr,Ptr::ptr> > > > histoMap; /** * Helper to make logarithmic bins. */ vector makeLogBins(double xlow, double xup, unsigned int n) const; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initDipoleMCCheck; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleMCCheck & operator=(const DipoleMCCheck &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleMCCheck. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleMCCheck. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleMCCheck class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleMCCheck"; } /** * The name of a file containing the dynamic library where the class * DipoleMCCheck is implemented. It may also include several, space-separated, * libraries if the class DipoleMCCheck 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_DipoleMCCheck_H */ diff --git a/Shower/Dipole/Utility/IntrinsicPtGenerator.cc b/Shower/Dipole/Utility/IntrinsicPtGenerator.cc --- a/Shower/Dipole/Utility/IntrinsicPtGenerator.cc +++ b/Shower/Dipole/Utility/IntrinsicPtGenerator.cc @@ -1,198 +1,196 @@ // -*- C++ -*- // // IntrinsicPtGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IntrinsicPtGenerator class. // #include "IntrinsicPtGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/Constants.h" #include "DipolePartonSplitter.h" #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/PDF/HwRemDecayer.h" using namespace Herwig; IntrinsicPtGenerator::IntrinsicPtGenerator() : HandlerBase(), theValenceIntrinsicPtScale(1.0*GeV), theSeaIntrinsicPtScale(1.0*GeV) {} -IntrinsicPtGenerator::~IntrinsicPtGenerator() {} - IBPtr IntrinsicPtGenerator::clone() const { return new_ptr(*this); } IBPtr IntrinsicPtGenerator::fullclone() const { return new_ptr(*this); } LorentzRotation IntrinsicPtGenerator::kick(PPair& in, PList& intermediates) { if ( theValenceIntrinsicPtScale == 0.0*GeV && theSeaIntrinsicPtScale == 0.0*GeV ) return LorentzRotation(); assert(ShowerHandler::currentHandler()); tHwRemDecPtr remDec = ShowerHandler::currentHandler()->remnantDecayer(); assert(remDec); Lorentz5Momentum Q = in.first->momentum() + in.second->momentum(); // first parton if (in.first->coloured()) { Axis perp; Energy pt = 0.*GeV; double phi = 2.*Constants::pi*UseRandom::rnd(); Axis dir = in.first->momentum().vect().unit(); perp = dir.orthogonal(); perp.rotate(phi,dir); double r = sqrt(-log(1.-UseRandom::rnd())); if ( remDec->content().first.isValenceQuark(in.first) ) pt = sqrt(2.) * theValenceIntrinsicPtScale * r; else { assert(in.first->id() == ParticleID::g || remDec->content().first.isSeaQuark(in.first)); pt = sqrt(2.) * theSeaIntrinsicPtScale * r; } PPtr nin = new_ptr(Particle(in.first->dataPtr())); DipolePartonSplitter::change(in.first,nin,true); nin->set5Momentum(Lorentz5Momentum(0.*GeV,in.first->momentum().vect() + pt * perp)); intermediates.push_back(in.first); in.first = nin; } // second parton if (in.second->coloured()) { Axis perp; Energy pt = 0.*GeV; double phi = 2.*Constants::pi*UseRandom::rnd(); Axis dir = in.second->momentum().vect().unit(); perp = dir.orthogonal(); perp.rotate(phi,dir); double r = sqrt(-log(1.-UseRandom::rnd())); if ( remDec->content().second.isValenceQuark(in.second) ) pt = sqrt(2.) * theValenceIntrinsicPtScale * r; else { assert(in.second->id() == ParticleID::g || remDec->content().second.isSeaQuark(in.second)); pt = sqrt(2.) * theSeaIntrinsicPtScale * r; } PPtr nin = new_ptr(Particle(in.second->dataPtr())); nin->colourInfo(new_ptr(ColourBase())); DipolePartonSplitter::change(in.second,nin,true); nin->set5Momentum(Lorentz5Momentum(0.*GeV,in.second->momentum().vect() + pt * perp)); intermediates.push_back(in.second); in.second = nin; } // restore mometum conservation Lorentz5Momentum nQ = in.first->momentum() + in.second->momentum(); double x = Q.m()/nQ.m(); nQ *= x; // work around for constructor problems // in Lorentz5Vector constructor, mass is not guaranteed // to be zero, event it was set as such before, // since gets recalculated in the LorentzVector Lorentz5Momentum scaled = x * in.first->momentum(); scaled.setMass(ZERO); scaled.rescaleEnergy(); in.first->set5Momentum(scaled); scaled = x * in.second->momentum(); scaled.setMass(ZERO); scaled.rescaleEnergy(); in.second->set5Momentum(scaled); // apparently, this is more stable than boosting directly with // n_Q.boostVector()-Q.boostVector() Boost beta1 = -Q.boostVector(); Boost beta2 = nQ.boostVector(); LorentzRotation transform (beta1); transform.boost(beta2); return transform; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IntrinsicPtGenerator::persistentOutput(PersistentOStream & os) const { os << ounit(theValenceIntrinsicPtScale,GeV) << ounit(theSeaIntrinsicPtScale,GeV); } void IntrinsicPtGenerator::persistentInput(PersistentIStream & is, int) { is >> iunit(theValenceIntrinsicPtScale,GeV) >> iunit(theSeaIntrinsicPtScale,GeV); } ClassDescription IntrinsicPtGenerator::initIntrinsicPtGenerator; // Definition of the static class description member. void IntrinsicPtGenerator::Init() { static ClassDocumentation documentation ("IntrinsicPtGenerator generates intrinsic pt for massless " "incoming partons in a shower independent way."); static Parameter interfaceValenceIntrinsicPtScale ("ValenceIntrinsicPtScale", "The width of the intrinsic pt Gaussian distribution for valence partons.", &IntrinsicPtGenerator::theValenceIntrinsicPtScale, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceSeaIntrinsicPtScale ("SeaIntrinsicPtScale", "The width of the intrinsic pt Gaussian distribution for sea partons.", &IntrinsicPtGenerator::theSeaIntrinsicPtScale, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); } diff --git a/Shower/Dipole/Utility/IntrinsicPtGenerator.h b/Shower/Dipole/Utility/IntrinsicPtGenerator.h --- a/Shower/Dipole/Utility/IntrinsicPtGenerator.h +++ b/Shower/Dipole/Utility/IntrinsicPtGenerator.h @@ -1,174 +1,166 @@ // -*- C++ -*- // // IntrinsicPtGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_IntrinsicPtGenerator_H #define HERWIG_IntrinsicPtGenerator_H // // This is the declaration of the IntrinsicPtGenerator class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Vectors/LorentzRotation.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief IntrinsicPtGenerator generates intrinsic pt for massless * incoming partons in a shower independent way. * * @see \ref IntrinsicPtGeneratorInterfaces "The interfaces" * defined for IntrinsicPtGenerator. */ class IntrinsicPtGenerator: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ IntrinsicPtGenerator(); - /** - * The destructor. - */ - virtual ~IntrinsicPtGenerator(); - //@} - public: /** * Generate intrinsic pt for the given incoming * partons and return the transformation to be * applied on the final state particles. Add the * old incoming partons to the given list. */ LorentzRotation kick(PPair& in, PList& intermediates); 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: /** * The mean of the Gaussian distribution for * the intrinsic pt of valence partons. */ Energy theValenceIntrinsicPtScale; /** * The mean of the Gaussian distribution for * the intrinsic pt of sea partons. */ Energy theSeaIntrinsicPtScale; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initIntrinsicPtGenerator; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IntrinsicPtGenerator & operator=(const IntrinsicPtGenerator &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of IntrinsicPtGenerator. */ template <> struct BaseClassTrait { /** Typedef of the first base class of IntrinsicPtGenerator. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the IntrinsicPtGenerator class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::IntrinsicPtGenerator"; } /** * The name of a file containing the dynamic library where the class * IntrinsicPtGenerator is implemented. It may also include several, space-separated, * libraries if the class IntrinsicPtGenerator 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_IntrinsicPtGenerator_H */ diff --git a/Shower/Dipole/Utility/PDFRatio.cc b/Shower/Dipole/Utility/PDFRatio.cc --- a/Shower/Dipole/Utility/PDFRatio.cc +++ b/Shower/Dipole/Utility/PDFRatio.cc @@ -1,144 +1,142 @@ // -*- C++ -*- // // PDFRatio.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PDFRatio class. // #include "PDFRatio.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/PDF/HwRemDecayer.h" using namespace Herwig; PDFRatio::PDFRatio() : HandlerBase(), theValenceExtrapolation(0.7), theSeaExtrapolation(0.6), theFreezingScale(1.0*GeV) {} -PDFRatio::~PDFRatio() {} - IBPtr PDFRatio::clone() const { return new_ptr(*this); } IBPtr PDFRatio::fullclone() const { return new_ptr(*this); } double PDFRatio::operator() (const PDF& pdf, Energy2 scale, tcPDPtr from, tcPDPtr to, double x, double z) const { if ( x/z > 1.0 ) return 0.0; if(z==1)return 1.0; if ( scale < sqr(theFreezingScale) ) scale = sqr(theFreezingScale); tcHwRemDecPtr remDec = ShowerHandler::currentHandler()->remnantDecayer(); const HwRemDecayer::HadronContent* theContent = 0; if ( remDec->content().first.hadron == pdf.particle() ) { theContent = &(remDec->content().first); } if ( remDec->content().second.hadron == pdf.particle() ) { theContent = &(remDec->content().second); } assert(theContent); double exFrom = theContent->isValenceQuarkData(from) ? theValenceExtrapolation : theSeaExtrapolation; double exTo = theContent->isValenceQuarkData(to) ? theValenceExtrapolation : theSeaExtrapolation; double xTo = x/z; double fromPDF = x < exFrom ? pdf.xfx(from,scale,x) : ((1.-x)/(1.-exFrom)) * pdf.xfx(from,scale,exFrom); if ( fromPDF < 1e-8 ) fromPDF = 0.0; double toPDF = xTo < exTo ? pdf.xfx(to,scale,xTo) : ((1.-xTo)/(1.-exTo)) * pdf.xfx(to,scale,exTo); if ( toPDF < 1e-8 ) toPDF = 0.0; if ( toPDF == 0.0 || fromPDF == 0.0 ) return 0.0; return toPDF / fromPDF; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void PDFRatio::persistentOutput(PersistentOStream & os) const { os << theValenceExtrapolation << theSeaExtrapolation << ounit(theFreezingScale,GeV); } void PDFRatio::persistentInput(PersistentIStream & is, int) { is >> theValenceExtrapolation >> theSeaExtrapolation >> iunit(theFreezingScale,GeV); } ClassDescription PDFRatio::initPDFRatio; // Definition of the static class description member. void PDFRatio::Init() { static ClassDocumentation documentation ("PDFRatio implements numerically stable pdf ratios."); static Parameter interfaceValenceExtrapolation ("ValenceExtrapolation", "The x from which on extrapolation should be done for valence partons.", &PDFRatio::theValenceExtrapolation, 0.7, 0.0, 1.0, false, false, Interface::limited); static Parameter interfaceSeaExtrapolation ("SeaExtrapolation", "The x from which on extrapolation should be done for valence partons.", &PDFRatio::theSeaExtrapolation, 0.6, 0.0, 1.0, false, false, Interface::limited); static Parameter interfaceFreezingScale ("FreezingScale", "The scale below which the PDFs are frozen.", &PDFRatio::theFreezingScale, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); } diff --git a/Shower/Dipole/Utility/PDFRatio.h b/Shower/Dipole/Utility/PDFRatio.h --- a/Shower/Dipole/Utility/PDFRatio.h +++ b/Shower/Dipole/Utility/PDFRatio.h @@ -1,178 +1,170 @@ // -*- C++ -*- // // PDFRatio.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_PDFRatio_H #define HERWIG_PDFRatio_H // // This is the declaration of the PDFRatio class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/PDF/PDF.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief PDFRatio implements numerically stable PDF ratios. * * @see \ref PDFRatioInterfaces "The interfaces" * defined for PDFRatio. */ class PDFRatio: public HandlerBase { public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ PDFRatio(); - /** - * The destructor. - */ - virtual ~PDFRatio(); - //@} - public: /** * For the given PDF, scale and partons from and to and * x,z values return the ratio xf_to(x/z) / xf_from(x) */ double operator() (const PDF& pdf, Energy2 scale, tcPDPtr from, tcPDPtr to, double x, double z) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The x from which on extrapolation should * be done for valence partons. */ double theValenceExtrapolation; /** * The x from which on extrapolation should * be done for sea partons. */ double theSeaExtrapolation; /** * The scale below which the PDF will be frozen */ Energy theFreezingScale; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initPDFRatio; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ PDFRatio & operator=(const PDFRatio &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of PDFRatio. */ template <> struct BaseClassTrait { /** Typedef of the first base class of PDFRatio. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the PDFRatio class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::PDFRatio"; } /** * The name of a file containing the dynamic library where the class * PDFRatio is implemented. It may also include several, space-separated, * libraries if the class PDFRatio 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_PDFRatio_H */ diff --git a/Shower/QTilde/Base/PartnerFinder.cc b/Shower/QTilde/Base/PartnerFinder.cc --- a/Shower/QTilde/Base/PartnerFinder.cc +++ b/Shower/QTilde/Base/PartnerFinder.cc @@ -1,699 +1,699 @@ // -*- C++ -*- // // PartnerFinder.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PartnerFinder class. // #include "PartnerFinder.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; DescribeClass describePartnerFinder ("Herwig::PartnerFinder","HwShower.so"); // some useful functions to avoid using #define namespace { // return bool if final-state particle inline bool FS(const tShowerParticlePtr a) { return a->isFinalState(); } // return colour line pointer inline Ptr::transient_pointer CL(const tShowerParticlePtr a, unsigned int index=0) { return a->colourInfo()->colourLines().empty() ? ThePEG::tColinePtr() : const_ptr_cast(a->colourInfo()->colourLines()[index]); } // return colour line size inline size_t CLSIZE(const tShowerParticlePtr a) { return a->colourInfo()->colourLines().size(); } inline Ptr::transient_pointer ACL(const tShowerParticlePtr a, unsigned int index=0) { return a->colourInfo()->antiColourLines().empty() ? ThePEG::tColinePtr() : const_ptr_cast(a->colourInfo()->antiColourLines()[index]); } inline size_t ACLSIZE(const tShowerParticlePtr a) { return a->colourInfo()->antiColourLines().size(); } } void PartnerFinder::persistentOutput(PersistentOStream & os) const { os << partnerMethod_ << QEDPartner_ << scaleChoice_; } void PartnerFinder::persistentInput(PersistentIStream & is, int) { is >> partnerMethod_ >> QEDPartner_ >> scaleChoice_; } void PartnerFinder::Init() { static ClassDocumentation documentation ("This class is responsible for finding the partners for each interaction types ", "and within the evolution scale range specified by the ShowerVariables ", "then to determine the initial evolution scales for each pair of partners."); static Switch interfacePartnerMethod ("PartnerMethod", "Choice of partner finding method for gluon evolution.", &PartnerFinder::partnerMethod_, 0, false, false); static SwitchOption interfacePartnerMethodRandom (interfacePartnerMethod, "Random", "Choose partners of a gluon randomly.", 0); static SwitchOption interfacePartnerMethodMaximum (interfacePartnerMethod, "Maximum", "Choose partner of gluon with largest angle.", 1); static Switch interfaceQEDPartner ("QEDPartner", "Control of which particles to use as the partner for QED radiation", &PartnerFinder::QEDPartner_, 0, false, false); static SwitchOption interfaceQEDPartnerAll (interfaceQEDPartner, "All", "Consider all possible choices which give a positive contribution" " in the soft limit.", 0); static SwitchOption interfaceQEDPartnerIIandFF (interfaceQEDPartner, "IIandFF", "Only allow initial-initial or final-final combinations", 1); static SwitchOption interfaceQEDPartnerIF (interfaceQEDPartner, "IF", "Only allow initial-final combinations", 2); static Switch interfaceScaleChoice ("ScaleChoice", "The choice of the evolution scales", &PartnerFinder::scaleChoice_, 0, false, false); static SwitchOption interfaceScaleChoicePartner (interfaceScaleChoice, "Partner", "Scale of all interactions is that of the evolution partner", 0); static SwitchOption interfaceScaleChoiceDifferent (interfaceScaleChoice, "Different", "Allow each interaction to have different scales", 1); } void PartnerFinder::setInitialEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, ShowerInteraction type, const bool setPartners) { // clear the existing partners for(ShowerParticleVector::const_iterator cit = particles.begin(); cit != particles.end(); ++cit) (*cit)->clearPartners(); // set them if(type==ShowerInteraction::QCD) { setInitialQCDEvolutionScales(particles,isDecayCase,setPartners); } else if(type==ShowerInteraction::QED) { setInitialQEDEvolutionScales(particles,isDecayCase,setPartners); } else if(type==ShowerInteraction::EW) { setInitialEWEvolutionScales(particles,isDecayCase,false); } else if(type==ShowerInteraction::QEDQCD) { setInitialQCDEvolutionScales(particles,isDecayCase,setPartners); setInitialQEDEvolutionScales(particles,isDecayCase,false); } else if(type==ShowerInteraction::ALL) { setInitialQCDEvolutionScales(particles,isDecayCase,setPartners); setInitialQEDEvolutionScales(particles,isDecayCase,false); setInitialEWEvolutionScales(particles,isDecayCase,false); } else assert(false); // \todo EW scales here // print out for debugging if(Debug::level>=10) { for(ShowerParticleVector::const_iterator cit = particles.begin(); cit != particles.end(); ++cit) { generator()->log() << "Particle: " << **cit << "\n"; if(!(**cit).partner()) continue; generator()->log() << "Primary partner: " << *(**cit).partner() << "\n"; for(vector::const_iterator it= (**cit).partners().begin(); it!=(**cit).partners().end();++it) { generator()->log() << static_cast(it->type) << " " << it->weight << " " << it->scale/GeV << " " << *(it->partner) << "\n"; } } generator()->log() << flush; } } void PartnerFinder::setInitialQCDEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, const bool setPartners) { // Loop over particles and consider only coloured particles which don't // have already their colour partner fixed and that don't have children // (the latter requirement is relaxed in the case isDecayCase is true). // Build a map which has as key one of these particles (i.e. a pointer // to a ShowerParticle object) and as a corresponding value the vector // of all its possible *normal* candidate colour partners, defined as follows: // --- have colour, and no children (this is not required in the case // isDecayCase is true); // --- if both are initial (incoming) state particles, then the (non-null) colourLine() // of one of them must match the (non-null) antiColourLine() of the other. // --- if one is an initial (incoming) state particle and the other is // a final (outgoing) state particle, then both must have the // same (non-null) colourLine() or the same (non-null) antiColourLine(); // Notice that this definition exclude the special case of baryon-violating // processes (as in R-parity Susy), which will show up as particles // without candidate colour partners, and that we will be treated a part later // (this means that no modifications of the following loop is needed! for ( const auto & sp : particles ) { // Skip colourless particles if(!sp->data().coloured()) continue; // find the partners auto partners = findQCDPartners(sp,particles); // must have a partner if(partners.empty()) { throw Exception() << "`Failed to make colour connections in " << "PartnerFinder::setQCDInitialEvolutionScales" << *sp << Exception::eventerror; } // Calculate the evolution scales for all possible pairs of of particles vector > scales; int position = -1; for(size_t ix=0; ix< partners.size(); ++ix) { scales.push_back(calculateInitialEvolutionScales(ShowerPPair(sp, partners[ix].second),isDecayCase)); if (!setPartners && partners[ix].second) position = ix; } assert(setPartners || position >= 0); // set partners if required if (setPartners) { // In the case of more than one candidate colour partners, // there are now two approaches to choosing the partner. The // first method is based on two assumptions: // 1) the choice of which is the colour partner is done // *randomly* between the available candidates. // 2) the choice of which is the colour partner is done // *independently* from each particle: in other words, // if for a particle "i" its selected colour partner is // the particle "j", then the colour partner of "j" // does not have to be necessarily "i". // The second method always chooses the furthest partner // for hard gluons and gluinos. // random choice if( partnerMethod_ == 0 ) { // random choice of partner position = UseRandom::irnd(partners.size()); } // take the one with largest angle else if (partnerMethod_ == 1 ) { if (sp->perturbative() == 1 && sp->dataPtr()->iColour()==PDT::Colour8 ) { assert(partners.size()==2); // Determine largest angle double maxAngle(0.); for(unsigned int ix=0;ixmomentum().vect(). angle(partners[ix].second->momentum().vect()); if(angle>maxAngle) { maxAngle = angle; position = ix; } } } else position = UseRandom::irnd(partners.size()); } else assert(false); // set the evolution partner sp->partner(partners[position].second); } // primary partner set, set the others and do the scale for(size_t ix=0; ixaddPartner(ShowerParticle::EvolutionPartner(partners[ix].second,1.,partners[ix].first, scales[ix].first)); } // set scales for all interactions to that of the partner, default Energy scale = scales[position].first; for(unsigned int ix=0;ixscales().QCD_c = sp->scales().QCD_c_noAO = (scaleChoice_==0 ? scale : scales[ix].first); } else if(partners[ix].first==ShowerPartnerType::QCDAntiColourLine) { sp->scales().QCD_ac = sp->scales().QCD_ac_noAO = (scaleChoice_==0 ? scale : scales[ix].first); } else assert(false); } } } void PartnerFinder::setInitialQEDEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, const bool setPartners) { // loop over all the particles for(const auto & sp : particles) { // not charged or photon continue if(!sp->dataPtr()->charged() && sp->dataPtr()->id()!=ParticleID::gamma) continue; // find the potential partners vector > partners = findQEDPartners(sp,particles,isDecayCase); if(partners.empty()) { throw Exception() << "Failed to find partner in " << "PartnerFinder::setQEDInitialEvolutionScales" << *sp << Exception::eventerror; } // calculate the probabilities double prob(0.); for(unsigned int ix=0;ixpartner()) { for(unsigned int ix=0;ixpartner()==partners[ix].second) { position = ix; break; } } } // set the partner if(setPartners||!sp->partner()||position<0) { prob = UseRandom::rnd(); for(unsigned int ix=0;ixprob) { position = ix; break; } prob -= partners[ix].first; } if(position>=0&&(setPartners||!sp->partner())) { sp->partner(partners[position].second); } } // must have a partner if(position<0) throw Exception() << "Failed to find partner in " << "PartnerFinder::setQEDInitialEvolutionScales" << *sp << Exception::eventerror; // Calculate the evolution scales for all possible pairs of of particles vector > scales; for(unsigned int ix=0;ix< partners.size();++ix) { scales.push_back(calculateInitialEvolutionScales(ShowerPPair(sp,partners[ix].second), isDecayCase)); } // store all the possible partners for(unsigned int ix=0;ixaddPartner(ShowerParticle::EvolutionPartner(partners[ix].second, partners[ix].first, ShowerPartnerType::QED, scales[ix].first)); } // set scales sp->scales().QED = scales[position].first; sp->scales().QED_noAO = scales[position].first; } } pair PartnerFinder:: calculateInitialEvolutionScales(const ShowerPPair &particlePair, const bool isDecayCase, int key) { bool FS1=FS(particlePair.first),FS2= FS(particlePair.second); if(FS1 && FS2){ return calculateFinalFinalScales(particlePair.first->momentum(),particlePair.second->momentum(), key); } else if(FS1 && !FS2) { pair rval = calculateInitialFinalScales(particlePair.second->momentum(), particlePair.first->momentum(), isDecayCase); return { rval.second, rval.first }; } else if(!FS1 &&FS2) return calculateInitialFinalScales(particlePair.first->momentum(),particlePair.second->momentum(),isDecayCase); else return calculateInitialInitialScales(particlePair.first->momentum(),particlePair.second->momentum()); } vector< pair > PartnerFinder::findQCDPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles) { vector< pair > partners; for(const auto & sp : particles) { if(!sp->data().coloured() || particle==sp) continue; // one initial-state and one final-state particle if(FS(particle) != FS(sp)) { // loop over all the colours of both particles for(size_t ix=0; ixsourceNeighbours().first) { tColinePair cpair = col->sourceNeighbours(); for(const auto & sp : particles) { if(( FS(sp) && ( CL(sp) == cpair.first || CL(sp) == cpair.second))|| (!FS(sp) && (ACL(sp) == cpair.first || ACL(sp) == cpair.second ))) { partners.push_back({ ShowerPartnerType:: QCDColourLine, sp }); } } } else if(col&&col->sinkNeighbours().first) { tColinePair cpair = col->sinkNeighbours(); for(const auto & sp : particles) { if(( FS(sp) && (ACL(sp) == cpair.first || ACL(sp) == cpair.second))|| (!FS(sp) && ( CL(sp) == cpair.first || CL(sp) == cpair.second))) { partners.push_back({ ShowerPartnerType:: QCDColourLine, sp }); } } } col = ACL(particle); if(FS(particle)&&col&&col->sinkNeighbours().first) { tColinePair cpair = col->sinkNeighbours(); for(const auto & sp : particles) { if(( FS(sp) && (ACL(sp) == cpair.first || ACL(sp) == cpair.second))|| (!FS(sp) && ( CL(sp) == cpair.first || CL(sp) == cpair.second ))) { partners.push_back({ ShowerPartnerType::QCDAntiColourLine, sp }); } } } else if(col&&col->sourceNeighbours().first) { tColinePair cpair = col->sourceNeighbours(); for(const auto & sp : particles) { if(( FS(sp) && ( CL(sp) == cpair.first || CL(sp) == cpair.second))|| (!FS(sp) && (ACL(sp) == cpair.first ||ACL(sp) == cpair.second))) { partners.push_back({ ShowerPartnerType::QCDAntiColourLine, sp }); } } } } // return the partners return partners; } vector< pair > PartnerFinder::findQEDPartners(tShowerParticlePtr particle, const ShowerParticleVector & particles, const bool isDecayCase) { vector< pair > partners; const double pcharge = particle->id()==ParticleID::gamma ? 1 : double(particle->data().iCharge()); vector< pair > photons; for (const auto & sp : particles) { if (particle == sp) continue; if (sp->id()==ParticleID::gamma) photons.push_back(make_pair(1.,sp)); if (!sp->data().charged() ) continue; double charge = pcharge*double((sp)->data().iCharge()); if ( FS(particle) != FS(sp) ) charge *=-1.; if ( QEDPartner_ != 0 && !isDecayCase ) { // only include II and FF as requested if ( QEDPartner_ == 1 && FS(particle) != FS(sp) ) continue; // only include IF is requested else if (QEDPartner_ == 2 && FS(particle) == FS(sp) ) continue; } if (particle->id()==ParticleID::gamma) charge = -abs(charge); // only keep positive dipoles if (charge<0.) partners.push_back({ -charge, sp }); } if (particle->id()==ParticleID::gamma && partners.empty()) return photons; return partners; } void PartnerFinder::setInitialEWEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, const bool setPartners) { // loop over all the particles for(ShowerParticleVector::const_iterator cit = particles.begin(); cit != particles.end(); ++cit) { // if not weakly interacting continue if( !weaklyInteracting( (**cit).dataPtr())) continue; // find the potential partners vector > partners = findEWPartners(*cit,particles,isDecayCase); if(partners.empty()) { throw Exception() << "Failed to find partner in " << "PartnerFinder::setEWInitialEvolutionScales" << (**cit) << Exception::eventerror; } // calculate the probabilities double prob(0.); for(unsigned int ix=0;ixpartner()) { for(unsigned int ix=0;ixpartner()==partners[ix].second) { position = ix; break; } } } // set the partner if(setPartners||!(*cit)->partner()||position<0) { prob = UseRandom::rnd(); for(unsigned int ix=0;ixprob) { position = ix; break; } prob -= partners[ix].first; } if(position>=0&&(setPartners||!(*cit)->partner())) { (*cit)->partner(partners[position].second); } } // must have a partner if(position<0) throw Exception() << "Failed to find partner in " << "PartnerFinder::setEWInitialEvolutionScales" << (**cit) << Exception::eventerror; // Calculate the evolution scales for all possible pairs of of particles vector > scales; for(unsigned int ix=0;ix< partners.size();++ix) { scales.push_back(calculateInitialEvolutionScales(ShowerPPair(*cit,partners[ix].second), isDecayCase, 0)); } // store all the possible partners for(unsigned int ix=0;ix > PartnerFinder::findEWPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles, - const bool isDecayCase ) { + const bool ) { vector< pair > partners; for(ShowerParticlePtr partner : particles) { if(particle==partner || !weaklyInteracting(partner->dataPtr())) continue; partners.push_back(make_pair(1.,partner)); } return partners; } pair PartnerFinder::calculateFinalFinalScales( const Lorentz5Momentum & p1, const Lorentz5Momentum & p2, int key) { static const double eps=1e-7; // Using JHEP 12(2003)045 we find that we need ktilde = 1/2(1+b-c+lambda) // ktilde = qtilde^2/Q^2 therefore qtilde = sqrt(ktilde*Q^2) // find momenta in rest frame of system // calculate quantities for the scales Energy2 Q2 = (p1+p2).m2(); double b = p1.mass2()/Q2; double c = p2.mass2()/Q2; if(b<0.) { if(b<-eps) { throw Exception() << "Negative Mass squared b = " << b << "in PartnerFinder::calculateFinalFinalScales()" << Exception::eventerror; } b = 0.; } if(c<0.) { if(c<-eps) { throw Exception() << "Negative Mass squared c = " << c << "in PartnerFinder::calculateFinalFinalScales()" << Exception::eventerror; } c = 0.; } // KMH & PR - 16 May 2008 - swapped lambda calculation from // double lam=2.*p1.vect().mag()/Q; to sqrt(kallen(1,b,c)), // which should be identical for p1 & p2 onshell in their COM // but in the inverse construction for the Nason method, this // was not the case, leading to misuse. const double lam=sqrt((1.+sqrt(b)+sqrt(c))*(1.-sqrt(b)-sqrt(c)) *(sqrt(b)-1.-sqrt(c))*(sqrt(c)-1.-sqrt(b))); Energy firstQ, secondQ; double kappab(0.), kappac(0.); //key = 0; // symmetric case pre-selection switch(key) { case 0: // symmetric case firstQ = sqrt(0.5*Q2*(1.+b-c+lam)); secondQ = sqrt(0.5*Q2*(1.-b+c+lam)); break; case 1: // maximum emission from both legs kappab=4.*(1.-2.*sqrt(c)-b+c); kappac=4.*(1.-2.*sqrt(b)-c+b); firstQ = sqrt(Q2*kappab); secondQ = sqrt(Q2*kappac); break; default: assert(false); } // calculate the scales return pair(firstQ, secondQ); } pair PartnerFinder::calculateInitialFinalScales(const Lorentz5Momentum& pb, const Lorentz5Momentum& pc, const bool isDecayCase) { if(!isDecayCase) { // In this case from JHEP 12(2003)045 we find the conditions // ktilde_b = (1+c) and ktilde_c = (1+2c) // We also find that c = m_c^2/Q^2. The process is a+b->c where // particle a is not colour connected (considered as a colour singlet). // Therefore we simply find that q_b = sqrt(Q^2+m_c^2) and // q_c = sqrt(Q^2+2 m_c^2) // We also assume that the first particle in the pair is the initial // state particle and the second is the final state one c const Energy2 mc2 = sqr(pc.mass()); const Energy2 Q2 = -(pb-pc).m2(); return { sqrt(Q2+mc2), sqrt(Q2+2*mc2) }; } else { // In this case from JHEP 12(2003)045 we find, for the decay // process b->c+a(neutral), the condition // (ktilde_b-1)*(ktilde_c-c)=(1/4)*sqr(1-a+c+lambda). // We also assume that the first particle in the pair is the initial // state particle (b) and the second is the final state one (c). // - We find maximal phase space coverage through emissions from // c if we set ktilde_c = 4.*(sqr(1.-sqrt(a))-c) // - We find the most 'symmetric' way to populate the phase space // occurs for (ktilde_b-1)=(ktilde_c-c)=(1/2)*(1-a+c+lambda) // - We find the most 'smooth' way to populate the phase space // occurs for... Energy2 mb2(sqr(pb.mass())); double a=(pb-pc).m2()/mb2; double c=sqr(pc.mass())/mb2; double lambda = 1. + a*a + c*c - 2.*a - 2.*c - 2.*a*c; lambda = sqrt(max(lambda,0.)); const double PROD = 0.25*sqr(1. - a + c + lambda); int key = 0; double ktilde_b, ktilde_c, cosi = 0.; switch (key) { case 0: // the 'symmetric' choice ktilde_c = 0.5*(1-a+c+lambda) + c ; ktilde_b = 1.+PROD/(ktilde_c-c) ; break; case 1: // the 'maximal' choice ktilde_c = 4.0*(sqr(1.-sqrt(a))-c); ktilde_b = 1.+PROD/(ktilde_c-c) ; break; case 2: // the 'smooth' choice c = max(c,1.*GeV2/mb2); cosi = (sqr(1-sqrt(c))-a)/lambda; ktilde_b = 2.0/(1.0-cosi); ktilde_c = (1.0-a+c+lambda)*(1.0+c-a-lambda*cosi)/(2.0*(1.0+cosi)); break; } return { sqrt(mb2*ktilde_b), sqrt(mb2*ktilde_c) }; } } pair PartnerFinder::calculateInitialInitialScales(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2) { // This case is quite simple. From JHEP 12(2003)045 we find the condition // that ktilde_b = ktilde_c = 1. In this case we have the process // b+c->a so we need merely boost to the CM frame of the two incoming // particles and then qtilde is equal to the energy in that frame const Energy Q = sqrt((p1+p2).m2()); return {Q,Q}; } diff --git a/Shower/QTilde/Kinematics/ShowerKinematics.cc b/Shower/QTilde/Kinematics/ShowerKinematics.cc --- a/Shower/QTilde/Kinematics/ShowerKinematics.cc +++ b/Shower/QTilde/Kinematics/ShowerKinematics.cc @@ -1,71 +1,71 @@ // -*- C++ -*- // // ShowerKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerKinematics class. // #include "ShowerKinematics.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; DescribeAbstractNoPIOClass describeShowerKinematics("Herwig::ShowerKinematics","Herwig.so"); void ShowerKinematics::updateChildren(const tShowerParticlePtr, const ShowerParticleVector &, - unsigned int pTscheme, + unsigned int , ShowerPartnerType) const { throw Exception() << "Base class ShowerKinematics::updateChildren called," << " should have been overriden in an inheriting class" << Exception::runerror; } void ShowerKinematics::resetChildren(const tShowerParticlePtr, const ShowerParticleVector &) const { throw Exception() << "Base class ShowerKinematics::resetChildren called," << " should have been overriden in an inheriting class" << Exception::runerror; } void ShowerKinematics::updateParent(const tShowerParticlePtr, const ShowerParticleVector &, unsigned int , ShowerPartnerType) const { throw Exception() << "Base class ShowerKinematics::updateParent called," << " should have been overriden in an inheriting class" << Exception::runerror; } void ShowerKinematics::reconstructChildren(const tShowerParticlePtr, const ShowerParticleVector &) const { throw Exception() << "Base class ShowerKinematics::reconstructChildren called," << " should have been overriden in an inheriting class" << Exception::runerror; } void ShowerKinematics::reconstructParent(const tShowerParticlePtr, const ParticleVector &) const { throw Exception() << "Base class ShowerKinematics::reconstructParent called," << " should have been overriden in an inheriting class" << Exception::runerror; } void ShowerKinematics::reconstructLast(const tShowerParticlePtr, Energy) const { throw Exception() << "Base class ShowerKinematics::reconstructLast called," << " should have been overriden in an inheriting class" << Exception::runerror; } void ShowerKinematics::updateLast(const tShowerParticlePtr, Energy,Energy) const { throw Exception() << "Base class ShowerKinematics::updatetLast called," << " should have been overriden in an inheriting class" << Exception::runerror; } diff --git a/Shower/QTilde/QTildeShowerHandler.cc b/Shower/QTilde/QTildeShowerHandler.cc --- a/Shower/QTilde/QTildeShowerHandler.cc +++ b/Shower/QTilde/QTildeShowerHandler.cc @@ -1,3253 +1,3251 @@ // -*- C++ -*- // // QTildeShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // This is the implementation of the non-inlined, non-templated member // functions of the QTildeShowerHandler class. // #include "QTildeShowerHandler.h" #include "ThePEG/Interface/Deleted.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/EnumIO.h" #include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "Herwig/PDF/MPIPDF.h" #include "Herwig/PDF/MinBiasPDF.h" #include "Herwig/Shower/QTilde/Base/ShowerTree.h" #include "Herwig/Shower/QTilde/Base/HardTree.h" #include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.h" #include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/Shower/QTilde/Base/ShowerVertex.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "ThePEG/PDF/PartonExtractor.h" #include "Herwig/Shower/RealEmissionProcess.h" #include "Herwig/Shower/QTilde/Kinematics/FS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/QTilde/Kinematics/IS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/QTilde/Kinematics/Decay_QTildeShowerKinematics1to2.h" #include "Herwig/MatrixElement/MEMinBias.h" using namespace Herwig; bool QTildeShowerHandler::_hardEmissionWarn = true; bool QTildeShowerHandler::_missingTruncWarn = true; QTildeShowerHandler::QTildeShowerHandler() : _maxtry(100), _meCorrMode(1), _evolutionScheme(1), _hardVetoReadOption(false), _iptrms(ZERO), _beta(0.), _gamma(ZERO), _iptmax(), _limitEmissions(0), _initialenhance(1.), _finalenhance(1.), _nReWeight(100), _reWeight(false), interaction_(ShowerInteraction::ALL), _trunc_Mode(true), _hardEmission(1), _softOpt(2), _hardPOWHEG(false), muPt(ZERO) {} -QTildeShowerHandler::~QTildeShowerHandler() {} - IBPtr QTildeShowerHandler::clone() const { return new_ptr(*this); } IBPtr QTildeShowerHandler::fullclone() const { return new_ptr(*this); } void QTildeShowerHandler::persistentOutput(PersistentOStream & os) const { os << _splittingGenerator << _maxtry << _meCorrMode << _hardVetoReadOption << _limitEmissions << _softOpt << _hardPOWHEG << ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV) << _vetoes << _fullShowerVetoes << _nReWeight << _reWeight << _trunc_Mode << _hardEmission << _evolutionScheme << ounit(muPt,GeV) << oenum(interaction_) << _reconstructor << _partnerfinder; } void QTildeShowerHandler::persistentInput(PersistentIStream & is, int) { is >> _splittingGenerator >> _maxtry >> _meCorrMode >> _hardVetoReadOption >> _limitEmissions >> _softOpt >> _hardPOWHEG >> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV) >> _vetoes >> _fullShowerVetoes >> _nReWeight >> _reWeight >> _trunc_Mode >> _hardEmission >> _evolutionScheme >> iunit(muPt,GeV) >> ienum(interaction_) >> _reconstructor >> _partnerfinder; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigQTildeShowerHandler("Herwig::QTildeShowerHandler", "HwShower.so"); void QTildeShowerHandler::Init() { static ClassDocumentation documentation ("TheQTildeShowerHandler class is the main class" " for the angular-ordered parton shower", "The Shower evolution was performed using an algorithm described in " "\\cite{Bahr:2008pv,Marchesini:1983bm,Marchesini:1987cf,Gieseke:2003rz,Masouminia:2021kne}.", // "%\\cite{Marchesini:1983bm}\n" "\\bibitem{Marchesini:1983bm}\n" " G.~Marchesini and B.~R.~Webber,\n" " ``Simulation Of QCD Jets Including Soft Gluon Interference,''\n" " Nucl.\\ Phys.\\ B {\\bf 238}, 1 (1984).\n" " %%CITATION = NUPHA,B238,1;%%\n" // "%\\cite{Marchesini:1987cf}\n" "\\bibitem{Marchesini:1987cf}\n" " G.~Marchesini and B.~R.~Webber,\n" " ``Monte Carlo Simulation of General Hard Processes with Coherent QCD\n" " Radiation,''\n" " Nucl.\\ Phys.\\ B {\\bf 310}, 461 (1988).\n" " %%CITATION = NUPHA,B310,461;%%\n" // "%\\cite{Gieseke:2003rz}\n" "\\bibitem{Gieseke:2003rz}\n" " S.~Gieseke, P.~Stephens and B.~Webber,\n" " ``New formalism for QCD parton showers,''\n" " JHEP {\\bf 0312}, 045 (2003)\n" " [arXiv:hep-ph/0310083].\n" " %%CITATION = JHEPA,0312,045;%%\n" // "%\\cite{Masouminia:2021kne}\n" "\\bibitem{Masouminia:2021kne}\n" " M.~R.~Masouminia and P.~Richardson,\n" " ``Implementation of angularly ordered electroweak parton shower in Herwig 7,''\n" " JHEP {\\bf 04}, 112 (2022)\n" " [arXiv:2108.10817 [hep-ph].\n" " %%CITATION = JHEP,04,112;%%\n" ); static Reference interfaceSplitGen("SplittingGenerator", "A reference to the SplittingGenerator object", &Herwig::QTildeShowerHandler::_splittingGenerator, false, false, true, false); static Parameter interfaceMaxTry ("MaxTry", "The maximum number of attempts to generate the shower from a" " particular ShowerTree", &QTildeShowerHandler::_maxtry, 100, 1, 100000, false, false, Interface::limited); static Parameter interfaceNReWeight ("NReWeight", "The number of attempts for the shower when reweighting", &QTildeShowerHandler::_nReWeight, 100, 10, 10000, false, false, Interface::limited); static Switch ifaceMECorrMode ("MECorrMode", "Choice of the ME Correction Mode", &QTildeShowerHandler::_meCorrMode, 1, false, false); static SwitchOption on (ifaceMECorrMode,"HardPlusSoft","hard+soft on", 1); static SwitchOption hard (ifaceMECorrMode,"Hard","only hard on", 2); static SwitchOption soft (ifaceMECorrMode,"Soft","only soft on", 3); static Switch ifaceHardVetoReadOption ("HardVetoReadOption", "Apply read-in scale veto to all collisions or just the primary one?", &QTildeShowerHandler::_hardVetoReadOption, false, false, false); static SwitchOption AllCollisions (ifaceHardVetoReadOption, "AllCollisions", "Read-in pT veto applied to primary and secondary collisions.", false); static SwitchOption PrimaryCollision (ifaceHardVetoReadOption, "PrimaryCollision", "Read-in pT veto applied to primary but not secondary collisions.", true); static Parameter ifaceiptrms ("IntrinsicPtGaussian", "RMS of intrinsic pT of Gaussian distribution:\n" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &QTildeShowerHandler::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV, false, false, Interface::limited); static Parameter ifacebeta ("IntrinsicPtBeta", "Proportion of inverse quadratic distribution in generating intrinsic pT.\n" "(1-Beta) is the proportion of Gaussian distribution", &QTildeShowerHandler::_beta, 0, 0, 1, false, false, Interface::limited); static Parameter ifacegamma ("IntrinsicPtGamma", "Parameter for inverse quadratic:\n" "2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))", &QTildeShowerHandler::_gamma,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static Parameter ifaceiptmax ("IntrinsicPtIptmax", "Upper bound on intrinsic pT for inverse quadratic", &QTildeShowerHandler::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static RefVector ifaceVetoes ("Vetoes", "The vetoes to be checked during showering", &QTildeShowerHandler::_vetoes, -1, false,false,true,true,false); static RefVector interfaceFullShowerVetoes ("FullShowerVetoes", "The vetos to be appliede on the full final state of the shower", &QTildeShowerHandler::_fullShowerVetoes, -1, false, false, true, false, false); static Switch interfaceLimitEmissions ("LimitEmissions", "Limit the number and type of emissions for testing", &QTildeShowerHandler::_limitEmissions, 0, false, false); static SwitchOption interfaceLimitEmissionsNoLimit (interfaceLimitEmissions, "NoLimit", "Allow an arbitrary number of emissions", 0); static SwitchOption interfaceLimitEmissionsOneInitialStateEmission (interfaceLimitEmissions, "OneInitialStateEmission", "Allow one emission in the initial state and none in the final state", 1); static SwitchOption interfaceLimitEmissionsOneFinalStateEmission (interfaceLimitEmissions, "OneFinalStateEmission", "Allow one emission in the final state and none in the initial state", 2); static SwitchOption interfaceLimitEmissionsHardOnly (interfaceLimitEmissions, "HardOnly", "Only allow radiation from the hard ME correction", 3); static SwitchOption interfaceLimitEmissionsOneEmission (interfaceLimitEmissions, "OneEmission", "Allow one emission in either the final state or initial state, but not both", 4); static Switch interfaceTruncMode ("TruncatedShower", "Include the truncated shower?", &QTildeShowerHandler::_trunc_Mode, 1, false, false); static SwitchOption interfaceTruncMode0 (interfaceTruncMode,"No","Truncated Shower is OFF", 0); static SwitchOption interfaceTruncMode1 (interfaceTruncMode,"Yes","Truncated Shower is ON", 1); static Switch interfaceHardEmission ("HardEmission", "Whether to use ME corrections or POWHEG for the hardest emission", &QTildeShowerHandler::_hardEmission, 0, false, false); static SwitchOption interfaceHardEmissionNone (interfaceHardEmission, "None", "No Corrections", 0); static SwitchOption interfaceHardEmissionMECorrection (interfaceHardEmission, "MECorrection", "Old fashioned ME correction", 1); static SwitchOption interfaceHardEmissionPOWHEG (interfaceHardEmission, "POWHEG", "Powheg style hard emission", 2); static Switch interfaceInteractions ("Interactions", "The interactions to be used in the shower", &QTildeShowerHandler::interaction_, ShowerInteraction::ALL, false, false); static SwitchOption interfaceInteractionsQCD (interfaceInteractions, "QCD", "Only QCD radiation", ShowerInteraction::QCD); static SwitchOption interfaceInteractionsQED (interfaceInteractions, "QED", "Only QEd radiation", ShowerInteraction::QED); static SwitchOption interfaceInteractionEWOnly (interfaceInteractions, "EWOnly", "Only EW", ShowerInteraction::EW); static SwitchOption interfaceInteractionQEDQCD (interfaceInteractions, "QEDQCD", "QED and QCD", ShowerInteraction::QEDQCD); static SwitchOption interfaceInteractionALL (interfaceInteractions, "ALL", "QED, QCD and EW", ShowerInteraction::ALL); static Deleted delReconstructionOption ("ReconstructionOption", "The old reconstruction option switch has been replaced with" " the new EvolutionScheme switch, see arXiv:1904.11866 for details"); static Switch interfaceEvolutionScheme ("EvolutionScheme", "The scheme to interpret the evolution variable in the case of multple emission.", &QTildeShowerHandler::_evolutionScheme, 1, false, false); static SwitchOption interfaceEvolutionSchemepT (interfaceEvolutionScheme, "pT", "pT scheme", 0); static SwitchOption interfaceEvolutionSchemeDotProduct (interfaceEvolutionScheme, "DotProduct", "Dot-product scheme", 1); static SwitchOption interfaceEvolutionSchemeQ2 (interfaceEvolutionScheme, "Q2", "Q2 scheme", 2); static Switch interfaceSoftCorrelations ("SoftCorrelations", "Option for the treatment of soft correlations in the parton shower", &QTildeShowerHandler::_softOpt, 2, false, false); static SwitchOption interfaceSoftCorrelationsNone (interfaceSoftCorrelations, "No", "No soft correlations", 0); static SwitchOption interfaceSoftCorrelationsFull (interfaceSoftCorrelations, "Full", "Use the full eikonal", 1); static SwitchOption interfaceSoftCorrelationsSingular (interfaceSoftCorrelations, "Singular", "Use original Webber-Marchisini form", 2); static Switch interfaceHardPOWHEG ("HardPOWHEG", "Treatment of powheg emissions which are too hard to have a shower interpretation", &QTildeShowerHandler::_hardPOWHEG, false, false, false); static SwitchOption interfaceHardPOWHEGAsShower (interfaceHardPOWHEG, "AsShower", "Still interpret as shower emissions", false); static SwitchOption interfaceHardPOWHEGRealEmission (interfaceHardPOWHEG, "RealEmission", "Generate shower from the real emmission configuration", true); static Reference interfaceKinematicsReconstructor ("KinematicsReconstructor", "Reference to the KinematicsReconstructor object", &QTildeShowerHandler::_reconstructor, false, false, true, false, false); static Reference interfacePartnerFinder ("PartnerFinder", "Reference to the PartnerFinder object", &QTildeShowerHandler::_partnerfinder, false, false, true, false, false); } tPPair QTildeShowerHandler::cascade(tSubProPtr sub, XCPtr xcomb) { // use me for reference in tex file etc useMe(); prepareCascade(sub); // set things up in the base class resetWeights(); hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); // start of the try block for the whole showering process unsigned int countFailures=0; while (countFailuresoutgoing().begin(), currentSubProcess()->outgoing().end()), hard,decay); ShowerTree::constructTrees(hard_,decay_,hard,decay); // if no hard process if(!hard_) throw Exception() << "Shower starting with a decay" << "is not implemented" << Exception::runerror; // perform the shower for the hard process showerHardProcess(hard_,xcomb); done_.push_back(hard_); hard_->updateAfterShower(decay_); // if no decaying particles to shower break out of the loop if(decay_.empty()) break; // shower the decay products while(!decay_.empty()) { // find particle whose production process has been showered ShowerDecayMap::iterator dit = decay_.begin(); while(!dit->second->parent()->hasShowered() && dit!=decay_.end()) ++dit; assert(dit!=decay_.end()); // get the particle ShowerTreePtr decayingTree = dit->second; // remove it from the multimap decay_.erase(dit); // make sure the particle has been decayed QTildeShowerHandler::decay(decayingTree,decay_); // now shower the decay showerDecay(decayingTree); done_.push_back(decayingTree); decayingTree->updateAfterShower(decay_); } // suceeded break out of the loop break; } catch (KinematicsReconstructionVeto) { resetWeights(); ++countFailures; } catch ( ... ) { hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); throw; } } // if loop exited because of too many tries, throw event away if (countFailures >= maxtry()) { resetWeights(); hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); throw Exception() << "Too many tries for main while loop " << "in QTildeShowerHandler::cascade()." << Exception::eventerror; } //enter the particles in the event record fillEventRecord(); // clear storage hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); // non hadronic case return if (!isResolvedHadron(incomingBeams().first ) && !isResolvedHadron(incomingBeams().second) ) return incomingBeams(); // remake the remnants (needs to be after the colours are sorted // out in the insertion into the event record) if ( firstInteraction() ) return remakeRemnant(sub->incoming()); //Return the new pair of incoming partons. remakeRemnant is not //necessary here, because the secondary interactions are not yet //connected to the remnants. return make_pair(findFirstParton(sub->incoming().first ), findFirstParton(sub->incoming().second)); } void QTildeShowerHandler::fillEventRecord() { // create a new step StepPtr pstep = newStep(); assert(!done_.empty()); assert(done_[0]->isHard()); // insert the steps for(unsigned int ix=0;ixfillEventRecord(pstep,doISR(),doFSR()); } } HardTreePtr QTildeShowerHandler::generateCKKW(ShowerTreePtr ) const { return HardTreePtr(); } void QTildeShowerHandler::doinit() { ShowerHandler::doinit(); // check on the reweighting for(unsigned int ix=0;ix<_fullShowerVetoes.size();++ix) { if(_fullShowerVetoes[ix]->behaviour()==1) { _reWeight = true; break; } } if(_reWeight && maximumTries()<_nReWeight) { throw Exception() << "Reweight being performed in the shower but the number of attempts for the" << "shower is less than that for the reweighting.\n" << "Maximum number of attempt for the shower " << fullName() << ":MaxTry is " << maximumTries() << "\nand for reweighting is " << fullName() << ":NReWeight is " << _nReWeight << "\n" << "we recommend the number of attempts is 10 times the number for reweighting\n" << Exception::runerror; } ShowerTree::_vmin2 = vMin(); ShowerTree::_spaceTime = includeSpaceTime(); } void QTildeShowerHandler::doinitrun() { ShowerHandler::doinitrun(); ShowerTree::_vmin2 = vMin(); ShowerTree::_spaceTime = includeSpaceTime(); } void QTildeShowerHandler::generateIntrinsicpT(vector particlesToShower) { if ( !ipTon() || !doISR() ) return; // don't do anything for the moment for secondary scatters if( !firstInteraction() ) return; // generate intrinsic pT for(unsigned int ix=0;ixprogenitor()->isFinalState()) continue; if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue; Energy ipt; if(UseRandom::rnd() > _beta) { ipt=_iptrms*sqrt(-log(UseRandom::rnd())); } else { ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.); } pair pt = make_pair(ipt,UseRandom::rnd(Constants::twopi)); _intrinsic[particlesToShower[ix]] = pt; } } void QTildeShowerHandler::setupMaximumScales(const vector & p, XCPtr xcomb) { // let POWHEG events radiate freely if(_hardEmission==2&&hardTree()) { vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy); return; } // return if no vetos if (!restrictPhasespace()) return; // find out if hard partonic subprocess. bool isPartonic(false); map::const_iterator cit = _currenttree->incomingLines().begin(); Lorentz5Momentum pcm; for(; cit!=currentTree()->incomingLines().end(); ++cit) { pcm += cit->first->progenitor()->momentum(); isPartonic |= cit->first->progenitor()->coloured(); } // find minimum pt from hard process, the maximum pt from all outgoing // coloured lines (this is simpler and more general than // 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will // be transverse mass. Energy ptmax = generator()->maximumCMEnergy(); // general case calculate the scale if ( !hardScaleIsMuF() || (hardVetoReadOption()&&!firstInteraction()) ) { // scattering process if(currentTree()->isHard()) { assert(xcomb); // coloured incoming particles if (isPartonic) { map::const_iterator cjt = currentTree()->outgoingLines().begin(); for(; cjt!=currentTree()->outgoingLines().end(); ++cjt) { if (cjt->first->progenitor()->coloured()) ptmax = min(ptmax,cjt->first->progenitor()->momentum().mt()); } } if (ptmax == generator()->maximumCMEnergy() ) ptmax = pcm.m(); if(hardScaleIsMuF()&&hardVetoReadOption()&& !firstInteraction()) { ptmax=min(ptmax,sqrt(xcomb->lastShowerScale())); } } // decay, incoming() is the decaying particle. else { ptmax = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } // hepeup.SCALUP is written into the lastXComb by the // LesHouchesReader itself - use this by user's choice. // Can be more general than this. else { if(currentTree()->isHard()) { assert(xcomb); ptmax = sqrt( xcomb->lastShowerScale() ); } else { ptmax = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } ptmax *= hardScaleFactor(); // set maxHardPt for all progenitors. For partonic processes this // is now the max pt in the FS, for non-partonic processes or // processes with no coloured FS the invariant mass of the IS vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax); } void QTildeShowerHandler::setupHardScales(const vector & p, XCPtr xcomb) { if ( hardScaleIsMuF() && (!hardVetoReadOption() || firstInteraction()) ) { Energy hardScale = ZERO; if(currentTree()->isHard()) { assert(xcomb); hardScale = sqrt( xcomb->lastShowerScale() ); } else { hardScale = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } hardScale *= hardScaleFactor(); vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->hardScale(hardScale); muPt = hardScale; } } void QTildeShowerHandler::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) { _hardme = HwMEBasePtr(); // extract the matrix element tStdXCombPtr lastXC = dynamic_ptr_cast(xcomb); if(lastXC) { _hardme = dynamic_ptr_cast(lastXC->matrixElement()); } _decayme = HwDecayerBasePtr(); // set the current tree currentTree(hard); hardTree(HardTreePtr()); // work out the type of event currentTree()->xcombPtr(dynamic_ptr_cast(xcomb)); currentTree()->identifyEventType(); checkFlags(); // generate the showering doShowering(true,xcomb); } RealEmissionProcessPtr QTildeShowerHandler::hardMatrixElementCorrection(bool hard) { // set the initial enhancement factors for the soft correction _initialenhance = 1.; _finalenhance = 1.; // see if we can get the correction from the matrix element // or decayer RealEmissionProcessPtr real; if(hard) { if(_hardme&&_hardme->hasMECorrection()) { _hardme->initializeMECorrection(_currenttree->perturbativeProcess(), _initialenhance,_finalenhance); if(hardMEC()) real = _hardme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess()); } } else { if(_decayme&&_decayme->hasMECorrection()) { _decayme->initializeMECorrection(_currenttree->perturbativeProcess(), _initialenhance,_finalenhance); if(hardMEC()) real = _decayme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess()); } } return real; } ShowerParticleVector QTildeShowerHandler::createTimeLikeChildren(tShowerParticlePtr, IdList ids) { // Create the ShowerParticle objects for the two children of // the emitting particle; set the parent/child relationship // if same as definition create particles, otherwise create cc ShowerParticleVector children; for(unsigned int ix=0;ix<2;++ix) { children.push_back(new_ptr(ShowerParticle(ids[ix+1],true))); if(children[ix]->id()==_progenitor->id()&&!ids[ix+1]->stable()&&abs(ids[ix+1]->id())!=ParticleID::tauminus) children[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass())); else children[ix]->set5Momentum(Lorentz5Momentum(ids[ix+1]->mass())); } return children; } bool QTildeShowerHandler::timeLikeShower(tShowerParticlePtr particle, ShowerInteraction type, Branching fb, bool first) { // don't do anything if not needed if(_limitEmissions == 1 || hardOnly() || ( _limitEmissions == 2 && _nfs != 0) || ( _limitEmissions == 4 && _nfs + _nis != 0) ) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } // generate the emission ShowerParticleVector children; // generate the emission if(!fb.kinematics) fb = selectTimeLikeBranching(particle,type,HardBranchingPtr()); // no emission, return if(!fb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } Branching fc[2] = {Branching(),Branching()}; assert(fb.kinematics); // has emitted // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); // check highest pT if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the children children = createTimeLikeChildren(particle,fb.ids); // update the children particle->showerKinematics()-> updateChildren(particle, children,_evolutionScheme,fb.type); // update number of emissions ++_nfs; if(_limitEmissions!=0) { if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } // select branchings for children fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); // shower the first particle if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); particle->showerKinematics()->updateParent(particle, children,_evolutionScheme,fb.type); // branching has happened if(first&&!children.empty()) particle->showerKinematics()->resetChildren(particle,children); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } bool QTildeShowerHandler::spaceLikeShower(tShowerParticlePtr particle, PPtr beam, ShowerInteraction type) { //using the pdf's associated with the ShowerHandler assures, that //modified pdf's are used for the secondary interactions via //CascadeHandler::resetPDFs(...) tcPDFPtr pdf; if(beam == incomingBeams().first) pdf = firstPDF().pdf(); if(beam == incomingBeams().second) pdf = secondPDF().pdf(); Energy freeze = pdfFreezingScale(); // don't do anything if not needed if(_limitEmissions == 2 || hardOnly() || ( _limitEmissions == 1 && _nis != 0 ) || ( _limitEmissions == 4 && _nis + _nfs != 0 ) ) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } Branching bb; // generate branching while (true) { bb=_splittingGenerator->chooseBackwardBranching(*particle,beam, _initialenhance, _beam,type, pdf,freeze); // return if no emission if(!bb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } // if not vetoed break if(!spaceLikeVetoed(bb,particle)) break; // otherwise reset scale and continue particle->vetoEmission(bb.type,bb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); } // assign the splitting function and shower kinematics particle->showerKinematics(bb.kinematics); if(bb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(bb.kinematics->pT()); // For the time being we are considering only 1->2 branching // particles as in Sudakov form factor tcPDPtr part[2]={bb.ids[0],bb.ids[2]}; // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr(ShowerParticle(part[0],false)); ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true)); ShowerParticleVector theChildren; theChildren.push_back(particle); theChildren.push_back(otherChild); //this updates the evolution scale particle->showerKinematics()-> updateParent(newParent, theChildren,_evolutionScheme,bb.type); // update the history if needed _currenttree->updateInitialStateShowerProduct(_progenitor,newParent); _currenttree->addInitialStateBranching(particle,newParent,otherChild); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower ++_nis; bool emitted = _limitEmissions==0 ? spaceLikeShower(newParent,beam,type) : false; if(newParent->spinInfo()) newParent->spinInfo()->develop(); // now reconstruct the momentum if(!emitted) { if(_intrinsic.find(_progenitor)==_intrinsic.end()) { bb.kinematics->updateLast(newParent,ZERO,ZERO); } else { pair kt=_intrinsic[_progenitor]; bb.kinematics->updateLast(newParent, kt.first*cos(kt.second), kt.first*sin(kt.second)); } } particle->showerKinematics()-> updateChildren(newParent, theChildren,_evolutionScheme,bb.type); if(_limitEmissions!=0) { if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } // perform the shower of the final-state particle timeLikeShower(otherChild,type,Branching(),true); particle->showerKinematics()-> updateChildren(newParent, theChildren,_evolutionScheme,bb.type); updateHistory(otherChild); if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop(); // return the emitted if(particle->spinInfo()) particle->spinInfo()->develop(); if(!theChildren.empty()){ particle->showerKinematics()->resetChildren(newParent,theChildren); } return true; } void QTildeShowerHandler::showerDecay(ShowerTreePtr decay) { // work out the type of event currentTree()->xcombPtr(StdXCombPtr()); currentTree()->identifyEventType(); _decayme = HwDecayerBasePtr(); _hardme = HwMEBasePtr(); // find the decayer // try the normal way if possible tDMPtr dm = decay->incomingLines().begin()->first->original() ->decayMode(); if(!dm) dm = decay->incomingLines().begin()->first->copy() ->decayMode(); if(!dm) dm = decay->incomingLines().begin()->first->progenitor()->decayMode(); // otherwise make a string and look it up if(!dm) { string tag = decay->incomingLines().begin()->first->original()->dataPtr()->name() + "->"; OrderedParticles outgoing; for(map::const_iterator it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) { if(abs(decay->incomingLines().begin()->first->original()->id()) == ParticleID::t && abs(it->first->original()->id())==ParticleID::Wplus && decay->treelinks().size() == 1) { ShowerTreePtr Wtree = decay->treelinks().begin()->first; for(map::const_iterator it2=Wtree->outgoingLines().begin();it2!=Wtree->outgoingLines().end();++it2) { outgoing.insert(it2->first->original()->dataPtr()); } } else { outgoing.insert(it->first->original()->dataPtr()); } } for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) { if(it!=outgoing.begin()) tag += ","; tag +=(**it).name(); } tag += ";"; dm = findDecayMode(tag); } if(dm) _decayme = dynamic_ptr_cast(dm->decayer()); // set the ShowerTree to be showered currentTree(decay); decay->applyTransforms(); hardTree(HardTreePtr()); // generate the showering doShowering(false,XCPtr()); // if no vetos // force calculation of spin correlations SpinPtr spInfo = decay->incomingLines().begin()->first->progenitor()->spinInfo(); if(spInfo) { if(!spInfo->developed()) spInfo->needsUpdate(); spInfo->develop(); } } bool QTildeShowerHandler::spaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, Branching fb) { // don't do anything if not needed if(_limitEmissions == 1 || hardOnly() || ( _limitEmissions == 3 && _nis != 0) || ( _limitEmissions == 4 && _nfs + _nis != 0) ) { return false; } // generate the emission ShowerParticleVector children; // generate the emission if(!fb.kinematics) fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type, HardBranchingPtr()); // no emission, return if(!fb.kinematics) return false; Branching fc[2]; if(particle->virtualMass()==ZERO) particle->virtualMass(_progenitor->progenitor()->mass()); fc[0] = Branching(); fc[1] = Branching(); assert(fb.kinematics); // has emitted // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the ShowerParticle objects for the two children children = createTimeLikeChildren(particle,fb.ids); // updateChildren the children particle->showerKinematics()-> updateChildren(particle, children,_evolutionScheme,fb.type); // select branchings for children fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass, type,HardBranchingPtr()); fc[1] = selectTimeLikeBranching (children[1],type,HardBranchingPtr()); // old default ++_nis; // shower the first particle _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); _currenttree->addInitialStateBranching(particle,children[0],children[1]); if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); updateHistory(children[1]); // TODO NEED AN UPDATE HERE FOR RECONOPT!=0 // branching has happened return true; } vector QTildeShowerHandler::setupShower(bool hard) { RealEmissionProcessPtr real; // generate hard me if needed if(_hardEmission==1) { real = hardMatrixElementCorrection(hard); if(real&&!real->outgoing().empty()) setupMECorrection(real); } // generate POWHEG hard emission if needed else if(_hardEmission==2) hardestEmission(hard); // set the initial colour partners setEvolutionPartners(hard,interaction_,false); // get the particles to be showered vector particlesToShower = currentTree()->extractProgenitors(); // return the answer return particlesToShower; } void QTildeShowerHandler::setEvolutionPartners(bool hard,ShowerInteraction type, bool clear) { // match the particles in the ShowerTree and hardTree if(hardTree() && !hardTree()->connect(currentTree())) throw Exception() << "Can't match trees in " << "QTildeShowerHandler::setEvolutionPartners()" << Exception::eventerror; // extract the progenitors vector particles = currentTree()->extractProgenitorParticles(); // clear the partners if needed if(clear) { for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); particles[ix]->clearPartners(); } } // sort out the colour partners if(hardTree()) { // find the partner for(unsigned int ix=0;ixparticles()[particles[ix]]->branchingParticle()->partner(); if(!partner) continue; for(map::const_iterator it=hardTree()->particles().begin(); it!=hardTree()->particles().end();++it) { if(it->second->branchingParticle()==partner) { particles[ix]->partner(it->first); break; } } if(!particles[ix]->partner()) throw Exception() << "Can't match partners in " << "QTildeShowerHandler::setEvolutionPartners()" << Exception::eventerror; } } // Set the initial evolution scales partnerFinder()-> setInitialEvolutionScales(particles,!hard,interaction_,!_hardtree); if(hardTree() && _hardPOWHEG) { bool tooHard=false; map::const_iterator eit=hardTree()->particles().end(); for(unsigned int ix=0;ix::const_iterator mit = hardTree()->particles().find(particles[ix]); Energy hardScale(ZERO); ShowerPartnerType type(ShowerPartnerType::Undefined); // final-state if(particles[ix]->isFinalState()) { if(mit!= eit && !mit->second->children().empty()) { hardScale = mit->second->scale(); type = mit->second->type(); } } // initial-state else { if(mit!= eit && mit->second->parent()) { hardScale = mit->second->parent()->scale(); type = mit->second->parent()->type(); } } if(type!=ShowerPartnerType::Undefined) { if(type==ShowerPartnerType::QED) { tooHard |= particles[ix]->scales().QED_noAOscales().QCD_c_noAOscales().QCD_ac_noAOscales().EWchildren().empty()) { ShowerParticleVector theChildren; for(unsigned int ix=0;ixchildren().size();++ix) { ShowerParticlePtr part = dynamic_ptr_cast (particle->children()[ix]); theChildren.push_back(part); } // update the history if needed if(particle==_currenttree->getFinalStateShowerProduct(_progenitor)) _currenttree->updateFinalStateShowerProduct(_progenitor, particle,theChildren); _currenttree->addFinalStateBranching(particle,theChildren); for(unsigned int ix=0;ixprogenitor()->partner()) return false; progenitor()->progenitor()->initializeFinalState(); if(hardTree()) { map::const_iterator eit=hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && !mit->second->children().empty() ) { bool output=truncatedTimeLikeShower(progenitor()->progenitor(), mit->second ,type,Branching(),true); if(output) updateHistory(progenitor()->progenitor()); return output; } } // do the shower bool output = hardOnly() ? false : timeLikeShower(progenitor()->progenitor() ,type,Branching(),true) ; if(output) updateHistory(progenitor()->progenitor()); return output; } bool QTildeShowerHandler::startSpaceLikeShower(PPtr parent, ShowerInteraction type) { // initialise the basis vectors if(!progenitor()->progenitor()->partner()) return false; progenitor()->progenitor()->initializeInitialState(parent); if(hardTree()) { map::const_iterator eit =hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && mit->second->parent() ) { return truncatedSpaceLikeShower( progenitor()->progenitor(), parent, mit->second->parent(), type ); } } // perform the shower return hardOnly() ? false : spaceLikeShower(progenitor()->progenitor(),parent,type); } bool QTildeShowerHandler:: startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction type) { // set up the particle basis vectors if(!progenitor()->progenitor()->partner()) return false; progenitor()->progenitor()->initializeDecay(); if(hardTree()) { map::const_iterator eit =hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && mit->second->parent() ) { HardBranchingPtr branch=mit->second; while(branch->parent()) branch=branch->parent(); return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxScales, minimumMass, branch ,type, Branching()); } } // perform the shower return hardOnly() ? false : spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type,Branching()); } bool QTildeShowerHandler::timeLikeVetoed(const Branching & fb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(fb.type); // check whether emission was harder than largest pt of hard subprocess if ( restrictPhasespace() && fb.kinematics->pT() > _progenitor->maxHardPt() ) return true; // soft matrix element correction veto if( softMEC()) { if(_hardme && _hardme->hasMECorrection()) { if(_hardme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } else if(_decayme && _decayme->hasMECorrection()) { if(_decayme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } } // veto on maximum pt if(fb.kinematics->pT()>_progenitor->maximumpT(type)) return true; // general vetos if (fb.kinematics && !_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoTimeLike(_progenitor,particle,fb,currentTree()); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if(vetoed) return true; } if ( firstInteraction() && profileScales() ) { double weight = profileScales()-> hardScaleProfile(_progenitor->hardScale(),fb.kinematics->pT()); if ( UseRandom::rnd() > weight ) return true; } return false; } bool QTildeShowerHandler::spaceLikeVetoed(const Branching & bb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(bb.type); // check whether emission was harder than largest pt of hard subprocess if (restrictPhasespace() && bb.kinematics->pT() > _progenitor->maxHardPt()) return true; // apply the soft correction if( softMEC() && _hardme && _hardme->hasMECorrection() ) { if(_hardme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), bb.ids, bb.kinematics->z(), bb.kinematics->scale(), bb.kinematics->pT())) return true; } // the more general vetos // check vs max pt for the shower if(bb.kinematics->pT()>_progenitor->maximumpT(type)) return true; if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,bb,currentTree()); switch ((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if (vetoed) return true; } if ( firstInteraction() && profileScales() ) { double weight = profileScales()-> hardScaleProfile(_progenitor->hardScale(),bb.kinematics->pT()); if ( UseRandom::rnd() > weight ) return true; } return false; } bool QTildeShowerHandler::spaceLikeDecayVetoed( const Branching & fb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction type = convertInteraction(fb.type); // apply the soft correction if( softMEC() && _decayme && _decayme->hasMECorrection() ) { if(_decayme->softMatrixElementVeto(particle, _progenitor->progenitor(), particle->isFinalState(), _progenitor->highestpT(), fb.ids, fb.kinematics->z(), fb.kinematics->scale(), fb.kinematics->pT())) return true; } // veto on hardest pt in the shower if(fb.kinematics->pT()> _progenitor->maximumpT(type)) return true; // general vetos if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,fb,currentTree()); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } if (vetoed) return true; } } return false; } void QTildeShowerHandler::hardestEmission(bool hard) { HardTreePtr ISRTree; // internal POWHEG in production or decay if( (( _hardme && _hardme->hasPOWHEGCorrection()!=0 ) || ( _decayme && _decayme->hasPOWHEGCorrection()!=0 ) ) ) { RealEmissionProcessPtr real; unsigned int type(0); // production if(_hardme) { assert(hard); real = _hardme->generateHardest( currentTree()->perturbativeProcess(), interaction_); type = _hardme->hasPOWHEGCorrection(); } // decay else { assert(!hard); real = _decayme->generateHardest( currentTree()->perturbativeProcess() ); type = _decayme->hasPOWHEGCorrection(); } if(real) { // set up ther hard tree if(!real->outgoing().empty()) _hardtree = new_ptr(HardTree(real)); // set up the vetos currentTree()->setVetoes(real->pT(),type); } // store initial state POWHEG radiation if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1) ISRTree = _hardtree; } else if (hard) { // Get minimum pT cutoff used in shower approximation Energy maxpt = 1.*GeV; if ( currentTree()->showerApproximation() ) { int colouredIn = 0; int colouredOut = 0; for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if( it->second->coloured() ) ++colouredOut; } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = currentTree()->incomingLines().begin(); it != currentTree()->incomingLines().end(); ++it ) { if( it->second->coloured() ) ++colouredIn; } if ( currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->fiPtCut() && currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->iiPtCut() ) maxpt = currentTree()->showerApproximation()->ffPtCut(); else if ( colouredIn == 2 && colouredOut == 0 ) maxpt = currentTree()->showerApproximation()->iiPtCut(); else if ( colouredIn == 0 && colouredOut > 1 ) maxpt = currentTree()->showerApproximation()->ffPtCut(); else if ( colouredIn == 2 && colouredOut == 1 ) maxpt = min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()); else if ( colouredIn == 1 && colouredOut > 1 ) maxpt = min(currentTree()->showerApproximation()->ffPtCut(), currentTree()->showerApproximation()->fiPtCut()); else maxpt = min(min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()), currentTree()->showerApproximation()->ffPtCut()); } // Generate hardtree from born and real emission subprocesses _hardtree = generateCKKW(currentTree()); // Find transverse momentum of hardest emission if (_hardtree){ for(set::iterator it=_hardtree->branchings().begin(); it!=_hardtree->branchings().end();++it) { if ((*it)->parent() && (*it)->status()==HardBranching::Incoming) maxpt=(*it)->branchingParticle()->momentum().perp(); if ((*it)->children().size()==2 && (*it)->status()==HardBranching::Outgoing){ if ((*it)->branchingParticle()->id()!=21 && abs((*it)->branchingParticle()->id())>5 ){ if ((*it)->children()[0]->branchingParticle()->id()==21 || abs((*it)->children()[0]->branchingParticle()->id())<6) maxpt=(*it)->children()[0]->branchingParticle()->momentum().perp(); else if ((*it)->children()[1]->branchingParticle()->id()==21 || abs((*it)->children()[1]->branchingParticle()->id())<6) maxpt=(*it)->children()[1]->branchingParticle()->momentum().perp(); } else { if ( abs((*it)->branchingParticle()->id())<6){ if (abs((*it)->children()[0]->branchingParticle()->id())<6) maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); else maxpt = (*it)->children()[0]->branchingParticle()->momentum().perp(); } else maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); } } } } // Hardest (pt) emission should be the first powheg emission. maxpt=min(sqrt(lastXCombPtr()->lastShowerScale()),maxpt); // set maximum pT for subsequent emissions from S events if ( currentTree()->isPowhegSEvent() ) { for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT(maxpt, ShowerInteraction::QCD ); } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = currentTree()->incomingLines().begin(); it != currentTree()->incomingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT(maxpt, ShowerInteraction::QCD ); } } } else _hardtree = generateCKKW(currentTree()); // if hard me doesn't have a FSR powheg // correction use decay powheg correction if (_hardme && _hardme->hasPOWHEGCorrection()<2) { addFSRUsingDecayPOWHEG(ISRTree); } // connect the trees if(_hardtree) { connectTrees(currentTree(),_hardtree,hard); } } void QTildeShowerHandler::addFSRUsingDecayPOWHEG(HardTreePtr ISRTree) { // check for intermediate colour singlet resonance const ParticleVector inter = _hardme->subProcess()->intermediates(); if (inter.size()!=1 || inter[0]->momentum().m2()/GeV2 < 0 || inter[0]->dataPtr()->iColour()!=PDT::Colour0) { return; } // ignore cases where outgoing particles are not coloured map out = currentTree()->outgoingLines(); if (out.size() != 2 || out. begin()->second->dataPtr()->iColour()==PDT::Colour0 || out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) { return; } // look up decay mode tDMPtr dm; string tag; string inParticle = inter[0]->dataPtr()->name() + "->"; vector outParticles; outParticles.push_back(out.begin ()->first->progenitor()->dataPtr()->name()); outParticles.push_back(out.rbegin()->first->progenitor()->dataPtr()->name()); for (int it=0; it<2; ++it){ tag = inParticle + outParticles[it] + "," + outParticles[(it+1)%2] + ";"; dm = generator()->findDecayMode(tag); if(dm) break; } // get the decayer HwDecayerBasePtr decayer; if(dm) decayer = dynamic_ptr_cast(dm->decayer()); // check if decayer has a FSR POWHEG correction if (!decayer || decayer->hasPOWHEGCorrection()<2) { return; } // generate the hardest emission // create RealEmissionProcess PPtr in = new_ptr(*inter[0]); RealEmissionProcessPtr newProcess(new_ptr(RealEmissionProcess())); newProcess->bornIncoming().push_back(in); newProcess->bornOutgoing().push_back(out.begin ()->first->progenitor()); newProcess->bornOutgoing().push_back(out.rbegin()->first->progenitor()); // generate the FSR newProcess = decayer->generateHardest(newProcess); HardTreePtr FSRTree; if(newProcess) { // set up ther hard tree if(!newProcess->outgoing().empty()) FSRTree = new_ptr(HardTree(newProcess)); // set up the vetos currentTree()->setVetoes(newProcess->pT(),2); } if(!FSRTree) return; // if there is no ISRTree make _hardtree from FSRTree if (!ISRTree){ vector inBranch,hardBranch; for(map::const_iterator cit =currentTree()->incomingLines().begin(); cit!=currentTree()->incomingLines().end();++cit ) { inBranch.push_back(new_ptr(HardBranching(cit->second,SudakovPtr(), HardBranchingPtr(), HardBranching::Incoming))); inBranch.back()->beam(cit->first->original()->parents()[0]); hardBranch.push_back(inBranch.back()); } if(inBranch[0]->branchingParticle()->dataPtr()->coloured()) { inBranch[0]->colourPartner(inBranch[1]); inBranch[1]->colourPartner(inBranch[0]); } for(set::iterator it=FSRTree->branchings().begin(); it!=FSRTree->branchings().end();++it) { if((**it).branchingParticle()->id()!=in->id()) hardBranch.push_back(*it); } hardBranch[2]->colourPartner(hardBranch[3]); hardBranch[3]->colourPartner(hardBranch[2]); HardTreePtr newTree = new_ptr(HardTree(hardBranch,inBranch, ShowerInteraction::QCD)); _hardtree = newTree; } // Otherwise modify the ISRTree to include the emission in FSRTree else { vector FSROut, ISROut; set::iterator itFSR, itISR; // get outgoing particles for(itFSR =FSRTree->branchings().begin(); itFSR!=FSRTree->branchings().end();++itFSR){ if ((**itFSR).status()==HardBranching::Outgoing) FSROut.push_back((*itFSR)->branchingParticle()); } for(itISR =ISRTree->branchings().begin(); itISR!=ISRTree->branchings().end();++itISR){ if ((**itISR).status()==HardBranching::Outgoing) ISROut.push_back((*itISR)->branchingParticle()); } // find COM frame formed by outgoing particles LorentzRotation eventFrameFSR, eventFrameISR; eventFrameFSR = ((FSROut[0]->momentum()+FSROut[1]->momentum()).findBoostToCM()); eventFrameISR = ((ISROut[0]->momentum()+ISROut[1]->momentum()).findBoostToCM()); // find rotation between ISR and FSR frames int j=0; if (ISROut[0]->id()!=FSROut[0]->id()) j=1; eventFrameISR.rotateZ( (eventFrameFSR*FSROut[0]->momentum()).phi()- (eventFrameISR*ISROut[j]->momentum()).phi() ); eventFrameISR.rotateY( (eventFrameFSR*FSROut[0]->momentum()).theta()- (eventFrameISR*ISROut[j]->momentum()).theta() ); eventFrameISR.invert(); for (itFSR=FSRTree->branchings().begin(); itFSR!=FSRTree->branchings().end();++itFSR){ if ((**itFSR).branchingParticle()->id()==in->id()) continue; for (itISR =ISRTree->branchings().begin(); itISR!=ISRTree->branchings().end();++itISR){ if ((**itISR).status()==HardBranching::Incoming) continue; if ((**itFSR).branchingParticle()->id()== (**itISR).branchingParticle()->id()){ // rotate FSRTree particle to ISRTree event frame (**itISR).branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).branchingParticle()->momentum()); (**itISR).branchingParticle()->rescaleMass(); // add the children of the FSRTree particles to the ISRTree if(!(**itFSR).children().empty()){ (**itISR).addChild((**itFSR).children()[0]); (**itISR).addChild((**itFSR).children()[1]); // rotate momenta to ISRTree event frame (**itISR).children()[0]->branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).children()[0]->branchingParticle()->momentum()); (**itISR).children()[1]->branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).children()[1]->branchingParticle()->momentum()); } } } } _hardtree = ISRTree; } } bool QTildeShowerHandler::truncatedTimeLikeShower(tShowerParticlePtr particle, HardBranchingPtr branch, ShowerInteraction type, Branching fb, bool first) { // select a branching if we don't have one if(!fb.kinematics) fb = selectTimeLikeBranching(particle,type,branch); // must be an emission, the forced one it not a truncated one assert(fb.kinematics); ShowerParticleVector children; Branching fc[2] = {Branching(),Branching()}; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the children children = createTimeLikeChildren(particle,fb.ids); // update the children particle->showerKinematics()-> updateChildren(particle, children,_evolutionScheme,fb.type); // select branchings for children if(!fc[0].kinematics) { // select branching for first particle if(!fb.hard && fb.iout ==1 ) fc[0] = selectTimeLikeBranching(children[0],type,branch); else if(fb.hard && !branch->children()[0]->children().empty() ) fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); else fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); } // select branching for the second particle if(!fc[1].kinematics) { // select branching for first particle if(!fb.hard && fb.iout ==2 ) fc[1] = selectTimeLikeBranching(children[1],type,branch); else if(fb.hard && !branch->children()[1]->children().empty() ) fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); else fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); } // shower the first particle if(fc[0].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 1) truncatedTimeLikeShower(children[0],branch,type,fc[0],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 2) truncatedTimeLikeShower(children[1],branch,type,fc[1],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[1]->children().empty() ) truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false); else timeLikeShower(children[1],type,fc[1],false); } if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,_evolutionScheme,fb.type); if(first&&!children.empty()) particle->showerKinematics()->resetChildren(particle,children); if(particle->spinInfo()) particle->spinInfo()->develop(); // TODO NEED AN UPDATE HERE FOR RECONOPT!=0 ? return true; } bool QTildeShowerHandler::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam, HardBranchingPtr branch, ShowerInteraction type) { tcPDFPtr pdf; if(firstPDF().particle() == beamParticle()) pdf = firstPDF().pdf(); if(secondPDF().particle() == beamParticle()) pdf = secondPDF().pdf(); Energy freeze = pdfFreezingScale(); Branching bb; // parameters of the force branching double z(0.); HardBranchingPtr timelike; for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) { if( branch->children()[ix]->status() ==HardBranching::Outgoing) { timelike = branch->children()[ix]; } if( branch->children()[ix]->status() ==HardBranching::Incoming ) z = branch->children()[ix]->z(); } // generate truncated branching tcPDPtr part[2]; if(z>=0.&&z<=1.) { while (true) { if( !isTruncatedShowerON() || hardOnly() ) break; bb = splittingGenerator()->chooseBackwardBranching( *particle, beam, 1., beamParticle(), type , pdf,freeze); if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) { bb = Branching(); break; } // particles as in Sudakov form factor part[0] = bb.ids[0]; part[1] = bb.ids[2]; double zsplit = bb.kinematics->z(); // apply the vetos for the truncated shower // if doesn't carry most of momentum ShowerInteraction type2 = convertInteraction(bb.type); if(type2==branch->sudakov()->interactionType() && zsplit < 0.5) { particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } // others if( part[0]->id() != particle->id() || // if particle changes type bb.kinematics->pT() > progenitor()->maximumpT(type2) || // pt veto bb.kinematics->scale() < branch->scale()) { // angular ordering veto particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } // and those from the base class if(spaceLikeVetoed(bb,particle)) { particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } break; } } if( !bb.kinematics ) { //do the hard emission ShoKinPtr kinematics = new_ptr(IS_QTildeShowerKinematics1to2( branch->scale(), z, branch->phi(), branch->children()[0]->pT(), branch->sudakov() )); // assign the splitting function and shower kinematics particle->showerKinematics( kinematics ); if(kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(kinematics->pT()); // For the time being we are considering only 1->2 branching // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) ); ShowerParticlePtr otherChild = new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(), true, true ) ); ShowerParticleVector theChildren; theChildren.push_back( particle ); theChildren.push_back( otherChild ); particle->showerKinematics()-> updateParent( newParent, theChildren,_evolutionScheme, branch->type()); // update the history if needed currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); currentTree()->addInitialStateBranching( particle, newParent, otherChild ); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower bool emitted=false; if(!hardOnly()) { if( branch->parent() ) { emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type); } else { emitted = spaceLikeShower( newParent, beam , type); } } if( !emitted ) { if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { kinematics->updateLast( newParent, ZERO, ZERO ); } else { pair kt = intrinsicpT()[progenitor()]; kinematics->updateLast( newParent, kt.first*cos( kt.second ), kt.first*sin( kt.second ) ); } } particle->showerKinematics()-> updateChildren( newParent, theChildren,_evolutionScheme,bb.type); if(hardOnly()) return true; // perform the shower of the final-state particle if( timelike->children().empty() ) { timeLikeShower( otherChild , type,Branching(),true); } else { truncatedTimeLikeShower( otherChild, timelike , type,Branching(), true); } updateHistory(otherChild); // return the emitted return true; } // assign the splitting function and shower kinematics particle->showerKinematics( bb.kinematics ); if(bb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(bb.kinematics->pT()); // For the time being we are considering only 1->2 branching // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) ); ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) ); ShowerParticleVector theChildren; theChildren.push_back( particle ); theChildren.push_back( otherChild ); particle->showerKinematics()-> updateParent( newParent, theChildren,_evolutionScheme, bb.type); // update the history if needed currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); currentTree()->addInitialStateBranching( particle, newParent, otherChild ); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type); // now reconstruct the momentum if( !emitted ) { if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { bb.kinematics->updateLast( newParent, ZERO, ZERO ); } else { pair kt = intrinsicpT()[ progenitor() ]; bb.kinematics->updateLast( newParent, kt.first*cos( kt.second ), kt.first*sin( kt.second ) ); } } particle->showerKinematics()-> updateChildren( newParent, theChildren,_evolutionScheme, bb.type); // perform the shower of the final-state particle timeLikeShower( otherChild , type,Branching(),true); updateHistory(otherChild); // return the emitted return true; } bool QTildeShowerHandler:: truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass, HardBranchingPtr branch, ShowerInteraction type, Branching fb) { // select a branching if we don't have one if(!fb.kinematics) fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch); // must be an emission, the forced one it not a truncated one assert(fb.kinematics); ShowerParticleVector children; Branching fc[2]={Branching(),Branching()}; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the ShowerParticle objects for the two children children = createTimeLikeChildren(particle,fb.ids); // updateChildren the children particle->showerKinematics()-> updateChildren(particle, children,_evolutionScheme, fb.type); // select branchings for children if(!fc[0].kinematics) { if(children[0]->id()==particle->id()) { // select branching for first particle if(!fb.hard) fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type,branch); else if(fb.hard && ! branch->children()[0]->children().empty() ) fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, branch->children()[0]); else fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, HardBranchingPtr()); } else { // select branching for first particle if(fb.hard && !branch->children()[0]->children().empty() ) fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); else fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); } } // select branching for the second particle if(!fc[1].kinematics) { if(children[1]->id()==particle->id()) { // select branching for first particle if(!fb.hard) fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type,branch); else if(fb.hard && ! branch->children()[1]->children().empty() ) fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, branch->children()[1]); else fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, HardBranchingPtr()); } else { if(fb.hard && !branch->children()[1]->children().empty() ) fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); else fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); } } // old default // update the history if needed currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); currentTree()->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[0]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[0]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } } // shower the second particle if(fc[1].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[1]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[1]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); // normal shower else timeLikeShower(children[0],type,fc[1],false); } } updateHistory(children[1]); // TODO DO WE NEED A CHECK IF RECONPT !=0 return true; } void QTildeShowerHandler::connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ) { ShowerParticleVector particles; // find the Sudakovs for(set::iterator cit=hardTree->branchings().begin(); cit!=hardTree->branchings().end();++cit) { // Sudakovs for ISR if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) { ++_nis; array br; br[0] = (**cit).parent()->branchingParticle()->id(); br[1] = (**cit). branchingParticle()->id(); br[2] = (**cit).parent()->children()[0]==*cit ? (**cit).parent()->children()[1]->branchingParticle()->id() : (**cit).parent()->children()[0]->branchingParticle()->id(); BranchingList branchings = splittingGenerator()->initialStateBranchings(); if(br[1]<0&&br[0]==br[1]) { br[0] = abs(br[0]); br[1] = abs(br[1]); } else if(br[1]<0) { br[1] = -br[1]; br[2] = -br[2]; } long index = abs(br[1]); SudakovPtr sudakov; for(BranchingList::const_iterator cjt = branchings.lower_bound(index); cjt != branchings.upper_bound(index); ++cjt ) { IdList ids = cjt->second.particles; if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { sudakov=cjt->second.sudakov; break; } } if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in " << "QTildeShowerHandler::connectTrees() for ISR" << Exception::runerror; (**cit).parent()->sudakov(sudakov); } // Sudakovs for FSR else if(!(**cit).children().empty()) { ++_nfs; array br; br[0] = (**cit) .branchingParticle()->id(); br[1] = (**cit).children()[0]->branchingParticle()->id(); br[2] = (**cit).children()[1]->branchingParticle()->id(); BranchingList branchings = splittingGenerator()->finalStateBranchings(); if(br[0]<0) { br[0] = abs(br[0]); br[1] = abs(br[1]); br[2] = abs(br[2]); } long index = br[0]; SudakovPtr sudakov; for(BranchingList::const_iterator cjt = branchings.lower_bound(index); cjt != branchings.upper_bound(index); ++cjt ) { IdList ids = cjt->second.particles; if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { sudakov=cjt->second.sudakov; break; } } if(!sudakov) { throw Exception() << "Can't find Sudakov for the hard emission in " << "QTildeShowerHandler::connectTrees()" << Exception::runerror; } (**cit).sudakov(sudakov); } } // calculate the evolution scale for(set::iterator cit=hardTree->branchings().begin(); cit!=hardTree->branchings().end();++cit) { particles.push_back((*cit)->branchingParticle()); } partnerFinder()-> setInitialEvolutionScales(particles,!hard,interaction_,true); hardTree->partnersSet(true); // inverse reconstruction if(hard) { kinematicsReconstructor()-> deconstructHardJets(hardTree,interaction_); } else kinematicsReconstructor()-> deconstructDecayJets(hardTree,interaction_); // now reset the momenta of the showering particles vector particlesToShower=showerTree->extractProgenitors(); // match them map partners; for(set::const_iterator bit=hardTree->branchings().begin(); bit!=hardTree->branchings().end();++bit) { Energy2 dmin( 1e30*GeV2 ); ShowerProgenitorPtr partner; for(vector::const_iterator pit=particlesToShower.begin(); pit!=particlesToShower.end();++pit) { if(partners.find(*pit)!=partners.end()) continue; if( (**bit).branchingParticle()->id() != (**pit).progenitor()->id() ) continue; if( (**bit).branchingParticle()->isFinalState() != (**pit).progenitor()->isFinalState() ) continue; if( (**pit).progenitor()->isFinalState() ) { Energy2 dtest = sqr( (**pit).progenitor()->momentum().x() - (**bit).showerMomentum().x() ) + sqr( (**pit).progenitor()->momentum().y() - (**bit).showerMomentum().y() ) + sqr( (**pit).progenitor()->momentum().z() - (**bit).showerMomentum().z() ) + sqr( (**pit).progenitor()->momentum().t() - (**bit).showerMomentum().t() ); // add mass difference for identical particles (e.g. Z0 Z0 production) dtest += 1e10*sqr((**pit).progenitor()->momentum().m()-(**bit).showerMomentum().m()); if( dtest < dmin ) { partner = *pit; dmin = dtest; } } else { // ensure directions are right if((**pit).progenitor()->momentum().z()/(**bit).showerMomentum().z()>ZERO) { partner = *pit; break; } } } if(!partner) throw Exception() << "Failed to match shower and hard trees in QTildeShowerHandler::hardestEmission" << Exception::eventerror; partners[partner] = *bit; } for(vector::const_iterator pit=particlesToShower.begin(); pit!=particlesToShower.end();++pit) { HardBranchingPtr partner = partners[*pit]; if((**pit).progenitor()->dataPtr()->stable()) { (**pit).progenitor()->set5Momentum(partner->showerMomentum()); (**pit).copy()->set5Momentum(partner->showerMomentum()); } else { Lorentz5Momentum oldMomentum = (**pit).progenitor()->momentum(); Lorentz5Momentum newMomentum = partner->showerMomentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); (**pit).progenitor()->transform(boost); (**pit).copy() ->transform(boost); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); (**pit).progenitor()->transform(boost); (**pit).copy() ->transform(boost); } } // correction boosts for daughter trees for(map >::const_iterator tit = showerTree->treelinks().begin(); tit != showerTree->treelinks().end();++tit) { ShowerTreePtr decayTree = tit->first; map::const_iterator cit = decayTree->incomingLines().begin(); // reset the momentum of the decay particle Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum(); Lorentz5Momentum newMomentum = tit->second.second->momentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); decayTree->transform(boost,true); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); decayTree->transform(boost,true); } } void QTildeShowerHandler::doShowering(bool hard,XCPtr xcomb) { // zero number of emissions _nis = _nfs = 0; // if MC@NLO H event and limited emissions // indicate both final and initial state emission if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) { _nis = _nfs = 1; } // extract particles to shower vector particlesToShower(setupShower(hard)); // check if we should shower bool colCharge = false; for(unsigned int ix=0;ixprogenitor()->dataPtr()->coloured() || particlesToShower[ix]->progenitor()->dataPtr()->charged()) { colCharge = true; break; } } if(!colCharge) { _currenttree->hasShowered(true); return; } // setup the maximum scales for the shower if (restrictPhasespace()) setupMaximumScales(particlesToShower,xcomb); // set the hard scales for the profiles setupHardScales(particlesToShower,xcomb); // specific stuff for hard processes and decays Energy minmass(ZERO), mIn(ZERO); // hard process generate the intrinsic p_T once and for all bool minBias = dynamic_ptr_cast::ptr>(_hardme); if(hard) { _intrinsic.clear(); if(!minBias) generateIntrinsicpT(particlesToShower); } // decay compute the minimum mass of the final-state else { for(unsigned int ix=0;ixprogenitor()->isFinalState()) { if(particlesToShower[ix]->progenitor()->dataPtr()->stable()) { auto dm= ShowerHandler::currentHandler()->retConstituentMasses()? particlesToShower[ix]->progenitor()->dataPtr()->constituentMass(): particlesToShower[ix]->progenitor()->dataPtr()->mass(); minmass += dm; } else minmass += particlesToShower[ix]->progenitor()->mass(); } else { mIn = particlesToShower[ix]->progenitor()->mass(); } } // throw exception if decay can't happen if ( minmass > mIn ) { throw Exception() << "QTildeShowerHandler.cc: Mass of decaying particle is " << "below constituent masses of decay products." << Exception::eventerror; } } // setup for reweighted bool reWeighting = _reWeight && hard && ShowerHandler::currentHandler()->firstInteraction(); double eventWeight=0.; unsigned int nTryReWeight(0); // create random particle vector (only need to do once) vector tmp; unsigned int nColouredIncoming = 0; while(particlesToShower.size()>0){ unsigned int xx=UseRandom::irnd(particlesToShower.size()); tmp.push_back(particlesToShower[xx]); particlesToShower.erase(particlesToShower.begin()+xx); } particlesToShower=tmp; for(unsigned int ix=0;ixprogenitor()->isFinalState() && particlesToShower[ix]->progenitor()->coloured()) ++nColouredIncoming; } bool switchRecon = hard && nColouredIncoming !=1; // main shower loop unsigned int ntry(0); bool reconstructed = false; do { // type of recon to use bool generalRecon = minBias >> (switchRecon && ntry>maximumTries()/2); // clear results of last attempt if needed if(ntry!=0) { currentTree()->clear(); setEvolutionPartners(hard,interaction_,true); _nis = _nfs = 0; // if MC@NLO H event and limited emissions // indicate both final and initial state emission if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) { _nis = _nfs = 1; } for(unsigned int ix=0; ixprogenitor()->spinInfo(); if(spin && spin->decayVertex() && dynamic_ptr_cast(spin->decayVertex())) { spin->decayVertex(VertexPtr()); } } for(unsigned int ix=0;ixprogenitor()->isFinalState() || (hard && !particlesToShower[ix]->progenitor()->isFinalState())) { if(particlesToShower[ix]->progenitor()->spinInfo()) particlesToShower[ix]->progenitor()->spinInfo()->reset(); } } } // loop over particles for(unsigned int ix=0;ixprogenitor()->isFinalState()) { if(!doFSR()) continue; // perform shower progenitor()->hasEmitted(startTimeLikeShower(interaction_)); } // initial-state radiation else { if(!doISR()) continue; // hard process if(hard) { // get the PDF setBeamParticle(_progenitor->beam()); if(!beamParticle()) { throw Exception() << "Incorrect type of beam particle in " << "QTildeShowerHandler::doShowering(). " << "This should not happen for conventional choices but may happen if you have used a" << " non-default choice and have not changed the create ParticleData line in the input files" << " for this particle to create BeamParticleData." << Exception::runerror; } // perform the shower // set the beam particle tPPtr beamparticle=progenitor()->original(); if(!beamparticle->parents().empty()) beamparticle=beamparticle->parents()[0]; // generate the shower progenitor()->hasEmitted(startSpaceLikeShower(beamparticle, interaction_)); } // decay else { // skip colour and electrically neutral particles if(!progenitor()->progenitor()->dataPtr()->coloured() && !progenitor()->progenitor()->dataPtr()->charged()) { progenitor()->hasEmitted(false); continue; } // perform shower // set the scales correctly. The current scale is the maximum scale for // emission not the starting scale ShowerParticle::EvolutionScales maxScales(progenitor()->progenitor()->scales()); progenitor()->progenitor()->scales() = ShowerParticle::EvolutionScales(); if(progenitor()->progenitor()->dataPtr()->charged()) { progenitor()->progenitor()->scales().QED = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QED_noAO = progenitor()->progenitor()->mass(); } if(progenitor()->progenitor()->hasColour()) { progenitor()->progenitor()->scales().QCD_c = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QCD_c_noAO = progenitor()->progenitor()->mass(); } if(progenitor()->progenitor()->hasAntiColour()) { progenitor()->progenitor()->scales().QCD_ac = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QCD_ac_noAO = progenitor()->progenitor()->mass(); } // perform the shower progenitor()->hasEmitted(startSpaceLikeDecayShower(maxScales,minmass, interaction_)); } } } // do the kinematic reconstruction, checking if it worked reconstructed = hard ? kinematicsReconstructor()-> reconstructHardJets (currentTree(),intrinsicpT(),interaction_,generalRecon) : kinematicsReconstructor()-> reconstructDecayJets(currentTree(),interaction_); if(!reconstructed) continue; // apply vetos on the full shower for(vector::const_iterator it=_fullShowerVetoes.begin(); it!=_fullShowerVetoes.end();++it) { int veto = (**it).applyVeto(currentTree()); if(veto<0) continue; // veto the shower if(veto==0) { reconstructed = false; break; } // veto the shower and reweight else if(veto==1) { reconstructed = false; break; } // veto the event else if(veto==2) { throw Veto(); } } if(reWeighting) { if(reconstructed) eventWeight += 1.; reconstructed=false; ++nTryReWeight; if(nTryReWeight==_nReWeight) { reWeighting = false; if(eventWeight==0.) throw Veto(); } } } while(!reconstructed&&maximumTries()>++ntry); // check if failed to generate the shower if(ntry==maximumTries()) { if(hard) throw ShowerHandler::ShowerTriesVeto(ntry); else throw Exception() << "Failed to generate the shower after " << ntry << " attempts in QTildeShowerHandler::showerDecay()" << Exception::eventerror; } // handle the weights and apply any reweighting required if(nTryReWeight>0) { tStdEHPtr seh = dynamic_ptr_cast(generator()->currentEventHandler()); static bool first = true; if(seh) { seh->reweight(eventWeight/double(nTryReWeight)); } else if(first) { generator()->log() << "Reweighting the shower only works with internal Herwig7 processes" << "Presumably you are showering Les Houches Events. These will not be" << "reweighted\n"; first = false; } } // tree has now showered _currenttree->hasShowered(true); hardTree(HardTreePtr()); } void QTildeShowerHandler:: convertHardTree(bool hard,ShowerInteraction type) { map cmap; // incoming particles for(map::const_iterator cit=currentTree()->incomingLines().begin();cit!=currentTree()->incomingLines().end();++cit) { map::const_iterator mit = hardTree()->particles().find(cit->first->progenitor()); // put the colour lines in the map ShowerParticlePtr oldParticle = cit->first->progenitor(); ShowerParticlePtr newParticle = mit->second->branchingParticle(); ColinePtr cLine = oldParticle-> colourLine(); ColinePtr aLine = oldParticle->antiColourLine(); if(newParticle->colourLine() && cmap.find(newParticle-> colourLine())==cmap.end()) cmap[newParticle-> colourLine()] = cLine; if(newParticle->antiColourLine() && cmap.find(newParticle->antiColourLine())==cmap.end()) cmap[newParticle->antiColourLine()] = aLine; // check whether or not particle emits bool emission = mit->second->parent(); if(emission) { if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); } if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); } newParticle = mit->second->parent()->branchingParticle(); } // get the new colour lines ColinePtr newCLine,newALine; // sort out colour lines if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newCLine = cmap[ctemp]; } else { newCLine = new_ptr(ColourLine()); cmap[ctemp] = newCLine; } } // and anticolour lines if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newALine = cmap[ctemp]; } else { newALine = new_ptr(ColourLine()); cmap[ctemp] = newALine; } } // remove colour lines from old particle if(aLine) { aLine->removeAntiColoured(cit->first->copy()); aLine->removeAntiColoured(cit->first->progenitor()); } if(cLine) { cLine->removeColoured(cit->first->copy()); cLine->removeColoured(cit->first->progenitor()); } // add particle to colour lines if(newCLine) newCLine->addColoured (newParticle); if(newALine) newALine->addAntiColoured(newParticle); // insert new particles cit->first->copy(newParticle); ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,false))); cit->first->progenitor(sp); currentTree()->incomingLines()[cit->first]=sp; cit->first->perturbative(!emission); // and the emitted particle if needed if(emission) { ShowerParticlePtr newOut = mit->second->parent()->children()[1]->branchingParticle(); if(newOut->colourLine()) { ColinePtr ctemp = newOut-> colourLine(); ctemp->removeColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addColoured (newOut); } if(newOut->antiColourLine()) { ColinePtr ctemp = newOut->antiColourLine(); ctemp->removeAntiColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addAntiColoured(newOut); } ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); out->perturbative(false); currentTree()->outgoingLines().insert(make_pair(out,sout)); } if(hard) { // sort out the value of x if(mit->second->beam()->momentum().z()>ZERO) { sp->x(newParticle->momentum(). plus()/mit->second->beam()->momentum(). plus()); } else { sp->x(newParticle->momentum().minus()/mit->second->beam()->momentum().minus()); } } } // outgoing particles for(map::const_iterator cit=currentTree()->outgoingLines().begin();cit!=currentTree()->outgoingLines().end();++cit) { map >::const_iterator tit; for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==cit->first->progenitor()) break; } map::const_iterator mit = hardTree()->particles().find(cit->first->progenitor()); if(mit==hardTree()->particles().end()) continue; // put the colour lines in the map ShowerParticlePtr oldParticle = cit->first->progenitor(); ShowerParticlePtr newParticle = mit->second->branchingParticle(); ShowerParticlePtr newOut; ColinePtr cLine = oldParticle-> colourLine(); ColinePtr aLine = oldParticle->antiColourLine(); if(newParticle->colourLine() && cmap.find(newParticle-> colourLine())==cmap.end()) cmap[newParticle-> colourLine()] = cLine; if(newParticle->antiColourLine() && cmap.find(newParticle->antiColourLine())==cmap.end()) cmap[newParticle->antiColourLine()] = aLine; // check whether or not particle emits bool emission = !mit->second->children().empty(); if(emission) { if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); } if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); } newParticle = mit->second->children()[0]->branchingParticle(); newOut = mit->second->children()[1]->branchingParticle(); if(newParticle->id()!=oldParticle->id()&&newParticle->id()==newOut->id()) swap(newParticle,newOut); } // get the new colour lines ColinePtr newCLine,newALine; // sort out colour lines if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newCLine = cmap[ctemp]; } else { newCLine = new_ptr(ColourLine()); cmap[ctemp] = newCLine; } } // and anticolour lines if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newALine = cmap[ctemp]; } else { newALine = new_ptr(ColourLine()); cmap[ctemp] = newALine; } } // remove colour lines from old particle if(aLine) { aLine->removeAntiColoured(cit->first->copy()); aLine->removeAntiColoured(cit->first->progenitor()); } if(cLine) { cLine->removeColoured(cit->first->copy()); cLine->removeColoured(cit->first->progenitor()); } // special for unstable particles if(newParticle->id()==oldParticle->id() && (tit!=currentTree()->treelinks().end()||!oldParticle->dataPtr()->stable())) { Lorentz5Momentum oldMomentum = oldParticle->momentum(); Lorentz5Momentum newMomentum = newParticle->momentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); oldParticle->transform(boost); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); oldParticle->transform(boost); if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); newParticle=oldParticle; } // add particle to colour lines if(newCLine) newCLine->addColoured (newParticle); if(newALine) newALine->addAntiColoured(newParticle); // insert new particles cit->first->copy(newParticle); ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,true))); cit->first->progenitor(sp); currentTree()->outgoingLines()[cit->first]=sp; cit->first->perturbative(!emission); // and the emitted particle if needed if(emission) { if(newOut->colourLine()) { ColinePtr ctemp = newOut-> colourLine(); ctemp->removeColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addColoured (newOut); } if(newOut->antiColourLine()) { ColinePtr ctemp = newOut->antiColourLine(); ctemp->removeAntiColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addAntiColoured(newOut); } ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); out->perturbative(false); currentTree()->outgoingLines().insert(make_pair(out,sout)); } // update any decay products if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(cit->first,sp)); } // reset the tree currentTree()->resetShowerProducts(); // reextract the particles and set the colour partners vector particles = currentTree()->extractProgenitorParticles(); // clear the partners for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); particles[ix]->clearPartners(); } // clear the tree hardTree(HardTreePtr()); // Set the initial evolution scales partnerFinder()-> setInitialEvolutionScales(particles,!hard,type,!_hardtree); } Branching QTildeShowerHandler::selectTimeLikeBranching(tShowerParticlePtr particle, ShowerInteraction type, HardBranchingPtr branch) { Branching fb; unsigned int iout=0; while (true) { // break if doing truncated shower and no truncated shower needed if(branch && (!isTruncatedShowerON()||hardOnly())) break; fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type); // no emission break if(!fb.kinematics) break; // special for truncated shower if(branch) { // check haven't evolved too far if(fb.kinematics->scale() < branch->scale()) { fb=Branching(); break; } // find the truncated line iout=0; if(fb.ids[1]->id()!=fb.ids[2]->id()) { if(fb.ids[1]->id()==particle->id()) iout=1; else if (fb.ids[2]->id()==particle->id()) iout=2; } else if(fb.ids[1]->id()==particle->id()) { if(fb.kinematics->z()>0.5) iout=1; else iout=2; } // apply the vetos for the truncated shower // no flavour changing branchings if(iout==0) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); // only if same interaction for forced branching ShowerInteraction type2 = convertInteraction(fb.type); // and evolution if(type2==branch->sudakov()->interactionType()) { if(zsplit < 0.5 || // hardest line veto fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // pt veto if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // standard vetos for all emissions if(timeLikeVetoed(fb,particle)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); continue; } // special for already decayed particles // don't allow flavour changing branchings bool vetoDecay = false; for(map >::const_iterator tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first == progenitor()) { map::const_iterator it = currentTree()->outgoingLines().find(progenitor()); if(it!=currentTree()->outgoingLines().end() && particle == it->second && fb.ids[0]!=fb.ids[1] && fb.ids[1]!=fb.ids[2]) { vetoDecay = true; break; } } } if(vetoDecay) { particle->vetoEmission(fb.type,fb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); continue; } break; } // normal case if(!branch) { if(fb.kinematics) fb.hard = false; return fb; } // truncated emission if(fb.kinematics) { fb.hard = false; fb.iout = iout; return fb; } // otherwise need to return the hard emission // construct the kinematics for the hard emission ShoKinPtr showerKin = new_ptr(FS_QTildeShowerKinematics1to2( branch->scale(), branch->children()[0]->z(), branch->phi(), branch->children()[0]->pT(), branch->sudakov() )); IdList idlist(3); idlist[0] = particle->dataPtr(); idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() ); fb.hard = true; fb.iout=0; // return it return fb; } Branching QTildeShowerHandler::selectSpaceLikeDecayBranching(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, HardBranchingPtr branch) { Branching fb; unsigned int iout=0; while (true) { // break if doing truncated shower and no truncated shower needed if(branch && (!isTruncatedShowerON()||hardOnly())) break; // select branching fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass, _initialenhance,type); // return if no radiation if(!fb.kinematics) break; // special for truncated shower if(branch) { // check haven't evolved too far if(fb.kinematics->scale() < branch->scale()) { fb=Branching(); break; } // find the truncated line iout=0; if(fb.ids[1]->id()!=fb.ids[2]->id()) { if(fb.ids[1]->id()==particle->id()) iout=1; else if (fb.ids[2]->id()==particle->id()) iout=2; } else if(fb.ids[1]->id()==particle->id()) { if(fb.kinematics->z()>0.5) iout=1; else iout=2; } // apply the vetos for the truncated shower // no flavour changing branchings if(iout==0) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } ShowerInteraction type2 = convertInteraction(fb.type); double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); if(type2==branch->sudakov()->interactionType()) { if(zsplit < 0.5 || // hardest line veto fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // pt veto if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // if not vetoed break if(spaceLikeDecayVetoed(fb,particle)) { // otherwise reset scale and continue particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } break; } // normal case if(!branch) { if(fb.kinematics) fb.hard = false; return fb; } // truncated emission if(fb.kinematics) { fb.hard = false; fb.iout = iout; return fb; } // otherwise need to return the hard emission // construct the kinematics for the hard emission ShoKinPtr showerKin = new_ptr(Decay_QTildeShowerKinematics1to2( branch->scale(), branch->children()[0]->z(), branch->phi(), branch->children()[0]->pT(), branch->sudakov())); IdList idlist(3); idlist[0] = particle->dataPtr(); idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); // create the branching fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine ); fb.hard=true; fb.iout=0; // return it return fb; } void QTildeShowerHandler::checkFlags() { string error = "Inconsistent hard emission set-up in QTildeShowerHandler::showerHardProcess(). "; if ( ( currentTree()->isMCatNLOSEvent() || currentTree()->isMCatNLOHEvent() ) ) { if (_hardEmission ==2 ) throw Exception() << error << "Cannot generate POWHEG matching with MC@NLO shower " << "approximation. Add 'set QTildeShowerHandler:HardEmission 0' to input file." << Exception::runerror; if ( canHandleMatchboxTrunc() ) throw Exception() << error << "Cannot use truncated qtilde shower with MC@NLO shower " << "approximation. Set LHCGenerator:EventHandler" << ":CascadeHandler to '/Herwig/Shower/ShowerHandler' or " << "'/Herwig/Shower/Dipole/DipoleShowerHandler'." << Exception::runerror; } else if ( ((currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) ) && _hardEmission != 2){ if ( canHandleMatchboxTrunc()) throw Exception() << error << "Unmatched events requested for POWHEG shower " << "approximation. Set QTildeShowerHandler:HardEmission to " << "'POWHEG'." << Exception::runerror; else if (_hardEmissionWarn) { _hardEmissionWarn = false; _hardEmission=2; throw Exception() << error << "Unmatched events requested for POWHEG shower " << "approximation. Changing QTildeShowerHandler:HardEmission from " << _hardEmission << " to 2" << Exception::warning; } } if ( currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) { if (currentTree()->showerApproximation()->needsTruncatedShower() && !canHandleMatchboxTrunc() ) throw Exception() << error << "Current shower handler cannot generate truncated shower. " << "Set Generator:EventHandler:CascadeHandler to " << "'/Herwig/Shower/PowhegShowerHandler'." << Exception::runerror; } else if ( currentTree()->truncatedShower() && _missingTruncWarn) { _missingTruncWarn=false; throw Exception() << "Warning: POWHEG shower approximation used without " << "truncated shower. Set Generator:EventHandler:" << "CascadeHandler to '/Herwig/Shower/PowhegShowerHandler' and " << "'MEMatching:TruncatedShower Yes'." << Exception::warning; } // else if ( !dipme && _hardEmissionMode > 1 && // firstInteraction()) // throw Exception() << error // << "POWHEG matching requested for LO events. Include " // << "'set Factory:ShowerApproximation MEMatching' in input file." // << Exception::runerror; } tPPair QTildeShowerHandler::remakeRemnant(tPPair oldp){ // get the parton extractor PartonExtractor & pex = *lastExtractor(); // get the new partons tPPair newp = make_pair(findFirstParton(oldp.first ), findFirstParton(oldp.second)); // if the same do nothing if(newp == oldp) return oldp; // Creates the new remnants and returns the new PartonBinInstances // ATTENTION Broken here for very strange configuration PBIPair newbins = pex.newRemnants(oldp, newp, newStep()); newStep()->addIntermediate(newp.first); newStep()->addIntermediate(newp.second); // return the new partons return newp; } PPtr QTildeShowerHandler::findFirstParton(tPPtr seed) const{ if(seed->parents().empty()) return seed; tPPtr parent = seed->parents()[0]; //if no parent there this is a loose end which will //be connected to the remnant soon. if(!parent || parent == incomingBeams().first || parent == incomingBeams().second ) return seed; else return findFirstParton(parent); } void QTildeShowerHandler::decay(ShowerTreePtr tree, ShowerDecayMap & decay) { // must be one incoming particle assert(tree->incomingLines().size()==1); // apply any transforms tree->applyTransforms(); // if already decayed return if(!tree->outgoingLines().empty()) return; // now we need to replace the particle with a new copy after the shower // find particle after the shower map >::const_iterator tit = tree->parent()->treelinks().find(tree); assert(tit!=tree->parent()->treelinks().end()); ShowerParticlePtr newparent=tit->second.second; PerturbativeProcessPtr newProcess = new_ptr(PerturbativeProcess()); newProcess->incoming().push_back(make_pair(newparent,PerturbativeProcessPtr())); DecayProcessMap decayMap; ShowerHandler::decay(newProcess,decayMap); ShowerTree::constructTrees(tree,decay,newProcess,decayMap); } namespace { ShowerProgenitorPtr findFinalStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) { map::iterator partner; Energy2 dmin(1e30*GeV2); for(map::iterator cit =tree->outgoingLines().begin(); cit!=tree->outgoingLines().end(); ++cit) { if(cit->second->id()!=id) continue; Energy2 test = sqr(cit->second->momentum().x()-momentum.x())+ sqr(cit->second->momentum().y()-momentum.y())+ sqr(cit->second->momentum().z()-momentum.z())+ sqr(cit->second->momentum().t()-momentum.t()); if(testfirst; } ShowerProgenitorPtr findInitialStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) { map::iterator partner; Energy2 dmin(1e30*GeV2); for(map::iterator cit =tree->incomingLines().begin(); cit!=tree->incomingLines().end(); ++cit) { if(cit->second->id()!=id) continue; Energy2 test = sqr(cit->second->momentum().x()-momentum.x())+ sqr(cit->second->momentum().y()-momentum.y())+ sqr(cit->second->momentum().z()-momentum.z())+ sqr(cit->second->momentum().t()-momentum.t()); if(testfirst; } void fixSpectatorColours(PPtr newSpect,ShowerProgenitorPtr oldSpect, ColinePair & cline,ColinePair & aline, bool reconnect) { cline.first = oldSpect->progenitor()->colourLine(); cline.second = newSpect->colourLine(); aline.first = oldSpect->progenitor()->antiColourLine(); aline.second = newSpect->antiColourLine(); if(!reconnect) return; if(cline.first) { cline.first ->removeColoured(oldSpect->copy()); cline.first ->removeColoured(oldSpect->progenitor()); cline.second->removeColoured(newSpect); cline.first ->addColoured(newSpect); } if(aline.first) { aline.first ->removeAntiColoured(oldSpect->copy()); aline.first ->removeAntiColoured(oldSpect->progenitor()); aline.second->removeAntiColoured(newSpect); aline.first ->addAntiColoured(newSpect); } } void fixInitialStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter, ColinePair cline,ColinePair aline,double x) { // sort out the colours if(emitted->dataPtr()->iColour()==PDT::Colour8) { // emitter if(cline.first && cline.first == emitter->progenitor()->antiColourLine() && cline.second !=newEmit->antiColourLine()) { // sort out not radiating line ColinePtr col = emitter->progenitor()->colourLine(); if(col) { col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } } else if(aline.first && aline.first == emitter->progenitor()->colourLine() && aline.second !=newEmit->colourLine()) { // sort out not radiating line ColinePtr anti = emitter->progenitor()->antiColourLine(); if(anti) { anti->removeAntiColoured(emitter->copy()); anti->removeAntiColoured(emitter->progenitor()); newEmit->colourLine()->removeAntiColoured(newEmit); anti->addAntiColoured(newEmit); } } else assert(false); // emitted if(cline.first && cline.second==emitted->colourLine()) { cline.second->removeColoured(emitted); cline.first->addColoured(emitted); } else if(aline.first && aline.second==emitted->antiColourLine()) { aline.second->removeAntiColoured(emitted); aline.first->addAntiColoured(emitted); } else assert(false); } else { if(emitter->progenitor()->antiColourLine() ) { ColinePtr col = emitter->progenitor()->antiColourLine(); col->removeAntiColoured(emitter->copy()); col->removeAntiColoured(emitter->progenitor()); if(newEmit->antiColourLine()) { newEmit->antiColourLine()->removeAntiColoured(newEmit); col->addAntiColoured(newEmit); } else if (emitted->colourLine()) { emitted->colourLine()->removeColoured(emitted); col->addColoured(emitted); } else assert(false); } if(emitter->progenitor()->colourLine() ) { ColinePtr col = emitter->progenitor()->colourLine(); col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); if(newEmit->colourLine()) { newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } else if (emitted->antiColourLine()) { emitted->antiColourLine()->removeAntiColoured(emitted); col->addAntiColoured(emitted); } else assert(false); } } // update the emitter emitter->copy(newEmit); ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,false)); sp->x(x); emitter->progenitor(sp); tree->incomingLines()[emitter]=sp; emitter->perturbative(false); // add emitted sp=new_ptr(ShowerParticle(*emitted,1,true)); ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(),emitted,sp)); gluon->perturbative(false); tree->outgoingLines().insert(make_pair(gluon,sp)); } void fixFinalStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter, ColinePair cline,ColinePair aline) { map >::const_iterator tit; // special case if decayed for(tit = tree->treelinks().begin(); tit != tree->treelinks().end();++tit) { if(tit->second.first && tit->second.second==emitter->progenitor()) break; } // sort out the colour lines if(cline.first && cline.first == emitter->progenitor()->antiColourLine() && cline.second !=newEmit->antiColourLine()) { // sort out not radiating line ColinePtr col = emitter->progenitor()->colourLine(); if(col) { col->removeColoured(emitter->copy()); col->removeColoured(emitter->progenitor()); newEmit->colourLine()->removeColoured(newEmit); col->addColoured(newEmit); } } else if(aline.first && aline.first == emitter->progenitor()->colourLine() && aline.second !=newEmit->colourLine()) { // sort out not radiating line ColinePtr anti = emitter->progenitor()->antiColourLine(); if(anti) { anti->removeAntiColoured(emitter->copy()); anti->removeAntiColoured(emitter->progenitor()); newEmit->colourLine()->removeAntiColoured(newEmit); anti->addAntiColoured(newEmit); } } else assert(false); // update the emitter emitter->copy(newEmit); ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,true)); emitter->progenitor(sp); tree->outgoingLines()[emitter]=sp; emitter->perturbative(false); // update for decaying particles if(tit!=tree->treelinks().end()) tree->updateLink(tit->first,make_pair(emitter,sp)); // add the emitted particle // sort out the colour if(cline.first && cline.second==emitted->antiColourLine()) { cline.second->removeAntiColoured(emitted); cline.first->addAntiColoured(emitted); } else if(aline.first && aline.second==emitted->colourLine()) { aline.second->removeColoured(emitted); aline.first->addColoured(emitted); } else assert(false); sp=new_ptr(ShowerParticle(*emitted,1,true)); ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(), emitted,sp)); gluon->perturbative(false); tree->outgoingLines().insert(make_pair(gluon,sp)); } } void QTildeShowerHandler::setupMECorrection(RealEmissionProcessPtr real) { assert(real); // II emission if(real->emitter() < real->incoming().size() && real->spectator() < real->incoming().size()) { // recoiling system for( map::const_iterator cjt= currentTree()->outgoingLines().begin(); cjt != currentTree()->outgoingLines().end();++cjt ) { cjt->first->progenitor()->transform(real->transformation()); cjt->first->copy()->transform(real->transformation()); } // the the radiating system ShowerProgenitorPtr emitter,spectator; unsigned int iemit = real->emitter(); unsigned int ispect = real->spectator(); int ig = int(real->emitted())-int(real->incoming().size()); emitter = findInitialStateLine(currentTree(), real->bornIncoming()[iemit]->id(), real->bornIncoming()[iemit]->momentum()); spectator = findInitialStateLine(currentTree(), real->bornIncoming()[ispect]->id(), real->bornIncoming()[ispect]->momentum()); // sort out the colours ColinePair cline,aline; fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->incoming()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false))); sp->x(ispect ==0 ? real->x().first :real->x().second); spectator->progenitor(sp); currentTree()->incomingLines()[spectator]=sp; spectator->perturbative(true); // now for the emitter fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig], emitter,cline,aline,iemit ==0 ? real->x().first :real->x().second); } // FF emission else if(real->emitter() >= real->incoming().size() && real->spectator() >= real->incoming().size()) { assert(real->outgoing()[real->emitted()-real->incoming().size()]->id()==ParticleID::g); // find the emitter and spectator in the shower tree ShowerProgenitorPtr emitter,spectator; int iemit = int(real->emitter())-int(real->incoming().size()); emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit]->id(), real->bornOutgoing()[iemit]->momentum()); int ispect = int(real->spectator())-int(real->incoming().size()); spectator = findFinalStateLine(currentTree(), real->bornOutgoing()[ispect]->id(), real->bornOutgoing()[ispect]->momentum()); map >::const_iterator tit; // first the spectator // special case if decayed for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==spectator->progenitor()) break; } // sort out the colours ColinePair cline,aline; fixSpectatorColours(real->outgoing()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->outgoing()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect],1,true))); spectator->progenitor(sp); currentTree()->outgoingLines()[spectator]=sp; spectator->perturbative(true); // update for decaying particles if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(spectator,sp)); // now the emitting particle int ig = int(real->emitted())-int(real->incoming().size()); fixFinalStateEmitter(currentTree(),real->outgoing()[iemit], real->outgoing()[ig], emitter,cline,aline); } // IF emission else { // scattering process if(real->incoming().size()==2) { ShowerProgenitorPtr emitter,spectator; unsigned int iemit = real->emitter(); unsigned int ispect = real->spectator(); int ig = int(real->emitted())-int(real->incoming().size()); ColinePair cline,aline; // incoming spectator if(ispect<2) { spectator = findInitialStateLine(currentTree(), real->bornIncoming()[ispect]->id(), real->bornIncoming()[ispect]->momentum()); fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true); // update the spectator spectator->copy(real->incoming()[ispect]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false))); sp->x(ispect ==0 ? real->x().first :real->x().second); spectator->progenitor(sp); currentTree()->incomingLines()[spectator]=sp; spectator->perturbative(true); } // outgoing spectator else { spectator = findFinalStateLine(currentTree(), real->bornOutgoing()[ispect-real->incoming().size()]->id(), real->bornOutgoing()[ispect-real->incoming().size()]->momentum()); // special case if decayed map >::const_iterator tit; for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==spectator->progenitor()) break; } fixSpectatorColours(real->outgoing()[ispect-real->incoming().size()],spectator,cline,aline,true); // update the spectator spectator->copy(real->outgoing()[ispect-real->incoming().size()]); ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect-real->incoming().size()],1,true))); spectator->progenitor(sp); currentTree()->outgoingLines()[spectator]=sp; spectator->perturbative(true); // update for decaying particles if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(spectator,sp)); } // incoming emitter if(iemit<2) { emitter = findInitialStateLine(currentTree(), real->bornIncoming()[iemit]->id(), real->bornIncoming()[iemit]->momentum()); fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig], emitter,aline,cline,iemit ==0 ? real->x().first :real->x().second); } // outgoing emitter else { emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit-real->incoming().size()]->id(), real->bornOutgoing()[iemit-real->incoming().size()]->momentum()); fixFinalStateEmitter(currentTree(),real->outgoing()[iemit-real->incoming().size()], real->outgoing()[ig],emitter,aline,cline); } } // decay process else { assert(real->spectator()==0); unsigned int iemit = real->emitter()-real->incoming().size(); int ig = int(real->emitted())-int(real->incoming().size()); ColinePair cline,aline; // incoming spectator ShowerProgenitorPtr spectator = findInitialStateLine(currentTree(), real->bornIncoming()[0]->id(), real->bornIncoming()[0]->momentum()); fixSpectatorColours(real->incoming()[0],spectator,cline,aline,false); // find the emitter ShowerProgenitorPtr emitter = findFinalStateLine(currentTree(), real->bornOutgoing()[iemit]->id(), real->bornOutgoing()[iemit]->momentum()); // recoiling system for( map::const_iterator cjt= currentTree()->outgoingLines().begin(); cjt != currentTree()->outgoingLines().end();++cjt ) { if(cjt->first==emitter) continue; cjt->first->progenitor()->transform(real->transformation()); cjt->first->copy()->transform(real->transformation()); } // sort out the emitter fixFinalStateEmitter(currentTree(),real->outgoing()[iemit], real->outgoing()[ig],emitter,aline,cline); } } // clean up the shower tree _currenttree->resetShowerProducts(); } diff --git a/Shower/QTilde/QTildeShowerHandler.h b/Shower/QTilde/QTildeShowerHandler.h --- a/Shower/QTilde/QTildeShowerHandler.h +++ b/Shower/QTilde/QTildeShowerHandler.h @@ -1,841 +1,833 @@ // -*- C++ -*- #ifndef Herwig_QTildeShowerHandler_H #define Herwig_QTildeShowerHandler_H // // This is the declaration of the QTildeShowerHandler class. // #include "QTildeShowerHandler.fh" #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.h" #include "Herwig/Shower/QTilde/Base/ShowerTree.h" #include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh" #include "Herwig/Shower/QTilde/Base/HardTree.h" #include "Herwig/Shower/QTilde/Base/Branching.h" #include "Herwig/Shower/QTilde/Base/ShowerVeto.h" #include "Herwig/Shower/QTilde/Base/FullShowerVeto.h" #include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.fh" #include "Herwig/Shower/QTilde/Base/PartnerFinder.fh" #include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.fh" #include "Herwig/MatrixElement/HwMEBase.h" #include "Herwig/Decay/HwDecayerBase.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" #include "Herwig/Shower/RealEmissionProcess.h" #include "Herwig/Utilities/Statistic.h" namespace Herwig { using namespace ThePEG; /** * The QTildeShowerHandler class. * * @see \ref QTildeShowerHandlerInterfaces "The interfaces" * defined for QTildeShowerHandler. */ class QTildeShowerHandler: public ShowerHandler { public: /** * Pointer to an XComb object */ typedef Ptr::pointer XCPtr; public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ QTildeShowerHandler(); - /** - * The destructor. - */ - virtual ~QTildeShowerHandler(); - //@} - public: /** * At the end of the Showering, transform ShowerParticle objects * into ThePEG particles and fill the event record with them. * Notice that the parent/child relationships and the * transformation from ShowerColourLine objects into ThePEG * ColourLine ones must be properly handled. */ void fillEventRecord(); /** * Return the relevant hard scale to be used in the profile scales */ virtual Energy hardScale() const { return muPt; } /** * Hook to allow vetoing of event after showering hard sub-process * as in e.g. MLM merging. */ virtual bool showerHardProcessVeto() const { return false; } /** * Generate hard emissions for CKKW etc */ virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const; /** * Members to perform the shower */ //@{ /** * Perform the shower of the hard process */ virtual void showerHardProcess(ShowerTreePtr,XCPtr); /** * Perform the shower of a decay */ virtual void showerDecay(ShowerTreePtr); //@} /** * Access to the flags and shower variables */ //@{ /** * Get the SplittingGenerator */ tSplittingGeneratorPtr splittingGenerator() const { return _splittingGenerator; } /** * Mode for hard emissions */ int hardEmission() const {return _hardEmission;} //@} /** * Connect the Hard and Shower trees */ virtual void connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ); /** * Access to switches for spin correlations */ //@{ /** * Soft correlations */ unsigned int softCorrelations() const { return _softOpt; } /** * Any correlations */ virtual bool correlations() const { return spinCorrelations()!=0||_softOpt!=0; } //@} public: /** * Access methods to access the objects */ //@{ /** * Access to the KinematicsReconstructor object */ tKinematicsReconstructorPtr kinematicsReconstructor() const { return _reconstructor; } /** * Access to the PartnerFinder object */ tPartnerFinderPtr partnerFinder() const { return _partnerfinder; } //@} protected: /** * Perform the shower */ void doShowering(bool hard,XCPtr); /** * Generate the hard matrix element correction */ virtual RealEmissionProcessPtr hardMatrixElementCorrection(bool); /** * Generate the hardest emission */ virtual void hardestEmission(bool hard); /** * Set up for applying a matrix element correction */ void setupMECorrection(RealEmissionProcessPtr real); /** * Extract the particles to be showered, set the evolution scales * and apply the hard matrix element correction * @param hard Whether this is a hard process or decay * @return The particles to be showered */ virtual vector setupShower(bool hard); /** * set the colour partners */ virtual void setEvolutionPartners(bool hard,ShowerInteraction, bool clear); /** * Methods to perform the evolution of an individual particle, including * recursive calling on the products */ //@{ /** * It does the forward evolution of the time-like input particle * (and recursively for all its radiation products). * accepting only emissions which conforms to the showerVariables * and soft matrix element correction. * If at least one emission has occurred then the method returns true. * @param particle The particle to be showered */ virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction, Branching fb, bool first); /** * It does the backward evolution of the space-like input particle * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * If at least one emission has occurred then the method returns true * @param particle The particle to be showered * @param beam The beam particle */ virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam, ShowerInteraction); /** * If does the forward evolution of the input on-shell particle * involved in a decay * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * @param particle The particle to be showered * @param maxscale The maximum scale for the shower. * @param minimumMass The minimum mass of the final-state system */ virtual bool spaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction, Branching fb); /** * Truncated shower from a time-like particle */ virtual bool truncatedTimeLikeShower(tShowerParticlePtr particle, HardBranchingPtr branch, ShowerInteraction type, Branching fb, bool first); /** * Truncated shower from a space-like particle */ virtual bool truncatedSpaceLikeShower(tShowerParticlePtr particle,PPtr beam, HardBranchingPtr branch, ShowerInteraction type); /** * Truncated shower from a time-like particle */ virtual bool truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass, HardBranchingPtr branch, ShowerInteraction type, Branching fb); //@} /** * Switches for matrix element corrections */ //@{ /** * Any ME correction? */ bool MECOn() const { return _hardEmission == 1; } /** * Any hard ME correction? */ bool hardMEC() const { return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode == 2); } /** * Any soft ME correction? */ bool softMEC() const { return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode > 2); } //@} /** * Is the truncated shower on? */ bool isTruncatedShowerON() const {return _trunc_Mode;} /** * Switch for intrinsic pT */ //@{ /** * Any intrinsic pT? */ bool ipTon() const { return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO ); } //@} /**@name Additional shower vetoes */ //@{ /** * Insert a veto. */ void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); } /** * Remove a veto. */ void removeVeto (ShowerVetoPtr v) { vector::iterator vit = find(_vetoes.begin(),_vetoes.end(),v); if (vit != _vetoes.end()) _vetoes.erase(vit); } //@} /** * Switches for vetoing hard emissions */ //@{ /** * Returns true if the hard veto read-in is to be applied to only * the primary collision and false otherwise. */ bool hardVetoReadOption() const {return _hardVetoReadOption;} //@} /** * Enhancement factors for radiation needed to generate the soft matrix * element correction. */ //@{ /** * Access the enhancement factor for initial-state radiation */ double initialStateRadiationEnhancementFactor() const { return _initialenhance; } /** * Access the enhancement factor for final-state radiation */ double finalStateRadiationEnhancementFactor() const { return _finalenhance; } /** * Set the enhancement factor for initial-state radiation */ void initialStateRadiationEnhancementFactor(double in) { _initialenhance=in; } /** * Set the enhancement factor for final-state radiation */ void finalStateRadiationEnhancementFactor(double in) { _finalenhance=in; } //@} /** * Access to set/get the HardTree currently beinging showered */ //@{ /** * The HardTree currently being showered */ tHardTreePtr hardTree() {return _hardtree;} /** * The HardTree currently being showered */ void hardTree(tHardTreePtr in) {_hardtree = in;} //@} /** * Access/set the beam particle for the current initial-state shower */ //@{ /** * Get the beam particle data */ Ptr::const_pointer beamParticle() const { return _beam; } /** * Set the beam particle data */ void setBeamParticle(Ptr::const_pointer in) { _beam=in; } //@} /** * Set/Get the current tree being evolver for inheriting classes */ //@{ /** * Get the tree */ tShowerTreePtr currentTree() { return _currenttree; } /** * Set the tree */ void currentTree(tShowerTreePtr tree) { _currenttree=tree; } //@} /** * Access the maximum number of attempts to generate the shower */ unsigned int maximumTries() const { return _maxtry; } /** * Set/Get the ShowerProgenitor for the current shower */ //@{ /** * Access the progenitor */ ShowerProgenitorPtr progenitor() { return _progenitor; } /** * Set the progenitor */ void progenitor(ShowerProgenitorPtr in) { _progenitor=in; } //@} /** * Calculate the intrinsic \f$p_T\f$. */ virtual void generateIntrinsicpT(vector); /** * Access to the intrinsic \f$p_T\f$ for inheriting classes */ map > & intrinsicpT() { return _intrinsic; } /** * find the maximally allowed pt acc to the hard process. */ void setupMaximumScales(const vector &,XCPtr); /** * find the relevant hard scales for profile scales. */ void setupHardScales(const vector &,XCPtr); /** * Convert the HardTree into an extra shower emission */ void convertHardTree(bool hard,ShowerInteraction type); protected: /** * Find the parton extracted from the incoming particle after ISR */ PPtr findFirstParton(tPPtr seed) const; /** * Fix Remnant connections after ISR */ tPPair remakeRemnant(tPPair oldp); protected: /** * Start the shower of a timelike particle */ virtual bool startTimeLikeShower(ShowerInteraction); /** * Update of the time-like stuff */ void updateHistory(tShowerParticlePtr particle); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeShower(PPtr,ShowerInteraction); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction); /** * Select the branching for the next time-like emission */ Branching selectTimeLikeBranching(tShowerParticlePtr particle, ShowerInteraction type, HardBranchingPtr branch); /** * Select the branching for the next space-like emission in a decay */ Branching selectSpaceLikeDecayBranching(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, HardBranchingPtr branch); /** * Create the timelike child of a branching */ ShowerParticleVector createTimeLikeChildren(tShowerParticlePtr particle, IdList ids); /** * Vetos for the timelike shower */ virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr); /** * Only generate the hard emission, for testing only. */ bool hardOnly() const {return _limitEmissions==3;} /** * Check the flags */ void checkFlags(); /** * */ void addFSRUsingDecayPOWHEG(HardTreePtr ISRTree); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * The main method which manages the showering of a subprocess. */ virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb); /** * Decay a ShowerTree */ void decay(ShowerTreePtr tree, ShowerDecayMap & decay); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeShowerHandler & operator=(const QTildeShowerHandler &) = delete; private: /** * Stuff from the ShowerHandler */ //@{ /** * The ShowerTree for the hard process */ ShowerTreePtr hard_; /** * The ShowerTree for the decays */ ShowerDecayMap decay_; /** * The ShowerTrees for which the initial shower */ vector done_; //@} private : /** * Pointer to the splitting generator */ SplittingGeneratorPtr _splittingGenerator; /** * Maximum number of tries to generate the shower of a particular tree */ unsigned int _maxtry; /** * Matrix element correction switch */ unsigned int _meCorrMode; /** * Control of the reconstruction option */ unsigned int _evolutionScheme; /** * If hard veto pT scale is being read-in this determines * whether the read-in value is applied to primary and * secondary (MPI) scatters or just the primary one, with * the usual computation of the veto being performed for * the secondary (MPI) scatters. */ bool _hardVetoReadOption; /** * rms intrinsic pT of Gaussian distribution */ Energy _iptrms; /** * Proportion of inverse quadratic intrinsic pT distribution */ double _beta; /** * Parameter for inverse quadratic: 2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT)) */ Energy _gamma; /** * Upper bound on intrinsic pT for inverse quadratic */ Energy _iptmax; /** * Limit the number of emissions for testing */ unsigned int _limitEmissions; /** * The progenitor of the current shower */ ShowerProgenitorPtr _progenitor; /** * Matrix element */ HwMEBasePtr _hardme; /** * Decayer */ HwDecayerBasePtr _decayme; /** * The ShowerTree currently being showered */ ShowerTreePtr _currenttree; /** * The HardTree currently being showered */ HardTreePtr _hardtree; /** * Radiation enhancement factors for use with the veto algorithm * if needed by the soft matrix element correction */ //@{ /** * Enhancement factor for initial-state radiation */ double _initialenhance; /** * Enhancement factor for final-state radiation */ double _finalenhance; //@} /** * The beam particle data for the current initial-state shower */ Ptr::const_pointer _beam; /** * Storage of the intrinsic \f$p_t\f$ of the particles */ map > _intrinsic; /** * Vetoes */ vector _vetoes; /** * Full Shower Vetoes */ vector _fullShowerVetoes; /** * Number of iterations for reweighting */ unsigned int _nReWeight; /** * Whether or not we are reweighting */ bool _reWeight; /** * number of IS emissions */ unsigned int _nis; /** * Number of FS emissions */ unsigned int _nfs; /** * The option for wqhich interactions to use */ ShowerInteraction interaction_; /** * Truncated shower switch */ bool _trunc_Mode; /** * Mode for the hard emissions */ int _hardEmission; /** * Option for the kernal for soft correlations */ unsigned int _softOpt; /** * Option for hard radiation in POWHEG events */ bool _hardPOWHEG; /** * True if no warnings about incorrect hard emission * mode setting have been issued yet */ static bool _hardEmissionWarn; /** * True if no warnings about missing truncated shower * have been issued yet */ static bool _missingTruncWarn; /** * The relevant hard scale to be used in the profile scales */ Energy muPt; private: /** * Pointer to the various objects */ //@{ /** * Pointer to the KinematicsReconstructor object */ KinematicsReconstructorPtr _reconstructor; /** * Pointer to the PartnerFinder object */ PartnerFinderPtr _partnerfinder; //@} }; } #endif /* HERWIG_QTildeShowerHandler_H */ diff --git a/Shower/QTilde/SplittingFunctions/HalfHalfZeroEWSplitFn.cc b/Shower/QTilde/SplittingFunctions/HalfHalfZeroEWSplitFn.cc --- a/Shower/QTilde/SplittingFunctions/HalfHalfZeroEWSplitFn.cc +++ b/Shower/QTilde/SplittingFunctions/HalfHalfZeroEWSplitFn.cc @@ -1,243 +1,243 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the HalfHalfZeroEWSplitFn class. // #include "HalfHalfZeroEWSplitFn.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "Herwig/Decay/TwoBodyDecayMatrixElement.h" #include "Herwig/Models/StandardModel/SMFFHVertex.h" using namespace Herwig; IBPtr HalfHalfZeroEWSplitFn::clone() const { return new_ptr(*this); } IBPtr HalfHalfZeroEWSplitFn::fullclone() const { return new_ptr(*this); } void HalfHalfZeroEWSplitFn::persistentOutput(PersistentOStream & os) const { os << ghqq_ << _theSM; } void HalfHalfZeroEWSplitFn::persistentInput(PersistentIStream & is, int) { is >> ghqq_ >> _theSM; } // The following static variable is needed for the type description system in ThePEG. DescribeClass describeHerwigHalfHalfZeroEWSplitFn("Herwig::HalfHalfZeroEWSplitFn", "HwShower.so"); void HalfHalfZeroEWSplitFn::Init() { static ClassDocumentation documentation ("The HalfHalfZeroEWSplitFn class implements the splitting q->qH"); } void HalfHalfZeroEWSplitFn::doinit() { SplittingFunction::doinit(); tcSMPtr sm = generator()->standardModel(); double sw2 = sm->sin2ThetaW(); ghqq_ = 1./sqrt(4.*sw2); _theSM = dynamic_ptr_cast(generator()->standardModel()); } void HalfHalfZeroEWSplitFn::getCouplings(double & gH, const IdList & ids) const { if(abs(ids[2]->id())==ParticleID::h0) { //get quark masses Energy mq; if(abs(ids[0]->id())==ParticleID::c) mq = getParticleData(ParticleID::c)->mass(); else if(abs(ids[0]->id())==ParticleID::b) mq = getParticleData(ParticleID::b)->mass(); else if(abs(ids[0]->id())==ParticleID::t) mq = getParticleData(ParticleID::t)->mass(); Energy mW = getParticleData(ParticleID::Wplus)->mass(); gH = ghqq_*(mq/mW); } else assert(false); } void HalfHalfZeroEWSplitFn::getCouplings(double & gH, const IdList & ids, const Energy2 t) const { if(abs(ids[2]->id())==ParticleID::h0) { //get quark masses Energy mq; if(abs(ids[0]->id())==ParticleID::c) mq = _theSM->mass(t,getParticleData(ParticleID::c)); else if(abs(ids[0]->id())==ParticleID::b) mq = _theSM->mass(t,getParticleData(ParticleID::b)); else if(abs(ids[0]->id())==ParticleID::t) mq = _theSM->mass(t,getParticleData(ParticleID::t)); Energy mW = getParticleData(ParticleID::Wplus)->mass(); //Energy mW = _theSM->mass(t,getParticleData(ParticleID::Wplus)); gH = ghqq_*(mq/mW); } else assert(false); } double HalfHalfZeroEWSplitFn::P(const double z, const Energy2 t, - const IdList &ids, const bool mass, const RhoDMatrix & rho) const { + const IdList &ids, const bool mass, const RhoDMatrix &) const { double gH(0.); getCouplings(gH,ids,t); double val = (1.-z); Energy mq, mH; //get masses if(mass) { mq = ids[0]->mass(); mH = ids[2]->mass(); } else { // to assure the particle mass in non-zero if(abs(ids[0]->id())==ParticleID::c) mq = getParticleData(ParticleID::c)->mass(); else if(abs(ids[0]->id())==ParticleID::b) mq = getParticleData(ParticleID::b)->mass(); else if(abs(ids[0]->id())==ParticleID::t) mq = getParticleData(ParticleID::t)->mass(); mH = getParticleData(ParticleID::h0)->mass(); } val += (4.*sqr(mq) - sqr(mH))/(t*(1. - z)*z); val *= sqr(gH); return colourFactor(ids)*val; } double HalfHalfZeroEWSplitFn::overestimateP(const double z, const IdList & ids) const { double gH(0.); getCouplings(gH,ids); return sqr(gH)*colourFactor(ids)*(1.-z); } double HalfHalfZeroEWSplitFn::ratioP(const double z, const Energy2 t, const IdList & ids, const bool mass, - const RhoDMatrix & rho) const { + const RhoDMatrix & ) const { double gH(0.); getCouplings(gH,ids,t); double val = 1.; Energy mq, mH; if(mass) { mq = ids[0]->mass(); mH = ids[2]->mass(); } else { // to assure the particle mass in non-zero if(abs(ids[0]->id())==ParticleID::c) mq = getParticleData(ParticleID::c)->mass(); else if(abs(ids[0]->id())==ParticleID::b) mq = getParticleData(ParticleID::b)->mass(); else if(abs(ids[0]->id())==ParticleID::t) mq = getParticleData(ParticleID::t)->mass(); mH = getParticleData(ParticleID::h0)->mass(); } val += (4.*sqr(mq) - sqr(mH))/(t*(1. - z)*z); return val; } double HalfHalfZeroEWSplitFn::integOverP(const double z, const IdList & ids, unsigned int PDFfactor) const { double gH(0.); getCouplings(gH,ids); double pre = colourFactor(ids)*sqr(gH); switch (PDFfactor) { case 0: //OverP return pre*(z-sqr(z)/2.); case 1: //OverP/z return pre*(log(z)-z); case 2: //OverP/(1-z) return pre*z; case 3: //OverP/[z(1-z)] return pre*log(z); default: throw Exception() << "HalfHalfZeroEWSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } double HalfHalfZeroEWSplitFn::invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor) const { double gH(0.); getCouplings(gH,ids); double pre = colourFactor(ids)*sqr(gH); switch (PDFfactor) { case 0: return 1. - sqrt(1. - 2.*r/pre); case 1: //OverP/z case 2: //OverP/(1-z) return r/pre; case 3: //OverP/[z(1-z)] return exp(r/pre); default: throw Exception() << "HalfHalfZeroEWSplitFn::invIntegOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } bool HalfHalfZeroEWSplitFn::accept(const IdList &ids) const { if(ids.size()!=3) return false; if(ids[2]->id()==ParticleID::h0) { if(ids[0]->id()==ids[1]->id() && (ids[0]->id()==4 || ids[0]->id()==5 || ids[0]->id()==6)) return true; } return false; } vector > HalfHalfZeroEWSplitFn::generatePhiForward(const double, const Energy2, const IdList & , const RhoDMatrix &) { // no dependence on the spin density matrix, dependence on off-diagonal terms cancels // and rest = splitting function for Tr(rho)=1 as required by defn return vector >(1,make_pair(0,1.)); } vector > HalfHalfZeroEWSplitFn::generatePhiBackward(const double, const Energy2, const IdList & , const RhoDMatrix &) { // no dependence on the spin density matrix, dependence on off-diagonal terms cancels // and rest = splitting function for Tr(rho)=1 as required by defn return vector >(1,make_pair(0,1.)); } DecayMEPtr HalfHalfZeroEWSplitFn::matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool) { // calculate the kernal DecayMEPtr kernal(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0))); //get masses Energy mq, mH; if(abs(ids[0]->id())==ParticleID::c) mq = getParticleData(ParticleID::c)->mass(); else if(abs(ids[0]->id())==ParticleID::b) mq = getParticleData(ParticleID::b)->mass(); else if(abs(ids[0]->id())==ParticleID::t) mq = getParticleData(ParticleID::t)->mass(); mH = getParticleData(ParticleID::h0)->mass(); double gH(0.); Energy2 tC = t/(z*(1-z)); getCouplings(gH,ids,tC); double mqt = mq/sqrt(tC); double mHt = mH/sqrt(tC); double num1 = gH*(1.+z)*mqt; double num2 = gH*sqrt(-sqr(mqt)*(1.-z) - sqr(mHt)*z + z*(1.-z)*(sqr(mqt)+z*(1.-z))); //watch this double dnum = sqrt(2.)*sqrt((1.-z)*sqr(z)); Complex phase = exp(Complex(0.,1.)*phi); Complex cphase = conj(phase); (*kernal)(0,0,0) = num1/dnum; (*kernal)(0,1,0) = cphase*num2/dnum; (*kernal)(1,0,0) = -phase*num2/dnum; (*kernal)(1,1,0) = num1/dnum; // return the answer return kernal; } diff --git a/UnderlyingEvent/MPIHandler.h b/UnderlyingEvent/MPIHandler.h --- a/UnderlyingEvent/MPIHandler.h +++ b/UnderlyingEvent/MPIHandler.h @@ -1,898 +1,890 @@ // -*- C++ -*- // // MPIHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MPIHandler_H #define HERWIG_MPIHandler_H // // This is the declaration of the MPIHandler class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/PDT/StandardMatchers.h" #include "Herwig/Utilities/GSLBisection.h" //#include "Herwig/Utilities/GSLMultiRoot.h" #include "Herwig/Utilities/GSLIntegrator.h" #include "Herwig/Shower/UEBase.h" #include #include "ProcessHandler.h" #include "MPIHandler.fh" namespace Herwig { using namespace ThePEG; /** \ingroup UnderlyingEvent * \class MPIHandler * This class is responsible for generating additional * semi hard partonic interactions. * * \author Manuel B\"ahr * * @see \ref MPIHandlerInterfaces "The interfaces" * defined for MPIHandler. * @see ProcessHandler * @see ShowerHandler * @see HwRemDecayer */ class MPIHandler: public UEBase { /** * Maximum number of scatters */ static const unsigned int maxScatters_ = 99; /** * Class for the integration is a friend to access private members */ friend struct Eikonalization; friend struct TotalXSecBisection; friend struct slopeAndTotalXSec; friend struct slopeInt; friend struct slopeBisection; public: /** A vector of SubProcessHandlers. */ typedef vector SubHandlerList; /** A vector of Cuts. */ typedef vector CutsList; /** A vector of ProcessHandlers. */ typedef vector ProcessHandlerList; /** A vector of cross sections. */ typedef vector XSVector; /** A pair of multiplicities: hard, soft. */ typedef pair MPair; - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ MPIHandler(): softMult_(0), identicalToUE_(-1), PtOfQCDProc_(-1.0*GeV), Ptmin_(-1.0*GeV), hardXSec_(0*millibarn), softXSec_(0*millibarn), totalXSecExp_(0*millibarn), softMu2_(ZERO), beta_(100.0/GeV2), algorithm_(2), numSubProcs_(0), colourDisrupt_(0.0), softInt_(true), twoComp_(true), DLmode_(2), avgNhard_(0.0), avgNsoft_(0.0), energyExtrapolation_(3), EEparamA_(0.6*GeV), EEparamB_(37.5*GeV), refScale_(7000.*GeV), pT0_(2.875*GeV), b_(0.3101), offset_(622.204*GeV) {} - /** - * The destructor. - */ - virtual ~MPIHandler(){} - //@} - public: /** @name Methods for the MPI generation. */ //@{ /* * @return true if for this beam setup MPI can be generated */ virtual bool beamOK() const; /** * Return true or false depending on whether soft interactions are enabled. */ virtual bool softInt() const {return softInt_;} /** * Get the soft multiplicity from the pretabulated multiplicity * distribution. Generated in multiplicity in the first place. * @return the number of extra soft events in this collision */ virtual unsigned int softMultiplicity() const {return softMult_;} /** * Sample from the pretabulated multiplicity distribution. * @return the number of extra events in this collision */ virtual unsigned int multiplicity(unsigned int sel=0); /** * Select a StandardXComb according to it's weight * @return that StandardXComb Object * @param sel is the subprocess that should be returned, * if more than one is specified. */ virtual tStdXCombPtr generate(unsigned int sel=0); //@} /** @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(); /** * Initialize this Multiple Interaction handler and all related objects needed to * generate additional events. */ virtual void initialize(); /** * Finalize this Multiple Interaction handler and all related objects needed to * generate additional events. */ virtual void finalize(); /** * Clean up the XCombs from our subprocesses after each event. * ThePEG cannot see them, so the usual cleaning misses these. */ virtual void clean(); /** * Write out accumulated statistics about integrated cross sections. */ void statistics() const; /** * The level of statistics. Controlls the amount of statistics * written out after each run to the EventGenerators * .out file. Simply the EventHandler method is called here. */ int statLevel() const {return eventHandler()->statLevel();} /** * Return the hard cross section above ptmin */ CrossSection hardXSec() const { return hardXSec_; } /** * Return the soft cross section below ptmin */ CrossSection softXSec() const { return softXSec_; } /** * Return the inelastic cross section */ CrossSection inelasticXSec() const { return inelXSec_; } /** * Return the non-diffractive cross section assumed by the model. * TODO: See comment at diffractiveXSec. */ CrossSection nonDiffractiveXSec() const { return (1.-diffratio_)*inelXSec_; } /** * Return the diffractive cross section assumed by the model. * For now the diffractive cross section is seen as a fixed part of the * inelastic cross section. * TODO: Energy dependence and/or Include diffraction in Eikonalisation. */ CrossSection diffractiveXSec() const { return diffratio_*inelXSec_; } /** @name Simple access functions. */ //@{ /** * Return the ThePEG::EventHandler assigned to this handler. * This methods shadows ThePEG::StepHandler::eventHandler(), because * it is not virtual in ThePEG::StepHandler. This is ok, because this * method would give a null-pointer at some stages, whereas this method * gives access to the explicitely copied pointer (in initialize()) * to the ThePEG::EventHandler. */ tEHPtr eventHandler() const {return theHandler;} /** * Return the current handler */ static const MPIHandler * currentHandler() { return currentHandler_; } /** * Return theAlgorithm. */ virtual int Algorithm() const {return algorithm_;} /** * Return the ptmin parameter of the model */ virtual Energy Ptmin() const { if(Ptmin_ > ZERO) return Ptmin_; else throw Exception() << "MPIHandler::Ptmin called without initialize before" << Exception::runerror; } /** * Return the slope of the soft pt spectrum as calculated. */ virtual InvEnergy2 beta() const { if(beta_ != 100.0/GeV2) return beta_; else throw Exception() << "MPIHandler::beta called without initialization" << Exception::runerror; } /** * Return the pt Cutoff of the Interaction that is identical to the UE * one. */ virtual Energy PtForVeto() const {return PtOfQCDProc_;} /** * Return the number of additional "hard" processes ( = multiple * parton scattering) */ virtual unsigned int additionalHardProcs() const {return numSubProcs_-1;} /** * Return the fraction of colour disrupted connections to the * suprocesses. */ virtual double colourDisrupt() const {return colourDisrupt_;} 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; //@} private: /** * Access the list of sub-process handlers. */ const SubHandlerList & subProcesses() const {return theSubProcesses;} /** * Access the list of sub-process handlers. */ SubHandlerList & subProcesses() {return theSubProcesses;} /** * Access the list of cuts. */ const CutsList & cuts() const {return theCuts;} /** * Access the list of cuts. */ CutsList & cuts() {return theCuts;} /** * Access the list of sub-process handlers. */ const ProcessHandlerList & processHandlers() const {return theProcessHandlers;} /** * Access the list of sub-process handlers. */ ProcessHandlerList & processHandlers() {return theProcessHandlers;} /** * Method to calculate the individual probabilities for N scatters in the event. * @param UEXSecs is(are) the inclusiv cross section(s) for the UE process(es). */ void Probs(XSVector UEXSecs); /** * Debug method to check the individual probabilities. * @param filename is the file the output gets written to */ void MultDistribution(string filename) const; /** * Return the value of the Overlap function A(b) for a given impact * parameter \a b. * @param b impact parameter * @param mu2 = inv hadron radius squared. 0 will use the value of * invRadius_ * @return inverse area. */ InvArea OverlapFunction(Length b, Energy2 mu2=ZERO) const; /** * Method to calculate the poisson probability for expectation value * \f$ = A(b)\sigma\f$, and multiplicity N. */ double poisson(Length b, CrossSection sigma, unsigned int N, Energy2 mu2=ZERO) const; /** * Returns the total cross section for the current CMenergy. The * decision which parametrization will be used is steered by a * external parameter of this class. */ CrossSection totalXSecExp() const; /** * Difference of the calculated total cross section and the * experimental one from totalXSecExp. * @param softXSec = the soft cross section that is used * @param softMu2 = the soft radius, if 0 the hard radius will be used */ CrossSection totalXSecDiff(CrossSection softXSec, Energy2 softMu2=ZERO) const; /** * Difference of the calculated elastic slope and the * experimental one from slopeExp. * @param softXSec = the soft cross section that is used * @param softMu2 = the soft radius, if 0 the hard radius will be used */ InvEnergy2 slopeDiff(CrossSection softXSec, Energy2 softMu2=ZERO) const; /** * Returns the value of the elastic slope for the current CMenergy. * The decision which parametrization will be used is steered by a * external parameter of this class. */ InvEnergy2 slopeExp() const; /** * Calculate the minimal transverse momentum from the extrapolation */ void overrideUECuts(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MPIHandler & operator=(const MPIHandler &) = delete; /** * A pointer to the EventHandler that calls us. Has to be saved, because the * method eventHandler() inherited from ThePEG::StepHandler returns a null-pointer * sometimes. Leif changed that in r1053 so that a valid pointer is present, when * calling doinitrun(). */ tEHPtr theHandler; /** * The list of SubProcessHandlers. */ SubHandlerList theSubProcesses; /** * The kinematical cuts used for this collision handler. */ CutsList theCuts; /** * List of ProcessHandler used to sample different processes independently */ ProcessHandlerList theProcessHandlers; /** * A ThePEG::Selector where the individual Probabilities P_N are stored * and the actual Multiplicities can be selected. */ Selector theMultiplicities; /** * Variable to store the soft multiplicity generated for a event. This * has to be stored as it is generated at the time of the hard * additional interactions but used later on. */ unsigned int softMult_; /** * Variable to store the multiplicity of the second hard process */ vector additionalMultiplicities_; /** * Variable to store the information, which process is identical to * the UE one (QCD dijets). * 0 means "real" hard one * n>0 means the nth additional hard scatter * -1 means no one! */ int identicalToUE_; /** * Variable to store the minimal pt of the process that is identical * to the UE one. This only has to be set, if it can't be determined * automatically (i.e. when reading QCD LesHouches files in). */ Energy PtOfQCDProc_; /** * Variable to store the parameter ptmin */ Energy Ptmin_; /** * Variable to store the hard cross section above ptmin */ CrossSection hardXSec_; /** * Variable to store the final soft cross section below ptmin */ CrossSection softXSec_; /** * Variable to store the inelastic cross section */ CrossSection inelXSec_; /** * Variable to store the total pp cross section (assuming rho=0!) as * measured at LHC. If this variable is set, this value is used in the * subsequent run instead of any of the Donnachie-Landshoff * parametrizations. */ CrossSection totalXSecExp_; /** * Variable to store the soft radius, that is calculated during * initialization for the two-component model. */ Energy2 softMu2_; /** * slope to the non-perturbative pt spectrum: \f$d\sigma/dp_T^2 = A \exp * (- beta p_T^2)\f$. Its value is determined durint initialization. */ InvEnergy2 beta_; /** * Switch to be set from outside to determine the algorithm used for * UE activity. */ int algorithm_; /** * Inverse hadron Radius squared \f$ (\mu^2) \f$. Used inside the overlap function. */ Energy2 invRadius_; /** * Member variable to store the actual number of separate SubProcesses */ unsigned int numSubProcs_; /** * Variable to store the relative number of colour disrupted * connections to additional subprocesses. This variable is used in * Herwig::HwRemDecayer but store here, to have access to all * parameters through one Object. */ double colourDisrupt_; /** * Flag to store whether soft interactions, i.e. pt < ptmin should be * simulated. */ bool softInt_; /** * Flag to steer wheather the soft part has a different radius, that * will be dynamically fixed. */ bool twoComp_; /** * Switch to determine which Donnachie & Landshoff parametrization * should be used. */ unsigned int DLmode_; /** * Variable to store the average hard multiplicity. */ double avgNhard_; /** * Variable to store the average soft multiplicity. */ double avgNsoft_; /** * The current handler */ static MPIHandler * currentHandler_; /** * Flag to store whether to calculate the minimal UE pt according to an * extrapolation formula or whether to use MPIHandler:Cuts[0]:OneCuts[0]:MinKT */ unsigned int energyExtrapolation_; /** * Parameters for the energy extrapolation formula */ Energy EEparamA_; Energy EEparamB_; Energy refScale_; Energy pT0_; double b_; Energy offset_; /** * Parameters to set the fraction of diffractive cross section in the inelastic cross section. */ double diffratio_=0.2; protected: /** @cond EXCEPTIONCLASSES */ /** * Exception class used by the MultipleInteractionHandler, when something * during initialization went wrong. * \todo understand!!! */ class InitError: public Exception {}; /** @endcond */ }; } namespace Herwig { /** * A struct for the 2D root finding that is necessary to determine the * soft cross section and the soft radius that is needed to describe * the total cross section correctly. * NOT IN USE CURRENTLY */ struct slopeAndTotalXSec : public GSLHelper { public: /** * Constructor */ slopeAndTotalXSec(tcMPIHPtr handler): handler_(handler) {} /** second argument type */ typedef Energy2 ArgType2; /** second value type */ typedef InvEnergy2 ValType2; /** first element of the vector like function to find root for * @param softXSec soft cross-section * @param softMu2 \f$\mu^2\f$ */ CrossSection f1(ArgType softXSec, ArgType2 softMu2) const { return handler_->totalXSecDiff(softXSec, softMu2); } /** second element of the vector like function to find root for * @param softXSec soft cross-section * @param softMu2 \f$\mu^2\f$ */ InvEnergy2 f2(ArgType softXSec, ArgType2 softMu2) const { return handler_->slopeDiff(softXSec, softMu2); } /** provide the actual units of use */ virtual ValType vUnit() const {return 1.0*millibarn;} /** otherwise rounding errors may get significant */ virtual ArgType aUnit() const {return 1.0*millibarn;} /** provide the actual units of use */ ValType2 vUnit2() const {return 1.0/GeV2;} /** otherwise rounding errors may get significant */ ArgType2 aUnit2() const {return GeV2;} private: /** * Pointer to the handler */ tcMPIHPtr handler_; }; /** * A struct for the root finding that is necessary to determine the * slope of the soft pt spectrum to match the soft cross section */ struct betaBisection : public GSLHelper{ public: /** * Constructor. * @param soft = soft cross section, i.e. the integral of the soft * pt spectrum f(u=p_T^2) = dsig exp(-beta*u/u_min) * @param dsig = dsigma_hard/dp_T^2 at the p_T cutoff * @param ptmin = p_T cutoff */ betaBisection(CrossSection soft, DiffXSec dsig, Energy ptmin) : softXSec_(soft), dsig_(dsig), ptmin_(ptmin) {} /** * Operator that is used inside the GSLBisection class */ virtual Energy2 operator ()(InvEnergy2 beta) const { if( fabs(beta*GeV2) < 1.E-4 ) beta = (beta > ZERO) ? 1.E-4/GeV2 : -1.E-4/GeV2; return (exp(beta*sqr(ptmin_)) - 1.0)/beta - softXSec_/dsig_; } /** provide the actual units of use */ virtual ValType vUnit() const {return 1.0*GeV2;} /** provide the actual units of use */ virtual ArgType aUnit() const {return 1.0/GeV2;} private: /** soft cross section */ CrossSection softXSec_; /** dsigma/dp_T^2 at ptmin */ DiffXSec dsig_; /** pt cutoff */ Energy ptmin_; }; /** * A struct for the root finding that is necessary to determine the * soft cross section and soft mu2 that are needed to describe the * total cross section AND elastic slope correctly. */ struct slopeBisection : public GSLHelper { public: /** Constructor */ slopeBisection(tcMPIHPtr handler) : handler_(handler) {} /** * Return the difference of the calculated elastic slope to the * experimental one for a given value of the soft mu2. During that, * the soft cross section get fixed. */ InvEnergy2 operator ()(Energy2 arg) const; /** Return the soft cross section that has been calculated */ CrossSection softXSec() const {return softXSec_;} private: /** const pointer to the MPIHandler to give access to member functions.*/ tcMPIHPtr handler_; /** soft cross section that is determined on the fly.*/ mutable CrossSection softXSec_; }; /** * A struct for the root finding that is necessary to determine the * soft cross section that is needed to describe the total cross * section correctly. */ struct TotalXSecBisection : public GSLHelper { public: /** * Constructor * @param handler The handler * @param softMu2 \f$\mu^2\f$ */ TotalXSecBisection(tcMPIHPtr handler, Energy2 softMu2=ZERO): handler_(handler), softMu2_(softMu2) {} /** * operator to return the cross section * @param argument input cross section */ CrossSection operator ()(CrossSection argument) const { return handler_->totalXSecDiff(argument, softMu2_); } /** provide the actual units of use */ virtual ValType vUnit() const {return 1.0*millibarn;} /** otherwise rounding errors may get significant */ virtual ArgType aUnit() const {return 1.0*millibarn;} private: /** * The handler */ tcMPIHPtr handler_; /** * \f$\mu^2\f$ */ Energy2 softMu2_; }; /** * Typedef for derivative of the length */ typedef decltype(mm/GeV2) LengthDiff; /** * A struct for the integrand for the slope */ struct slopeInt : public GSLHelper{ public: /** Constructor * @param handler The handler * @param hard The hard cross section * @param soft The soft cross section * @param softMu2 \f$\mu^2\f$ */ slopeInt(tcMPIHPtr handler, CrossSection hard, CrossSection soft=0*millibarn, Energy2 softMu2=ZERO) : handler_(handler), hardXSec_(hard), softXSec_(soft), softMu2_(softMu2) {} /** * Operator to return the answer * @param arg The argument */ ValType operator ()(ArgType arg) const; private: /** * Pointer to the Handler that calls this integrand */ tcMPIHPtr handler_; /** * The hard cross section to be eikonalized */ CrossSection hardXSec_; /** * The soft cross section to be eikonalized. Default is zero */ CrossSection softXSec_; /** * The inv radius^2 of the soft interactions. */ Energy2 softMu2_; }; /** * A struct for the eikonalization of the inclusive cross section. */ struct Eikonalization : public GSLHelper{ /** * The constructor * @param handler is the pointer to the MPIHandler to get access to * MPIHandler::OverlapFunction and member variables of the MPIHandler. * @param option is a flag, whether the inelastic or the total * @param handler The handler * @param hard The hard cross section * @param soft The soft cross section * @param softMu2 \f$\mu^2\f$ * cross section should be returned (-2 or -1). For option = N > 0 the integrand * is N*(A(b)*sigma)^N/N! exp(-A(b)*sigma) this is the P_N*sigma where * P_N is the Probability of having exactly N interaction (including the hard one) * This is equation 14 from "Jimmy4: Multiparton Interactions in HERWIG for the LHC" */ Eikonalization(tcMPIHPtr handler, int option, CrossSection hard, CrossSection soft=0*millibarn, Energy2 softMu2=ZERO) : theHandler(handler), theoption(option), hardXSec_(hard), softXSec_(soft), softMu2_(softMu2) {} /** * Get the function value */ Length operator ()(Length argument) const; private: /** * Pointer to the Handler that calls this integrand */ tcMPIHPtr theHandler; /** * A flag to switch between the calculation of total and inelastic cross section * or calculations for the individual probabilities. See the constructor */ int theoption; /** * The hard cross section to be eikonalized */ CrossSection hardXSec_; /** * The soft cross section to be eikonalized. Default is zero */ CrossSection softXSec_; /** * The inv radius^2 of the soft interactions. */ Energy2 softMu2_; }; } #endif /* HERWIG_MPIHandler_H */ diff --git a/UnderlyingEvent/ProcessHandler.cc b/UnderlyingEvent/ProcessHandler.cc --- a/UnderlyingEvent/ProcessHandler.cc +++ b/UnderlyingEvent/ProcessHandler.cc @@ -1,443 +1,432 @@ // -*- C++ -*- // // ProcessHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ProcessHandler class. // #include "ProcessHandler.h" #include "ThePEG/Utilities/DescribeClass.h" #include "MPISampler.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Handlers/SubProcessHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/Handlers/LuminosityFunction.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Cuts/Cuts.h" #include "Herwig/Utilities/GaussianIntegrator.h" #include "gsl/gsl_sf_bessel.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "ProcessHandler.tcc" #endif #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; ProcessHandler::ProcessHandler() : theBinStrategy(2) {} -ProcessHandler::ProcessHandler(const ProcessHandler & x) - : Interfaced(x), LastXCombInfo<>(x), - theSampler(x.theSampler), theHandler(x.theHandler), - theCuts(x.theCuts), theSubProcess(x.theSubProcess), - theXCombs(x.theXCombs), theXSecs(x.theXSecs), - theBinStrategy(x.theBinStrategy), theMEXMap(x.theMEXMap), - theMaxDims(x.theMaxDims) {} - - -ProcessHandler::~ProcessHandler() {} - void ProcessHandler::initialize(tSubHdlPtr sub, tCutsPtr cut, tEHPtr eh) { /* This method should be called during the "read" phase! However due to the unpredictable order in which objects are set up by ThePEG it is not guaranteed that the EventHandler is present. So we move that to doinitrun of the MPIHandler! */ if( !eh || !sub || !cut ) throw Exception() << "ProcessHandler was created without specifying a SubProcess " << "or a Cut Object or the EventHandler." << Exception::runerror; theHandler = eh; theCuts = cut; theSubProcess = sub; theSampler = new_ptr(MPISampler()); Energy maxEnergy = lumiFn().maximumCMEnergy(); xCombs().clear(); xSecs().clear(); cuts()->initialize(sqr(maxEnergy), lumiFn().Y()); CutsPtr kincuts = (*subProcess()).cuts()? (*subProcess()).cuts(): cuts(); if ( (*subProcess()).cuts() ) kincuts->initialize(sqr(maxEnergy), lumiFn().Y()); PExtrPtr pextract = (*subProcess()).pExtractor(); // Use an empty ckkw handler for the additional interactions: tCascHdlPtr ckkw = tCascHdlPtr(); PartonPairVec vpc = pextract->getPartons(maxEnergy, incoming(), *kincuts); // The last parton bin pair was in fact the bins corresponding to // the incoming particles, so we remove them, but save them to // keep them referenced. PBPair orig = vpc.back(); vpc.pop_back(); for ( PartonPairVec::iterator ppit = vpc.begin(); ppit != vpc.end(); ++ppit ) for ( MEVector::const_iterator meit = (*subProcess()).MEs().begin(); meit != (*subProcess()).MEs().end(); ++meit ) addME(maxEnergy, subProcess(), pextract, kincuts, ckkw, *meit, *ppit); xSecs().resize(xCombs().size()); theMaxDims.clear(); switch ( binStrategy() ) { case 0: { theMaxDims.push_back(0); for ( int i = 0, N = xCombs().size(); i < N; ++i ) theMaxDims[0] = max(theMaxDims[0], xCombs()[i]->nDim()); break; } case 1: { for ( int i = 0, N = xCombs().size(); i < N; ++i ) theMEXMap[xCombs()[i]->matrixElement()].push_back(xCombs()[i]); MEXMap::const_iterator mei = theMEXMap.begin(); for ( int i = 0, N = theMEXMap.size(); i < N; ++i, ++mei) { theMaxDims.push_back(0); for ( int j = 0, M = mei->second.size(); j < M; ++j ) theMaxDims[i] = max(theMaxDims[i], mei->second[j]->nDim()); } break; } case 2: { for ( int i = 0, N = xCombs().size(); i < N; ++i ) theMaxDims.push_back(xCombs()[i]->nDim()); break; } } tMPISamplerPtr smplr = dynamic_ptr_cast(sampler()); smplr->setProcessHandler(this); //sample 2 PSpoints to check for zero xsec in advance smplr->initialize(); } void ProcessHandler:: addME(Energy maxEnergy, tSubHdlPtr sub, tPExtrPtr extractor, tCutsPtr cuts, tCascHdlPtr ckkw, tMEPtr me, const PBPair & pBins) { typedef MEBase::DiagramVector DiagramVector; typedef map DiagramMap; cPDPair pin(pBins.first->parton(), pBins.second->parton()); DiagramVector diag = me->diagrams(); DiagramMap tdiag; DiagramMap tmdiag; for ( int i = 0, N = diag.size(); i < N; ++i ) { if ( diag[i]->partons()[0] == pin.first && diag[i]->partons()[1] == pin.second ) tdiag[diag[i]->getTag()].push_back(diag[i]); if ( diag[i]->partons()[0] == pin.second && diag[i]->partons()[1] == pin.first ) tmdiag[diag[i]->getTag()].push_back(diag[i]); } bool mirror = false; if ( ( mirror = tdiag.empty() ) ) tdiag = tmdiag; for ( DiagramMap::iterator dit = tdiag.begin(); dit != tdiag.end(); ++dit ) { //todo: hope that it is no problem that I take the EventHandler here and not the ProcessHandler: StdXCombPtr xcomb = new_ptr(StandardXComb(maxEnergy, incoming(), eventHandler(), sub, extractor, ckkw, pBins, cuts, me, dit->second, mirror)); if ( xcomb->checkInit() ) xCombs().push_back(xcomb); else generator()->logWarning( InitError() << "The matrix element '" << xcomb->matrixElement()->name() << "' cannot generate the diagram '" << dit->first << "' when used together with the parton extractor '" << xcomb->pExtractor()->name() << "'. The corresponding diagram is switched off." << Exception::warning); } } tStdXCombPtr ProcessHandler::select(int bin, double weight) { int i = upper_bound(xSecs().begin(), xSecs().end(), UseRandom::rnd()*xSecs().back()) - xSecs().begin(); tStdXCombPtr lastXC; switch ( binStrategy() ) { case 0: lastXC = xCombs()[i]; break; case 1: { MEXMap::iterator mei = theMEXMap.begin(); for ( int j = 0; j < bin; ++j) ++mei; lastXC = mei->second[i]; break; } case 2: lastXC = xCombs()[bin]; break; } // clean up the old XComb object before switching to a new one if ( theLastXComb && theLastXComb != lastXC ) theLastXComb->clean(); theLastXComb = lastXC; lastXC->select(weight); lastXC->accept(); lastXC->matrixElement()->setXComb(lastXC); return lastXC; } CrossSection ProcessHandler:: dSigDR(const pair ll, Energy2 maxS, int ibin, int nr, const double * r) { PPair inc = make_pair(incoming().first->produceParticle(), incoming().second->produceParticle()); SimplePhaseSpace::CMS(inc, maxS); XVector xv; switch ( binStrategy() ) { case 0: xv = xCombs(); break; case 1: { MEXMap::iterator mei = theMEXMap.begin(); for ( int i = 0; i < ibin; ++i) ++mei; xv = mei->second; break; } case 2: xv = XVector(1, xCombs()[ibin]); break; } xSecs().resize(xv.size()); for ( int i = 0, N = xv.size(); i < N; ++i ) xv[i]->prepare(inc); CrossSection sum = 0.0*nanobarn; for ( int i = 0, N = xv.size(); i < N; ++i ) xSecs()[i] = ( sum += xv[i]->dSigDR(ll, nr, r) ); return sum; } CrossSection ProcessHandler::dSigDR(const vector & r) { double jac = 1.0; pair ll = lumiFn().generateLL(&r[0], jac); Energy2 maxS = sqr(lumiFn().maximumCMEnergy())/exp(ll.first + ll.second); int bin = sampler()->lastBin(); CrossSection x = jac*lumiFn().value(incoming(), ll.first, ll.second) *dSigDR(ll, maxS, bin, nDim(bin) - lumiDim(), &r[lumiDim()]); return x; } int ProcessHandler::nBins() const { switch ( binStrategy() ) { case 0: return 1; case 1: return theMEXMap.size(); case 2: return xCombs().size(); } return -1; } void ProcessHandler::doinitrun() { Interfaced::doinitrun(); sampler()->initrun(); for ( int i = 0, N = xCombs().size(); i < N; ++i ) xCombs()[i]->reset(); double weight(0); //sample N PSpoints to get an estimate of the xsec for(unsigned int i=0; i<100000; i++){ weight = sampler()->generate(); tStdXCombPtr lastXC = select(sampler()->lastBin(), weight); } } CrossSection ProcessHandler::integratedXSec() const { if ( sampler()->integratedXSec() == 0.0*nanobarn ) return sampler()->maxXSec(); Stat tot; for ( int i = 0, N = xCombs().size(); i < N; ++i ) { const StandardXComb & x = *xCombs()[i]; Stat s; s = Stat(x.stats().attempts(), x.stats().accepted(), x.stats().sumWeights(), sampler()->integratedXSec(), sampler()->sumWeights()); tot += s; } return tot.xSec(); } void ProcessHandler::statistics(ostream & os, Stat & tot) const { if ( statLevel() == 0 ) return; map partonMap; map meMap; map extractMap; // Stat tot; for ( int i = 0, N = xCombs().size(); i < N; ++i ) { const StandardXComb & x = *xCombs()[i]; Stat s; s = Stat(x.stats().attempts(), x.stats().accepted(), x.stats().sumWeights(), sampler()->integratedXSec(), sampler()->sumWeights()); partonMap[x.partons()] += s; meMap[x.matrixElement()] += s; extractMap[x.pExtractor()] += s; tot += s; } string line = "=======================================" "=======================================\n"; if ( tot.accepted <= 0 ) { os << line << "No events generated by event handler '" << name() << "'." << endl; return; } os //<< line << "Statistics for event handler \'" << name() << "\':\n" << " " << "generated number of Cross-section\n" << " " << " events attempts (nb)\n"; os << line << "Total:" << setw(42) << tot.accepted << setw(13) << tot.attempted << setw(17) << tot.xSec()/nanobarn << endl << line; if ( statLevel() == 1 ) return; os << "Per matrix element breakdown:\n"; for ( map::iterator i = meMap.begin(); i != meMap.end(); ++i ) { string n = i->first->name(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted << setw(13) << i->second.attempted << setw(17) << i->second.xSec()/nanobarn << endl; } os << line; if ( statLevel() == 2 ) return; os << "Per parton extractor breakdown:\n"; for ( map::iterator i = extractMap.begin(); i != extractMap.end(); ++i ) { string n = i->first->name(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted << setw(13) << i->second.attempted << setw(17) << i->second.xSec()/millibarn << endl; } os << line; os << "Per incoming partons breakdown:\n"; for ( map::iterator i = partonMap.begin(); i != partonMap.end(); ++i ) { string n = i->first.first->PDGName() + " " + i->first.second->PDGName(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted << setw(13) << i->second.attempted << setw(17) << i->second.xSec()/millibarn << endl; } os << line; if ( statLevel() == 3 ) return; os << "Detailed breakdown:\n"; double xsectot = sampler()->integratedXSec()/ (sampler()->sumWeights()*nanobarn); for ( int i = 0, N = xCombs().size(); i < N; ++i ) { const StandardXComb & x = *xCombs()[i]; os << "(" << x.pExtractor()->name() << ") " << x.partons().first->PDGName() << " " << x.partons().second->PDGName() << " (" << x.matrixElement()->name() << " " << x.lastDiagram()->getTag() << ") " << endl << setw(48) << x.stats().accepted() << setw(13) << x.stats().attempts() << setw(17) << x.stats().sumWeights()*xsectot << endl; } os << line; } void ProcessHandler::persistentOutput(PersistentOStream & os) const { os << theBinStrategy << theSubProcess << theCuts << theLastXComb << theXCombs << ounit(theXSecs, nanobarn) << theMaxDims << theMEXMap << theSampler << theHandler; } void ProcessHandler::persistentInput(PersistentIStream & is, int) { is >> theBinStrategy >> theSubProcess >> theCuts >> theLastXComb >> theXCombs >> iunit(theXSecs, nanobarn) >> theMaxDims >> theMEXMap >> theSampler >> theHandler; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigProcessHandler("Herwig::ProcessHandler", "JetCuts.so SimpleKTCut.so HwMPI.so"); void ProcessHandler::Init() { static ClassDocumentation documentation ("There is soon documentation for the ProcessHandler class"); /* * Object will be created outside of *.in files * static Switch interfaceBinStrategy ("BinStrategy", "The strategy to be used when sampling different ThePEG::XComb " "objects. An ThePEG::XComb objet represents a pair of incoming " "parton types as defined by a ThePEG::PartonExtractor and a " "matrix element.", &ProcessHandler::theBinStrategy, 2, false, false); static SwitchOption interfaceBinStrategy0 (interfaceBinStrategy, "AllAtOnce", "All bins are sampled together.", 0); static SwitchOption interfaceBinStrategy1 (interfaceBinStrategy, "PerME", "All bins which have the same matrix element object are sampled together.", 1); static SwitchOption interfaceBinStrategy2 (interfaceBinStrategy, "Individual", "All bins are sampled individually.", 2); */ } diff --git a/UnderlyingEvent/ProcessHandler.h b/UnderlyingEvent/ProcessHandler.h --- a/UnderlyingEvent/ProcessHandler.h +++ b/UnderlyingEvent/ProcessHandler.h @@ -1,422 +1,409 @@ // -*- C++ -*- // // ProcessHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ProcessHandler_H #define HERWIG_ProcessHandler_H // // This is the declaration of the ProcessHandler class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Handlers/SubProcessHandler.h" #include "ThePEG/Handlers/LuminosityFunction.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/SamplerBase.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/Handlers/CascadeHandler.h" #include #include "ProcessHandler.fh" #include "stat.h" namespace Herwig { using namespace ThePEG; /** \ingroup UnderlyingEvent * \class ProcessHandler * This class is for handling the sampling of * semi hard partonic interactions. If several types of partonic interactions * are needed. Each of them has it's own ProcessHandler. A reference to them is * stored in MPIHandler, which administers everything. * * \author Manuel B\"ahr * * @see \ref ProcessHandlerInterfaces "The interfaces" * defined for ProcessHandler. * @see MPISampler * @see MPIHandler */ class ProcessHandler: public Interfaced, public LastXCombInfo<> { public: /** A weighted list of pointers to StandardXComb objects. */ typedef Selector XSelector; /** A vector of pointers to StandardXComb objects. */ typedef vector XVector; /** A vector of cross sections. */ typedef vector XSVector; /** Map of pointers to StandardXComb objects indexed by pointers to * the corresponding MEBase object. */ typedef map MEXMap; public: - /** @name Standard constructors and destructors. */ - //@{ /** * The default constructor. */ ProcessHandler(); - /** - * The copy constructor. - */ - ProcessHandler(const ProcessHandler &); - - /** - * The destructor. - */ - virtual ~ProcessHandler(); - //@} - public: /** @name Methods for the MPI generation. */ //@{ /** * Select a StandardXComb according to it's weight * @return that StandardXComb Object */ inline tStdXCombPtr generate(); //@} /** @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(); /** * Initialize this Multiple Interaction handler and all related objects needed to * generate additional events. */ void initialize(tSubHdlPtr sub, tCutsPtr cuts, tEHPtr eh); /** * Return the integrated cross section. */ CrossSection integratedXSec() const; /** * Write out accumulated statistics about intergrated cross sections * and stuff. */ void statistics(ostream &, Stat &) const; /** @name Functions used for the actual generation */ //@{ /** * Return the cross section for the chosen phase space point. * @param r a vector of random numbers to be used in the generation * of a phase space point. */ virtual CrossSection dSigDR(const vector & r); /** @name Simple access functions. */ //@{ /** * The level of statistics. Controlls the amount of statistics * written out after each run to the EventGenerators * .out file. Simply the EventHandler method is called here. */ inline int statLevel() const; /** * The pair of incoming particle types obtained via the EventHandler */ inline const cPDPair & incoming() const; /** * Access the luminosity function via the EventHandler. */ inline const LuminosityFunction & lumiFn() const; /** * The number of phase space dimensions used by the luminosity * function. Calls the corresponding StandardEventHandler method. */ inline int lumiDim() const; /** * Return the number of separate bins of StandardXComb objects to * sample. */ int nBins() const; /** * Return the number of phase space dimensions needed for the * sampling of indicated bin of StandardXComb objects. */ inline int maxDim(int bin) const; /** * The number of dimensions of the basic phase space to generate * sub-processes in for a given bin of StandardXComb objects. */ inline int nDim(int bin) const; /** * Return the maximum number attemts allowed to select a sub-process * for each event. Calls the corresponding StandardEventHandler method. */ inline long maxLoop() const; protected: /** * Generate a phase space point and return the corresponding cross * section. Is called from sSigDR(const vector &). * @param ll a pair of doubles giving the logarithms of the (inverse * energy fractions of the maximum CMS energy of the incoming * particles. * @param maxS the maximum squared CMS energy of the incoming particles. * @param ibin the preselected bin of StandardXComb objects to choose * sub-process from * @param nr the number of random numbers availiable in \a r. * @param r an array of random numbers to be used to generate a * phase-space point. */ virtual CrossSection dSigDR(const pair ll, Energy2 maxS, int ibin, int nr, const double * r); /** * Select an StandardXComb. Given a preselected bin, \a ibin of * StandardXComb objects pick one to generate the corresponding * sub-process with the given \a weight. */ tStdXCombPtr select(int bin, double weight); /** * Create and add StandardXComb objects. * * @param maxEnergy the maximum CMS energy of the incoming particles. * @param sub a pointer to the SubProcessHandler object. * @param extractor a pointer to the PartonExtractor object. * @param cuts a pointer to the Cuts object. * @param ckkw a currently empty pointer to a CascadeHandler to be used for CKKW reweighting. * @param me a pointer to the MEBase object. * @param pBins a pair of PartonBins describing the * partons extracted from the particles */ void addME(Energy maxEnergy, tSubHdlPtr sub, tPExtrPtr extractor, tCutsPtr cuts, tCascHdlPtr ckkw, tMEPtr me, const PBPair & pBins); /** * Return the vector of StandardXComb objects. */ inline const XVector & xCombs() const; /** * Return the vector of StandardXComb objects. */ inline XVector & xCombs(); /** * Return the vector of cross sections. */ inline const XSVector & xSecs() const; /** * Return the vector of cross sections. */ inline XSVector & xSecs(); /** * Return the strategy to be used when sampling different StandardXComb * objects. * @return 0 if all StandardXComb objects are sampled together. 1 if * all StandardXComb objects which have the same matrix element object are * sampled together. 2 if all StandardXComb objects are sampled separately. */ inline int binStrategy() const; /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ inline 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. */ inline virtual IBPtr fullclone() const; //@} private: /** * Return the ThePEG::EventHandler assigned to this handler. * This methods shadows ThePEG::StepHandler::eventHandler(), because * it is not virtual in ThePEG::StepHandler. This is ok, because this * method would give a null-pointer at some stages, whereas this method * gives access to the explicitely copied pointer (in doinitrun()) * to the ThePEG::EventHandler. */ inline tEHPtr eventHandler() const; /** * Return the sampler assigned to this handler. */ inline tSamplerPtr sampler(); /** * Return the sampler assigned to this handler. */ inline tcSamplerPtr sampler() const; /** * Return a reference to the Cuts of this * MultipleInteractionHandler. Note that these cuts may be overridden by the * SubProcess chosen. */ inline tCutsPtr cuts() const; /** * Access the sub-process handler. */ inline tSubHdlPtr subProcess(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ProcessHandler & operator=(const ProcessHandler &) = delete; /** * The phase space sampler responsible for generating phase space * points according to the cross section given by this handler. */ SamplerPtr theSampler; /** * A pointer to the EventHandler that calls us. Has to be saved, because the * method eventHandler() inherited from ThePEG::StepHandler returns a null-pointer * sometimes. Leif changed that in r1053 so that a valid pointer is present, when * calling doinitrun(). */ tEHPtr theHandler; /** * The kinematical cuts used for this collision handler. */ tCutsPtr theCuts;//used a transient pointer, //because regular pointer is already in MPIHandler /** * The SubProcessHandler that is connected to this ProcessHandler. */ tSubHdlPtr theSubProcess;//used a transient pointer, //because regular pointer is already in MPIHandler /** * The StandardXComb objects. */ XVector theXCombs; /** * The (incrementally summed) cross sections associated with the * StandardXComb objects for the last selected phase space point. */ XSVector theXSecs; /** * The strategy to be used when sampling different StandardXComb * objects. 0 means all StandardXComb objects are sampled * together. 1 means all StandardXComb objects which have the same * matrix element object are sampled together. 2 means all * StandardXComb objects are sampled separately. */ int theBinStrategy; /** * The map used to store all XBins with the same matrix element for * option 1 in theBinStrategy. */ MEXMap theMEXMap; /** * The number of degrees of freedom needed to generate the phase * space for the different bins. */ vector theMaxDims; protected: /** @cond EXCEPTIONCLASSES */ /** * Exception class used by the MultipleInteractionHandler, when something * during initialization went wrong. * \todo understand!!! */ class InitError: public Exception {}; /** @endcond */ }; } #include "ProcessHandler.icc" #endif /* HERWIG_ProcessHandler_H */