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/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/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/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/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/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/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/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/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 */