diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -1,101 +1,102 @@ Makefile$ Makefile\.in$ \.deps$ \.libs$ \.l[ao]$ \.so$ \.so\. \.o$ ~$ \.pyc$ \.codereplace$ \.orig$ \.tar\.(gz|bz2)$ ^autom4te.cache$ ^config.herwig$ ^config.log$ ^config.status$ ^configure$ ^include/Herwig$ ^Config/config.guess$ ^Config/config.h$ ^Config/config.h.in$ ^Config/config.sub$ ^Config/depcomp$ ^Config/compile$ ^Config/install-sh$ ^Config/missing$ ^Config/stamp-h1$ ^Config/ar-lib$ ^Contrib/make_makefiles.sh$ ^Utilities/hgstamp.inc$ ^Doc/HerwigDefaults.in$ ^Doc/refman-html$ ^Doc/fixinterfaces.pl$ ^Doc/refman.conf$ ^Doc/refman.h$ ^Doc/AllInterfaces.h$ ^Doc/HerwigDefaults.rpo$ ^Doc/Herwig-refman.tag$ ^Doc/tagfileThePEG.tag$ ^Doc/.*\.log$ ^INSTALL$ ^aclocal.m4$ ^confdefs.h$ ^conftest.c$ ^conftest.err$ ^include/done-all-links$ ^libtool$ \.dirstamp$ ^src/hgstamp.inc$ ^src/herwigopts.h$ ^src/herwigopts.c$ ^src/defaults/Analysis.in$ ^src/defaults/Decays.in$ ^src/defaults/decayers.in$ ^src/herwig-config$ ^src/.*\.(run|tex|out|log|rpo|spc|top|dump|dot|aux|pdf|ps|png|svg|hepmc|dvi)$ ^src/Makefile-UserModules$ ^lib/done-all-links$ ^lib/apple-fixes$ ^src/defaults/PDF.in$ ^src/defaults/done-all-links$ ^src/tune$ ^src/Herwig$ ^src/Herwig-scratch$ ^src/tests/.*\.(time|mult|Bmult|chisq)$ ^Tests/.*/.*\.(top|ps|pyc|info|dat|pdf|png)$ ^Tests/.*\.(top|ps|pyc|info|dat|pdf|png|log|out)$ ^Tests/.*\.(top|run|tex|mult|Bmult|aida|yoda)$ ^Tests/Rivet-.*$ ^Tests/Rivet/(LEP|DIS|LHC|TVT|Star|BFactory|ISR|SppS)-.*\.in$ ^Tests/plots$ ^Tests/Herwig$ ^Tests/.*index.html$ ^Herwig\- ^Models/Feynrules/python/Makefile-FR$ ^MatrixElement/Matchbox/External/MadGraph/mg2herwig.py$ ^MatrixElement/Matchbox/Scales/MatchboxScale.cc$ ^Utilities/Statistics/herwig-combinedistributions$ ^Utilities/Statistics/herwig-combineruns$ ^Utilities/Statistics/herwig-makedistributions$ ^src/defaults/MatchboxDefaults.in$ ^src/defaults/setup.gosam.in$ ^src/Matchbox/LO-DefaultShower.in$ ^src/Matchbox/LO-DipoleShower.in$ ^src/Matchbox/LO-NoShower.in$ ^src/Matchbox/MCatLO-DefaultShower.in$ ^src/Matchbox/MCatLO-DipoleShower.in$ ^src/Matchbox/MCatNLO-DefaultShower.in$ ^src/Matchbox/MCatNLO-DipoleShower.in$ ^src/Matchbox/NLO-NoShower.in$ ^src/Matchbox/Powheg-DefaultShower.in$ ^src/Matchbox/Powheg-DipoleShower.in$ ^src/Matchbox/done-all-links$ ^src/snippets/done-all-links$ ^Utilities/XML/xml_test$ ^Utilities/utilities_test$ ^Utilities/versionstring.h$ test\.(log|trs)$ test-suite\.log$ ^Config/test-driver$ +param_card\.dat$ diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -1,20 +1,21 @@ 168ae2110e964d62fbc1331a1c2e095952a67748 release-2-5-2 3abb4fa42e20e332796c2572334c2d77204cd0e0 release-2-4-2 4796ca080aafd5daa3b7349b015cb1df944428a2 release-2-5-0 76da042f056eb153981b4d005d5474ffb90a5e88 release-2-4-1 81a684a558413c69df314365eabf09893ffd43d8 release-2-6-0 bd75cd00d99f4bdbaed992daf98f0a73c0f91e9b release-2-4-0 ff6ecc8d49ce10299303b050394bd5cb5837f1c3 release-2-5-1 d0389f5453b2c210923e1adc7b872b18269de668 release-2-6-1 f8998033021185942533b824607285feb3fbd2dc release-2-6-1a cead23e428b9aacaf2d709e722624e54f844498b release-2-6-1b 191db4655439045f912cb21bd905e729d59ec7bc release-2-6-2 edb538156e9c3d64bb842934b4cebf0126aeb9ea release-2-6-3 eb4a104591859ecac18746b1ad54d6aa0c2a5d1a release-2-7-0 568971ac5b3c1d044c9259f2280a8304fc5a62e9 trunk-before-QED 6e3edb6cfeb4ee48687eb4eb3d016026fc59d602 trunk-after-QED 633abb80b571aa23088957df60e9b0000bbb8a22 release-2-7-1 1bdde095d2346c15ee548e5406a96f0fc6d6e0f1 beforeHQ a0f9fb821396092bdbeee532bcb0bd624f58335b before_MB_merge 270c1e6b34aa7f758f1d9868c4d3e1ec4bf4e709 herwig-7-0-0 6e0f198c1c2603ecd1a0b6cfe40105cda4bd58c5 herwig-7-0-1 +566c1de845a8070559cda45b1bdb40afa18cb2cc herwig-7-0-2 diff --git a/AUTHORS b/AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -1,56 +1,56 @@ ================================================================================ -Herwig 7 (Herwig++ 3) +Herwig 7.0.2 ================================================================================ Please contact for any queries. -------------------------------------------------------------------------------- Herwig is actively developed by: -------------------------------------------------------------------------------- Johannes Bellm Stefan Gieseke David Grellscheid Simon Plätzer Michael Rauch Christian Reuschle Peter Richardson Peter Schichtel Mike Seymour Andrzej Siödmok Alix Wilcock -------------------------------------------------------------------------------- With contributions by: -------------------------------------------------------------------------------- Nadine Fischer Marco A. Harrendorf Graeme Nail Andreas Papaefstathiou Daniel Rauch -------------------------------------------------------------------------------- Former authors are: -------------------------------------------------------------------------------- Ken Arnold Manuel Bähr Luca d'Errico Martyn Gigg Keith Hamilton Seyi Latunde-Dada Alberto Ribon Christian Röhr Pavel Růžička Alex Schofield Thomas Schuh Alexander Sherstnev Philip Stephens Martin Stoll Louise Suter Jon Tully Bryan Webber David Winn Benedikt Zimmermann diff --git a/DipoleShower/Base/DipoleEventReweight.h b/DipoleShower/Base/DipoleEventReweight.h --- a/DipoleShower/Base/DipoleEventReweight.h +++ b/DipoleShower/Base/DipoleEventReweight.h @@ -1,107 +1,117 @@ // -*- C++ -*- // // DipoleEventReweight.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_DipoleEventReweight_H #define Herwig_DipoleEventReweight_H // // This is the declaration of the DipoleEventReweight class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/StandardModel/AlphaSBase.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * \brief Reweight full final states produced by the shower * * @see \ref DipoleEventReweightInterfaces "The interfaces" * defined for DipoleEventReweight. */ class DipoleEventReweight: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DipoleEventReweight(); /** * The destructor. */ virtual ~DipoleEventReweight(); //@} public: /** * Return the weight for the given incoming, outgoing coloured and - * hard colour neutral particles + * hard colour neutral particles, after an emission was generated */ virtual double weight(const PPair& in, const PList& out, const PList& hard, Ptr::tptr as) const = 0; /** - * Return the weight for the given incoming, outgoing coloured and - * hard colour neutral particles + * Return the weight which is applied to a cascade only once even if there was + * no emission from the cascade at all. */ - virtual double weightNoEmission(const PPair& in, const PList& out, const PList& hard, + virtual double weightCascade(const PPair& in, const PList& out, const PList& hard, Ptr::tptr as) const = 0; + /** + * Return true, if the event reweight should be applied to the hard scattering + */ + virtual bool firstInteraction() const = 0; + + /** + * Return true, if the event reweight should be applied to secondary interactions + */ + virtual bool secondaryInteractions() const = 0; + public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleEventReweight & operator=(const DipoleEventReweight &); }; } #endif /* Herwig_DipoleEventReweight_H */ diff --git a/DipoleShower/Base/DipoleSplittingGenerator.cc b/DipoleShower/Base/DipoleSplittingGenerator.cc --- a/DipoleShower/Base/DipoleSplittingGenerator.cc +++ b/DipoleShower/Base/DipoleSplittingGenerator.cc @@ -1,587 +1,611 @@ // -*- C++ -*- // // DipoleSplittingGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleSplittingGenerator class. // #include #include "DipoleSplittingGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/DipoleShower/DipoleShowerHandler.h" using namespace Herwig; DipoleSplittingGenerator::DipoleSplittingGenerator() : HandlerBase(), theExponentialGenerator(0), prepared(false), presampling(false), theDoCompensate(false) { if ( ShowerHandler::currentHandler() ) setGenerator(ShowerHandler::currentHandler()->generator()); } DipoleSplittingGenerator::~DipoleSplittingGenerator() { if ( theExponentialGenerator ) { delete theExponentialGenerator; theExponentialGenerator = 0; } } IBPtr DipoleSplittingGenerator::clone() const { return new_ptr(*this); } IBPtr DipoleSplittingGenerator::fullclone() const { return new_ptr(*this); } void DipoleSplittingGenerator::wrap(Ptr::ptr other) { assert(!prepared); theOtherGenerator = other; } +void DipoleSplittingGenerator::resetVariations() { + for ( map::iterator w = currentWeights.begin(); + w != currentWeights.end(); ++w ) + w->second = 1.; +} + void DipoleSplittingGenerator::prepare(const DipoleSplittingInfo& sp) { generatedSplitting = sp; generatedSplitting.splittingKinematics(splittingKernel()->splittingKinematics()); generatedSplitting.splittingParameters().resize(splittingKernel()->nDimAdditional()); if ( wrapping() ) { generatedSplitting.emitterData(theSplittingKernel->emitter(generatedSplitting.index())); generatedSplitting.spectatorData(theSplittingKernel->spectator(generatedSplitting.index())); generatedSplitting.emissionData(theSplittingKernel->emission(generatedSplitting.index())); parameters.resize(theOtherGenerator->nDim()); prepared = true; return; } generatedSplitting.emitterData(splittingKernel()->emitter(generatedSplitting.index())); generatedSplitting.spectatorData(splittingKernel()->spectator(generatedSplitting.index())); generatedSplitting.emissionData(splittingKernel()->emission(generatedSplitting.index())); presampledSplitting = generatedSplitting; prepared = true; parameters.resize(nDim()); theExponentialGenerator = new exsample::exponential_generator(); theExponentialGenerator->sampling_parameters().maxtry = maxtry(); theExponentialGenerator->sampling_parameters().presampling_points = presamplingPoints(); theExponentialGenerator->sampling_parameters().freeze_grid = freezeGrid(); + theExponentialGenerator->detuning(detuning()); theExponentialGenerator->docompensate(theDoCompensate); theExponentialGenerator->function(this); theExponentialGenerator->initialize(); } void DipoleSplittingGenerator::fixParameters(const DipoleSplittingInfo& sp, Energy optHardPt) { assert(generator()); assert(!presampling); assert(prepared); assert(sp.index() == generatedSplitting.index()); generatedSplitting.scale(sp.scale()); parameters[3] = sp.scale()/generator()->maximumCMEnergy(); generatedSplitting.hardPt(sp.hardPt()); parameters[0] = splittingKinematics()->ptToRandom(optHardPt == ZERO ? generatedSplitting.hardPt() : min(generatedSplitting.hardPt(),optHardPt), sp.scale(), sp.emitterX(), sp.spectatorX(), generatedSplitting.index(), *splittingKernel()); size_t shift = 4; if ( generatedSplitting.index().emitterPDF().pdf() && generatedSplitting.index().spectatorPDF().pdf() ) { generatedSplitting.emitterX(sp.emitterX()); generatedSplitting.spectatorX(sp.spectatorX()); parameters[4] = sp.emitterX(); parameters[5] = sp.spectatorX(); shift += 2; } if ( generatedSplitting.index().emitterPDF().pdf() && !generatedSplitting.index().spectatorPDF().pdf() ) { generatedSplitting.emitterX(sp.emitterX()); parameters[4] = sp.emitterX(); ++shift; } if ( !generatedSplitting.index().emitterPDF().pdf() && generatedSplitting.index().spectatorPDF().pdf() ) { generatedSplitting.spectatorX(sp.spectatorX()); parameters[4] = sp.spectatorX(); ++shift; } if ( splittingReweight() ) { parameters[shift] = splittingReweight()->evaluate(sp); ++shift; } if ( splittingKernel()->nDimAdditional() ) copy(sp.lastSplittingParameters().begin(),sp.lastSplittingParameters().end(),parameters.begin()+shift); if ( sp.emitter() ) generatedSplitting.emitter(sp.emitter()); if ( sp.spectator() ) generatedSplitting.spectator(sp.spectator()); } int DipoleSplittingGenerator::nDim() const { assert(!wrapping()); assert(prepared); int ret = 4; // 0 pt, 1 z, 2 phi, 3 scale, 4/5 xs + parameters if ( generatedSplitting.index().emitterPDF().pdf() ) { ++ret; } if ( generatedSplitting.index().spectatorPDF().pdf() ) { ++ret; } if ( splittingReweight() ) ++ret; ret += splittingKernel()->nDimAdditional(); return ret; } const vector& DipoleSplittingGenerator::sampleFlags() { assert(!wrapping()); if ( !theFlags.empty() ) return theFlags; theFlags.resize(nDim(),false); theFlags[0] = true; theFlags[1] = true; theFlags[2] = true; // 0 pt, 1 z, 2 phi return theFlags; } const pair,vector >& DipoleSplittingGenerator::support() { assert(!wrapping()); if ( !theSupport.first.empty() ) return theSupport; vector lower(nDim(),0.); vector upper(nDim(),1.); pair kSupport = generatedSplitting.splittingKinematics()->kappaSupport(generatedSplitting); pair xSupport = generatedSplitting.splittingKinematics()->xiSupport(generatedSplitting); lower[0] = kSupport.first; lower[1] = xSupport.first; upper[0] = kSupport.second; upper[1] = xSupport.second; if ( splittingReweight() ) { pair bounds = splittingReweight()->reweightBounds(generatedSplitting.index()); int pos = 4; if ( generatedSplitting.index().emitterPDF().pdf() ) { ++pos; } if ( generatedSplitting.index().spectatorPDF().pdf() ) { ++pos; } lower[pos] = bounds.first; upper[pos] = bounds.second; } theSupport.first = lower; theSupport.second = upper; return theSupport; } void DipoleSplittingGenerator::startPresampling() { assert(!wrapping()); splittingKernel()->startPresampling(generatedSplitting.index()); presampling = true; } void DipoleSplittingGenerator::stopPresampling() { assert(!wrapping()); splittingKernel()->stopPresampling(generatedSplitting.index()); presampling = false; } bool DipoleSplittingGenerator::haveOverestimate() const { assert(!wrapping()); assert(prepared); return generatedSplitting.splittingKinematics()->haveOverestimate() && splittingKernel()->haveOverestimate(generatedSplitting); } bool DipoleSplittingGenerator::overestimate(const vector& point) { assert(!wrapping()); assert(prepared); assert(!presampling); assert(haveOverestimate()); if ( ! generatedSplitting.splittingKinematics()->generateSplitting(point[0],point[1],point[2], generatedSplitting, *splittingKernel()) ) return 0.; generatedSplitting.splittingKinematics()->prepareSplitting(generatedSplitting); return ( generatedSplitting.splittingKinematics()->jacobianOverestimate() * splittingKernel()->overestimate(generatedSplitting) * (splittingReweight() ? splittingReweight()->evaluate(generatedSplitting) : 1.) ); } double DipoleSplittingGenerator::invertOverestimateIntegral(double value) const { assert(!wrapping()); assert(prepared); assert(!presampling); assert(haveOverestimate()); return splittingKernel()->invertOverestimateIntegral(generatedSplitting,value); } double DipoleSplittingGenerator::evaluate(const vector& point) { assert(!wrapping()); assert(prepared); assert(generator()); DipoleSplittingInfo& split = ( !presampling ? generatedSplitting : presampledSplitting ); split.continuesEvolving(); size_t shift = 4; if ( presampling ) { split.scale(point[3] * generator()->maximumCMEnergy()); if ( split.index().emitterPDF().pdf() && split.index().spectatorPDF().pdf() ) { split.emitterX(point[4]); split.spectatorX(point[5]); shift += 2; } if ( split.index().emitterPDF().pdf() && !split.index().spectatorPDF().pdf() ) { split.emitterX(point[4]); ++shift; } if ( !split.index().emitterPDF().pdf() && split.index().spectatorPDF().pdf() ) { split.spectatorX(point[4]); ++shift; } if ( splittingReweight() ) ++shift; if ( splittingKernel()->nDimAdditional() ) copy(point.begin()+shift,point.end(),split.splittingParameters().begin()); split.hardPt(split.splittingKinematics()->ptMax(split.scale(), split.emitterX(), split.spectatorX(), split.index(), *splittingKernel())); } if ( ! split.splittingKinematics()->generateSplitting(point[0],point[1],point[2],split,*splittingKernel()) ) { split.lastValue(0.); return 0.; } split.splittingKinematics()->prepareSplitting(split); if ( split.stoppedEvolving() ) { split.lastValue(0.); return 0.; } + if ( !presampling ) + splittingKernel()->clearAlphaPDFCache(); double kernel = splittingKernel()->evaluate(split); if ( splittingReweight() ) { if ( !presampling ) kernel *= splittingReweight()->evaluate(split); else kernel *= point[shift-1]; } double jac = split.splittingKinematics()->jacobian(); // multiply in the profile scales when relevant assert(ShowerHandler::currentHandler()); if ( ShowerHandler::currentHandler()->firstInteraction() && ShowerHandler::currentHandler()->profileScales() && !presampling ) { Energy hard = ShowerHandler::currentHandler()->hardScale(); if ( hard > ZERO ) kernel *= ShowerHandler::currentHandler()->profileScales()->hardScaleProfile(hard,split.lastPt()); } split.lastValue( abs(jac) * kernel ); if ( isnan(split.lastValue()) || isinf(split.lastValue()) ) { generator()->log() << "DipoleSplittingGenerator:evaluate(): problematic splitting kernel encountered for " << splittingKernel()->name() << "\n" << flush; split.lastValue(0.0); } if ( kernel < 0. ) return 0.; return split.lastValue(); } -void DipoleSplittingGenerator::doGenerate(Energy optCutoff) { +void DipoleSplittingGenerator::doGenerate(map& variations, + Energy optCutoff) { assert(!wrapping()); double res = 0.; Energy startPt = generatedSplitting.hardPt(); double optKappaCutoff = 0.0; if ( optCutoff > splittingKinematics()->IRCutoff() ) { optKappaCutoff = splittingKinematics()->ptToRandom(optCutoff, generatedSplitting.scale(), generatedSplitting.emitterX(), generatedSplitting.spectatorX(), generatedSplitting.index(), *splittingKernel()); } + resetVariations(); + while (true) { try { if ( optKappaCutoff == 0.0 ) { res = theExponentialGenerator->generate(); } else { res = theExponentialGenerator->generate(optKappaCutoff); } } catch (exsample::exponential_regenerate&) { + resetVariations(); generatedSplitting.hardPt(startPt); continue; } catch (exsample::hit_and_miss_maxtry&) { throw DipoleShowerHandler::RedoShower(); } catch (exsample::selection_maxtry&) { throw DipoleShowerHandler::RedoShower(); } break; } + for ( map::const_iterator w = currentWeights.begin(); + w != currentWeights.end(); ++w ) { + map::iterator v = variations.find(w->first); + if ( v != variations.end() ) + v->second *= w->second; + else + variations[w->first] = w->second; + } + if ( res == 0. ) { generatedSplitting.lastPt(0.0*GeV); generatedSplitting.didStopEvolving(); } else { generatedSplitting.continuesEvolving(); if ( theMCCheck ) theMCCheck->book(generatedSplitting.emitterX(), generatedSplitting.spectatorX(), generatedSplitting.scale(), startPt, generatedSplitting.lastPt(), generatedSplitting.lastZ(), 1.); } } Energy DipoleSplittingGenerator::generate(const DipoleSplittingInfo& split, + map& variations, Energy optHardPt, Energy optCutoff) { fixParameters(split,optHardPt); if ( wrapping() ) { - return theOtherGenerator->generateWrapped(generatedSplitting,optHardPt,optCutoff); + return theOtherGenerator->generateWrapped(generatedSplitting,variations,optHardPt,optCutoff); } - doGenerate(optCutoff); + doGenerate(variations,optCutoff); return generatedSplitting.lastPt(); } Energy DipoleSplittingGenerator::generateWrapped(DipoleSplittingInfo& split, + map& variations, Energy optHardPt, Energy optCutoff) { assert(!wrapping()); DipoleSplittingInfo backup = generatedSplitting; generatedSplitting = split; fixParameters(split,optHardPt); try { - doGenerate(optCutoff); + doGenerate(variations,optCutoff); } catch (...) { split = generatedSplitting; generatedSplitting = backup; throw; } Energy pt = generatedSplitting.lastPt(); split = generatedSplitting; generatedSplitting = backup; return pt; } void DipoleSplittingGenerator::completeSplitting(DipoleSplittingInfo& sp) const { pair conf = sp.configuration(); sp = generatedSplitting; sp.configuration(conf); } Ptr::tptr DipoleSplittingGenerator::splittingKernel() const { if ( wrapping() ) return theOtherGenerator->splittingKernel(); return theSplittingKernel; } Ptr::tptr DipoleSplittingGenerator::splittingReweight() const { if ( wrapping() ) return theOtherGenerator->splittingReweight(); return theSplittingReweight; } Ptr::tptr DipoleSplittingGenerator::splittingKinematics() const { if ( wrapping() ) return theOtherGenerator->splittingKinematics(); return theSplittingKernel->splittingKinematics(); } void DipoleSplittingGenerator::splittingKernel(Ptr::tptr sp) { theSplittingKernel = sp; if ( theSplittingKernel->mcCheck() ) theMCCheck = theSplittingKernel->mcCheck(); } void DipoleSplittingGenerator::splittingReweight(Ptr::tptr sp) { theSplittingReweight = sp; } void DipoleSplittingGenerator::debugGenerator(ostream& os) const { os << "--- DipoleSplittingGenerator ---------------------------------------------------\n"; os << " generating splittings using\n" << " splittingKernel = " << splittingKernel()->name() << " splittingKinematics = " << generatedSplitting.splittingKinematics()->name() << "\n" << " to sample splittings of type:\n"; os << generatedSplitting; os << "--------------------------------------------------------------------------------\n"; } void DipoleSplittingGenerator::debugLastEvent(ostream& os) const { os << "--- DipoleSplittingGenerator ---------------------------------------------------\n"; os << " last generated event:\n"; os << generatedSplitting; os << "--------------------------------------------------------------------------------\n"; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleSplittingGenerator::persistentOutput(PersistentOStream & os) const { os << theOtherGenerator << theSplittingKernel << theSplittingReweight << theMCCheck << theDoCompensate; } void DipoleSplittingGenerator::persistentInput(PersistentIStream & is, int) { is >> theOtherGenerator >> theSplittingKernel >> theSplittingReweight >> theMCCheck >> theDoCompensate; } ClassDescription DipoleSplittingGenerator::initDipoleSplittingGenerator; // Definition of the static class description member. void DipoleSplittingGenerator::Init() { static ClassDocumentation documentation ("DipoleSplittingGenerator is used by the dipole shower " "to sample splittings from a given dipole splitting kernel."); static Reference interfaceSplittingKernel ("SplittingKernel", "Set the splitting kernel to sample from.", &DipoleSplittingGenerator::theSplittingKernel, false, false, true, false, false); static Reference interfaceSplittingReweight ("SplittingReweight", "Set the splitting reweight.", &DipoleSplittingGenerator::theSplittingReweight, false, false, true, true, false); static Reference interfaceMCCheck ("MCCheck", "[debug option] MCCheck", &DipoleSplittingGenerator::theMCCheck, false, false, true, true, false); interfaceMCCheck.rank(-1); } diff --git a/DipoleShower/Base/DipoleSplittingGenerator.h b/DipoleShower/Base/DipoleSplittingGenerator.h --- a/DipoleShower/Base/DipoleSplittingGenerator.h +++ b/DipoleShower/Base/DipoleSplittingGenerator.h @@ -1,449 +1,481 @@ // -*- C++ -*- // // DipoleSplittingGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_DipoleSplittingGenerator_H #define HERWIG_DipoleSplittingGenerator_H // // This is the declaration of the DipoleSplittingGenerator class. // #include "ThePEG/Handlers/HandlerBase.h" #include "Herwig/DipoleShower/Kernels/DipoleSplittingKernel.h" #include "DipoleSplittingReweight.h" #include "Herwig/DipoleShower/Utility/DipoleMCCheck.h" #include "Herwig/Sampling/exsample/exponential_generator.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleSplittingGenerator is used by the dipole shower * to sample splittings from a given dipole splitting kernel. * * @see \ref DipoleSplittingGeneratorInterfaces "The interfaces" * defined for DipoleSplittingGenerator. */ class DipoleSplittingGenerator: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DipoleSplittingGenerator(); /** * The destructor. */ virtual ~DipoleSplittingGenerator(); //@} public: /** * Return the dipole splitting kernel. */ Ptr::tptr splittingKernel() const; /** * Return the dipole splitting reweight. */ Ptr::tptr splittingReweight() const; /** * Return the dipole splitting kinematics. */ Ptr::tptr splittingKinematics() const; /** * Set the dipole splitting kernel. */ void splittingKernel(Ptr::tptr sp); /** * Set the dipole splitting reweight. */ void splittingReweight(Ptr::tptr sp); /** * Make a wrapper around another generator. */ void wrap(Ptr::ptr other); /** * Return true, if this is actually a wrapper around * another splitting generator. */ bool wrapping() const { return theOtherGenerator; } public: /** + * Reset the current variations to one + */ + void resetVariations(); + + /** * Prepare to fill the given splitting. */ void prepare(const DipoleSplittingInfo&); /** * Fix parameters from the fiven DipoleSplittingInfo * and generate the next splitting. Return the * pt selected for the next splitting. */ Energy generate(const DipoleSplittingInfo&, + map& variations, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Fix parameters from the fiven DipoleSplittingInfo * and generate the next splitting. Return the * pt selected for the next splitting when called * from a wrapping generator. */ Energy generateWrapped(DipoleSplittingInfo&, + map& variations, Energy optHardPt = ZERO, Energy optCutoff = ZERO); /** * Complete the given splitting. */ void completeSplitting(DipoleSplittingInfo&) const; /** * Return the last generated splitting */ const DipoleSplittingInfo& lastSplitting() const { return generatedSplitting; } public: /** * Print debug information on the splitting * handled. */ void debugGenerator(ostream&) const; /** * Print debug information on the last * generated event. */ void debugLastEvent(ostream&) const; protected: /** * Update parameters given a splitting. */ void fixParameters(const DipoleSplittingInfo&, Energy optHardPt = ZERO); /** * With the parameters previuosly supplied * through fixParameters generate the next * splitting. */ - void doGenerate(Energy optCutoff = ZERO); + void doGenerate(map& variations, + Energy optCutoff = ZERO); public: /** * Return the number of random numbers * needed to sample this kernel. */ int nDim() const; /** * Flag, which variables are free variables. */ const vector& sampleFlags(); /** * Return the support of the splitting kernel. * The lower bound on the first variable is * assumed to correspond to the cutoff on the * evolution variable. */ const pair,vector >& support(); /** * Return the parameter point associated to the splitting * previously supplied through fixParameters. */ const vector& parameterPoint() const { return parameters; } /** * Indicate that presampling of this kernel * will be performed in the next calls to * evaluate until stopPresampling() is called. */ void startPresampling(); /** * Indicate that presampling of this kernel * is done until startPresampling() is called. */ void stopPresampling(); /** * Return the number of points to presample this * splitting generator. */ unsigned long presamplingPoints() const { return splittingKernel()->presamplingPoints(); } /** * Return the maximum number of trials * to generate a splitting. */ unsigned long maxtry() const { return splittingKernel()->maxtry(); } /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long freezeGrid() const { return splittingKernel()->freezeGrid(); } /** + * Return the detuning factor applied to the sampling overestimate kernel + */ + double detuning() const { return splittingKernel()->detuning(); } + + /** * Return true, if this splitting generator * is able to deliver an overestimate to the sampled * kernel. */ bool haveOverestimate() const; /** * Return an overestimate to the sampled kernel. */ bool overestimate(const vector&); /** * Invert the integral over the overestimate to equal * the given value. */ double invertOverestimateIntegral(double) const; /** * Evalute the splitting kernel. */ double evaluate(const vector&); /** + * Indicate that a veto with the given kernel value and overestimate has occured. + */ + void veto(const vector&, double p, double r) { + splittingKernel()->veto(generatedSplitting, p, r, currentWeights); + } + + /** + * Indicate that an accept with the given kernel value and overestimate has occured. + */ + void accept(const vector&, double p, double r) { + splittingKernel()->accept(generatedSplitting, p, r, currentWeights); + } + + /** * True, if sampler should apply compensation */ void doCompensate(bool yes = true) { theDoCompensate = yes; } public: /**@name Wrap to the exsample2 interface until this is finally cleaned up. */ //@{ inline const vector& variable_flags () { return sampleFlags(); } inline size_t evolution_variable () const { return 0; } inline double evolution_cutoff () { return support().first[0]; } inline const vector& parameter_point () const { return parameterPoint(); } inline void start_presampling () { startPresampling(); } inline void stop_presampling () { stopPresampling(); } inline size_t dimension () const { return nDim(); } inline unsigned long presampling_points () const { return presamplingPoints(); } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * Pointer to another generator to wrap around. */ Ptr::ptr theOtherGenerator; /** * The dipole splitting kernel to sample * splitting from. */ Ptr::ptr theSplittingKernel; /** * The dipole splitting reweight. */ Ptr::ptr theSplittingReweight; /** * Pointer to the exponential generator */ exsample::exponential_generator* theExponentialGenerator; /** * The dipole splitting to be completed. */ DipoleSplittingInfo generatedSplitting; /** * A backup of the dipole splitting to be * completed, if this generator is presampled. */ DipoleSplittingInfo presampledSplitting; /** * True, if prepared to sample splittings * of a given kind. */ bool prepared; /** * Wether or not the kernel is currently * being presampled. */ bool presampling; /** * The parameter point. */ vector parameters; /** * The sampling flags */ vector theFlags; /** * The support. */ pair,vector > theSupport; /** * Pointer to a check histogram object */ Ptr::ptr theMCCheck; /** * True, if sampler should apply compensation */ bool theDoCompensate; + /** + * The currently used weight map + */ + map currentWeights; + private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initDipoleSplittingGenerator; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleSplittingGenerator & operator=(const DipoleSplittingGenerator &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleSplittingGenerator. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleSplittingGenerator. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleSplittingGenerator class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleSplittingGenerator"; } /** * The name of a file containing the dynamic library where the class * DipoleSplittingGenerator is implemented. It may also include several, space-separated, * libraries if the class DipoleSplittingGenerator depends on other classes (base classes * excepted). In this case the listed libraries will be dynamically * linked in the order they are specified. */ static string library() { return "HwDipoleShower.so"; } }; /** @endcond */ } #endif /* HERWIG_DipoleSplittingGenerator_H */ diff --git a/DipoleShower/DipoleShowerHandler.cc b/DipoleShower/DipoleShowerHandler.cc --- a/DipoleShower/DipoleShowerHandler.cc +++ b/DipoleShower/DipoleShowerHandler.cc @@ -1,1098 +1,1099 @@ // -*- C++ -*- // // DipoleShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleShowerHandler class. // #include #include "DipoleShowerHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" // include theses to have complete types #include "Herwig/Shower/Base/Evolver.h" #include "Herwig/Shower/Base/ShowerParticle.h" #include "Herwig/PDF/MPIPDF.h" #include "Herwig/PDF/MinBiasPDF.h" #include "Herwig/Shower/Base/ShowerTree.h" #include "Herwig/Shower/Base/KinematicsReconstructor.h" #include "Herwig/Shower/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include "Herwig/DipoleShower/Utility/DipolePartonSplitter.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" using namespace Herwig; bool DipoleShowerHandler::firstWarn = true; DipoleShowerHandler::DipoleShowerHandler() : ShowerHandler(), chainOrderVetoScales(true), nEmissions(0), discardNoEmissions(false), firstMCatNLOEmission(false), doFSR(true), doISR(true), realignmentScheme(0), verbosity(0), printEvent(0), nTries(0), didRadiate(false), didRealign(false), theRenormalizationScaleFreeze(1.*GeV), theFactorizationScaleFreeze(2.*GeV), isMCatNLOSEvent(false), isMCatNLOHEvent(false), theDoCompensate(false), theFreezeGrid(500000), maxPt(ZERO), muPt(ZERO) {} DipoleShowerHandler::~DipoleShowerHandler() {} IBPtr DipoleShowerHandler::clone() const { return new_ptr(*this); } IBPtr DipoleShowerHandler::fullclone() const { return new_ptr(*this); } tPPair DipoleShowerHandler::cascade(tSubProPtr sub, XCPtr, Energy optHardPt, Energy optCutoff) { useMe(); prepareCascade(sub); + resetWeights(); if ( !doFSR && ! doISR ) return sub->incoming(); eventRecord().clear(); eventRecord().prepare(sub,dynamic_ptr_cast(lastXCombPtr()),pdfs()); if ( eventRecord().outgoing().empty() && !doISR ) return sub->incoming(); if ( !eventRecord().incoming().first->coloured() && !eventRecord().incoming().second->coloured() && !doFSR ) return sub->incoming(); nTries = 0; while ( true ) { try { didRadiate = false; didRealign = false; isMCatNLOSEvent = false; isMCatNLOHEvent = false; if ( eventRecord().xcombPtr() ) { Ptr::tptr subme = dynamic_ptr_cast::tptr>(eventRecord().xcombPtr()->matrixElement()); Ptr::tptr me = dynamic_ptr_cast::tptr>(eventRecord().xcombPtr()->matrixElement()); Ptr::tptr dipme = dynamic_ptr_cast::tptr>(eventRecord().xcombPtr()->matrixElement()); if ( subme ) { if ( subme->showerApproximation() ) { // don't do this for POWHEG-type corrections if ( !subme->showerApproximation()->needsSplittingGenerator() ) { theShowerApproximation = subme->showerApproximation(); if ( subme->realShowerSubtraction() ) isMCatNLOHEvent = true; else if ( subme->virtualShowerSubtraction() ) isMCatNLOSEvent = true; } } } else if ( me ) { if ( me->factory()->showerApproximation() ) { if ( !me->factory()->showerApproximation()->needsSplittingGenerator() ) { theShowerApproximation = me->factory()->showerApproximation(); isMCatNLOSEvent = true; } } } string error = "Inconsistent hard emission set-up in DipoleShowerHandler::cascade. "; if (evolver()->hardEmissionMode()==1 || evolver()->hardEmissionMode()==3 ) throw Exception() << error << "Cannot generate POWHEG corrections " << "for particle decays using DipoleShowerHandler. " << "Check value of Evolver:HardEmissionMode." << Exception::runerror; if ( ( isMCatNLOSEvent || isMCatNLOHEvent ) && evolver()->hardEmissionMode()==2) throw Exception() << error << "Cannot generate POWHEG matching with MC@NLO shower approximation. " << "Add 'set Evolver:HardEmissionMode 0' to input file." << Exception::runerror; if (me && me->factory()->showerApproximation()){ if(me->factory()->showerApproximation()->needsTruncatedShower()) throw Exception() << error << "No truncated shower needed with DipoleShowerHandler. Add " << "'set MEMatching:TruncatedShower No' to input file." << Exception::runerror; if (!( isMCatNLOSEvent || isMCatNLOHEvent ) && evolver()->hardEmissionMode()==0 && firstWarn){ firstWarn=false; throw Exception() << error << "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'" << Exception::warning; } } else if (subme && subme->factory()->showerApproximation()){ if(subme->factory()->showerApproximation()->needsTruncatedShower()) throw Exception() << error << "No truncated shower needed with DipoleShowerHandler. Add " << "'set MEMatching:TruncatedShower No' to input file." << Exception::runerror; if (!( isMCatNLOSEvent || isMCatNLOHEvent ) && evolver()->hardEmissionMode()==0 && firstWarn){ firstWarn=false; throw Exception() << error << "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'" << Exception::warning; } } else if (dipme && evolver()->hardEmissionMode() == 0 && firstWarn){ firstWarn=false; throw Exception() << error << "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'" << Exception::warning; } else if (!dipme && evolver()->hardEmissionMode()==2 && ShowerHandler::currentHandler()->firstInteraction()) throw Exception() << error << "POWHEG matching requested for LO events. Include " << "'set Factory:ShowerApproximation MEMatching' in input file." << Exception::runerror; } hardScales(lastXCombPtr()->lastShowerScale()); if ( verbosity > 1 ) { generator()->log() << "DipoleShowerHandler starting off:\n"; eventRecord().debugLastEvent(generator()->log()); generator()->log() << flush; } unsigned int nEmitted = 0; if ( firstMCatNLOEmission ) { if ( !isMCatNLOHEvent ) nEmissions = 1; else nEmissions = 0; } if ( !firstMCatNLOEmission ) { doCascade(nEmitted,optHardPt,optCutoff); if ( discardNoEmissions ) { if ( !didRadiate ) throw Veto(); if ( nEmissions ) if ( nEmissions < nEmitted ) throw Veto(); } } else { if ( nEmissions == 1 ) doCascade(nEmitted,optHardPt,optCutoff); } if ( intrinsicPtGenerator ) { if ( eventRecord().incoming().first->coloured() && eventRecord().incoming().second->coloured() ) { SpinOneLorentzRotation rot = intrinsicPtGenerator->kick(eventRecord().incoming(), eventRecord().intermediates()); eventRecord().transform(rot); } } didRealign = realign(); constituentReshuffle(); break; } catch (RedoShower&) { + resetWeights(); + if ( ++nTries > maxtry() ) throw ShowerTriesVeto(maxtry()); eventRecord().clear(); eventRecord().prepare(sub,dynamic_ptr_cast(lastXCombPtr()),pdfs()); continue; } catch (...) { throw; } } return eventRecord().fillEventRecord(newStep(),firstInteraction(),didRealign); } void DipoleShowerHandler::constituentReshuffle() { if ( constituentReshuffler ) { constituentReshuffler->reshuffle(eventRecord().outgoing(), eventRecord().incoming(), eventRecord().intermediates()); } } void DipoleShowerHandler::hardScales(Energy2 muf) { maxPt = generator()->maximumCMEnergy(); if ( restrictPhasespace() ) { if ( !hardScaleIsMuF() || !firstInteraction() ) { if ( !eventRecord().outgoing().empty() ) { for ( PList::const_iterator p = eventRecord().outgoing().begin(); p != eventRecord().outgoing().end(); ++p ) maxPt = min(maxPt,(**p).momentum().mt()); } else { assert(!eventRecord().hard().empty()); Lorentz5Momentum phard(ZERO,ZERO,ZERO,ZERO); for ( PList::const_iterator p = eventRecord().hard().begin(); p != eventRecord().hard().end(); ++p ) phard += (**p).momentum(); Energy mhard = phard.m(); maxPt = mhard; } maxPt *= hardScaleFactor(); } else { maxPt = hardScaleFactor()*sqrt(muf); } muPt = maxPt; } else { muPt = hardScaleFactor()*sqrt(muf); } for ( list::iterator ch = eventRecord().chains().begin(); ch != eventRecord().chains().end(); ++ch ) { Energy minVetoScale = -1.*GeV; for ( list::iterator dip = ch->dipoles().begin(); dip != ch->dipoles().end(); ++dip ) { // max scale per config Energy maxFirst = 0.0*GeV; Energy maxSecond = 0.0*GeV; for ( vector::ptr>::iterator k = kernels.begin(); k != kernels.end(); ++k ) { pair conf = make_pair(true,false); if ( (**k).canHandle(dip->index(conf)) ) { Energy scale = evolutionOrdering()->hardScale(dip->emitter(conf),dip->spectator(conf), dip->emitterX(conf),dip->spectatorX(conf), **k,dip->index(conf)); maxFirst = max(maxFirst,scale); } conf = make_pair(false,true); if ( (**k).canHandle(dip->index(conf)) ) { Energy scale = evolutionOrdering()->hardScale(dip->emitter(conf),dip->spectator(conf), dip->emitterX(conf),dip->spectatorX(conf), **k,dip->index(conf)); maxSecond = max(maxSecond,scale); } } if ( dip->leftParticle()->vetoScale() >= ZERO ) { maxFirst = min(maxFirst,sqrt(dip->leftParticle()->vetoScale())); if ( minVetoScale >= ZERO ) minVetoScale = min(minVetoScale,sqrt(dip->leftParticle()->vetoScale())); else minVetoScale = sqrt(dip->leftParticle()->vetoScale()); } if ( dip->rightParticle()->vetoScale() >= ZERO ) { maxSecond = min(maxSecond,sqrt(dip->rightParticle()->vetoScale())); if ( minVetoScale >= ZERO ) minVetoScale = min(minVetoScale,sqrt(dip->rightParticle()->vetoScale())); else minVetoScale = sqrt(dip->rightParticle()->vetoScale()); } maxFirst = min(maxPt,maxFirst); dip->emitterScale(make_pair(true,false),maxFirst); maxSecond = min(maxPt,maxSecond); dip->emitterScale(make_pair(false,true),maxSecond); } if ( !evolutionOrdering()->independentDipoles() && chainOrderVetoScales && minVetoScale >= ZERO ) { for ( list::iterator dip = ch->dipoles().begin(); dip != ch->dipoles().end(); ++dip ) { dip->leftScale(min(dip->leftScale(),minVetoScale)); dip->rightScale(min(dip->rightScale(),minVetoScale)); } } } } Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner, const Dipole& dip, pair 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; } DipoleSplittingInfo candidate; candidate.index(index); candidate.configuration(conf); candidate.emitterX(emitterX); candidate.spectatorX(spectatorX); if ( generators().find(candidate.index()) == generators().end() ) getGenerators(candidate.index()); // // NOTE -- needs proper fixing at some point // // For some very strange reason, equal_range gives back // key ranges it hasn't been asked for. This particularly // happens e.g. for FI dipoles of the same kind, but different // PDF (hard vs MPI PDF). I can't see a reason for this, // as DipoleIndex properly implements comparison for equality // and (lexicographic) ordering; for the time being, we // use equal_range, extented by an explicit check for wether // the key is indeed what we wanted. See line after (*) comment // below. // pair gens = generators().equal_range(candidate.index()); Energy winnerScale = 0.0*GeV; GeneratorMap::iterator winnerGen = generators().end(); for ( GeneratorMap::iterator gen = gens.first; gen != gens.second; ++gen ) { // (*) see NOTE above if ( !(gen->first == candidate.index()) ) continue; if ( startScale <= gen->second->splittingKinematics()->IRCutoff() ) continue; Energy dScale = gen->second->splittingKinematics()->dipoleScale(emitter->momentum(), spectator->momentum()); // in very exceptional cases happening in DIS if ( isnan(dScale/GeV ) ) throw RedoShower(); candidate.scale(dScale); candidate.continuesEvolving(); Energy hardScale = evolutionOrdering()->maxPt(startScale,candidate,*(gen->second->splittingKernel())); Energy maxPossible = gen->second->splittingKinematics()->ptMax(candidate.scale(), candidate.emitterX(), candidate.spectatorX(), candidate.index(), *gen->second->splittingKernel()); Energy ircutoff = optCutoff < gen->second->splittingKinematics()->IRCutoff() ? gen->second->splittingKinematics()->IRCutoff() : optCutoff; if ( maxPossible <= ircutoff ) { continue; } if ( maxPossible >= hardScale ) candidate.hardPt(hardScale); else { hardScale = maxPossible; candidate.hardPt(maxPossible); } - gen->second->generate(candidate,optHardPt,optCutoff); + 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 ( winnerGen == generators().end() ) { winner.didStopEvolving(); return 0.0*GeV; } if ( winner.stoppedEvolving() ) return 0.0*GeV; return winnerScale; } void DipoleShowerHandler::doCascade(unsigned int& emDone, Energy optHardPt, Energy optCutoff) { if ( nEmissions ) if ( emDone == nEmissions ) return; DipoleSplittingInfo winner; DipoleSplittingInfo dipoleWinner; while ( eventRecord().haveChain() ) { if ( verbosity > 2 ) { generator()->log() << "DipoleShowerHandler selecting splittings for the chain:\n" << eventRecord().currentChain() << flush; } list::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,make_pair(true,false),optHardPt,optCutoff); if ( nextLeftScale > winnerScale ) { winnerScale = nextLeftScale; winner = dipoleWinner; winnerDip = dip; } nextRightScale = getWinner(dipoleWinner,*dip,make_pair(false,true),optHardPt,optCutoff); if ( nextRightScale > winnerScale ) { winnerScale = nextRightScale; winner = dipoleWinner; winnerDip = dip; } if ( evolutionOrdering()->independentDipoles() ) { Energy dipScale = max(nextLeftScale,nextRightScale); if ( dip->leftScale() > dipScale ) dip->leftScale(dipScale); if ( dip->rightScale() > dipScale ) dip->rightScale(dipScale); } } if ( verbosity > 1 ) { if ( winnerDip != eventRecord().currentChain().dipoles().end() ) generator()->log() << "DipoleShowerHandler selected the splitting:\n" << winner << " for the dipole\n" << (*winnerDip) << flush; else generator()->log() << "DipoleShowerHandler could not select a splitting above the IR cutoff\n" << flush; } // pop the chain if no dipole did radiate if ( winnerDip == eventRecord().currentChain().dipoles().end() ) { - if ( theEventReweight ) { - double w = theEventReweight->weightNoEmission(eventRecord().incoming(), - eventRecord().outgoing(), - eventRecord().hard(),theGlobalAlphaS); - Ptr::tptr eh = - dynamic_ptr_cast::tptr>(eventHandler()); - assert(eh); - eh->reweight(w); - } eventRecord().popChain(); + if ( theEventReweight && eventRecord().chains().empty() ) + if ( (theEventReweight->firstInteraction() && firstInteraction()) || + (theEventReweight->secondaryInteractions() && !firstInteraction()) ) { + double w = theEventReweight->weightCascade(eventRecord().incoming(), + eventRecord().outgoing(), + eventRecord().hard(),theGlobalAlphaS); + reweight_ *= w; + } continue; } // otherwise perform the splitting didRadiate = true; isMCatNLOSEvent = false; isMCatNLOHEvent = false; pair::iterator,list::iterator> children; DipoleChain* firstChain = 0; DipoleChain* secondChain = 0; eventRecord().split(winnerDip,winner,children,firstChain,secondChain); assert(firstChain && secondChain); evolutionOrdering()->setEvolutionScale(winnerScale,winner,*firstChain,children); if ( !secondChain->dipoles().empty() ) evolutionOrdering()->setEvolutionScale(winnerScale,winner,*secondChain,children); if ( verbosity > 1 ) { generator()->log() << "DipoleShowerHandler did split the last selected dipole into:\n" << (*children.first) << (*children.second) << flush; } if ( verbosity > 2 ) { generator()->log() << "After splitting the last selected dipole, " << "DipoleShowerHandler encountered the following chains:\n" << (*firstChain) << (*secondChain) << flush; } - if ( theEventReweight ) { - double w = theEventReweight->weight(eventRecord().incoming(), - eventRecord().outgoing(), - eventRecord().hard(),theGlobalAlphaS); - Ptr::tptr eh = - dynamic_ptr_cast::tptr>(eventHandler()); - assert(eh); - eh->reweight(w); - } + if ( theEventReweight ) + if ( (theEventReweight->firstInteraction() && firstInteraction()) || + (theEventReweight->secondaryInteractions() && !firstInteraction()) ) { + double w = theEventReweight->weight(eventRecord().incoming(), + eventRecord().outgoing(), + eventRecord().hard(),theGlobalAlphaS); + reweight_ *= w; + } if ( nEmissions ) if ( ++emDone == nEmissions ) return; } } bool DipoleShowerHandler::realign() { if ( !didRadiate && !intrinsicPtGenerator ) return false; if ( eventRecord().incoming().first->coloured() || eventRecord().incoming().second->coloured() ) { if ( eventRecord().incoming().first->momentum().perp2()/GeV2 < 1e-10 && eventRecord().incoming().second->momentum().perp2()/GeV2 < 1e-10 ) return false; pair inMomenta (eventRecord().incoming().first->momentum(), eventRecord().incoming().second->momentum()); SpinOneLorentzRotation transform((inMomenta.first+inMomenta.second).findBoostToCM()); Axis dir = (transform * inMomenta.first).vect().unit(); Axis rot (-dir.y(),dir.x(),0); double theta = dir.theta(); if ( lastParticles().first->momentum().z() < ZERO ) theta = -theta; transform.rotate(-theta,rot); inMomenta.first = transform*inMomenta.first; inMomenta.second = transform*inMomenta.second; assert(inMomenta.first.z() > ZERO && inMomenta.second.z() < ZERO); Energy2 sHat = (eventRecord().incoming().first->momentum() + eventRecord().incoming().second->momentum()).m2(); pair 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 ( vector::ptr>::iterator k = kernels.begin(); k != kernels.end(); ++k ) { (**k).alphaS(as); (**k).renormalizationScaleFreeze(theRenormalizationScaleFreeze); (**k).factorizationScaleFreeze(theFactorizationScaleFreeze); } // clear the generators to be rebuild // actually, there shouldn't be any generators // when this happens. generators().clear(); } void DipoleShowerHandler::resetReweight(Ptr::tptr rw) { for ( GeneratorMap::iterator k = generators().begin(); k != generators().end(); ++k ) k->second->splittingReweight(rw); } void DipoleShowerHandler::getGenerators(const DipoleIndex& ind, Ptr::tptr rw) { bool gotone = false; for ( vector::ptr>::iterator k = kernels.begin(); k != kernels.end(); ++k ) { if ( (**k).canHandle(ind) ) { if ( verbosity > 0 ) { generator()->log() << "DipoleShowerHandler encountered the dipole configuration\n" << ind << " in event number " << eventHandler()->currentEvent()->number() << "\nwhich can be handled by the splitting kernel '" << (**k).name() << "'.\n" << flush; } gotone = true; Ptr::ptr nGenerator = new_ptr(DipoleSplittingGenerator()); nGenerator->doCompensate(theDoCompensate); nGenerator->splittingKernel(*k); nGenerator->splittingKernel()->renormalizationScaleFactor(renormalizationScaleFactor()); nGenerator->splittingKernel()->factorizationScaleFactor(factorizationScaleFactor()); nGenerator->splittingKernel()->freezeGrid(theFreezeGrid); GeneratorMap::const_iterator equivalent = generators().end(); for ( GeneratorMap::const_iterator eq = generators().begin(); eq != generators().end(); ++eq ) { if ( !eq->second->wrapping() ) if ( (**k).canHandleEquivalent(ind,*(eq->second->splittingKernel()),eq->first) ) { equivalent = eq; if ( verbosity > 0 ) { generator()->log() << "The dipole configuration " << ind << " can equivalently be handled by the existing\n" << "generator for configuration " << eq->first << " using the kernel '" << eq->second->splittingKernel()->name() << "'\n" << flush; } break; } } if ( equivalent != generators().end() ) { nGenerator->wrap(equivalent->second); } DipoleSplittingInfo dummy; dummy.index(ind); nGenerator->splittingReweight(rw); nGenerator->prepare(dummy); generators().insert(make_pair(ind,nGenerator)); } } if ( !gotone ) { generator()->logWarning(Exception() << "DipoleShowerHandler could not " << "find a splitting kernel which is able " << "to handle splittings off the dipole " << ind << ".\n" << "Please check the input files." << Exception::warning); } } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleShowerHandler::doinit() { ShowerHandler::doinit(); if ( theGlobalAlphaS ) resetAlphaS(theGlobalAlphaS); } void DipoleShowerHandler::dofinish() { ShowerHandler::dofinish(); } void DipoleShowerHandler::doinitrun() { ShowerHandler::doinitrun(); } void DipoleShowerHandler::persistentOutput(PersistentOStream & os) const { os << kernels << theEvolutionOrdering << constituentReshuffler << intrinsicPtGenerator << theGlobalAlphaS << chainOrderVetoScales << nEmissions << discardNoEmissions << firstMCatNLOEmission << doFSR << doISR << realignmentScheme << verbosity << printEvent << ounit(theRenormalizationScaleFreeze,GeV) << ounit(theFactorizationScaleFreeze,GeV) << isMCatNLOSEvent << isMCatNLOHEvent << theShowerApproximation << theDoCompensate << theFreezeGrid << theEventReweight << ounit(maxPt,GeV) << ounit(muPt,GeV); } void DipoleShowerHandler::persistentInput(PersistentIStream & is, int) { is >> kernels >> theEvolutionOrdering >> constituentReshuffler >> intrinsicPtGenerator >> theGlobalAlphaS >> chainOrderVetoScales >> nEmissions >> discardNoEmissions >> firstMCatNLOEmission >> doFSR >> doISR >> realignmentScheme >> verbosity >> printEvent >> iunit(theRenormalizationScaleFreeze,GeV) >> iunit(theFactorizationScaleFreeze,GeV) >> isMCatNLOSEvent >> isMCatNLOHEvent >> theShowerApproximation >> theDoCompensate >> theFreezeGrid >> theEventReweight >> iunit(maxPt,GeV) >> iunit(muPt,GeV); } 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); static Switch interfaceDoFSR ("DoFSR", "Switch on or off final state radiation.", &DipoleShowerHandler::doFSR, true, false, false); static SwitchOption interfaceDoFSROn (interfaceDoFSR, "On", "Switch on final state radiation.", true); static SwitchOption interfaceDoFSROff (interfaceDoFSR, "Off", "Switch off final state radiation.", false); static Switch interfaceDoISR ("DoISR", "Switch on or off initial state radiation.", &DipoleShowerHandler::doISR, true, false, false); static SwitchOption interfaceDoISROn (interfaceDoISR, "On", "Switch on initial state radiation.", true); static SwitchOption interfaceDoISROff (interfaceDoISR, "Off", "Switch off initial state radiation.", false); static Switch 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 on or off the chain ordering for veto scales.", &DipoleShowerHandler::chainOrderVetoScales, true, false, false); static SwitchOption interfaceChainOrderVetoScalesOn (interfaceChainOrderVetoScales, "On", "Switch on chain ordering for veto scales.", true); static SwitchOption interfaceChainOrderVetoScalesOff (interfaceChainOrderVetoScales, "Off", "Switch off chain ordering for veto scales.", false); interfaceChainOrderVetoScales.rank(-1); static Parameter 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 interfaceDiscardNoEmissionsOn (interfaceDiscardNoEmissions, "On", "Discard events without radiation.", true); static SwitchOption interfaceDiscardNoEmissionsOff (interfaceDiscardNoEmissions, "Off", "Do not discard events without radiation.", false); interfaceDiscardNoEmissions.rank(-1); static Switch interfaceFirstMCatNLOEmission ("FirstMCatNLOEmission", "[debug option] Only perform the first MC@NLO emission.", &DipoleShowerHandler::firstMCatNLOEmission, false, false, false); static SwitchOption interfaceFirstMCatNLOEmissionOn (interfaceFirstMCatNLOEmission, "On", "", true); static SwitchOption interfaceFirstMCatNLOEmissionOff (interfaceFirstMCatNLOEmission, "Off", "", false); interfaceFirstMCatNLOEmission.rank(-1); static Parameter 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 Reference interfaceEventReweight ("EventReweight", "", &DipoleShowerHandler::theEventReweight, false, false, true, true, false); } diff --git a/DipoleShower/Kernels/DipoleSplittingKernel.cc b/DipoleShower/Kernels/DipoleSplittingKernel.cc --- a/DipoleShower/Kernels/DipoleSplittingKernel.cc +++ b/DipoleShower/Kernels/DipoleSplittingKernel.cc @@ -1,235 +1,369 @@ // -*- C++ -*- // // DipoleSplittingKernel.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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) {} + theVirtualitySplittingScale(false), + presampling(false) {} DipoleSplittingKernel::~DipoleSplittingKernel() {} // 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 + << thePresamplingPoints << theMaxtry << theFreezeGrid << theDetuning << theFlavour << theMCCheck << theStrictLargeN << theFactorizationScaleFactor << theRenormalizationScaleFactor << ounit(theRenormalizationScaleFreeze,GeV) << ounit(theFactorizationScaleFreeze,GeV) << theVirtualitySplittingScale; } void DipoleSplittingKernel::persistentInput(PersistentIStream & is, int) { is >> theAlphaS >> iunit(theScreeningScale,GeV) >> theSplittingKinematics >> thePDFRatio - >> thePresamplingPoints >> theMaxtry >> theFreezeGrid + >> thePresamplingPoints >> theMaxtry >> theFreezeGrid >> theDetuning >> theFlavour >> theMCCheck >> theStrictLargeN >> theFactorizationScaleFactor >> theRenormalizationScaleFactor >> iunit(theRenormalizationScaleFreeze,GeV) >> iunit(theFactorizationScaleFreeze,GeV) >> theVirtualitySplittingScale; } double DipoleSplittingKernel::alphaPDF(const DipoleSplittingInfo& split, - Energy optScale) const { + 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 rScale = sqr(theRenormalizationScaleFactor)*scale; + Energy2 rScale = sqr(theRenormalizationScaleFactor*rScaleFactor)*scale; rScale = rScale > sqr(renormalizationScaleFreeze()) ? rScale : sqr(renormalizationScaleFreeze()); - Energy2 fScale = sqr(theFactorizationScaleFactor)*scale; + Energy2 fScale = sqr(theFactorizationScaleFactor*fScaleFactor)*scale; fScale = fScale > sqr(factorizationScaleFreeze()) ? fScale : sqr(factorizationScaleFreeze()); - double ret = alphaS()->value(rScale) / (2.*Constants::pi); + double alphas = 1.0; + double pdf = 1.0; - if ( split.index().initialStateEmitter() ) { - assert(pdfRatio()); - ret *= - split.lastEmitterZ() * - (*pdfRatio())(split.index().emitterPDF(), fScale, - split.index().emitterData(),split.emitterData(), - split.emitterX(),split.lastEmitterZ()); + // check if we are potentially reweighting and cache evaluations + bool evaluatePDF = true; + bool evaluateAlphaS = true; + bool variations = + !ShowerHandler::currentHandler()->showerVariations().empty() && + !presampling; + if ( variations ) { + /* + cerr << "--------------------------------------------------------------------------------\n" + << flush; + cerr << "variations ... central scale/GeV = " + << sqrt(scale/GeV2) << " r = " + << rScaleFactor << " f = " << fScaleFactor << "\n" + << flush; + */ + map::const_iterator pit = thePDFCache.find(fScaleFactor); + evaluatePDF = (pit == thePDFCache.end()); + if ( !evaluatePDF ) { + //cerr << "PDF is cached: "; + pdf = pit->second; + //cerr << pdf << "\n" << flush; + } + map::const_iterator ait = theAlphaSCache.find(rScaleFactor); + evaluateAlphaS = (ait == theAlphaSCache.end()); + if ( !evaluateAlphaS ) { + //cerr << "alphas is cached: "; + alphas = ait->second; + //cerr << alphas << "\n" << flush; + } } - if ( split.index().initialStateSpectator() ) { - assert(pdfRatio()); - ret *= - split.lastSpectatorZ() * - (*pdfRatio())(split.index().spectatorPDF(), fScale, - split.index().spectatorData(),split.spectatorData(), - split.spectatorX(),split.lastSpectatorZ()); + if ( evaluateAlphaS ) + alphas = alphaS()->value(rScale); + + 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 ) { + //cerr << "caching PDF = " << pdf << "\n" << flush; + thePDFCache[fScaleFactor] = pdf; + } + + if ( evaluateAlphaS && variations ) { + //cerr << "caching alphas = " << alphas << "\n" << flush; + theAlphaSCache[rScaleFactor] = alphas; + } + + double ret = alphas*pdf / (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 ) ) { + /* + cerr << "reweighting in accept for: " + << var->first + << " using " + << var->second.renormalizationScaleFactor << " " + << var->second.factorizationScaleFactor << " " + << var->second.firstInteraction << " " + << var->second.secondaryInteractions << "\n" << flush; + */ + 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 ) ) { + /* + cerr << "reweighting in veto for: " + << var->first + << " using " + << var->second.renormalizationScaleFactor << " " + << var->second.factorizationScaleFactor << " " + << var->second.firstInteraction << " " + << var->second.secondaryInteractions << "\n" << flush; + */ + 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 interfaceStrictLargeNOn (interfaceStrictLargeN, "On", "Replace C_F -> C_A/2 where present", true); static SwitchOption interfaceStrictLargeNOff (interfaceStrictLargeN, "Off", "Keep C_F=4/3", false); interfaceStrictLargeN.rank(-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); + } diff --git a/DipoleShower/Kernels/DipoleSplittingKernel.h b/DipoleShower/Kernels/DipoleSplittingKernel.h --- a/DipoleShower/Kernels/DipoleSplittingKernel.h +++ b/DipoleShower/Kernels/DipoleSplittingKernel.h @@ -1,439 +1,495 @@ // -*- C++ -*- // // DipoleSplittingKernel.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_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/DipoleShower/Utility/PDFRatio.h" #include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" #include "Herwig/DipoleShower/Kinematics/DipoleSplittingKinematics.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&) {} + 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&) {} + 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; /** + * 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.; } 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; } protected: /** * Return the common factor of (alphas/2pi)*(pdf ratio) */ double alphaPDF(const DipoleSplittingInfo&, - Energy optScale = ZERO) const; + 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; /** * 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; + /** + * Cache for alphas evaluations + */ + mutable map theAlphaSCache; + + /** + * Cache for PDF evaluations + */ + mutable map thePDFCache; + + /** + * True, if we are presampling + */ + bool presampling; + 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 &); }; } #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/DipoleShower/Kinematics/DipoleSplittingKinematics.cc b/DipoleShower/Kinematics/DipoleSplittingKinematics.cc --- a/DipoleShower/Kinematics/DipoleSplittingKinematics.cc +++ b/DipoleShower/Kinematics/DipoleSplittingKinematics.cc @@ -1,239 +1,274 @@ // -*- C++ -*- // // DipoleSplittingKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleSplittingKinematics class. // #include "DipoleSplittingKinematics.h" #include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.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() {} DipoleSplittingKinematics::~DipoleSplittingKinematics() {} void DipoleSplittingKinematics::persistentOutput(PersistentOStream & os) const { os << ounit(theIRCutoff,GeV) << theXMin << theMCCheck; } void DipoleSplittingKinematics::persistentInput(PersistentIStream & is, int) { is >> iunit(theIRCutoff,GeV) >> theXMin >> theMCCheck; } 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::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); using namespace RandomHelpers; if ( sampling == FlatZ ) { pair kw = generate(flat(zLims.first,zLims.second),r); - weight *= kw.second; - return kw.first; + + 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); - weight *= kw.second; - return kw.first; + + 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); - weight *= kw.second; - return kw.first; + + 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); - weight *= kw.second; - return kw.first; + + 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; if ( !spacelike ) P = p1 + p2; else P = p1 - p2; Energy2 Q2 = abs(P.m2()); Lorentz5Momentum Q = !spacelike ? Lorentz5Momentum(ZERO,ZERO,ZERO,sqrt(Q2),sqrt(Q2)) : Lorentz5Momentum(ZERO,ZERO,sqrt(Q2),ZERO,-sqrt(Q2)); if ( spacelike && Q.z() < P.z() ) Q.setZ(-Q.z()); bool boost = abs((P-Q).vect().mag2()/GeV2) > 1e-10 || abs((P-Q).t()/GeV) > 1e-5; boost &= (P*Q-Q.mass2())/GeV2 > 1e-8; Lorentz5Momentum inFrame1; if ( boost ) inFrame1 = p1 + ((P*p1-Q*p1)/(P*Q-Q.mass2()))*(P-Q); else inFrame1 = p1; Energy ptx = inFrame1.x(); Energy pty = inFrame1.y(); Energy q = 2.*inFrame1.z(); Energy Qp = sqrt(4.*(sqr(ptx)+sqr(pty))+sqr(q)); Energy Qy = sqrt(4.*sqr(pty)+sqr(q)); double cPhi = cos(phi); double sPhi = sqrt(1.-sqr(cPhi)); if ( phi > Constants::pi ) sPhi = -sPhi; Lorentz5Momentum kt; if ( !spacelike ) { kt.setT(ZERO); kt.setX(pt*Qy*cPhi/Qp); kt.setY(-pt*(4*ptx*pty*cPhi/Qp+q*sPhi)/Qy); kt.setZ(2.*pt*(-ptx*q*cPhi/Qp + pty*sPhi)/Qy); } else { kt.setT(2.*pt*(ptx*q*cPhi+pty*Qp*sPhi)/(q*Qy)); kt.setX(pt*(Qp*q*cPhi+4.*ptx*pty*sPhi)/(q*Qy)); kt.setY(pt*Qy*sPhi/q); kt.setZ(ZERO); } if ( boost ) kt = kt + ((P*kt-Q*kt)/(P*Q-Q.mass2()))*(P-Q); kt.setMass(-pt); kt.rescaleRho(); return kt; } // 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); } diff --git a/DipoleShower/Kinematics/IFLightKinematics.cc b/DipoleShower/Kinematics/IFLightKinematics.cc --- a/DipoleShower/Kinematics/IFLightKinematics.cc +++ b/DipoleShower/Kinematics/IFLightKinematics.cc @@ -1,248 +1,253 @@ // -*- C++ -*- // // IFLightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IFLightKinematics class. // #include "IFLightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" using namespace Herwig; IFLightKinematics::IFLightKinematics() : DipoleSplittingKinematics(), theCollinearScheme(false) {} 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(); double s = sqrt(1.-sqr(pt/dInfo.hardPt())); return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); } bool IFLightKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split) { if ( info.emitterX() < xMin() ) { jacobian(0.0); return false; } double weight = 1.0; Energy pt = generatePt(kappa,info.scale(), info.emitterX(),info.spectatorX(), info.index(),split, weight); if ( pt < IRCutoff() || pt > info.hardPt() ) { jacobian(0.0); return false; } double z = 0.0; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emitterData()->id() == ParticleID::g ) { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZ, info,split,weight); } } if ( info.index().emitterData()->id() != ParticleID::g ) { if ( info.emitterData()->id() != ParticleID::g ) { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } else { z = generateZ(xi,pt,FlatZ, info,split,weight); } } + if ( weight == 0. && z == -1. ) { + jacobian(0.0); + return false; + } + double ratio = sqr(pt/info.scale()); double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); if ( rho < 0.0 ) { jacobian(0.0); return false; } double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); double u = 0.5*((1.-z+ratio)/(1.-z))*(1.-sqrt(rho)); if ( x < info.emitterX() || x > 1. || u < 0. || u > 1. ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian(weight*(1./z)); lastPt(pt); lastZ(z); lastPhi(phi); lastEmitterZ(x); if ( theMCCheck ) theMCCheck->book(info.emitterX(),1.,info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void IFLightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); double ratio = sqr(pt)/(2.*pEmitter*pSpectator); double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); double u = 0.5*((1.-z+ratio)/(1.-z))*(1.-sqrt(rho)); Lorentz5Momentum kt = getKt (pEmitter, pSpectator, pt, dInfo.lastPhi(),true); Lorentz5Momentum em; Lorentz5Momentum emm; Lorentz5Momentum spe; if ( !theCollinearScheme && x > u && (1.-x)/(x-u) < 1. ) { em = ((1.-u)/(x-u))*pEmitter + ((u/x)*(1.-x)/(x-u))*pSpectator - kt/(x-u); em.setMass(0.*GeV); em.rescaleEnergy(); emm = ((1.-x)/(x-u))*pEmitter + ((u/x)*(1.-u)/(x-u))*pSpectator - kt/(x-u); emm.setMass(0.*GeV); emm.rescaleEnergy(); spe = (1.-u/x)*pSpectator; spe.setMass(0.*GeV); spe.rescaleEnergy(); } else { em = (1./x)*pEmitter; emm = ((1.-x)*(1.-u)/x)*pEmitter + u*pSpectator + kt; emm.setMass(0.*GeV); emm.rescaleEnergy(); spe = ((1.-x)*u/x)*pEmitter + (1.-u)*pSpectator - kt; spe.setMass(0.*GeV); spe.rescaleEnergy(); } emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IFLightKinematics::persistentOutput(PersistentOStream & os) const { os << theCollinearScheme; } void IFLightKinematics::persistentInput(PersistentIStream & is, 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 interfaceCollinearSchemeOn (interfaceCollinearScheme, "On", "Switch on the collinear scheme.", true); static SwitchOption interfaceCollinearSchemeOff (interfaceCollinearScheme, "Off", "Switch off the collinear scheme", false); interfaceCollinearScheme.rank(-1); } diff --git a/DipoleShower/Kinematics/IILightKinematics.cc b/DipoleShower/Kinematics/IILightKinematics.cc --- a/DipoleShower/Kinematics/IILightKinematics.cc +++ b/DipoleShower/Kinematics/IILightKinematics.cc @@ -1,282 +1,287 @@ // -*- C++ -*- // // IILightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the IILightKinematics class. // #include "IILightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" using namespace Herwig; IILightKinematics::IILightKinematics() : DipoleSplittingKinematics(), theCollinearScheme(false), didCollinear(false) {} 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(); double s = sqrt(1.-sqr(pt/dInfo.hardPt())); return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); } bool IILightKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split) { if ( info.emitterX() < xMin() || info.spectatorX() < xMin() ) { jacobian(0.0); return false; } double weight = 1.0; Energy pt = generatePt(kappa,info.scale(), info.emitterX(),info.spectatorX(), info.index(),split, weight); if ( pt < IRCutoff() || pt > info.hardPt() ) { jacobian(0.0); return false; } double z = 0.0; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emitterData()->id() == ParticleID::g ) { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZ, info,split,weight); } } if ( info.index().emitterData()->id() != ParticleID::g ) { if ( info.emitterData()->id() != ParticleID::g ) { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } else { z = generateZ(xi,pt,FlatZ, info,split,weight); } } + if ( weight == 0. && z == -1. ) { + jacobian(0.0); + return false; + } + double ratio = sqr(pt/info.scale()); double x = z*(1.-z)/(1.-z+ratio); double v = ratio*z /(1.-z+ratio); if ( x < 0. || x > 1. || v < 0. || v > 1.-x ) { jacobian(0.0); return false; } if ( !theCollinearScheme && (1.-v-x)/(v+x) < 1. ) { if ( (x+v) < info.emitterX() || x/(x+v) < info.spectatorX() ) { jacobian(0.0); return false; } } else { if ( x < info.emitterX() ) { jacobian(0.0); return false; } } double phi = 2.*Constants::pi*rphi; jacobian(weight*(1./z)); lastPt(pt); lastZ(z); lastPhi(phi); if ( !theCollinearScheme && (1.-v-x)/(v+x) < 1. ) { lastEmitterZ(x+v); lastSpectatorZ(x/(x+v)); } else { lastEmitterZ(x); lastSpectatorZ(1.); } if ( theMCCheck ) theMCCheck->book(info.emitterX(),info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void IILightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); double ratio = sqr(pt)/(2.*pEmitter*pSpectator); double x = z*(1.-z)/(1.-z+ratio); double v = ratio*z /(1.-z+ratio); Lorentz5Momentum kt = getKt (pEmitter, pSpectator, pt, dInfo.lastPhi()); if ( !theCollinearScheme && (1.-v-x)/(v+x) < 1. ) { Lorentz5Momentum em = (1./(v+x))*pEmitter+(v*(1.-v-x)/(x*(x+v)))*pSpectator+kt/(x+v); em.setMass(0.*GeV); em.rescaleEnergy(); Lorentz5Momentum emm = ((1.-v-x)/(v+x))*pEmitter+(v/(x*(x+v)))*pSpectator+kt/(x+v); emm.setMass(0.*GeV); emm.rescaleEnergy(); Lorentz5Momentum spe = (1.+v/x)*pSpectator; spe.setMass(0.*GeV); spe.rescaleEnergy(); emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); didCollinear = false; } else { Lorentz5Momentum em = (1./x)*pEmitter; em.setMass(0.*GeV); em.rescaleEnergy(); Lorentz5Momentum emm = ((1.-x-v)/x)*pEmitter+v*pSpectator+kt; emm.setMass(0.*GeV); emm.rescaleEnergy(); Lorentz5Momentum spe = pSpectator; emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); K = em + spe - emm; K2 = K.m2(); Ktilde = pEmitter + pSpectator; KplusKtilde = K + Ktilde; KplusKtilde2 = KplusKtilde.m2(); didCollinear = true; } } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void IILightKinematics::persistentOutput(PersistentOStream & os) const { os << theCollinearScheme; } void IILightKinematics::persistentInput(PersistentIStream & is, int) { 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 interfaceCollinearScheme ("CollinearScheme", "[experimental] Switch on or off the collinear scheme", &IILightKinematics::theCollinearScheme, false, false, false); static SwitchOption interfaceCollinearSchemeOn (interfaceCollinearScheme, "On", "Switch on the collinear scheme.", true); static SwitchOption interfaceCollinearSchemeOff (interfaceCollinearScheme, "Off", "Switch off the collinear scheme", false); interfaceCollinearScheme.rank(-1); } diff --git a/DipoleShower/Makefile.am b/DipoleShower/Makefile.am --- a/DipoleShower/Makefile.am +++ b/DipoleShower/Makefile.am @@ -1,14 +1,14 @@ SUBDIRS = Base Kernels Kinematics Utility AlphaS pkglib_LTLIBRARIES = HwDipoleShower.la -HwDipoleShower_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 5:0:0 +HwDipoleShower_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 6:0:0 HwDipoleShower_la_LIBADD = \ Base/libHwDipoleShowerBase.la \ Kernels/libHwDipoleShowerKernels.la \ Kinematics/libHwDipoleShowerKinematics.la \ Utility/libHwDipoleShowerUtility.la HwDipoleShower_la_SOURCES = \ DipoleShowerHandler.h DipoleShowerHandler.cc diff --git a/MatrixElement/General/MEvv2ss.cc b/MatrixElement/General/MEvv2ss.cc --- a/MatrixElement/General/MEvv2ss.cc +++ b/MatrixElement/General/MEvv2ss.cc @@ -1,283 +1,309 @@ // -*- C++ -*- // // MEvv2ss.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEvv2ss class. // #include "MEvv2ss.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using ThePEG::Helicity::TensorWaveFunction; using ThePEG::Helicity::incoming; using ThePEG::Helicity::outgoing; void MEvv2ss::doinit() { GeneralHardME::doinit(); scalar1_.resize(numberOfDiags()); scalar2_.resize(numberOfDiags()); + scalar3_.resize(numberOfDiags()); vector_ .resize(numberOfDiags()); tensor_ .resize(numberOfDiags()); initializeMatrixElements(PDT::Spin1, PDT::Spin1, PDT::Spin0, PDT::Spin0); for(size_t i = 0; i < numberOfDiags(); ++i ) { HPDiagram dg = getProcessInfo()[i]; if( !dg.intermediate ) { contact_ = dynamic_ptr_cast(dg.vertices.first); } else if(dg.channelType == HPDiagram::tChannel) { - AbstractVSSVertexPtr vss1 = - dynamic_ptr_cast(dg.vertices.first); - AbstractVSSVertexPtr vss2 = - dynamic_ptr_cast(dg.vertices.second); - scalar2_[i] = make_pair(vss1, vss2); + if (dg.intermediate->iSpin() == PDT::Spin0 ) { + AbstractVSSVertexPtr vss1 = + dynamic_ptr_cast(dg.vertices.first); + AbstractVSSVertexPtr vss2 = + dynamic_ptr_cast(dg.vertices.second); + scalar2_[i] = make_pair(vss1, vss2); + } + else if( dg.intermediate->iSpin() == PDT::Spin1 ) { + AbstractVVSVertexPtr vvs1 = + dynamic_ptr_cast(dg.vertices.first); + AbstractVVSVertexPtr vvs2 = + dynamic_ptr_cast(dg.vertices.second); + scalar3_[i] = make_pair(vvs1, vvs2); + } + else + assert(false); } else { if( dg.intermediate->iSpin() == PDT::Spin0 ) { AbstractVVSVertexPtr vvs = dynamic_ptr_cast(dg.vertices.first); AbstractSSSVertexPtr sss = dynamic_ptr_cast(dg.vertices.second); scalar1_[i] = make_pair(vvs, sss); } else if( dg.intermediate->iSpin() == PDT::Spin1 ) { AbstractVVVVertexPtr vvv = dynamic_ptr_cast(dg.vertices.first); AbstractVSSVertexPtr vss = dynamic_ptr_cast(dg.vertices.second); vector_[i] = make_pair(vvv, vss); } else if( dg.intermediate->iSpin() == PDT::Spin2 ) { AbstractVVTVertexPtr vvt = dynamic_ptr_cast(dg.vertices.first); AbstractSSTVertexPtr sst = dynamic_ptr_cast(dg.vertices.second); tensor_[i] = make_pair(vvt, sst); } } } } double MEvv2ss::me2() const { VBVector v1(2), v2(2); for( size_t i = 0; i < 2; ++i ) { v1[i] = VectorWaveFunction(rescaledMomenta()[0],mePartonData()[0], 2*i, incoming); v2[i] = VectorWaveFunction(rescaledMomenta()[1],mePartonData()[1], 2*i, incoming); } ScalarWaveFunction sca1(rescaledMomenta()[2],mePartonData()[2], Complex(1.,0.),outgoing); ScalarWaveFunction sca2(rescaledMomenta()[3],mePartonData()[3], Complex(1.,0.),outgoing); double full_me(0.); vv2ssME(v1, v2, sca1, sca2, full_me , true); #ifndef NDEBUG if( debugME() ) debug(full_me); #endif return full_me; } ProductionMatrixElement MEvv2ss::vv2ssME(const VBVector & v1, const VBVector & v2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, double & me2, bool first) const { const Energy2 m2(scale()); const Energy masst = sca1.mass(), massu = sca2.mass(); // weights for the selection of the diagram vector me(numberOfDiags(), 0.); // weights for the selection of the colour flow vector flow(numberOfFlows(),0.); //loop over vector helicities for(unsigned int iv1 = 0; iv1 < 2; ++iv1) { for(unsigned int iv2 = 0; iv2 < 2; ++iv2) { vector flows(numberOfFlows(),0.); // loop over diagrams for(HPCount ix = 0; ix < numberOfDiags(); ++ix) { Complex diag(0.); const HPDiagram & current = getProcessInfo()[ix]; // do four-point diag first if(current.channelType == HPDiagram::fourPoint) { diag = contact_->evaluate(m2, v1[iv1], v2[iv2], sca1, sca2); } else { tcPDPtr offshell = current.intermediate; if(current.channelType == HPDiagram::tChannel) { - if(current.ordered.second) { - ScalarWaveFunction interS = scalar2_[ix].first-> - evaluate(m2, 3, offshell, v1[iv1], sca1, masst); - diag = scalar2_[ix].second->evaluate(m2, v2[iv2], interS, sca2); + if(offshell->iSpin() == PDT::Spin0) { + if(current.ordered.second) { + ScalarWaveFunction interS = scalar2_[ix].first-> + evaluate(m2, 3, offshell, v1[iv1], sca1, masst); + diag = scalar2_[ix].second->evaluate(m2, v2[iv2], interS, sca2); + } + else { + ScalarWaveFunction interS = scalar2_[ix].first-> + evaluate(m2, 3, offshell, v1[iv1], sca2, massu); + diag = scalar2_[ix].second->evaluate(m2, v2[iv2], interS, sca1); + } } else { - ScalarWaveFunction interS = scalar2_[ix].first-> - evaluate(m2, 3, offshell, v1[iv1], sca2, massu); - diag = scalar2_[ix].second->evaluate(m2, v2[iv2], interS, sca1); + if(current.ordered.second) { + VectorWaveFunction interV = scalar3_[ix].first-> + evaluate(m2, 3, offshell, v1[iv1], sca1); + diag = scalar3_[ix].second->evaluate(m2, v2[iv2], interV, sca2); + } + else { + VectorWaveFunction interV = scalar3_[ix].first-> + evaluate(m2, 3, offshell, v1[iv1], sca2); + diag = scalar3_[ix].second->evaluate(m2, v2[iv2], interV, sca1); + } } } else if(current.channelType == HPDiagram::sChannel) { if(offshell->iSpin() == PDT::Spin0) { ScalarWaveFunction interS = scalar1_[ix].first-> evaluate(m2, 1, offshell, v1[iv1], v2[iv2]); diag = scalar1_[ix].second->evaluate(m2, interS, sca1, sca2); } else if(offshell->iSpin() == PDT::Spin1) { VectorWaveFunction interV = vector_[ix].first-> evaluate(m2, 1, offshell, v1[iv1], v2[iv2]); diag = vector_[ix].second->evaluate(m2, interV, sca1, sca2); } else if(offshell->iSpin() == PDT::Spin2) { TensorWaveFunction interT = tensor_[ix].first-> evaluate(m2, 1, offshell, v1[iv1], v2[iv2]); diag = tensor_[ix].second->evaluate(m2, sca1, sca2, interT); } } else diag = 0.; } me[ix] += norm(diag); diagramME()[ix](2*iv1, 2*iv2, 0, 0) = diag; //Compute flows for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) { assert(current.colourFlow[iy].first> scalar1_ >> scalar2_ >> vector_ >> tensor_ >> contact_; + is >> scalar1_ >> scalar2_ >> scalar3_ >> vector_ >> tensor_ >> contact_; initializeMatrixElements(PDT::Spin1, PDT::Spin1, PDT::Spin0, PDT::Spin0); } ClassDescription MEvv2ss::initMEvv2ss; // Definition of the static class description member. void MEvv2ss::Init() { static ClassDocumentation documentation ("This class implements the ME for the vector-vector to scalar-scalar " "hard-process"); } void MEvv2ss::constructVertex(tSubProPtr sub) { ParticleVector ext = hardParticles(sub); VBVector v1, v2; // set up the wavefunctions with real momenta VectorWaveFunction(v1, ext[0], incoming, false, true); VectorWaveFunction(v2, ext[1], incoming, false, true); ScalarWaveFunction sca1(ext[2], outgoing, true); ScalarWaveFunction sca2(ext[3], outgoing, true); // calculate rescaled moment setRescaledMomenta(ext); // wavefunctions with rescaled momenta VectorWaveFunction v1r (rescaledMomenta()[0], ext[0]->dataPtr(), incoming); VectorWaveFunction v2r (rescaledMomenta()[1], ext[1]->dataPtr(), incoming); sca1 = ScalarWaveFunction(rescaledMomenta()[2], ext[2]->dataPtr(), outgoing); sca2 = ScalarWaveFunction(rescaledMomenta()[3], ext[3]->dataPtr(), outgoing); for( unsigned int ihel = 0; ihel < 2; ++ihel ) { v1r.reset(2*ihel); v1[ihel] = v1r; v2r.reset(2*ihel); v2[ihel] = v2r; } double dummy(0.); ProductionMatrixElement pme = vv2ssME(v1, v2, sca1, sca2, dummy , false); #ifndef NDEBUG if( debugME() ) debug(dummy); #endif createVertex(pme,ext); } void MEvv2ss::debug(double me2) const { if( !generator()->logfile().is_open() ) return; if( mePartonData()[0]->id() != 21 || mePartonData()[1]->id() != 21) return; long id3 = abs(mePartonData()[2]->id()); long id4 = abs(mePartonData()[3]->id()); int type = -1; //SUSY gg>~q~q if( ((id3 >= 1000001 && id3 <= 1000006 ) && (id4 >= 1000001 && id4 <= 1000006 ) ) || ((id3 >= 2000001 && id3 <= 2000006 ) && (id4 >= 2000001 && id4 <= 2000006 ) ) ) { type = 0; } // Sextet production else if(mePartonData()[2]->iColour() == PDT::Colour6 && mePartonData()[3]->iColour() == PDT::Colour6bar ) { type = 1; } else { return; } double gs4 = sqr( 4.*Constants::pi*SM().alphaS(scale())); int Nc = SM().Nc(); Energy4 s2 = sqr(sHat()); Energy2 m3s = meMomenta()[2].m2(); Energy2 m4s = meMomenta()[3].m2(); Energy4 spt2 = uHat()*tHat() - m3s*m4s; Energy2 t3 = tHat()-m3s, u4 = uHat()-m4s; Energy4 t3s = sqr(t3) , u4s = sqr(u4); Energy8 pre = gs4*(sqr(spt2) + s2*m3s*m4s); // matrix element double analytic(0.); // triplet scalars if(type==0) { analytic = pre*Nc* ( u4s + t3s - s2/sqr(Nc) )/2./(sqr(Nc) - 1.)/s2/t3s/u4s; } // sextet scalars else if(type==1) { analytic = pre*(Nc+2.)/(sqr(Nc)-1.)/Nc* ((Nc+2.)*(Nc-1.)/t3s/u4s - sqr(Nc)/t3/u4/s2); } double diff = abs(analytic - me2)/(analytic+me2); if( diff > 1e-10 ) { generator()->log() << mePartonData()[0]->PDGName() << "," << mePartonData()[1]->PDGName() << "->" << mePartonData()[2]->PDGName() << "," << mePartonData()[3]->PDGName() << " difference: " << setprecision(10) << diff << " ratio: " << analytic/me2 << '\n'; } } diff --git a/MatrixElement/General/MEvv2ss.h b/MatrixElement/General/MEvv2ss.h --- a/MatrixElement/General/MEvv2ss.h +++ b/MatrixElement/General/MEvv2ss.h @@ -1,227 +1,232 @@ // -*- C++ -*- // // MEvv2ss.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MEvv2ss_H #define HERWIG_MEvv2ss_H // // This is the declaration of the MEvv2ss class. // #include "GeneralHardME.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractSSSVertex.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" namespace Herwig { using namespace ThePEG; using ThePEG::Helicity::VectorWaveFunction; using ThePEG::Helicity::ScalarWaveFunction; /** * This is the implementation of the matrix element for the process * vector-vector to scalar-scalar. It inherits from GeneralHardME and * implements the required virtual functions. * * @see \ref MEff2ffInterfaces "The Interfaces" * defined for MEff2ff. * @see GeneralHardME */ class MEvv2ss: public GeneralHardME { public: /** A vector of VectorWaveFunction objects*/ typedef vector VBVector; public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; //@} /** * Set the Hardvertex for the spin correlations * @param sub */ virtual void constructVertex(tSubProPtr sub); private: /** * Calculate the matrix element. * @param v1 A vector of VectorWaveFunction objects for the first boson * @param v2 A vector of VectorWaveFunction objects for the second boson * @param sca1 A ScalarWaveFunction for the first outgoing * @param sca2 A ScalarWaveFunction for the second outgoing * @param me2 The value of the spin-summed matrix element squared * (to be calculated) * @param first Whether or not first call to decide if colour decomposition etc * should be calculated */ ProductionMatrixElement vv2ssME(const VBVector & v1, const VBVector & v2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, double & me2, bool first) const; protected: /** * A debugging function to test the value of me2 against an * analytic function. * @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$ */ virtual void debug(double me2) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initMEvv2ss; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEvv2ss & operator=(const MEvv2ss &); private: /** @name The dynamically casted vertices. */ //@{ /** * Intermediate s-channel scalar */ vector > scalar1_; /** * Intermediate t-channel scalar */ vector > scalar2_; /** + * Intermediate t-channel scalar + */ + vector > scalar3_; + + /** * Intermediate s-channel vector */ vector > vector_; /** * Intermediate s-channel tensor */ vector > tensor_; /** * The contact vertex */ AbstractVVSSVertexPtr contact_; //@} }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEvv2ss. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MEvv2ss. */ typedef Herwig::GeneralHardME NthBase; }; /** This template specialization informs ThePEG about the name of * the MEvv2ss 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::MEvv2ss"; } }; /** @endcond */ } #endif /* HERWIG_MEvv2ss_H */ diff --git a/MatrixElement/Matchbox/MatchboxFactory.cc b/MatrixElement/Matchbox/MatchboxFactory.cc --- a/MatrixElement/Matchbox/MatchboxFactory.cc +++ b/MatrixElement/Matchbox/MatchboxFactory.cc @@ -1,1971 +1,2109 @@ // -*- C++ -*- // // MatchboxFactory.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2012 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatchboxFactory class. // #include "MatchboxFactory.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/SamplerBase.h" #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" #include "Herwig/MatrixElement/Matchbox/Utility/SU2Helper.h" #include "Herwig/Utilities/RunDirectories.h" #include #include #include using std::ostream_iterator; using namespace Herwig; using std::ostream_iterator; MatchboxFactory::MatchboxFactory() : SubProcessHandler(), theNLight(0), theOrderInAlphaS(0), theOrderInAlphaEW(0), theBornContributions(true), theVirtualContributions(true), theRealContributions(true), theIndependentVirtuals(false), theIndependentPKs(false), theSubProcessGroups(false), theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0), theFixedCouplings(false), theFixedQEDCouplings(false), theVetoScales(false), theDipoleSet(0), theVerbose(false), theDiagramWeightVerbose(false), theDiagramWeightVerboseNBins(200), theInitVerbose(false), theSubtractionData(""), theSubtractionPlotType(1), theSubtractionScatterPlot(false), thePoleData(""), theRealEmissionScales(false), theAllProcesses(false), theMECorrectionsOnly(false), theLoopSimCorrections(false), ranSetup(false), theFirstPerturbativePDF(true), theSecondPerturbativePDF(true), - inProductionMode(false), theSpinCorrelations(false),theAlphaParameter(1.) {} + inProductionMode(false), theSpinCorrelations(false),theAlphaParameter(1.), + theEnforceChargeConservation(true), theEnforceColourConservation(true), + theEnforceLeptonNumberConservation(true), theEnforceQuarkNumberConservation(true), + theLeptonFlavourDiagonal(true), theQuarkFlavourDiagonal(true) {} MatchboxFactory::~MatchboxFactory() {} bool& MatchboxFactory::theIsMatchboxRun() { static bool flag = false; return flag; } IBPtr MatchboxFactory::clone() const { return new_ptr(*this); } IBPtr MatchboxFactory::fullclone() const { return new_ptr(*this); } void MatchboxFactory::prepareME(Ptr::ptr me) { Ptr::ptr amp = dynamic_ptr_cast::ptr>((*me).amplitude()); me->matchboxAmplitude(amp); me->factory(this); if ( phasespace() && !me->phasespace() ) me->phasespace(phasespace()); if ( scaleChoice() && !me->scaleChoice() ) me->scaleChoice(scaleChoice()); if ( !reweighters().empty() ) { for ( vector::const_iterator rw = reweighters().begin(); rw != reweighters().end(); ++rw ) me->addReweighter(*rw); } if ( !preweighters().empty() ) { for ( vector::const_iterator rw = preweighters().begin(); rw != preweighters().end(); ++rw ) me->addPreweighter(*rw); } } string pid(const PDVector& key) { ostringstream res; res << "[" << key[0]->PDGName() << "," << key[1]->PDGName() << "->"; for ( PDVector::const_iterator k = key.begin() + 2; k != key.end(); ++k ) res << (**k).PDGName() << (k != --key.end() ? "," : ""); res << "]"; return res.str(); } vector::ptr> MatchboxFactory:: makeMEs(const vector& proc, unsigned int orderas, bool virt) { generator()->log() << "determining subprocesses for "; copy(proc.begin(),proc.end(),ostream_iterator(generator()->log()," ")); generator()->log() << "\n" << flush; map::ptr,set > ampProcs; map::ptr> > procAmps; set processes = makeSubProcesses(proc); // TODO Fix me for 3.0.x // At the moment we got troubles with processes with no coloured // legs so they will not be supported set colouredProcesses; for ( set::const_iterator pr = processes.begin(); pr != processes.end(); ++pr ) { for ( PDVector::const_iterator pp = pr->begin(); pp != pr->end(); ++pp ) { if ( (**pp).coloured() ) { colouredProcesses.insert(*pr); break; } } } if ( colouredProcesses.size() != processes.size() ) { generator()->log() << "Some or all of the generated subprocesses do not contain coloured legs.\n" << "Processes of this kind are currently not supported.\n" << flush; } if ( colouredProcesses.empty() ) { throw Exception() << "MatchboxFactory::makeMEs(): No processes with coloured legs have been found. " << "This run will be aborted." << Exception::runerror; } processes = colouredProcesses; // end unsupported processes // detect external particles with non-zero width for the hard process bool trouble = false; string troubleMaker; for ( set::const_iterator pr = processes.begin(); pr != processes.end(); ++pr ) { for ( PDVector::const_iterator pp = pr->begin(); pp != pr->end(); ++pp ) { if ( (**pp).hardProcessWidth() != ZERO ) { trouble = true; troubleMaker = (**pp).PDGName(); break; } } } if ( trouble ) { throw Exception() << "MatchboxFactory::makeMEs(): Particle '" << troubleMaker << "' appears as external\nprocess leg with non-zero " << "width to be used in the hard process calculation.\n" << "Please check your setup and consider setting HardProcessWidth to zero." << Exception::runerror; } vector::ptr> matchAmplitudes; unsigned int lowestAsOrder = allProcesses() ? 0 : orderas; unsigned int highestAsOrder = orderas; unsigned int lowestAeOrder = allProcesses() ? 0 : orderInAlphaEW(); unsigned int highestAeOrder = orderInAlphaEW(); for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) { for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) { for ( vector::ptr>::const_iterator amp = amplitudes().begin(); amp != amplitudes().end(); ++amp ) { if ( !theSelectedAmplitudes.empty() ) { if ( find(theSelectedAmplitudes.begin(),theSelectedAmplitudes.end(),*amp) == theSelectedAmplitudes.end() ) continue; } if ( !theDeselectedAmplitudes.empty() ) { if ( find(theDeselectedAmplitudes.begin(),theDeselectedAmplitudes.end(),*amp) != theDeselectedAmplitudes.end() ) continue; } (**amp).orderInGs(oas); (**amp).orderInGem(oae); if ( (**amp).orderInGs() != oas || (**amp).orderInGem() != oae ) { continue; } matchAmplitudes.push_back(*amp); } } } size_t combinations = processes.size()*matchAmplitudes.size(); size_t procCount = 0; generator()->log() << "building matrix elements." << flush; boost::progress_display * progressBar = new boost::progress_display(combinations,generator()->log()); for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) { for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) { for ( vector::ptr>::const_iterator amp = matchAmplitudes.begin(); amp != matchAmplitudes.end(); ++amp ) { (**amp).orderInGs(oas); (**amp).orderInGem(oae); for ( set::const_iterator p = processes.begin(); p != processes.end(); ++p ) { ++(*progressBar); if ( !(**amp).canHandle(*p,this,virt) ) continue; if ( (**amp).isExternal() ) externalAmplitudes().insert(*amp); ++procCount; Process proc(*p,oas,oae); ampProcs[*amp].insert(proc); procAmps[proc].insert(*amp); } } } } delete progressBar; generator()->log() << flush; bool clash = false; for ( map::ptr> >::const_iterator check = procAmps.begin(); check != procAmps.end(); ++check ) { if ( check->second.size() > 1 ) { clash = true; generator()->log() << "Several different amplitudes have been found for: " << check->first.legs[0]->PDGName() << " " << check->first.legs[1]->PDGName() << " -> "; for ( PDVector::const_iterator p = check->first.legs.begin() + 2; p != check->first.legs.end(); ++p ) generator()->log() << (**p).PDGName() << " "; generator()->log() << "at alpha_s^" << check->first.orderInAlphaS << " and alpha_ew^" << check->first.orderInAlphaEW << "\n"; generator()->log() << "The following amplitudes claim responsibility:\n"; for ( set::ptr>::const_iterator a = check->second.begin(); a != check->second.end(); ++a ) { generator()->log() << (**a).name() << " "; } generator()->log() << "\n"; } } if ( clash ) { throw Exception() << "MatchboxFactory: Ambiguous amplitude setup - please check your input files.\n" << "To avoid this problem use the SelectAmplitudes or DeselectAmplitudes interfaces.\n" << Exception::runerror; } bool canDoSpinCorrelations = true; vector::ptr> res; for ( map::ptr,set >::const_iterator ap = ampProcs.begin(); ap != ampProcs.end(); ++ap ) { canDoSpinCorrelations &= ap->first->canFillRhoMatrix(); for ( set::const_iterator m = ap->second.begin(); m != ap->second.end(); ++m ) { Ptr::ptr me = ap->first->makeME(m->legs); me->subProcess() = *m; me->amplitude(ap->first); me->matchboxAmplitude(ap->first); prepareME(me); string pname = "ME" + ap->first->name() + pid(m->legs); if ( ! (generator()->preinitRegister(me,pname) ) ) throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing." << Exception::runerror; if ( me->diagrams().empty() )continue; res.push_back(me); if ( theFirstPerturbativePDF ) theIncoming.insert(m->legs[0]->id()); if ( theSecondPerturbativePDF ) theIncoming.insert(m->legs[1]->id()); } } if ( spinCorrelations() && !canDoSpinCorrelations ) { generator()->log() << "Warning: Spin correlations have been requested, but no amplitude is " << "capable of performing these.\n"; theSpinCorrelations = false; } generator()->log() << "created " << procCount << " subprocesses.\n"; generator()->log() << "--------------------------------------------------------------------------------\n" << flush; return res; } int MatchboxFactory::orderOLPProcess(const Process& proc, Ptr::tptr amp, int type) { map,int>& procs = olpProcesses()[amp]; map,int>::const_iterator it = procs.find(make_pair(proc,type)); if ( it != procs.end() ) return it->second; int id = procs.size(); procs[make_pair(proc,type)] = id + 1; return id + 1; } void MatchboxFactory::productionMode() { if ( inProductionMode ) return; if ( !bornContributions() && !virtualContributions() && !realContributions() ) throw Exception() << "MatchboxFactory: At least one cross section contribution needs to be enabled.\n" << "Please check your setup.\n" << Exception::runerror; bool needTrueVirtuals = virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections(); for ( vector::ptr>::iterator amp = amplitudes().begin(); amp != amplitudes().end(); ++amp ) { if ( !needTrueVirtuals && (**amp).oneLoopAmplitude() ) { Repository::clog() << "One-loop contributions from '" << (**amp).name() << "' are not required and will be disabled.\n" << flush; (**amp).disableOneLoop(); } } if ( subtractionData() != "" && !subProcessGroups() ) { throw Exception() << "MatchboxFactory: Plain NLO settings are required for subtraction checks.\n" << "Please check your setup.\n" << Exception::runerror; } if ( showerApproximation() && !virtualContributions() && !realContributions() ) { Repository::clog() << "Warning: Matching requested for LO run. Matching disabled.\n" << flush; showerApproximation(Ptr::tptr()); } if ( showerApproximation() && (subtractionData() != "" || subProcessGroups()) ) { Repository::clog() << "Warning: Matching requested for plain NLO run. Matching disabled.\n" << flush; showerApproximation(Ptr::tptr()); } if ( showerApproximation() ) { if ( spinCorrelations() && !showerApproximation()->hasSpinCorrelations() ) { Repository::clog() << "Warning: Spin correlations have been requested but the matching " << "object is not capable of these. Spin correlations will be turned of.\n" << flush; theSpinCorrelations = false; } } inProductionMode = true; } void MatchboxFactory::setup() { useMe(); if ( !ranSetup ) { if ( !inProductionMode ) throw Exception() << "MatchboxFactory: The MatchboxFactory object '" << name() << "' has not been switched to production mode.\n" << "Did you use 'do " << name() << ":ProductionMode' before isolating the event generator?\n" << Exception::runerror; olpProcesses().clear(); externalAmplitudes().clear(); theHighestVirtualsize = 0; theIncoming.clear(); bool needTrueVirtuals = virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections(); for ( vector::ptr>::iterator amp = amplitudes().begin(); amp != amplitudes().end(); ++amp ) (**amp).factory(this); if ( bornMEs().empty() ) { if ( particleGroups().find("j") == particleGroups().end() ) throw Exception() << "MatchboxFactory: Could not find a jet particle group named 'j'" << Exception::runerror; // rebind the particle data objects for ( map::iterator g = particleGroups().begin(); g != particleGroups().end(); ++g ) for ( PDVector::iterator p = g->second.begin(); p != g->second.end(); ++p ) { #ifndef NDEBUG long checkid = (**p).id(); #endif *p = getParticleData((**p).id()); assert((**p).id() == checkid); } const PDVector& partons = particleGroups()["j"]; unsigned int nl = 0; for ( PDVector::const_iterator p = partons.begin(); p != partons.end(); ++p ) { if ( abs((**p).id()) < 7 && (**p).hardProcessMass() == ZERO ) ++nl; if ( (**p).id() > 0 && (**p).id() < 7 && (**p).hardProcessMass() == ZERO ) nLightJetVec( (**p).id() ); if ( (**p).id() > 0 && (**p).id() < 7 && (**p).hardProcessMass() != ZERO ) nHeavyJetVec( (**p).id() ); } nLight(nl/2); if ( particleGroups().find("p") == particleGroups().end() ) throw Exception() << "MatchboxFactory: Could not find a hadron particle group named 'p'" << Exception::runerror; const PDVector& partonsInP = particleGroups()["p"]; for ( PDVector::const_iterator pip = partonsInP.begin(); pip != partonsInP.end(); ++pip ) { if ( (**pip).id() > 0 && (**pip).id() < 7 && (**pip).hardProcessMass() == ZERO ) nLightProtonVec( (**pip).id() ); } vector::ptr> mes; for ( vector >::const_iterator p = processes.begin(); p != processes.end(); ++p ) { if( needTrueVirtuals ) { theHighestVirtualsize = max(theHighestVirtualsize,(int((*p).size()))); } mes = makeMEs(*p,orderInAlphaS(),needTrueVirtuals); copy(mes.begin(),mes.end(),back_inserter(bornMEs())); if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { if ( realEmissionProcesses.empty() ) { vector rproc = *p; rproc.push_back("j"); mes = makeMEs(rproc,orderInAlphaS()+1,false); copy(mes.begin(),mes.end(),back_inserter(realEmissionMEs())); } } } if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { if ( !realEmissionProcesses.empty() ) { for ( vector >::const_iterator q = realEmissionProcesses.begin(); q != realEmissionProcesses.end(); ++q ) { mes = makeMEs(*q,orderInAlphaS()+1,false); copy(mes.begin(),mes.end(),back_inserter(realEmissionMEs())); } } } } if ( loopInducedMEs().empty() ) { for ( vector >::const_iterator p = loopInducedProcesses.begin(); p != loopInducedProcesses.end(); ++p ) { vector::ptr> mes = makeMEs(*p,orderInAlphaS(),false); copy(mes.begin(),mes.end(),back_inserter(loopInducedMEs())); } } if( bornMEs().empty() && realEmissionMEs().empty() && loopInducedMEs().empty() ) throw Exception() << "MatchboxFactory: No matrix elements have been found.\n\ Please check if your order of Alpha_s and Alpha_ew have the right value.\n" << Exception::runerror; // check if we have virtual contributions bool haveVirtuals = true; // check DR conventions of virtual contributions bool virtualsAreDR = false; bool virtualsAreCDR = false; // check finite term conventions of virtual contributions bool virtualsAreCS = false; bool virtualsAreBDK = false; bool virtualsAreExpanded = false; // renormalization scheme bool virtualsAreDRbar = false; // check and prepare the Born and virtual matrix elements for ( vector::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { prepareME(*born); haveVirtuals &= (**born).haveOneLoop(); if ( needTrueVirtuals ) { if ( (**born).haveOneLoop() ) { virtualsAreDRbar |= (**born).isDRbar(); virtualsAreDR |= (**born).isDR(); virtualsAreCDR |= !(**born).isDR(); virtualsAreCS |= (**born).isCS(); virtualsAreBDK |= (**born).isBDK(); virtualsAreExpanded |= (**born).isExpanded(); } } } // prepare the loop induced matrix elements for ( vector::ptr>::iterator looped = loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) { prepareME(*looped); } if ( needTrueVirtuals ) { // check the additional insertion operators if ( !virtuals().empty() ) haveVirtuals = true; for ( vector::ptr>::const_iterator virt = virtuals().begin(); virt != virtuals().end(); ++virt ) { virtualsAreDRbar |= (**virt).isDRbar(); virtualsAreDR |= (**virt).isDR(); virtualsAreCDR |= !(**virt).isDR(); virtualsAreCS |= (**virt).isCS(); virtualsAreBDK |= (**virt).isBDK(); virtualsAreExpanded |= (**virt).isExpanded(); } // check for consistent conventions on virtuals, if we are to include them if ( virtualContributions() ) { if ( !haveVirtuals ) { throw Exception() << "MatchboxFactory: Could not find amplitudes for all virtual contributions needed.\n" << Exception::runerror; } if ( virtualsAreDR && virtualsAreCDR ) { throw Exception() << "MatchboxFactory: Virtual corrections use inconsistent regularization schemes.\n" << Exception::runerror; } if ( (virtualsAreCS && virtualsAreBDK) || (virtualsAreCS && virtualsAreExpanded) || (virtualsAreBDK && virtualsAreExpanded) || (!virtualsAreCS && !virtualsAreBDK && !virtualsAreExpanded) ) { throw Exception() << "MatchboxFactory: Virtual corrections use inconsistent conventions on finite terms.\n" << Exception::runerror; } } // prepare dipole insertion operators if ( virtualContributions() ) { for ( vector::ptr>::const_iterator virt = DipoleRepository::insertionIOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionIOperators(dipoleSet()).end(); ++virt ) { (**virt).factory(this); if ( virtualsAreDRbar ) (**virt).useDRbar(); if ( virtualsAreDR ) (**virt).useDR(); else (**virt).useCDR(); if ( virtualsAreCS ) (**virt).useCS(); if ( virtualsAreBDK ) (**virt).useBDK(); if ( virtualsAreExpanded ) (**virt).useExpanded(); } for ( vector::ptr>::const_iterator virt = DipoleRepository::insertionPKOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) { (**virt).factory(this); if ( virtualsAreDRbar ) (**virt).useDRbar(); if ( virtualsAreDR ) (**virt).useDR(); else (**virt).useCDR(); if ( virtualsAreCS ) (**virt).useCS(); if ( virtualsAreBDK ) (**virt).useBDK(); if ( virtualsAreExpanded ) (**virt).useExpanded(); } } } // prepare the real emission matrix elements if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { for ( vector::ptr>::iterator real = realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) { prepareME(*real); } } // start creating matrix elements MEs().clear(); // setup born and virtual contributions if ( bornContributions() || virtualContributions() ) { generator()->log() << "preparing Born" << (virtualContributions() ? " and virtual" : "") << " matrix elements.\n" << flush; } if ( (bornContributions() && !virtualContributions()) || (bornContributions() && meCorrectionsOnly()) || (bornContributions() && virtualContributions() && independentVirtuals()) ) { for ( vector::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { if ( (**born).onlyOneLoop() ) continue; Ptr::ptr bornme = (**born).cloneMe(); string pname = fullName() + "/" + (**born).name(); if ( virtualContributions() && independentVirtuals() ) pname += ".Born"; if ( ! (generator()->preinitRegister(bornme,pname) ) ) throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing." << Exception::runerror; if ( bornme->isOLPTree() ) { int id = orderOLPProcess(bornme->subProcess(), (**born).matchboxAmplitude(), ProcessType::treeME2); bornme->olpProcess(ProcessType::treeME2,id); } bornme->needsNoCorrelations(); bornme->cloneDependencies(); MEs().push_back(bornme); } } if ( bornContributions() && !loopInducedMEs().empty() ) { for ( vector::ptr>::iterator looped = loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) { Ptr::ptr loopme = (**looped).cloneMe(); string pname = fullName() + "/" + (**looped).name() + ".LoopInduced"; if ( ! (generator()->preinitRegister(loopme,pname) ) ) throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing." << Exception::runerror; if ( loopme->isOLPTree() ) { int id = orderOLPProcess(loopme->subProcess(), (**looped).matchboxAmplitude(), ProcessType::loopInducedME2); loopme->olpProcess(ProcessType::loopInducedME2,id); } loopme->needsNoCorrelations(); loopme->cloneDependencies(); MEs().push_back(loopme); } } if ( needTrueVirtuals ) { bornVirtualMEs().clear(); boost::progress_display * progressBar = new boost::progress_display(bornMEs().size(),generator()->log()); if ( thePoleData != "" ) if ( thePoleData[thePoleData.size()-1] != '/' ) thePoleData += "/"; for ( vector::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { Ptr::ptr nlo = (**born).cloneMe(); string pname = fullName() + "/" + (**born).name(); if ( !independentVirtuals() && !(!bornContributions() && virtualContributions()) ) pname += ".BornVirtual"; else if ( independentPKs() && !nlo->onlyOneLoop() ) pname += ".VirtualVI"; else pname += ".Virtual"; if ( ! (generator()->preinitRegister(nlo,pname) ) ) throw Exception() << "MatchboxFactory: NLO ME " << pname << " already existing." << Exception::runerror; nlo->virtuals().clear(); if ( !nlo->onlyOneLoop() ) { for ( vector::ptr>::const_iterator virt = virtuals().begin(); virt != virtuals().end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlo->virtuals().push_back(*virt); } for ( vector::ptr>::const_iterator virt = DipoleRepository::insertionIOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionIOperators(dipoleSet()).end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlo->virtuals().push_back(*virt); } if ( !independentVirtuals() || ( independentVirtuals() && !independentPKs() ) ) { for ( vector::ptr>::const_iterator virt = DipoleRepository::insertionPKOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlo->virtuals().push_back(*virt); } } if ( nlo->virtuals().empty() ) throw Exception() << "MatchboxFactory: No insertion operators have been found for " << (**born).name() << "\n" << Exception::runerror; if ( checkPoles() ) { if ( !virtualsAreExpanded ) { throw Exception() << "MatchboxFactory: Cannot check epsilon poles if virtuals are not in `expanded' convention.\n" << Exception::runerror; } } } if ( !bornContributions() || independentVirtuals() ) { nlo->doOneLoopNoBorn(); } else { nlo->doOneLoop(); } if ( nlo->isOLPLoop() ) { int id = orderOLPProcess(nlo->subProcess(), (**born).matchboxAmplitude(), ProcessType::oneLoopInterference); nlo->olpProcess(ProcessType::oneLoopInterference,id); if ( !nlo->onlyOneLoop() && nlo->needsOLPCorrelators() ) { id = orderOLPProcess(nlo->subProcess(), (**born).matchboxAmplitude(), ProcessType::colourCorrelatedME2); nlo->olpProcess(ProcessType::colourCorrelatedME2,id); } } nlo->needsCorrelations(); nlo->cloneDependencies(); bornVirtualMEs().push_back(nlo); MEs().push_back(nlo); if ( independentVirtuals() && independentPKs() && !nlo->onlyOneLoop() ) { Ptr::ptr nlopk = (**born).cloneMe(); string pnamepk = fullName() + "/" + (**born).name(); pnamepk += ".VirtualPK"; if ( ! (generator()->preinitRegister(nlopk,pnamepk) ) ) throw Exception() << "MatchboxFactory: NLO ME " << pnamepk << " already existing." << Exception::runerror; nlopk->virtuals().clear(); for ( vector::ptr>::const_iterator virt = DipoleRepository::insertionPKOperators(dipoleSet()).begin(); virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) { if ( (**virt).apply((**born).diagrams().front()->partons()) ) nlopk->virtuals().push_back(*virt); } if ( !nlopk->virtuals().empty() ) { nlopk->doOneLoopNoBorn(); nlopk->doOneLoopNoLoops(); if ( nlopk->isOLPLoop() ) { int id = orderOLPProcess(nlopk->subProcess(), (**born).matchboxAmplitude(), ProcessType::treeME2); nlopk->olpProcess(ProcessType::treeME2,id); if ( nlopk->needsOLPCorrelators() ) { id = orderOLPProcess(nlopk->subProcess(), (**born).matchboxAmplitude(), ProcessType::colourCorrelatedME2); nlopk->olpProcess(ProcessType::colourCorrelatedME2,id); } } nlopk->needsCorrelations(); nlopk->cloneDependencies(); bornVirtualMEs().push_back(nlopk); MEs().push_back(nlopk); } } ++(*progressBar); } delete progressBar; generator()->log() << "--------------------------------------------------------------------------------\n" << flush; } theSplittingDipoles.clear(); set bornProcs; if ( showerApproximation() ) { if ( showerApproximation()->needsSplittingGenerator() ) { for ( vector::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) for ( MEBase::DiagramVector::const_iterator d = (**born).diagrams().begin(); d != (**born).diagrams().end(); ++d ) bornProcs.insert((**d).partons()); } } if ( realContributions() || meCorrectionsOnly() || (showerApproximation() && virtualContributions()) || (showerApproximation() && loopSimCorrections()) ) { generator()->log() << "preparing subtracted matrix elements.\n" << flush; if ( theSubtractionData != "" ) if ( theSubtractionData[theSubtractionData.size()-1] != '/' ) theSubtractionData += "/"; subtractedMEs().clear(); for ( vector::ptr>::iterator born = bornMEs().begin(); born != bornMEs().end(); ++born ) { if ( (**born).onlyOneLoop() ) continue; (**born).needsCorrelations(); if ( (**born).isOLPTree() ) { int id = orderOLPProcess((**born).subProcess(), (**born).matchboxAmplitude(), ProcessType::colourCorrelatedME2); (**born).olpProcess(ProcessType::colourCorrelatedME2,id); bool haveGluon = false; for ( PDVector::const_iterator p = (**born).subProcess().legs.begin(); p != (**born).subProcess().legs.end(); ++p ) if ( (**p).id() == 21 ) { haveGluon = true; break; } if ( haveGluon ) { id = orderOLPProcess((**born).subProcess(), (**born).matchboxAmplitude(), ProcessType::spinColourCorrelatedME2); (**born).olpProcess(ProcessType::spinColourCorrelatedME2,id); } if ( showerApproximation() ) { id = orderOLPProcess((**born).subProcess(), (**born).matchboxAmplitude(), ProcessType::treeME2); (**born).olpProcess(ProcessType::treeME2,id); } } } boost::progress_display * progressBar = new boost::progress_display(realEmissionMEs().size(),generator()->log()); for ( vector::ptr>::iterator real = realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) { Ptr::ptr sub = new_ptr(SubtractedME()); string pname = fullName() + "/" + (**real).name() + ".SubtractedReal"; if ( ! (generator()->preinitRegister(sub,pname) ) ) throw Exception() << "MatchboxFactory: Subtracted ME " << pname << " already existing." << Exception::runerror; sub->factory(this); (**real).needsNoCorrelations(); if ( (**real).isOLPTree() ) { int id = orderOLPProcess((**real).subProcess(), (**real).matchboxAmplitude(), ProcessType::treeME2); (**real).olpProcess(ProcessType::treeME2,id); } sub->head(*real); sub->dependent().clear(); sub->getDipoles(); if ( sub->dependent().empty() ) { // finite real contribution if ( realContributions() ) { Ptr::ptr fme = dynamic_ptr_cast::ptr>(sub->head())->cloneMe(); string qname = fullName() + "/" + (**real).name() + ".FiniteReal"; if ( ! (generator()->preinitRegister(fme,qname) ) ) throw Exception() << "MatchboxFactory: ME " << qname << " already existing." << Exception::runerror; MEs().push_back(fme); finiteRealMEs().push_back(fme); } sub->head(tMEPtr()); ++(*progressBar); continue; } if ( realEmissionScales() ) sub->doRealEmissionScales(); subtractedMEs().push_back(sub); if ( realContributions() ) if ( !showerApproximation() || (showerApproximation() && showerApproximation()->hasHEvents()) ) MEs().push_back(sub); if ( showerApproximation() ) { if ( virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections() ) { Ptr::ptr subv = new_ptr(*sub); string vname = sub->fullName() + ".SubtractionIntegral"; if ( ! (generator()->preinitRegister(subv,vname) ) ) throw Exception() << "MatchboxFactory: Subtracted ME " << vname << " already existing." << Exception::runerror; subv->cloneDependencies(vname); subv->doVirtualShowerSubtraction(); subtractedMEs().push_back(subv); MEs().push_back(subv); } if ( loopSimCorrections() ) { Ptr::ptr subv = new_ptr(*sub); string vname = sub->fullName() + ".SubtractionIntegral"; if ( ! (generator()->preinitRegister(subv,vname) ) ) throw Exception() << "MatchboxFactory: Subtracted ME " << vname << " already existing." << Exception::runerror; subv->cloneDependencies(vname); subv->doLoopSimSubtraction(); subtractedMEs().push_back(subv); MEs().push_back(subv); } sub->doRealShowerSubtraction(); if ( showerApproximation()->needsSplittingGenerator() ) for ( set::const_iterator p = bornProcs.begin(); p != bornProcs.end(); ++p ) { vector::ptr> sdip = sub->splitDipoles(*p); set::ptr>& dips = theSplittingDipoles[*p]; copy(sdip.begin(),sdip.end(),inserter(dips,dips.begin())); } } ++(*progressBar); } delete progressBar; generator()->log() << "--------------------------------------------------------------------------------\n" << flush; } if ( !theSplittingDipoles.empty() ) { map::ptr,Ptr::ptr> cloneMap; for ( map::ptr> >::const_iterator sd = theSplittingDipoles.begin(); sd != theSplittingDipoles.end(); ++sd ) { for ( set::ptr>::const_iterator d = sd->second.begin(); d != sd->second.end(); ++d ) { cloneMap[*d] = Ptr::ptr(); } } for ( map::ptr,Ptr::ptr>::iterator cd = cloneMap.begin(); cd != cloneMap.end(); ++cd ) { Ptr::ptr cloned = cd->first->cloneMe(); string dname = cd->first->fullName() + ".splitting"; if ( ! (generator()->preinitRegister(cloned,dname)) ) throw Exception() << "MatchboxFactory: Dipole '" << dname << "' already existing." << Exception::runerror; cloned->cloneDependencies(); cloned->showerApproximation(Ptr::tptr()); cloned->doSplitting(); cd->second = cloned; } for ( map::ptr> >::iterator sd = theSplittingDipoles.begin(); sd != theSplittingDipoles.end(); ++sd ) { set::ptr> cloned; for ( set::ptr>::iterator d = sd->second.begin(); d != sd->second.end(); ++d ) { cloned.insert(cloneMap[*d]); } sd->second = cloned; } } if ( !externalAmplitudes().empty() ) { generator()->log() << "Initializing external amplitudes.\n" << flush; for ( set::tptr>::const_iterator ext = externalAmplitudes().begin(); ext != externalAmplitudes().end(); ++ext ) { if ( !(**ext).initializeExternal() ) { throw Exception() << "Failed to initialize amplitude '" << (**ext).name() << "'\n" << Exception::runerror; } } generator()->log() << "--------------------------------------------------------------------------------\n" << flush; } if ( !olpProcesses().empty() ) { generator()->log() << "Initializing one-loop provider(s).\n" << flush; map::tptr,map,int> > olps; for ( map::tptr,map,int> >::const_iterator oit = olpProcesses().begin(); oit != olpProcesses().end(); ++oit ) { olps[oit->first] = oit->second; } for ( map::tptr,map,int> >::const_iterator olpit = olps.begin(); olpit != olps.end(); ++olpit ) { if ( !olpit->first->startOLP(olpit->second) ) { throw Exception() << "MatchboxFactory: Failed to start OLP for amplitude '" << olpit->first->name() << "'\n" << Exception::runerror; } } generator()->log() << "--------------------------------------------------------------------------------\n" << flush; } generator()->log() << "Process setup finished.\n" << flush; ranSetup = true; } } void MatchboxFactory::SplittingChannel::print(ostream& os) const { os << "--- SplittingChannel setup -----------------------------------------------------\n"; os << " Born process "; const StandardXComb& bxc = *bornXComb; os << bxc.mePartonData()[0]->PDGName() << " " << bxc.mePartonData()[1]->PDGName() << " -> "; for ( cPDVector::const_iterator p = bxc.mePartonData().begin() + 2; p != bxc.mePartonData().end(); ++p ) { os << (**p).PDGName() << " "; } os << "\n"; os << " to real emission process "; const StandardXComb& rxc = *realXComb; os << rxc.mePartonData()[0]->PDGName() << " " << rxc.mePartonData()[1]->PDGName() << " -> "; for ( cPDVector::const_iterator p = rxc.mePartonData().begin() + 2; p != rxc.mePartonData().end(); ++p ) { os << (**p).PDGName() << " "; } os << "\n"; os << " with dipole:\n"; dipole->print(os); os << "--------------------------------------------------------------------------------\n"; os << flush; } list MatchboxFactory::getSplittingChannels(tStdXCombPtr xcptr) const { if ( xcptr->lastProjector() ) xcptr = xcptr->lastProjector(); const StandardXComb& xc = *xcptr; cPDVector proc = xc.mePartonData(); map::ptr> >::const_iterator splitEntries = splittingDipoles().find(proc); list res; if ( splitEntries == splittingDipoles().end() ) return res; const set::ptr>& splitDipoles = splitEntries->second; SplittingChannel channel; if ( !splitDipoles.empty() ) { Ptr::tptr bornME = const_ptr_cast::tptr>((**splitDipoles.begin()).underlyingBornME()); channel.bornXComb = bornME->makeXComb(xc.maxEnergy(),xc.particles(),xc.eventHandlerPtr(), const_ptr_cast(xc.subProcessHandler()), xc.pExtractor(),xc.CKKWHandler(), xc.partonBins(),xc.cuts(),xc.diagrams(),xc.mirror(), PartonPairVec()); } for ( set::ptr>::const_iterator sd = splitDipoles.begin(); sd != splitDipoles.end(); ++sd ) { channel.dipole = *sd; vector realXCombs = (**sd).makeRealXCombs(channel.bornXComb); for ( vector::const_iterator rxc = realXCombs.begin(); rxc != realXCombs.end(); ++rxc ) { channel.realXComb = *rxc; if ( showerApproximation()->needsTildeXCombs() ) { channel.tildeXCombs.clear(); assert(!channel.dipole->partnerDipoles().empty()); for ( vector::tptr>::const_iterator p = channel.dipole->partnerDipoles().begin(); p != channel.dipole->partnerDipoles().end(); ++p ) { StdXCombPtr txc = channel.dipole->makeBornXComb(channel.realXComb); if ( txc ) channel.tildeXCombs.push_back(txc); } } res.push_back(channel); } } if ( initVerbose() ) { generator()->log() << "--- MatchboxFactory splitting channels ----------------------------------------------\n"; const StandardXComb& bxc = *xcptr; generator()->log() << " hard process handled is: "; generator()->log() << bxc.mePartonData()[0]->PDGName() << " " << bxc.mePartonData()[1]->PDGName() << " -> "; for ( cPDVector::const_iterator p = bxc.mePartonData().begin() + 2; p != bxc.mePartonData().end(); ++p ) { generator()->log() << (**p).PDGName() << " "; } generator()->log() << "\n"; for ( list::const_iterator sp = res.begin(); sp != res.end(); ++sp ) { sp->print(generator()->log()); } generator()->log() << "-------------------------------------------------------------------------------------\n" << flush; } return res; } void MatchboxFactory::print(ostream& os) const { os << "--- MatchboxFactory setup -----------------------------------------------------------\n"; if ( !amplitudes().empty() ) { os << " generated Born matrix elements:\n"; for ( vector::ptr>::const_iterator m = bornMEs().begin(); m != bornMEs().end(); ++m ) { (**m).print(os); } os << flush; os << " generated real emission matrix elements:\n"; for ( vector::ptr>::const_iterator m = realEmissionMEs().begin(); m != realEmissionMEs().end(); ++m ) { (**m).print(os); } os << flush; } os << " generated Born+virtual matrix elements:\n"; for ( vector::ptr>::const_iterator bv = bornVirtualMEs().begin(); bv != bornVirtualMEs().end(); ++bv ) { (**bv).print(os); } os << " generated subtracted matrix elements:\n"; for ( vector::ptr>::const_iterator sub = subtractedMEs().begin(); sub != subtractedMEs().end(); ++sub ) { os << " '" << (**sub).name() << "'\n"; } os << "--------------------------------------------------------------------------------\n"; os << flush; } void MatchboxFactory::doinit() { theIsMatchboxRun() = true; if ( RunDirectories::empty() ) RunDirectories::pushRunId(generator()->runName()); setup(); if ( theShowerApproximation ) theShowerApproximation->init(); if ( initVerbose() && !ranSetup ) print(Repository::clog()); Ptr::tptr eh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); assert(eh); SubProcessHandler::doinit(); } void MatchboxFactory::doinitrun() { theIsMatchboxRun() = true; if ( theShowerApproximation ) theShowerApproximation->initrun(); Ptr::tptr eh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); assert(eh); SubProcessHandler::doinitrun(); } const string& MatchboxFactory::buildStorage() { return RunDirectories::buildStorage(); } const string& MatchboxFactory::runStorage() { return RunDirectories::runStorage(); } void MatchboxFactory::persistentOutput(PersistentOStream & os) const { os << theDiagramGenerator << theProcessData << theNLight << theNLightJetVec << theNHeavyJetVec << theNLightProtonVec << theOrderInAlphaS << theOrderInAlphaEW << theBornContributions << theVirtualContributions << theRealContributions << theIndependentVirtuals << theIndependentPKs << theSubProcessGroups << thePhasespace << theScaleChoice << theFactorizationScaleFactor << theRenormalizationScaleFactor << theFixedCouplings << theFixedQEDCouplings << theVetoScales << theAmplitudes << theBornMEs << theVirtuals << theRealEmissionMEs << theLoopInducedMEs << theBornVirtualMEs << theSubtractedMEs << theFiniteRealMEs << theVerbose<> theDiagramGenerator >> theProcessData >> theNLight >> theNLightJetVec >> theNHeavyJetVec >> theNLightProtonVec >> theOrderInAlphaS >> theOrderInAlphaEW >> theBornContributions >> theVirtualContributions >> theRealContributions >> theIndependentVirtuals >> theIndependentPKs >> theSubProcessGroups >> thePhasespace >> theScaleChoice >> theFactorizationScaleFactor >> theRenormalizationScaleFactor >> theFixedCouplings >> theFixedQEDCouplings >> theVetoScales >> theAmplitudes >> theBornMEs >> theVirtuals >> theRealEmissionMEs >> theLoopInducedMEs >> theBornVirtualMEs >> theSubtractedMEs >> theFiniteRealMEs >> theVerbose >> theDiagramWeightVerbose >> theDiagramWeightVerboseNBins >> theInitVerbose >> theSubtractionData >> theSubtractionPlotType >> theSubtractionScatterPlot >> thePoleData >> theParticleGroups >> processes >> loopInducedProcesses >> realEmissionProcesses >> theShowerApproximation >> theSplittingDipoles >> theRealEmissionScales >> theAllProcesses >> theOLPProcesses >> theExternalAmplitudes >> theSelectedAmplitudes >> theDeselectedAmplitudes >> theDipoleSet >> theReweighters >> thePreweighters >> theMECorrectionsOnly>> theLoopSimCorrections>>theHighestVirtualsize >> ranSetup >> theIncoming >> theFirstPerturbativePDF >> theSecondPerturbativePDF - >> inProductionMode >> theSpinCorrelations>>theAlphaParameter; + >> inProductionMode >> theSpinCorrelations >> theAlphaParameter + >> theEnforceChargeConservation >> theEnforceColourConservation + >> theEnforceLeptonNumberConservation >> theEnforceQuarkNumberConservation + >> theLeptonFlavourDiagonal >> theQuarkFlavourDiagonal; } string MatchboxFactory::startParticleGroup(string name) { particleGroupName = StringUtils::stripws(name); particleGroup.clear(); return ""; } string MatchboxFactory::endParticleGroup(string) { if ( particleGroup.empty() ) throw Exception() << "MatchboxFactory: Empty particle group." << Exception::runerror; particleGroups()[particleGroupName] = particleGroup; particleGroup.clear(); return ""; } vector MatchboxFactory::parseProcess(string in) { vector process = StringUtils::split(in); if ( process.size() < 3 ) throw Exception() << "MatchboxFactory: Invalid process." << Exception::runerror; for ( vector::iterator p = process.begin(); p != process.end(); ++p ) { *p = StringUtils::stripws(*p); } vector pprocess; for ( vector::const_iterator p = process.begin(); p != process.end(); ++p ) { if ( *p == "->" ) continue; pprocess.push_back(*p); } return pprocess; } string MatchboxFactory::doProcess(string in) { processes.push_back(parseProcess(in)); return ""; } string MatchboxFactory::doLoopInducedProcess(string in) { loopInducedProcesses.push_back(parseProcess(in)); return ""; } string MatchboxFactory::doSingleRealProcess(string in) { realEmissionProcesses.push_back(parseProcess(in)); return ""; } struct SortPID { inline bool operator()(PDPtr a, PDPtr b) const { return a->id() < b->id(); } }; +// +// @TODO +// +// SP: After improving this for standard model process building this should +// actually got into a separate process builder class or something along these +// lines to have it better factored for use with BSM models. +// +// + set MatchboxFactory:: makeSubProcesses(const vector& proc) const { if ( proc.empty() ) throw Exception() << "MatchboxFactory: No process specified." << Exception::runerror; vector groups; typedef map::const_iterator GroupIterator; for ( vector::const_iterator gr = proc.begin(); gr != proc.end(); ++gr ) { GroupIterator git = particleGroups().find(*gr); if ( git == particleGroups().end() ) { throw Exception() << "MatchboxFactory: Particle group '" << *gr << "' not defined." << Exception::runerror; } groups.push_back(git->second); } vector counts(groups.size(),0); PDVector proto(groups.size()); set allProcs; - /* - cerr << "using the groups:\n"; - for ( size_t k = 0; k < groups.size(); ++k ) { - cerr << k << " : "; - for ( PDVector::const_iterator p = groups[k].begin(); - p != groups[k].end(); ++p ) - cerr << (**p).PDGName() << " "; - cerr << "\n" << flush; - } - */ - while ( true ) { for ( size_t k = 0; k < groups.size(); ++k ) proto[k] = groups[k][counts[k]]; - /* - cerr << "trying : "; - for ( vector::const_iterator c = counts.begin(); - c != counts.end(); ++c ) - cerr << *c << " "; - cerr << "\n" << flush; - for ( size_t k = 0; k < groups.size(); ++k ) - cerr << groups[k][counts[k]]->PDGName() << " "; - cerr << "\n" << flush; - */ + int charge = 0; + int colour = 0; + int nleptons = 0; + int nquarks = 0; + int ncolour = 0; - int charge = -proto[0]->iCharge() -proto[1]->iCharge(); - for ( size_t k = 2; k < proto.size(); ++k ) - charge += proto[k]->iCharge(); + int nleptonsGen[4]; + int nquarksGen[4]; + for ( size_t i = 0; i < 4; ++i ) { + nleptonsGen[i] = 0; + nquarksGen[i] = 0; + } - if ( charge == 0 ) { + for ( size_t k = 0; k < proto.size(); ++k ) { + int sign = k > 1 ? 1 : -1; + charge += sign * proto[k]->iCharge(); + colour += sign * proto[k]->iColour(); + if ( abs(proto[k]->id()) <= 8 ) { + int generation = (abs(proto[k]->id()) - 1)/2; + nquarks += sign * ( proto[k]->id() < 0 ? -1 : 1); + nquarksGen[generation] += sign * ( proto[k]->id() < 0 ? -1 : 1); + } + if ( abs(proto[k]->id()) > 10 && + abs(proto[k]->id()) <= 18 ) { + int generation = (abs(proto[k]->id()) - 11)/2; + nleptons += sign * ( proto[k]->id() < 0 ? -1 : 1); + nleptonsGen[generation] += sign * ( proto[k]->id() < 0 ? -1 : 1); + } + if ( proto[k]->coloured() ) + ++ncolour; + } + + bool pass = true; + + if ( theEnforceChargeConservation ) + pass &= (charge == 0); + + if ( theEnforceColourConservation ) + pass &= (colour % 8 == 0) && (ncolour > 1); + + if ( theEnforceLeptonNumberConservation ) { + pass &= (nleptons == 0); + if ( theLeptonFlavourDiagonal ) { + for ( size_t i = 0; i < 4; ++i ) + pass &= (nleptonsGen[i] == 0); + } + } + + if ( theEnforceQuarkNumberConservation ) { + pass &= (nquarks == 0); + if ( theQuarkFlavourDiagonal ) { + for ( size_t i = 0; i < 4; ++i ) + pass &= (nquarksGen[i] == 0); + } + } + + if ( pass ) { for ( int i = 0; i < 2; ++i ) { if ( proto[i]->coloured() && proto[i]->hardProcessMass() != ZERO ) throw Exception() << "Inconsistent flavour scheme detected with massive incoming " << proto[i]->PDGName() << ". Check your setup." << Exception::runerror; } sort(proto.begin()+2,proto.end(),SortPID()); allProcs.insert(proto); } vector::reverse_iterator c = counts.rbegin(); vector::const_reverse_iterator g = groups.rbegin(); while ( c != counts.rend() ) { if ( ++(*c) == g->size() ) { *c = 0; ++c; ++g; } else { break; } } if ( c == counts.rend() ) break; } return allProcs; } void MatchboxFactory::Init() { static ClassDocumentation documentation ("MatchboxFactory", "NLO QCD corrections have been calculated " "using Matchbox \\cite{Platzer:2011bc}, \\cite{Matchbox:2015}", "%\\cite{Platzer:2011bc}\n" "\\bibitem{Platzer:2011bc}\n" "S.~Platzer and S.~Gieseke,\n" "``Dipole Showers and Automated NLO Matching in Herwig,''\n" "arXiv:1109.6256 [hep-ph].\n" "%%CITATION = ARXIV:1109.6256;%%\n" "%\\cite{Matchbox:2015}\n" "\\bibitem{Matchbox:2015}\n" "Herwig collaboration,\n" "``Precision LHC Event Generation with Herwig,''\n" "in preparation."); static Reference interfaceDiagramGenerator ("DiagramGenerator", "Set the diagram generator.", &MatchboxFactory::theDiagramGenerator, false, false, true, true, false); static Reference interfaceProcessData ("ProcessData", "Set the process data object to be used.", &MatchboxFactory::theProcessData, false, false, true, true, false); static Parameter interfaceOrderInAlphaS ("OrderInAlphaS", "The order in alpha_s to consider.", &MatchboxFactory::theOrderInAlphaS, 0, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceOrderInAlphaEW ("OrderInAlphaEW", "The order in alpha_EW", &MatchboxFactory::theOrderInAlphaEW, 2, 0, 0, false, false, Interface::lowerlim); static Switch interfaceBornContributions ("BornContributions", "Switch on or off the Born contributions.", &MatchboxFactory::theBornContributions, true, false, false); static SwitchOption interfaceBornContributionsOn (interfaceBornContributions, "On", "Switch on Born contributions.", true); static SwitchOption interfaceBornContributionsOff (interfaceBornContributions, "Off", "Switch off Born contributions.", false); static Switch interfaceVirtualContributions ("VirtualContributions", "Switch on or off the virtual contributions.", &MatchboxFactory::theVirtualContributions, true, false, false); static SwitchOption interfaceVirtualContributionsOn (interfaceVirtualContributions, "On", "Switch on virtual contributions.", true); static SwitchOption interfaceVirtualContributionsOff (interfaceVirtualContributions, "Off", "Switch off virtual contributions.", false); static Switch interfaceRealContributions ("RealContributions", "Switch on or off the real contributions.", &MatchboxFactory::theRealContributions, true, false, false); static SwitchOption interfaceRealContributionsOn (interfaceRealContributions, "On", "Switch on real contributions.", true); static SwitchOption interfaceRealContributionsOff (interfaceRealContributions, "Off", "Switch off real contributions.", false); static Switch interfaceIndependentVirtuals ("IndependentVirtuals", "Switch on or off virtual contributions as separate subprocesses.", &MatchboxFactory::theIndependentVirtuals, true, false, false); static SwitchOption interfaceIndependentVirtualsOn (interfaceIndependentVirtuals, "On", "Switch on virtual contributions as separate subprocesses.", true); static SwitchOption interfaceIndependentVirtualsOff (interfaceIndependentVirtuals, "Off", "Switch off virtual contributions as separate subprocesses.", false); static Switch interfaceIndependentPKs ("IndependentPKOperators", "Switch on or off PK oeprators as separate subprocesses.", &MatchboxFactory::theIndependentPKs, true, false, false); static SwitchOption interfaceIndependentPKsOn (interfaceIndependentPKs, "On", "Switch on PK operators as separate subprocesses.", true); static SwitchOption interfaceIndependentPKsOff (interfaceIndependentPKs, "Off", "Switch off PK operators as separate subprocesses.", false); static Switch interfaceSubProcessGroups ("SubProcessGroups", "Switch on or off production of sub-process groups.", &MatchboxFactory::theSubProcessGroups, false, false, false); static SwitchOption interfaceSubProcessGroupsOn (interfaceSubProcessGroups, "On", "On", true); static SwitchOption interfaceSubProcessGroupsOff (interfaceSubProcessGroups, "Off", "Off", false); static Reference interfacePhasespace ("Phasespace", "Set the phasespace generator.", &MatchboxFactory::thePhasespace, false, false, true, true, false); static Reference interfaceScaleChoice ("ScaleChoice", "Set the scale choice object.", &MatchboxFactory::theScaleChoice, false, false, true, true, false); static Parameter interfaceFactorizationScaleFactor ("FactorizationScaleFactor", "The factorization scale factor.", &MatchboxFactory::theFactorizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceRenormalizationScaleFactor ("RenormalizationScaleFactor", "The renormalization scale factor.", &MatchboxFactory::theRenormalizationScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Switch interfaceFixedCouplings ("FixedCouplings", "Switch on or off fixed couplings.", &MatchboxFactory::theFixedCouplings, true, false, false); static SwitchOption interfaceFixedCouplingsOn (interfaceFixedCouplings, "On", "On", true); static SwitchOption interfaceFixedCouplingsOff (interfaceFixedCouplings, "Off", "Off", false); static Switch interfaceFixedQEDCouplings ("FixedQEDCouplings", "Switch on or off fixed QED couplings.", &MatchboxFactory::theFixedQEDCouplings, true, false, false); static SwitchOption interfaceFixedQEDCouplingsOn (interfaceFixedQEDCouplings, "On", "On", true); static SwitchOption interfaceFixedQEDCouplingsOff (interfaceFixedQEDCouplings, "Off", "Off", false); static Switch interfaceVetoScales ("VetoScales", "Switch on or setting veto scales.", &MatchboxFactory::theVetoScales, false, false, false); static SwitchOption interfaceVetoScalesOn (interfaceVetoScales, "On", "On", true); static SwitchOption interfaceVetoScalesOff (interfaceVetoScales, "Off", "Off", false); static RefVector interfaceAmplitudes ("Amplitudes", "The amplitude objects.", &MatchboxFactory::theAmplitudes, -1, false, false, true, true, false); static RefVector interfaceBornMEs ("BornMEs", "The Born matrix elements to be used", &MatchboxFactory::theBornMEs, -1, false, false, true, true, false); static RefVector interfaceVirtuals ("Virtuals", "The virtual corrections to include", &MatchboxFactory::theVirtuals, -1, false, false, true, true, false); static RefVector interfaceRealEmissionMEs ("RealEmissionMEs", "The RealEmission matrix elements to be used", &MatchboxFactory::theRealEmissionMEs, -1, false, false, true, true, false); static RefVector interfaceBornVirtuals ("BornVirtualMEs", "The generated Born/virtual contributions", &MatchboxFactory::theBornVirtualMEs, -1, false, true, true, true, false); static RefVector interfaceSubtractedMEs ("SubtractedMEs", "The generated subtracted real emission contributions", &MatchboxFactory::theSubtractedMEs, -1, false, true, true, true, false); static RefVector interfaceFiniteRealMEs ("FiniteRealMEs", "The generated finite real contributions", &MatchboxFactory::theFiniteRealMEs, -1, false, true, true, true, false); static Switch interfaceVerbose ("Verbose", "Print full infomation on each evaluated phase space point.", &MatchboxFactory::theVerbose, false, false, false); static SwitchOption interfaceVerboseOn (interfaceVerbose, "On", "On", true); static SwitchOption interfaceVerboseOff (interfaceVerbose, "Off", "Off", false); static Switch interfaceVerboseDia ("DiagramWeightVerbose", "Print full infomation on each evaluated phase space point.", &MatchboxFactory::theDiagramWeightVerbose, false, false, false); static SwitchOption interfaceVerboseDiaOn (interfaceVerboseDia, "On", "On", true); static SwitchOption interfaceVerboseDiaOff (interfaceVerboseDia, "Off", "Off", false); static Parameter interfaceVerboseDiaNbins ("DiagramWeightVerboseNBins", "No. of Bins for DiagramWeightVerbose Diagrams.", &MatchboxFactory::theDiagramWeightVerboseNBins, 200, 0, 0, false, false, Interface::lowerlim); static Switch interfaceInitVerbose ("InitVerbose", "Print setup information.", &MatchboxFactory::theInitVerbose, false, false, false); static SwitchOption interfaceInitVerboseOn (interfaceInitVerbose, "On", "On", true); static SwitchOption interfaceInitVerboseOff (interfaceInitVerbose, "Off", "Off", false); static Parameter interfaceSubtractionData ("SubtractionData", "Prefix for subtraction check data.", &MatchboxFactory::theSubtractionData, "", false, false); static Switch interfaceSubtractionPlotType ("SubtractionPlotType", "Switch for controlling what kind of plot is generated for checking the subtraction", &MatchboxFactory::theSubtractionPlotType, 1, false, false); static SwitchOption interfaceSubtractionPlotTypeLinearRatio (interfaceSubtractionPlotType, "LinRatio", "Switch on the linear plot of the ratio", 1); static SwitchOption interfaceSubtractionPlotTypeLogRelDiff (interfaceSubtractionPlotType, "LogRelDiff", "Switch on the logarithmic plot of the relative difference", 2); static Switch interfaceSubtractionScatterPlot ("SubtractionScatterPlot", "Switch for controlling whether subtraction data should be plotted for each phase space point individually", &MatchboxFactory::theSubtractionScatterPlot, false, false, false); static SwitchOption interfaceSubtractionScatterPlotOff (interfaceSubtractionScatterPlot, "Off", "Switch off the scatter plot", false); static SwitchOption interfaceSubtractionScatterPlotOn (interfaceSubtractionScatterPlot, "On", "Switch on the scatter plot", true); static Parameter interfacePoleData ("PoleData", "Prefix for subtraction check data.", &MatchboxFactory::thePoleData, "", false, false); static RefVector interfaceParticleGroup ("ParticleGroup", "The particle group just started.", &MatchboxFactory::particleGroup, -1, false, false, true, false, false); static Command interfaceStartParticleGroup ("StartParticleGroup", "Start a particle group.", &MatchboxFactory::startParticleGroup, false); static Command interfaceEndParticleGroup ("EndParticleGroup", "End a particle group.", &MatchboxFactory::endParticleGroup, false); static Command interfaceProcess ("Process", "Set the process(es) to consider.", &MatchboxFactory::doProcess, false); static Command interfaceLoopInducedProcess ("LoopInducedProcess", "Set the loop induced process(es) to consider.", &MatchboxFactory::doLoopInducedProcess, false); static Command interfaceSingleRealProcess ("SingleRealProcess", "Set the real emission process(es) to consider.", &MatchboxFactory::doSingleRealProcess, false); static Reference interfaceShowerApproximation ("ShowerApproximation", "Set the shower approximation to be considered.", &MatchboxFactory::theShowerApproximation, false, false, true, true, false); static Switch interfaceRealEmissionScales ("RealEmissionScales", "Switch on or off calculation of subtraction scales from real emission kinematics.", &MatchboxFactory::theRealEmissionScales, false, false, false); static SwitchOption interfaceRealEmissionScalesOn (interfaceRealEmissionScales, "On", "On", true); static SwitchOption interfaceRealEmissionScalesOff (interfaceRealEmissionScales, "Off", "Off", false); static Switch interfaceAllProcesses ("AllProcesses", "Consider all processes up to a maximum coupling order specified by the coupling order interfaces.", &MatchboxFactory::theAllProcesses, false, false, false); static SwitchOption interfaceAllProcessesYes (interfaceAllProcesses, "Yes", "Include all processes.", true); static SwitchOption interfaceAllProcessesNo (interfaceAllProcesses, "No", "Only consider processes matching the exact order in the couplings.", false); static RefVector interfaceSelectAmplitudes ("SelectAmplitudes", "The amplitude objects to be favoured in clashing responsibilities.", &MatchboxFactory::theSelectedAmplitudes, -1, false, false, true, true, false); static RefVector interfaceDeselectAmplitudes ("DeselectAmplitudes", "The amplitude objects to be disfavoured in clashing responsibilities.", &MatchboxFactory::theDeselectedAmplitudes, -1, false, false, true, true, false); static Switch interfaceDipoleSet ("DipoleSet", "The set of subtraction terms to be considered.", &MatchboxFactory::theDipoleSet, 0, false, false); static SwitchOption interfaceDipoleSetCataniSeymour (interfaceDipoleSet, "CataniSeymour", "Use default Catani-Seymour dipoles.", 0); static RefVector interfaceReweighters ("Reweighters", "Reweight objects for matrix elements.", &MatchboxFactory::theReweighters, -1, false, false, true, false, false); static RefVector interfacePreweighters ("Preweighters", "Preweight objects for matrix elements.", &MatchboxFactory::thePreweighters, -1, false, false, true, false, false); static Switch interfaceMECorrectionsOnly ("MECorrectionsOnly", "Prepare only ME corrections, but no NLO calculation.", &MatchboxFactory::theMECorrectionsOnly, false, false, false); static SwitchOption interfaceMECorrectionsOnlyYes (interfaceMECorrectionsOnly, "Yes", "Produce only ME corrections.", true); static SwitchOption interfaceMECorrectionsOnlyNo (interfaceMECorrectionsOnly, "No", "Produce full NLO.", false); static Switch interfaceLoopSimCorrections ("LoopSimCorrections", "Prepare LoopSim corrections.", &MatchboxFactory::theLoopSimCorrections, false, false, false); static SwitchOption interfaceLoopSimCorrectionsYes (interfaceLoopSimCorrections, "Yes", "Produce loopsim corrections.", true); static SwitchOption interfaceLoopSimCorrectionsNo (interfaceLoopSimCorrections, "No", "Produce full NLO.", false); static Switch interfaceFirstPerturbativePDF ("FirstPerturbativePDF", "", &MatchboxFactory::theFirstPerturbativePDF, true, false, false); static SwitchOption interfaceFirstPerturbativePDFYes (interfaceFirstPerturbativePDF, "Yes", "", true); static SwitchOption interfaceFirstPerturbativePDFNo (interfaceFirstPerturbativePDF, "No", "", false); static Switch interfaceSecondPerturbativePDF ("SecondPerturbativePDF", "", &MatchboxFactory::theSecondPerturbativePDF, true, false, false); static SwitchOption interfaceSecondPerturbativePDFYes (interfaceSecondPerturbativePDF, "Yes", "", true); static SwitchOption interfaceSecondPerturbativePDFNo (interfaceSecondPerturbativePDF, "No", "", false); static Command interfaceProductionMode ("ProductionMode", "Switch this factory to production mode.", &MatchboxFactory::doProductionMode, false); static Switch interfaceSpinCorrelations ("SpinCorrelations", "Fill information for the spin correlations, if possible.", &MatchboxFactory::theSpinCorrelations, false, false, false); static SwitchOption interfaceSpinCorrelationsYes (interfaceSpinCorrelations, "Yes", "", true); static SwitchOption interfaceSpinCorrelationsNo (interfaceSpinCorrelations, "No", "", false); - static Parameter interfaceAlphaParameter ("AlphaParameter", "Nagy-AlphaParameter.", &MatchboxFactory::theAlphaParameter, 1.0, 0.0, 0, false, false, Interface::lowerlim); + + static Switch interfaceEnforceChargeConservation + ("EnforceChargeConservation", + "Enforce charge conservation while generating the hard process.", + &MatchboxFactory::theEnforceChargeConservation, true, false, false); + static SwitchOption interfaceEnforceChargeConservationYes + (interfaceEnforceChargeConservation, + "Yes", + "Enforce charge conservation.", + true); + static SwitchOption interfaceEnforceChargeConservationNo + (interfaceEnforceChargeConservation, + "No", + "Do not enforce charge conservation.", + false); + + static Switch interfaceEnforceColourConservation + ("EnforceColourConservation", + "Enforce colour conservation while generating the hard process.", + &MatchboxFactory::theEnforceColourConservation, true, false, false); + static SwitchOption interfaceEnforceColourConservationYes + (interfaceEnforceColourConservation, + "Yes", + "Enforce colour conservation.", + true); + static SwitchOption interfaceEnforceColourConservationNo + (interfaceEnforceColourConservation, + "No", + "Do not enforce colour conservation.", + false); + + static Switch interfaceEnforceLeptonNumberConservation + ("EnforceLeptonNumberConservation", + "Enforce lepton number conservation while generating the hard process.", + &MatchboxFactory::theEnforceLeptonNumberConservation, true, false, false); + static SwitchOption interfaceEnforceLeptonNumberConservationYes + (interfaceEnforceLeptonNumberConservation, + "Yes", + "Enforce lepton number conservation.", + true); + static SwitchOption interfaceEnforceLeptonNumberConservationNo + (interfaceEnforceLeptonNumberConservation, + "No", + "Do not enforce lepton number conservation.", + false); + + static Switch interfaceEnforceQuarkNumberConservation + ("EnforceQuarkNumberConservation", + "Enforce quark number conservation while generating the hard process.", + &MatchboxFactory::theEnforceQuarkNumberConservation, true, false, false); + static SwitchOption interfaceEnforceQuarkNumberConservationYes + (interfaceEnforceQuarkNumberConservation, + "Yes", + "Enforce quark number conservation.", + true); + static SwitchOption interfaceEnforceQuarkNumberConservationNo + (interfaceEnforceQuarkNumberConservation, + "No", + "Do not enforce quark number conservation.", + false); + + static Switch interfaceLeptonFlavourDiagonal + ("LeptonFlavourDiagonal", + "Assume that lepton interactions are flavour diagonal while generating the hard process.", + &MatchboxFactory::theLeptonFlavourDiagonal, true, false, false); + static SwitchOption interfaceLeptonFlavourDiagonalYes + (interfaceLeptonFlavourDiagonal, + "Yes", + "Assume that lepton interactions are flavour diagonal.", + true); + static SwitchOption interfaceLeptonFlavourDiagonalNo + (interfaceLeptonFlavourDiagonal, + "No", + "Do not assume that lepton interactions are flavour diagonal.", + false); + + static Switch interfaceQuarkFlavourDiagonal + ("QuarkFlavourDiagonal", + "Assume that quark interactions are flavour diagonal while generating the hard process.", + &MatchboxFactory::theQuarkFlavourDiagonal, true, false, false); + static SwitchOption interfaceQuarkFlavourDiagonalYes + (interfaceQuarkFlavourDiagonal, + "Yes", + "Assume that quark interactions are flavour diagonal.", + true); + static SwitchOption interfaceQuarkFlavourDiagonalNo + (interfaceQuarkFlavourDiagonal, + "No", + "Do not assume that quark interactions are flavour diagonal.", + false); + } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigMatchboxFactory("Herwig::MatchboxFactory", "Herwig.so"); diff --git a/MatrixElement/Matchbox/MatchboxFactory.h b/MatrixElement/Matchbox/MatchboxFactory.h --- a/MatrixElement/Matchbox/MatchboxFactory.h +++ b/MatrixElement/Matchbox/MatchboxFactory.h @@ -1,1248 +1,1285 @@ // -*- C++ -*- // // MatchboxFactory.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2012 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_MatchboxFactory_H #define HERWIG_MatchboxFactory_H // // This is the declaration of the MatchboxFactory class. // #include "ThePEG/Handlers/SubProcessHandler.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include "Herwig/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h" #include "Herwig/MatrixElement/Matchbox/Utility/ProcessData.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.fh" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief MatchboxFactory automatically sets up a NLO * QCD calculation carried out in dipole subtraction. * * @see \ref MatchboxFactoryInterfaces "The interfaces" * defined for MatchboxFactory. */ class MatchboxFactory: public SubProcessHandler { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ MatchboxFactory(); /** * The destructor. */ virtual ~MatchboxFactory(); //@} public: /** * Flag to indicate that at least one MatchboxFactory object is in action */ static bool isMatchboxRun() { return theIsMatchboxRun(); } /** @name Process and diagram information */ //@{ /** * Return the diagram generator. */ Ptr::tptr diagramGenerator() const { return theDiagramGenerator; } /** * Set the diagram generator. */ void diagramGenerator(Ptr::ptr dg) { theDiagramGenerator = dg; } /** * Return the process data. */ Ptr::tptr processData() const { return theProcessData; } /** * Set the process data. */ void processData(Ptr::ptr pd) { theProcessData = pd; } /** * Return the number of light flavours, this matrix * element is calculated for. */ unsigned int nLight() const { return theNLight; } /** * Set the number of light flavours, this matrix * element is calculated for. */ void nLight(unsigned int n) { theNLight = n; } /** * Return the vector that contains the PDG ids of * the light flavours, which are contained in the * jet particle group. */ vector nLightJetVec() const { return theNLightJetVec; } /** * Set the elements of the vector that contains the PDG * ids of the light flavours, which are contained in the * jet particle group. */ void nLightJetVec(int n) { theNLightJetVec.push_back(n); } /** * Return the vector that contains the PDG ids of * the heavy flavours, which are contained in the * jet particle group. */ vector nHeavyJetVec() const { return theNHeavyJetVec; } /** * Set the elements of the vector that contains the PDG * ids of the heavy flavours, which are contained in the * jet particle group. */ void nHeavyJetVec(int n) { theNHeavyJetVec.push_back(n); } /** * Return the vector that contains the PDG ids of * the light flavours, which are contained in the * proton particle group. */ vector nLightProtonVec() const { return theNLightProtonVec; } /** * Set the elements of the vector that contains the PDG * ids of the light flavours, which are contained in the * proton particle group. */ void nLightProtonVec(int n) { theNLightProtonVec.push_back(n); } /** * Return the order in \f$\alpha_S\f$. */ unsigned int orderInAlphaS() const { return theOrderInAlphaS; } /** * Set the order in \f$\alpha_S\f$. */ void orderInAlphaS(unsigned int o) { theOrderInAlphaS = o; } /** * Return the order in \f$\alpha_{EM}\f$. */ unsigned int orderInAlphaEW() const { return theOrderInAlphaEW; } /** * Set the order in \f$\alpha_{EM}\f$. */ void orderInAlphaEW(unsigned int o) { theOrderInAlphaEW = o; } /** * Return true, if all processes up to a maximum order are considered */ bool allProcesses() const { return theAllProcesses; } /** * Switch on/off inclusino off all processes up to a maximum order */ void setAllProcesses(bool on = true) { theAllProcesses = on; } /** * Return true, if Born contributions should be included. */ bool bornContributions() const { return theBornContributions; } /** * Switch on or off Born contributions */ void setBornContributions(bool on = true) { theBornContributions = on; } /** * Return true, if virtual contributions should be included. */ bool virtualContributions() const { return theVirtualContributions; } /** * Switch on or off virtual contributions */ void setVirtualContributions(bool on = true) { theVirtualContributions = on; } /** * Produce matrix element corrections, but no NLO */ bool meCorrectionsOnly() const { return theMECorrectionsOnly; } /** * Switch to produce matrix element corrections, but no NLO */ void setMECorrectionsOnly(bool on = true) { theMECorrectionsOnly = on; } /** * Produce matrix element corrections, with LoopSim NLO */ bool loopSimCorrections() const { return theLoopSimCorrections; } /** * Switch to produce matrix element corrections, with LoopSim NLO */ void setLoopSimCorrections(bool on = true) { theLoopSimCorrections = on; } /** * Return true, if subtracted real emission contributions should be included. */ bool realContributions() const { return theRealContributions; } /** * Switch on or off subtracted real emission contributions */ void setRealContributions(bool on = true) { theRealContributions = on; } /** * Return true, if virtual contributions should be treated as independent subprocesses */ bool independentVirtuals() const { return theIndependentVirtuals; } /** * Switch on/off virtual contributions should be treated as independent subprocesses */ void setIndependentVirtuals(bool on = true) { theIndependentVirtuals = on; } /** * Return true, if PK operator contributions should be treated as independent subprocesses */ bool independentPKs() const { return theIndependentPKs; } /** * Switch on/off PK operator contributions should be treated as independent subprocesses */ void setIndependentPKs(bool on = true) { theIndependentPKs = on; } /** * Return true, if SubProcessGroups should be * setup from this MEGroup. If not, a single SubProcess * is constructed from the data provided by the * head matrix element. */ bool subProcessGroups() const { return theSubProcessGroups; } /** * Switch on or off producing subprocess groups. */ void setSubProcessGroups(bool on = true) { theSubProcessGroups = on; } /** * Return true, if subtraction scales should be caluclated from real emission kinematics */ bool realEmissionScales() const { return theRealEmissionScales; } /** * Switch on/off that subtraction scales should be caluclated from real emission kinematics */ void setRealEmissionScales(bool on = true) { theRealEmissionScales = on; } /** * Set the shower approximation. */ void showerApproximation(Ptr::tptr app) { theShowerApproximation = app; } /** * Return the shower approximation. */ Ptr::tptr showerApproximation() const { return theShowerApproximation; } //@} /** @name Phasespace generation and scale choice */ //@{ /** * Return the phase space generator to be used. */ Ptr::tptr phasespace() const { return thePhasespace; } /** * Set the phase space generator to be used. */ void phasespace(Ptr::ptr ps) { thePhasespace = ps; } /** * Set the scale choice object */ void scaleChoice(Ptr::ptr sc) { theScaleChoice = sc; } /** * Return the scale choice object */ Ptr::tptr scaleChoice() const { return theScaleChoice; } /** * Get the factorization scale factor */ double factorizationScaleFactor() const { return theFactorizationScaleFactor; } /** * Set the factorization scale factor */ void factorizationScaleFactor(double f) { theFactorizationScaleFactor = f; } /** * Get the renormalization scale factor */ double renormalizationScaleFactor() const { return theRenormalizationScaleFactor; } /** * Set the renormalization scale factor */ void renormalizationScaleFactor(double f) { theRenormalizationScaleFactor = f; } /** * Return true, if fixed couplings are used. */ bool fixedCouplings() const { return theFixedCouplings; } /** * Switch on fixed couplings. */ void setFixedCouplings(bool on = true) { theFixedCouplings = on; } /** * Return true, if fixed couplings are used. */ bool fixedQEDCouplings() const { return theFixedQEDCouplings; } /** * Switch on fixed couplings. */ void setFixedQEDCouplings(bool on = true) { theFixedQEDCouplings = on; } /** * Return true, if veto scales should be set * for the real emission */ bool vetoScales() const { return theVetoScales; } /** * Switch on setting veto scales */ void doVetoScales() { theVetoScales = true; } /** * Switch off setting veto scales */ void noVetoScales() { theVetoScales = true; } //@} /** @name Amplitudes and caching */ //@{ /** * Return the amplitudes to be considered */ const vector::ptr>& amplitudes() const { return theAmplitudes; } /** * Access the amplitudes to be considered */ vector::ptr>& amplitudes() { return theAmplitudes; } //@} /** @name Matrix element objects. */ //@{ /** * Return the Born matrix elements to be considered */ const vector::ptr>& bornMEs() const { return theBornMEs; } /** * Access the Born matrix elements to be considered */ vector::ptr>& bornMEs() { return theBornMEs; } /** * Return the loop induced matrix elements to be considered */ const vector::ptr>& loopInducedMEs() const { return theLoopInducedMEs; } /** * Access the loop induced matrix elements to be considered */ vector::ptr>& loopInducedMEs() { return theLoopInducedMEs; } /** * Return the processes to be ordered from an OLP */ const map::tptr, map,int> >& olpProcesses() const { return theOLPProcesses; } /** * Access the processes to be ordered from an OLP */ map::tptr, map,int> >& olpProcesses() { return theOLPProcesses; } /** * Order an OLP process and return its id */ int orderOLPProcess(const Process& p, Ptr::tptr amp, int type); /** * Return the amplitudes which need external initialization */ const set::tptr>& externalAmplitudes() const { return theExternalAmplitudes; } /** * Access the amplitudes which need external initialization */ set::tptr>& externalAmplitudes() { return theExternalAmplitudes; } /** * Return the virtual corrections to be considered */ const vector::ptr>& virtuals() const { return theVirtuals; } /** * Access the virtual corrections to be considered */ vector::ptr>& virtuals() { return theVirtuals; } /** * Return the produced NLO matrix elements */ const vector::ptr>& bornVirtualMEs() const { return theBornVirtualMEs; } /** * Access the produced NLO matrix elements */ vector::ptr>& bornVirtualMEs() { return theBornVirtualMEs; } /** * Return the real emission matrix elements to be considered */ const vector::ptr>& realEmissionMEs() const { return theRealEmissionMEs; } /** * Access the real emission matrix elements to be considered */ vector::ptr>& realEmissionMEs() { return theRealEmissionMEs; } /** * Return, which set of dipoles should be considered */ int dipoleSet() const { return theDipoleSet; } /** * Return, which set of dipoles should be considered */ void dipoleSet(int s) { theDipoleSet = s; } /** * Return the produced subtracted matrix elements */ const vector::ptr>& subtractedMEs() const { return theSubtractedMEs; } /** * Access the produced subtracted matrix elements */ vector::ptr>& subtractedMEs() { return theSubtractedMEs; } /** * Return the produced finite real emission matrix elements */ const vector::ptr>& finiteRealMEs() const { return theFiniteRealMEs; } /** * Access the produced finite real emission elements */ vector::ptr>& finiteRealMEs() { return theFiniteRealMEs; } /** * Return the map of Born processes to splitting dipoles */ const map::ptr> >& splittingDipoles() const { return theSplittingDipoles; } /** * Identify a splitting channel */ struct SplittingChannel { /** * The Born XComb */ StdXCombPtr bornXComb; /** * The real XComb */ StdXCombPtr realXComb; /** * The set of tilde XCombs to consider for the real xcomb */ vector tildeXCombs; /** * The dipole in charge of the splitting */ Ptr::ptr dipole; /** * Dump the setup */ void print(ostream&) const; }; /** * Generate all splitting channels for the Born process handled by * the given XComb */ list getSplittingChannels(tStdXCombPtr xc) const; /** * Return the reweight objects for matrix elements */ const vector& reweighters() const { return theReweighters; } /** * Access the reweight objects for matrix elements */ vector& reweighters() { return theReweighters; } /** * Return the preweight objects for matrix elements */ const vector& preweighters() const { return thePreweighters; } /** * Access the preweight objects for matrix elements */ vector& preweighters() { return thePreweighters; } //@} /** @name Setup the matrix elements */ //@{ /** * Return true if this object needs to be initialized before all * other objects (except those for which this function also returns * true). This default version always returns false, but subclasses * may override it to return true. */ virtual bool preInitialize() const { return true; } /** * Prepare a matrix element. */ void prepareME(Ptr::ptr); /** * Check consistency and switch to porduction mode. */ void productionMode(); /** * Setup everything */ virtual void setup(); /** * The highest multiplicity of legs having virtual contributions.(needed for madgraph) */ size_t highestVirt(){return theHighestVirtualsize;} //@} /** @name Diagnostic information */ //@{ /** * Return true, if verbose */ bool verbose() const { return theVerbose; } /** * Switch on diagnostic information. */ void setVerbose(bool on = true) { theVerbose = on; } /** * Return true, if diagram weight is verbose */ bool verboseDia() const { return theDiagramWeightVerbose; } /** * Number of bins for diagram weight verbosity */ int diagramWeightVerboseNBins() const {return theDiagramWeightVerboseNBins;} /** * Return true, if verbose while initializing */ bool initVerbose() const { return theInitVerbose || verbose(); } /** * Switch on diagnostic information while initializing */ void setInitVerbose(bool on = true) { theInitVerbose = on; } /** * Dump the setup */ void print(ostream&) const; /** * Return the subtraction data prefix. */ const string& subtractionData() const { return theSubtractionData; } /** * Set the subtraction data prefix. */ void subtractionData(const string& s) { theSubtractionData = s; } /** * Return the subtraction plot type. */ const int& subtractionPlotType() const { return theSubtractionPlotType; } /** * Set the subtraction plot type. */ void subtractionPlotType(const int& t) { theSubtractionPlotType = t; } /** * Return whether subtraction data should be plotted for all phase space points individually */ const bool& subtractionScatterPlot() const { return theSubtractionScatterPlot; } /** * Set whether subtraction data should be plotted for all phase space points individually */ void subtractionScatterPlot(const bool& s) { theSubtractionScatterPlot = s; } /** * Return the pole data prefix. */ const string& poleData() const { return thePoleData; } /** * Set the pole data prefix. */ void poleData(const string& s) { thePoleData = s; } /** * Return true, if cancellationn of epsilon poles should be checked. */ bool checkPoles() const { return poleData() != ""; } //@} /** @name Process generation */ //@{ /** * Return the particle groups. */ const map& particleGroups() const { return theParticleGroups; } /** * Access the particle groups. */ map& particleGroups() { return theParticleGroups; } /** * Return true, if the given particle is incoming */ bool isIncoming(cPDPtr p) const { return theIncoming.find(p->id()) != theIncoming.end(); } /** * Return true, if spin correlation information should be provided, if possible. */ bool spinCorrelations() const { return theSpinCorrelations; } /** * Indicate that spin correlation information should be provided, if possible. */ void setSpinCorrelations(bool yes) { theSpinCorrelations = yes; } //@} /** @name Truncated qtilde shower information */ //@{ /** * Return the subprocess of the real emission */ tSubProPtr hardTreeSubprocess() { return theHardtreeSubprocess; } /** * Set the subprocess of the real emission for use in calculating the shower hardtree */ void setHardTreeSubprocess(tSubProPtr hardTree) { theHardtreeSubprocess = hardTree; } /** * Return the born emitter */ int hardTreeEmitter() { return theHardtreeEmitter; } /** * Set the born emitter for use in calculating the shower hardtree */ void setHardTreeEmitter(int emitter) { theHardtreeEmitter = emitter; } /** * Return the born spectator */ int hardTreeSpectator() { return theHardtreeSpectator; } /** * Set the born spectator for use in calculating the shower hardtree */ void setHardTreeSpectator(int spectator) { theHardtreeSpectator = spectator; } //@} /** @name Data handling */ //@{ /** * Return (and possibly create) a directory to contain amplitude * information. */ const string& buildStorage(); /** * Return (and possibly create) a directory to contain integration grid * information. */ const string& runStorage(); /** * alpha of http://arxiv.org/pdf/hep-ph/0307268v2.pdf to restrict * dipole phase space */ double alphaParameter() const { return theAlphaParameter; } /** * set the alpha parameter (needed for massive PK-Operator) */ void setAlphaParameter(double a) { theAlphaParameter = a; } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * Flag to indicate that at least one MatchboxFactory object is in action */ static bool& theIsMatchboxRun(); /** * The diagram generator. */ Ptr::ptr theDiagramGenerator; /** * The process data object to be used */ Ptr::ptr theProcessData; /** * The number of light flavours, this matrix * element is calculated for. */ unsigned int theNLight; /** * Vector with the PDG ids of the light quark flavours, * which are contained in the jet particle group. */ vector theNLightJetVec; /** * Vector with the PDG ids of the heavy quark flavours, * which are contained in the jet particle group. */ vector theNHeavyJetVec; /** * Vector with the PDG ids of the light quark flavours, * which are contained in the proton particle group. */ vector theNLightProtonVec; /** * The order in \f$\alpha_S\f$. */ unsigned int theOrderInAlphaS; /** * The order in \f$\alpha_{EM}\f$. */ unsigned int theOrderInAlphaEW; /** * Switch on or off Born contributions */ bool theBornContributions; /** * Switch on or off virtual contributions */ bool theVirtualContributions; /** * Switch on or off subtracted real emission contributions should be included. */ bool theRealContributions; /** * True if virtual contributions should be treated as independent subprocesses */ bool theIndependentVirtuals; /** * True if PK operator contributions should be treated as independent subprocesses */ bool theIndependentPKs; /** * True, if SubProcessGroups should be * setup from this MEGroup. If not, a single SubProcess * is constructed from the data provided by the * head matrix element. */ bool theSubProcessGroups; /** * The phase space generator to be used. */ Ptr::ptr thePhasespace; /** * The scale choice object */ Ptr::ptr theScaleChoice; /** * The factorization scale factor. */ double theFactorizationScaleFactor; /** * The renormalization scale factor. */ double theRenormalizationScaleFactor; /** * Use non-running couplings. */ bool theFixedCouplings; /** * Use non-running couplings. */ bool theFixedQEDCouplings; /** * True, if veto scales should be set * for the real emission */ bool theVetoScales; /** * The amplitudes to be considered */ vector::ptr> theAmplitudes; /** * The Born matrix elements to be considered */ vector::ptr> theBornMEs; /** * The loop induced matrix elements to be considered */ vector::ptr> theLoopInducedMEs; /** * The virtual corrections to be considered */ vector::ptr> theVirtuals; /** * The real emission matrix elements to be considered */ vector::ptr> theRealEmissionMEs; /** * The produced NLO matrix elements */ vector::ptr> theBornVirtualMEs; /** * The produced subtracted matrix elements */ vector::ptr> theSubtractedMEs; /** * The produced finite real emission matrix elements */ vector::ptr> theFiniteRealMEs; /** * Which set of dipoles should be considered */ int theDipoleSet; /** * Switch on or off verbosity */ bool theVerbose; /** * Switch on or off diagram weight verbosity */ bool theDiagramWeightVerbose; /** * Number of bins for diagram weight verbosity */ int theDiagramWeightVerboseNBins; /** * True, if verbose while initializing */ bool theInitVerbose; /** * Prefix for subtraction data */ string theSubtractionData; /** * Set the type of plot that is to be generated for subtraction checking */ int theSubtractionPlotType; /** * Set whether subtraction data should be plotted for all phase space points individually */ bool theSubtractionScatterPlot; /** * Prefix for pole data. */ string thePoleData; /** * Command to limit the real emission process to be considered. */ string doSingleRealProcess(string); /** * The real emission process to be included; if empty, all possible * ones will be considered. */ vector > realEmissionProcesses; /** * Particle groups. */ map theParticleGroups; /** * Command to start a particle group. */ string startParticleGroup(string); /** * The name of the particle group currently edited. */ string particleGroupName; /** * The particle group currently edited. */ PDVector particleGroup; /** * Command to end a particle group. */ string endParticleGroup(string); /** * Parse a process description */ vector parseProcess(string); /** * Command to set the process. */ string doProcess(string); /** * Command to set the process. */ string doLoopInducedProcess(string); /** * The process to consider in terms of particle groups. */ vector > processes; /** * The loop induced process to consider in terms of particle groups. */ vector > loopInducedProcesses; /** * Generate subprocesses. */ set makeSubProcesses(const vector&) const; /** * Generate matrix element objects for the given process. */ vector::ptr> makeMEs(const vector&, unsigned int orderas, bool virt); /** * The shower approximation. */ Ptr::ptr theShowerApproximation; /** * The map of Born processes to splitting dipoles */ map::ptr> > theSplittingDipoles; /** * True, if subtraction scales should be caluclated from real emission kinematics */ bool theRealEmissionScales; /** * Consider all processes with order in couplings specifying the * maximum order. */ bool theAllProcesses; /** * The processes to be ordered from an OLP */ map::tptr,map,int> > theOLPProcesses; /** * Amplitudes which need external initialization */ set::tptr> theExternalAmplitudes; /** * Amplitudes to be selected on clashing responsibilities. */ vector::ptr> theSelectedAmplitudes; /** * Amplitudes to be deselected on clashing responsibilities. */ vector::ptr> theDeselectedAmplitudes; /** * Reweight objects for matrix elements */ vector theReweighters; /** * Preweight objects for matrix elements */ vector thePreweighters; /** * Produce matrix element corrections, but no NLO */ bool theMECorrectionsOnly; /** * The highest multiplicity of legs having virtual contributions.(needed for madgraph) */ int theHighestVirtualsize; /** * Produce matrix element corrections, with LoopSim NLO */ bool theLoopSimCorrections; /** * True, if the setup has already been run. */ bool ranSetup; /** * PDG ids of incoming particles */ set theIncoming; /** * True, if first incoming partons originate from perturbative PDF */ bool theFirstPerturbativePDF; /** * True, if second incoming partons originate from perturbative PDF */ bool theSecondPerturbativePDF; /** * True, if this Factory is in production mode. */ bool inProductionMode; /** * The real emission subprocess used when calculating the hardtree * in the truncated qtilde shower */ tSubProPtr theHardtreeSubprocess; /** * The born emitter used when calculating the hardtree in * the truncated shower */ int theHardtreeEmitter; /** * The born spectator used when calculating the hardtree in * the truncated shower */ int theHardtreeSpectator; /** * True, if spin correlation information should be provided, if possible. */ bool theSpinCorrelations; - + + /** + * The alpha parameter to be used for the dipole subtraction + */ double theAlphaParameter; /** + * Wether or not charge conservation should be enforced for the processes + * constructed. + */ + bool theEnforceChargeConservation; + + /** + * Wether or not colour conservation should be enforced for the processes + * constructed. + */ + bool theEnforceColourConservation; + + /** + * Wether or not lepton number conservation should be enforced for the processes + * constructed. + */ + bool theEnforceLeptonNumberConservation; + + /** + * Wether or not quark number conservation should be enforced for the processes + * constructed. + */ + bool theEnforceQuarkNumberConservation; + + /** + * Assume flavour diagonal lepton interactions + */ + bool theLeptonFlavourDiagonal; + + /** + * Assume flavour diagonal quark interactions + */ + bool theQuarkFlavourDiagonal; + + /** * Command for production mode */ string doProductionMode(string) { productionMode(); return ""; } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchboxFactory & operator=(const MatchboxFactory &); }; } #endif /* HERWIG_MatchboxFactory_H */ diff --git a/MatrixElement/Matchbox/Matching/DipoleMatching.cc b/MatrixElement/Matchbox/Matching/DipoleMatching.cc --- a/MatrixElement/Matchbox/Matching/DipoleMatching.cc +++ b/MatrixElement/Matchbox/Matching/DipoleMatching.cc @@ -1,139 +1,137 @@ // -*- C++ -*- // // DipoleMatching.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2012 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DipoleMatching class. // #include "DipoleMatching.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" using namespace Herwig; DipoleMatching::DipoleMatching() {} DipoleMatching::~DipoleMatching() {} IBPtr DipoleMatching::clone() const { return new_ptr(*this); } IBPtr DipoleMatching::fullclone() const { return new_ptr(*this); } CrossSection DipoleMatching::dSigHatDR() const { double xme2 = 0.; pair ij(dipole()->bornEmitter(), dipole()->bornSpectator()); double ccme2 = dipole()->underlyingBornME()->largeNColourCorrelatedME2(ij,theLargeNBasis); if(ccme2==0.)return 0.*nanobarn; double lnme2=dipole()->underlyingBornME()->largeNME2(theLargeNBasis); if(lnme2==0){ generator()->log() <<"\nDipoleMatching: "; generator()->log() <<"\n LargeNME2 is ZERO, while largeNColourCorrelatedME2 is not ZERO." ; generator()->log() <<"\n This is too seriuos.\n" ; generator()->log() << Exception::runerror; } ccme2 *= dipole()->underlyingBornME()->me2() /lnme2; xme2 = dipole()->me2Avg(ccme2); xme2 /= dipole()->underlyingBornME()->lastXComb().lastAlphaS(); double bornPDF = bornPDFWeight(dipole()->underlyingBornME()->lastScale()); if ( bornPDF == 0.0 ) return ZERO; xme2 *= bornPDF; if ( profileScales() ) xme2 *= profileScales()->hardScaleProfile(dipole()->showerHardScale(),dipole()->lastPt()); CrossSection res = sqr(hbarc) * realXComb()->jacobian() * subtractionScaleWeight() * xme2 / (2. * realXComb()->lastSHat()); return res; } double DipoleMatching::me2() const { throw Exception() << "DipoleMatching::me2(): Not intented to use. Disable the ShowerApproximationGenerator." << Exception::runerror; return 0.; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DipoleMatching::persistentOutput(PersistentOStream & os) const { os << theShowerHandler; } void DipoleMatching::persistentInput(PersistentIStream & is, int) { is >> theShowerHandler; } void DipoleMatching::doinit() { ShowerApproximation::doinit(); if ( theShowerHandler ) { - if ( theShowerHandler->scaleFactorOption() < 2 ) { - hardScaleFactor(theShowerHandler->hardScaleFactor()); - factorizationScaleFactor(theShowerHandler->factorizationScaleFactor()); - renormalizationScaleFactor(theShowerHandler->renormalizationScaleFactor()); - } + hardScaleFactor(theShowerHandler->hardScaleFactor()); + factorizationScaleFactor(theShowerHandler->factorizationScaleFactor()); + renormalizationScaleFactor(theShowerHandler->renormalizationScaleFactor()); profileScales(theShowerHandler->profileScales()); restrictPhasespace(theShowerHandler->restrictPhasespace()); hardScaleIsMuF(theShowerHandler->hardScaleIsMuF()); } } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigDipoleMatching("Herwig::DipoleMatching", "HwDipoleMatching.so HwShower.so"); void DipoleMatching::Init() { static ClassDocumentation documentation ("DipoleMatching implements NLO matching with the dipole shower."); static Reference interfaceShowerHandler ("ShowerHandler", "", &DipoleMatching::theShowerHandler, false, false, true, true, false); } diff --git a/MatrixElement/Matchbox/Matching/QTildeMatching.cc b/MatrixElement/Matchbox/Matching/QTildeMatching.cc --- a/MatrixElement/Matchbox/Matching/QTildeMatching.cc +++ b/MatrixElement/Matchbox/Matching/QTildeMatching.cc @@ -1,523 +1,521 @@ // -*- C++ -*- // // QTildeMatching.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2012 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the QTildeMatching class. // #include "QTildeMatching.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/TildeKinematics.h" using namespace Herwig; QTildeMatching::QTildeMatching() : theCorrectForXZMismatch(true) {} QTildeMatching::~QTildeMatching() {} IBPtr QTildeMatching::clone() const { return new_ptr(*this); } IBPtr QTildeMatching::fullclone() const { return new_ptr(*this); } void QTildeMatching::checkCutoff() { if ( showerTildeKinematics() ) { showerTildeKinematics()-> prepare(realCXComb(),bornCXComb()); showerTildeKinematics()->dipole(dipole()); showerTildeKinematics()->getShowerVariables(); } } void QTildeMatching::getShowerVariables() { // already filled from checkCutoff in this case if ( showerTildeKinematics() ) return; // get the shower variables calculateShowerVariables(); // check for the cutoff dipole()->isAboveCutoff(isAboveCutoff()); // get the hard scale dipole()->showerHardScale(hardScale()); // check for phase space dipole()->isInShowerPhasespace(isInShowerPhasespace()); } bool QTildeMatching::isInShowerPhasespace() const { assert((theQTildeSudakov->cutOffOption() == 0 || theQTildeSudakov->cutOffOption() == 2) && "implementation only provided for default and pt cutoff"); Energy qtildeHard = ZERO; Energy qtilde = dipole()->showerScale(); assert(!dipole()->showerParameters().empty()); double z = dipole()->showerParameters()[0]; // FF if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() > 1 ) { qtildeHard = theQTildeFinder-> calculateFinalFinalScales(bornCXComb()->meMomenta()[dipole()->bornEmitter()], bornCXComb()->meMomenta()[dipole()->bornSpectator()], bornCXComb()->mePartonData()[dipole()->bornEmitter()]->iColour() == PDT::Colour3).first; } // FI if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() < 2 ) { qtildeHard = theQTildeFinder-> calculateInitialFinalScales(bornCXComb()->meMomenta()[dipole()->bornSpectator()], bornCXComb()->meMomenta()[dipole()->bornEmitter()],false).second; } // IF if ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() > 1 ) { qtildeHard = theQTildeFinder-> calculateInitialFinalScales(bornCXComb()->meMomenta()[dipole()->bornEmitter()], bornCXComb()->meMomenta()[dipole()->bornSpectator()],false).first; if ( z < (dipole()->bornEmitter() == 0 ? bornCXComb()->lastX1() : bornCXComb()->lastX2()) ) return false; } // II if ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() < 2 ) { qtildeHard = theQTildeFinder-> calculateInitialInitialScales(bornCXComb()->meMomenta()[dipole()->bornEmitter()], bornCXComb()->meMomenta()[dipole()->bornSpectator()]).first; if ( z < (dipole()->bornEmitter() == 0 ? bornCXComb()->lastX1() : bornCXComb()->lastX2()) ) return false; } Energy Qg = theQTildeSudakov->kinScale(); Energy2 pt2 = ZERO; if ( dipole()->bornEmitter() > 1 ) { Energy mu = max(Qg,realCXComb()->meMomenta()[dipole()->realEmitter()].mass()); if ( bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == ParticleID::g ) pt2 = sqr(z*(1.-z)*qtilde) - sqr(mu); else pt2 = sqr(z*(1.-z)*qtilde) - sqr((1.-z)*mu) - z*sqr(Qg); } if ( dipole()->bornEmitter() < 2 ) { pt2 = sqr((1.-z)*qtilde) - z*sqr(Qg); } if ( pt2 < max(theQTildeSudakov->pT2min(),sqr(safeCut()) )) return false; bool hardVeto = restrictPhasespace() && sqrt(pt2) >= dipole()->showerHardScale(); return qtilde <= qtildeHard && !hardVeto; } bool QTildeMatching::isAboveCutoff() const { assert((theQTildeSudakov->cutOffOption() == 0 || theQTildeSudakov->cutOffOption() == 2) && "implementation only provided for default and pt cutoff"); Energy qtilde = dipole()->showerScale(); assert(!dipole()->showerParameters().empty()); double z = dipole()->showerParameters()[0]; Energy Qg = theQTildeSudakov->kinScale(); if ( dipole()->bornEmitter() > 1 ) { Energy mu = max(Qg,realCXComb()->meMomenta()[dipole()->realEmitter()].mass()); if ( bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == ParticleID::g ) return sqr(z*(1.-z)*qtilde) - sqr(mu) >= max(theQTildeSudakov->pT2min(),sqr(safeCut())); else return sqr(z*(1.-z)*qtilde) - sqr((1.-z)*mu) - z*sqr(Qg) >= max(theQTildeSudakov->pT2min(),sqr(safeCut())); } if ( dipole()->bornEmitter() < 2 ) { return sqr((1.-z)*qtilde) - z*sqr(Qg) >= max(theQTildeSudakov->pT2min(),sqr(safeCut())); } return false; } CrossSection QTildeMatching::dSigHatDR() const { assert(!dipole()->showerParameters().empty()); pair vars = make_pair(sqr(dipole()->showerScale()), dipole()->showerParameters()[0]); pair ij(dipole()->bornEmitter(), dipole()->bornSpectator()); double ccme2 = dipole()->underlyingBornME()->largeNColourCorrelatedME2(ij,theLargeNBasis); if(ccme2==0.)return 0.*nanobarn; double lnme2=dipole()->underlyingBornME()->largeNME2(theLargeNBasis); if(lnme2==0){ generator()->log() <<"\nQTildeMatching: "; generator()->log() <<"\n largeNME2 is ZERO, while largeNColourCorrelatedME2 is not ZERO." ; generator()->log() <<"\n This is too seriuos.\n" ; generator()->log() << Exception::runerror; } ccme2 *= dipole()->underlyingBornME()->me2() /lnme2; Energy2 prop = ZERO; if ( dipole()->bornEmitter() > 1 ) { prop = (realCXComb()->meMomenta()[dipole()->realEmitter()] + realCXComb()->meMomenta()[dipole()->realEmission()]).m2() - bornCXComb()->meMomenta()[dipole()->bornEmitter()].m2(); } else { prop = 2.*vars.second*(realCXComb()->meMomenta()[dipole()->realEmitter()]* realCXComb()->meMomenta()[dipole()->realEmission()]); } // note alphas included downstream from subtractionScaleWeight() double xme2 = -8.*Constants::pi*ccme2*splitFn(vars)*realXComb()->lastSHat()/prop; xme2 *= pow(realCXComb()->lastSHat() / bornCXComb()->lastSHat(), bornCXComb()->mePartonData().size()-4.); double bornPDF = bornPDFWeight(dipole()->underlyingBornME()->lastScale()); if ( bornPDF == 0.0 ) return ZERO; xme2 *= bornPDF; xme2 *= dipole()->realEmissionME()->finalStateSymmetry() / dipole()->underlyingBornME()->finalStateSymmetry(); // take care of mismatch between z and x as we are approaching the // hard phase space boundary // TODO get rid of this useless scale option business and simplify PDF handling in here if ( dipole()->bornEmitter() < 2 && theCorrectForXZMismatch ) { Energy2 emissionScale = ZERO; if ( emissionScaleInSubtraction() == showerScale ) { emissionScale = showerFactorizationScale(); } else if ( emissionScaleInSubtraction() == realScale ) { emissionScale = dipole()->realEmissionME()->lastScale(); } else if ( emissionScaleInSubtraction() == bornScale ) { emissionScale = dipole()->underlyingBornME()->lastScale(); } double xzMismatch = dipole()->subtractionParameters()[0] / dipole()->showerParameters()[0]; double realCorrectedPDF = dipole()->bornEmitter() == 0 ? dipole()->realEmissionME()->pdf1(emissionScale,theExtrapolationX, xzMismatch) : dipole()->realEmissionME()->pdf2(emissionScale,theExtrapolationX, xzMismatch); double realPDF = dipole()->bornEmitter() == 0 ? dipole()->realEmissionME()->pdf1(emissionScale,theExtrapolationX,1.0) : dipole()->realEmissionME()->pdf2(emissionScale,theExtrapolationX,1.0); if ( realPDF == 0.0 || realCorrectedPDF == 0.0 ) return ZERO; xme2 *= realCorrectedPDF / realPDF; } Energy qtilde = sqrt(vars.first); double z = vars.second; Energy2 pt2 = ZERO; Energy Qg = theQTildeSudakov->kinScale(); if ( dipole()->bornEmitter() > 1 ) { Energy mu = max(Qg,realCXComb()->meMomenta()[dipole()->realEmitter()].mass()); if ( bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == ParticleID::g ) pt2 = sqr(z*(1.-z)*qtilde) - sqr(mu); else pt2 = sqr(z*(1.-z)*qtilde) - sqr((1.-z)*mu) - z*sqr(Qg); } if ( dipole()->bornEmitter() < 2 ) { pt2 = sqr((1.-z)*qtilde) - z*sqr(Qg); } assert(pt2 >= ZERO); if ( profileScales() ) xme2 *= profileScales()->hardScaleProfile(dipole()->showerHardScale(),sqrt(pt2)); CrossSection res = sqr(hbarc) * realXComb()->jacobian() * subtractionScaleWeight() * xme2 / (2. * realXComb()->lastSHat()); return res; } double QTildeMatching::me2() const { throw Exception() << "QTildeMatching::me2(): Not intented to use. Disable the ShowerApproximationGenerator." << Exception::runerror; return 0.; } void QTildeMatching::calculateShowerVariables() const { Lorentz5Momentum n; Energy2 Q2 = ZERO; const Lorentz5Momentum& pb = bornCXComb()->meMomenta()[dipole()->bornEmitter()]; const Lorentz5Momentum& pc = bornCXComb()->meMomenta()[dipole()->bornSpectator()]; if ( dipole()->bornEmitter() > 1 ) { Q2 = (pb+pc).m2(); } else { Q2 = -(pb-pc).m2(); } if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() > 1 ) { double b = sqr(bornCXComb()->meMomenta()[dipole()->bornEmitter()].m())/Q2; double c = sqr(bornCXComb()->meMomenta()[dipole()->bornSpectator()].m())/Q2; double lambda = sqrt(1.+sqr(b)+sqr(c)-2.*b-2.*c-2.*b*c); n = (1.-0.5*(1.-b+c-lambda))*pc - 0.5*(1.-b+c-lambda)*pb; } if ( dipole()->bornEmitter() > 1 && dipole()->bornSpectator() < 2 ) { n = bornCXComb()->meMomenta()[dipole()->bornSpectator()]; } if ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() > 1 ) { double c = sqr(bornCXComb()->meMomenta()[dipole()->bornSpectator()].m())/Q2; n = (1.+c)*pc - c*pb; } if ( dipole()->bornEmitter() < 2 && dipole()->bornSpectator() < 2 ) { n = bornCXComb()->meMomenta()[dipole()->bornSpectator()]; } // the light-cone condition is numerically not very stable, so we // explicitly push it on the light-cone here n.setMass(ZERO); n.rescaleEnergy(); double z = 0.0; if ( dipole()->bornEmitter() > 1 ) { z = 1. - (n*realCXComb()->meMomenta()[dipole()->realEmission()])/ (n*bornCXComb()->meMomenta()[dipole()->bornEmitter()]); } else { z = 1. - (n*realCXComb()->meMomenta()[dipole()->realEmission()])/ (n*realCXComb()->meMomenta()[dipole()->realEmitter()]); } // allow small violations (numerical inaccuracies) if ( z <= 0 && z >= -1e-6 ) { z = std::numeric_limits::epsilon(); } else if ( z >= 1 && z <= 1+1e-6 ) { z = 1-std::numeric_limits::epsilon(); } Energy2 qtilde2 = ZERO; Energy2 q2 = ZERO; if ( dipole()->bornEmitter() > 1 ) { q2 = (realCXComb()->meMomenta()[dipole()->realEmitter()] + realCXComb()->meMomenta()[dipole()->realEmission()]).m2(); qtilde2 = (q2 - bornCXComb()->meMomenta()[dipole()->bornEmitter()].m2())/(z*(1.-z)); } else { q2 = -(realCXComb()->meMomenta()[dipole()->realEmitter()] - realCXComb()->meMomenta()[dipole()->realEmission()]).m2(); qtilde2 = (q2 + bornCXComb()->meMomenta()[dipole()->bornEmitter()].m2())/(1.-z); } if ( qtilde2 < ZERO ) { qtilde2 = ZERO; } assert(qtilde2 >= ZERO && z > 0.0 && z < 1.0); dipole()->showerScale(sqrt(qtilde2)); dipole()->showerParameters().resize(1); dipole()->showerParameters()[0] = z; } double QTildeMatching::splitFn(const pair& vars) const { const Energy2& qtilde2 = vars.first; const double& z = vars.second; double Nc = SM().Nc(); // final state branching if ( dipole()->bornEmitter() > 1 ) { // final state quark quark branching if ( abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 7 ) { Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(z)-2.*sqr(m)/(z*qtilde2))/(1.-z); } // final state gluon branching if ( bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == ParticleID::g ) { if ( realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { // ATTENTION the factor 2 here is intentional as it cancels to the 1/2 // stemming from the large-N colour correlator return 2.*Nc*(z/(1.-z)+(1.-z)/z+z*(1.-z)); } if ( abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { Energy m = realCXComb()->mePartonData()[dipole()->realEmission()]->hardProcessMass(); return (1./2.)*(1.-2.*z*(1.-z)+2.*sqr(m)/(z*(1.-z)*qtilde2)); } } // final state squark branching if ((abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) > 1000000 && abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 1000007) || (abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) > 2000000 && abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 2000007)){ Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return ((sqr(Nc)-1.)/Nc)*(z-sqr(m)/(z*qtilde2))/(1.-z); } // final state gluino branching if (bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == 1000021){ Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return Nc*(1.+sqr(z)-2.*sqr(m)/(z*qtilde2))/(1.-z); } } // initial state branching if ( dipole()->bornEmitter() < 2 ) { // g/g if ( realCXComb()->mePartonData()[dipole()->realEmitter()]->id() == ParticleID::g && realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { // see above for factor of 2 return 2.*Nc*(z/(1.-z)+(1.-z)/z+z*(1.-z)); } // q/q if ( abs(realCXComb()->mePartonData()[dipole()->realEmitter()]->id()) < 7 && realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(z))/(1.-z); } // g/q if ( realCXComb()->mePartonData()[dipole()->realEmitter()]->id() == ParticleID::g && abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { return (1./2.)*(1.-2.*z*(1.-z)); } // q/g if ( abs(realCXComb()->mePartonData()[dipole()->realEmitter()]->id()) < 7 && abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(1.-z))/z; } } return 0.0; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void QTildeMatching::doinit() { assert(theShowerHandler && theQTildeFinder && theQTildeSudakov); theShowerHandler->init(); theQTildeFinder->init(); theQTildeSudakov->init(); - if ( theShowerHandler->scaleFactorOption() < 2 ) { - hardScaleFactor(theShowerHandler->hardScaleFactor()); - factorizationScaleFactor(theShowerHandler->factorizationScaleFactor()); - renormalizationScaleFactor(theShowerHandler->renormalizationScaleFactor()); - } + hardScaleFactor(theShowerHandler->hardScaleFactor()); + factorizationScaleFactor(theShowerHandler->factorizationScaleFactor()); + renormalizationScaleFactor(theShowerHandler->renormalizationScaleFactor()); profileScales(theShowerHandler->profileScales()); restrictPhasespace(theShowerHandler->restrictPhasespace()); hardScaleIsMuF(theShowerHandler->hardScaleIsMuF()); ShowerApproximation::doinit(); } void QTildeMatching::doinitrun() { assert(theShowerHandler && theQTildeFinder && theQTildeSudakov); theShowerHandler->initrun(); theQTildeFinder->initrun(); theQTildeSudakov->initrun(); ShowerApproximation::doinitrun(); } void QTildeMatching::persistentOutput(PersistentOStream & os) const { os << theQTildeFinder << theQTildeSudakov << theShowerHandler << theCorrectForXZMismatch; } void QTildeMatching::persistentInput(PersistentIStream & is, int) { is >> theQTildeFinder >> theQTildeSudakov >> theShowerHandler >> theCorrectForXZMismatch; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigQTildeMatching("Herwig::QTildeMatching", "HwShower.so HwQTildeMatching.so"); void QTildeMatching::Init() { static ClassDocumentation documentation ("QTildeMatching implements NLO matching with the default shower."); static Reference interfaceQTildeFinder ("QTildeFinder", "Set the partner finder to calculate hard scales.", &QTildeMatching::theQTildeFinder, false, false, true, false, false); static Reference interfaceQTildeSudakov ("QTildeSudakov", "Set the partner finder to calculate hard scales.", &QTildeMatching::theQTildeSudakov, false, false, true, false, false); static Reference interfaceShowerHandler ("ShowerHandler", "", &QTildeMatching::theShowerHandler, false, false, true, true, false); static Switch interfaceCorrectForXZMismatch ("CorrectForXZMismatch", "Correct for x/z mismatch near hard phase space boundary.", &QTildeMatching::theCorrectForXZMismatch, true, false, false); static SwitchOption interfaceCorrectForXZMismatchYes (interfaceCorrectForXZMismatch, "Yes", "Include the correction factor.", true); static SwitchOption interfaceCorrectForXZMismatchNo (interfaceCorrectForXZMismatch, "No", "Do not include the correction factor.", false); } diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h b/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h --- a/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h +++ b/MatrixElement/Matchbox/Matching/ShowerApproximationKernel.h @@ -1,462 +1,478 @@ // -*- C++ -*- // // ShowerApproximationKernel.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2012 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Herwig_ShowerApproximationKernel_H #define Herwig_ShowerApproximationKernel_H // // This is the declaration of the ShowerApproximationKernel class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h" #include "Herwig/Sampling/exsample/exponential_generator.h" namespace Herwig { using namespace ThePEG; class ShowerApproximationGenerator; /** * \ingroup Matchbox * \author Simon Platzer * * \brief ShowerApproximationKernel generates emissions according to a * shower approximation entering a NLO matching. * */ class ShowerApproximationKernel: public HandlerBase { public: /** * Exception to communicate sampler maxtry events. */ struct MaxTryException {}; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ ShowerApproximationKernel(); /** * The destructor. */ virtual ~ShowerApproximationKernel(); //@} public: /** * Set the XComb object describing the Born process */ void setBornXComb(tStdXCombPtr xc) { theBornXComb = xc; } /** * Return the XComb object describing the Born process */ tcStdXCombPtr bornCXComb() const { return theBornXComb; } /** * Return the XComb object describing the Born process */ tStdXCombPtr bornXComb() const { return theBornXComb; } /** * Set the XComb object describing the real emission process */ void setRealXComb(tStdXCombPtr xc) { theRealXComb = xc; } /** * Return the XComb object describing the real emission process */ tcStdXCombPtr realCXComb() const { return theRealXComb; } /** * Return the XComb object describing the real emission process */ tStdXCombPtr realXComb() const { return theRealXComb; } /** * Set the tilde xcomb objects associated to the real xcomb */ void setTildeXCombs(const vector& xc) { theTildeXCombs = xc; } /** * Return the tilde xcomb objects associated to the real xcomb */ const vector& tildeXCombs() const { return theTildeXCombs; } /** * Set the dipole in charge for the emission */ void setDipole(Ptr::tptr dip) { theDipole = dip; } /** * Return the dipole in charge for the emission */ Ptr::tptr dipole() const { return theDipole; } /** * Set the shower approximation. */ void showerApproximation(Ptr::tptr app) { theShowerApproximation = app; } /** * Return the shower approximation. */ Ptr::tptr showerApproximation() const { return theShowerApproximation; } /** * Set the shower approximation generator. */ void showerApproximationGenerator(Ptr::tptr); /** * Return the shower approximation generator. */ Ptr::tptr showerApproximationGenerator() const; /** * Generate the next emission */ double generate(); public: /** * Set a pt cut on the dipole to generate the radiation */ void ptCut(Energy pt) { dipole()->ptCut(pt); } /** * Return the number of random numbers * needed to sample this kernel. */ int nDim() const { return nDimBorn() + dipole()->nDimRadiation(); } /** * Return the number of random numbers * needed to sample the Born process. */ int nDimBorn() const { return bornCXComb()->lastRandomNumbers().size(); } /** * Flag, which variables are free variables. */ const vector& sampleFlags(); /** * Return the support of the splitting kernel. * The lower bound on the first variable is * assumed to correspond to the cutoff on the * evolution variable. */ const pair,vector >& support(); /** * Return the parameter point associated to the splitting * previously supplied through fixParameters. */ const vector& parameterPoint(); /** * Indicate that presampling of this kernel * will be performed in the next calls to * evaluate until stopPresampling() is called. */ void startPresampling(); /** * Indicate that presampling of this kernel * is done until startPresampling() is called. */ void stopPresampling(); /** + * Indicate that a veto with the given kernel value and overestimate has occured. + */ + void veto(const vector&, double, double) { + /** use born and real xcombs in here to figure out what we need to reweight; + it should have its kinematic variables completed at this step */ + } + + /** + * Indicate that an accept with the given kernel value and overestimate has occured. + */ + void accept(const vector&, double, double) { + /** use born and real xcombs in here to figure out what we need to reweight; + it should have its kinematic variables completed at this step */ + } + + /** * Return true, if currently being presampled */ bool presampling() const { return thePresampling; } /** * Return the number of points to presample this * splitting generator. */ unsigned long presamplingPoints() const { return thePresamplingPoints; } /** * Return the maximum number of trials * to generate a splitting. */ unsigned long maxtry() const { return theMaxTry; } /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long freezeGrid() const { return theFreezeGrid; } /** * Set the number of points to presample this * splitting generator. */ void presamplingPoints(unsigned long p) { thePresamplingPoints = p; } /** * Set the maximum number of trials * to generate a splitting. */ void maxtry(unsigned long p) { theMaxTry = p; } /** * Set the number of accepted points after which the grid should * be frozen */ void freezeGrid(unsigned long n) { theFreezeGrid = n; } /** * Evalute the splitting kernel. */ double evaluate(const vector&); /** * Return the index of the random number corresponding * to the evolution variable. */ int evolutionVariable() const { return nDimBorn() + (showerApproximation()->showerInvertedTildeKinematics() ? showerApproximation()->showerInvertedTildeKinematics()->evolutionVariable() : dipole()->invertedTildeKinematics()->evolutionVariable()); } /** * Return the cutoff on the evolution * random number corresponding to the pt cut. */ double evolutionCutoff() const { return showerApproximation()->showerInvertedTildeKinematics() ? showerApproximation()->showerInvertedTildeKinematics()->evolutionCutoff() : dipole()->invertedTildeKinematics()->evolutionCutoff(); } /** * True, if sampler should apply compensation */ void doCompensate(bool yes = true) { theDoCompensate = yes; } public: /**@name Wrap to the exsample2 interface until this is finally cleaned up. */ //@{ inline const vector& variable_flags () { return sampleFlags(); } inline size_t evolution_variable () const { return evolutionVariable(); } inline double evolution_cutoff () const { return evolutionCutoff(); } inline const vector& parameter_point () { return parameterPoint(); } inline void start_presampling () { startPresampling(); } inline void stop_presampling () { stopPresampling(); } inline size_t dimension () const { return nDim(); } inline unsigned long presampling_points () const { return presamplingPoints(); } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The dipole in charge of the emission */ Ptr::ptr theDipole; /** * The shower approximation to consider */ Ptr::ptr theShowerApproximation; /** * The XComb off which radiation will be generated */ StdXCombPtr theBornXComb; /** * The XComb describing the process after radiation */ StdXCombPtr theRealXComb; /** * The tilde xcomb objects associated to the real xcomb */ vector theTildeXCombs; /** * True, if currently being presampled */ bool thePresampling; /** * The number of points to presample this * splitting generator. */ unsigned long thePresamplingPoints; /** * The maximum number of trials * to generate a splitting. */ unsigned long theMaxTry; /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long theFreezeGrid; /** * The sampling flags */ vector theFlags; /** * The support. */ pair,vector > theSupport; /** * The shower approximation generator. */ Ptr::tptr theShowerApproximationGenerator; /** * The last parameter point */ vector theLastParameterPoint; /** * The last random numbers used for Born sampling */ vector theLastBornPoint; /** * Define the Sudakov sampler */ typedef exsample::exponential_generator ExponentialGenerator; /** * Define a pointer to the Sudakov sampler */ typedef exsample::exponential_generator* ExponentialGeneratorPtr; /** * The Sudakov sampler */ ExponentialGeneratorPtr sampler; /** * True, if sampler should apply compensation */ bool theDoCompensate; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerApproximationKernel & operator=(const ShowerApproximationKernel &); }; } #endif /* Herwig_ShowerApproximationKernel_H */ diff --git a/MatrixElement/Matchbox/Phasespace/RandomHelpers.h b/MatrixElement/Matchbox/Phasespace/RandomHelpers.h --- a/MatrixElement/Matchbox/Phasespace/RandomHelpers.h +++ b/MatrixElement/Matchbox/Phasespace/RandomHelpers.h @@ -1,1358 +1,1362 @@ // -*- C++ -*- // // RandomHelpers.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2012 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_RandomHelpers_H #define HERWIG_RandomHelpers_H #include "ThePEG/Config/ThePEG.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * \brief Phasespace generation utilities. */ namespace RandomHelpers { /** * \ingroup Matchbox * \author Simon Platzer * \brief Small helper. */ inline double sign(double x) { return x < 0. ? -1. : 1.; } /** * \ingroup Matchbox * \author Simon Platzer * \brief Define the generator concept. */ template struct Generator { /** * Return the lower bound of the density generated. */ double lower() const; /** * Return the upper bound of the density generated. */ double upper() const; /** * Return the density's value */ double value(double x) const; /** * Return the density's normalization */ double normalization() const; /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const; }; /** * \ingroup Matchbox * \author Simon Platzer * \brief A density expression. */ struct Expression {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Container base class for a general density. */ template<> struct Generator { /** * The destructor. */ virtual ~Generator() {} /** * Return the lower bound of the density generated. */ virtual double lower() const = 0; /** * Return the upper bound of the density generated. */ virtual double upper() const = 0; /** * Return the density's value */ virtual double value(double x) const = 0; /** * Return the density's normalization */ virtual double normalization() const = 0; /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ virtual double operator()(double r) const = 0; }; /** * \ingroup Matchbox * \author Simon Platzer * \brief A density container. */ template struct Container {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Container class for a general density. */ template class Generator > : public Generator { /** * The generator. */ Generator generator; public: /** * Construct from generator. */ Generator(const Generator& gen) : generator(gen) {} /** * Return the lower bound of the density generated. */ virtual double lower() const { return generator.lower(); } /** * Return the upper bound of the density generated. */ virtual double upper() const { return generator.upper(); } /** * Return the density's value */ virtual double value(double x) const { return generator.value(x); } /** * Return the density's normalization */ virtual double normalization() const { return generator.normalization(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ virtual double operator()(double r) const { return generator(r); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate a random variable and return its weight. */ template pair generate(const Generator& gen, double r) { double x = gen(r); - return make_pair(x,gen.normalization()/gen.value(x)); + + if ( gen.value(x) != 0. ) + return make_pair(x,gen.normalization()/gen.value(x)); + else + return make_pair(x,0.); } /** * \ingroup Matchbox * \author Simon Platzer * \brief Remap a density to a new interval. */ template struct Remap {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate a density remapped to a new interval. */ template class Generator > { /** * The underlying generator. */ Generator theGenerator; /** * The new lower bound. */ double theLower; /** * The new upper bound. */ double theUpper; /** * Construct from generator and new boundaries. */ Generator(const Generator& gen, double low, double up) : theGenerator(gen), theLower(low), theUpper(up) { if ( low >= up ) throw std::logic_error("[Generator] Invalid boundaries."); } /** * Return the generator. */ const Generator& generator() const { return theGenerator; } /** * Return the lower bound of the density generated. */ double lower() const { return theLower; } /** * Return the upper bound of the density generated. */ double upper() const { return theUpper; } /** * Return the density's value */ double value(double y) const { double xm = generator().lower(); double xp = generator().upper(); double ym = lower(); double yp = upper(); double x = ((xp-xm)/(yp-ym))*y+(yp*xm-ym*xp)/(yp-ym); return generator().value(x); } /** * Return the density's normalization */ double normalization() const { double xm = generator().lower(); double xp = generator().upper(); double ym = lower(); double yp = upper(); return ((yp-ym)/(xp-xm))*generator().normalization(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { double xm = generator().lower(); double xp = generator().upper(); double ym = lower(); double yp = upper(); double x = ((yp-ym)/(xp-xm))*generator()(r)+(xp*ym-xm*yp)/(xp-xm); return x; } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Indicate remapping of a density. */ struct on { /** * The new lower boundary. */ double lower; /** * The new upper boundary. */ double upper; /** * Construct from boundaries. */ on(double a, double b) :lower(a), upper(b) {} }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct a remapped density generator. */ template Generator > operator*(const Generator& gen, const on& interval) { return Generator >(gen,interval.lower,interval.upper); } /** * \ingroup Matchbox * \author Simon Platzer * \brief Rescale a density. */ template struct Rescale {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate a rescaled density. */ template class Generator > { /** * The underlying generator. */ Generator theGenerator; /** * The rescaling factor. */ double theScale; public: /** * Construct from generator and scale. */ Generator(const Generator& gen, double sc) : theGenerator(gen), theScale(sc) { } /** * Return the generator. */ const Generator& generator() const { return theGenerator; } /** * Return the scale */ double scale() const { return theScale; } /** * Return the lower bound of the density generated. */ double lower() const { return generator().lower(); } /** * Return the upper bound of the density generated. */ double upper() const { return generator().upper(); } /** * Return the density's value */ double value(double x) const { return scale()*generator().value(x); } /** * Return the density's normalization */ double normalization() const { return scale()*generator().normalization(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { return generator()(r); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct a rescaled density. */ template Generator > operator*(double a, const Generator& gen) { return Generator >(gen,a); } /** * \ingroup Matchbox * \author Simon Platzer * \brief Add two densities. */ template struct Sum {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate the sum of two densities. */ template class Generator > { /** * The first generator. */ Generator theFirstGenerator; /** * The second generator. */ Generator theSecondGenerator; /** * The lower boundary. */ double theLower; /** * The upper boundary. */ double theUpper; /** * The fraction of the unit interval considered for the first * generator. */ double theFraction; public: /** * Construct from generators. */ Generator(const Generator& firstGen, const Generator& secondGen) : theFirstGenerator(firstGen), theSecondGenerator(secondGen), theLower(min(firstGen.lower(),secondGen.lower())), theUpper(max(firstGen.upper(),secondGen.upper())), theFraction(1.) { theFraction = firstGenerator().normalization() / normalization(); } /** * Return the first generator. */ const Generator& firstGenerator() const { return theFirstGenerator; } /** * Return the second generator. */ const Generator& secondGenerator() const { return theSecondGenerator; } /** * Return the lower bound of the density generated. */ double lower() const { return theLower; } /** * Return the upper bound of the density generated. */ double upper() const { return theUpper; } /** * Return the fraction of the unit interval considered for the first * generator. */ double fraction() const { return theFraction; } /** * Return the density's value */ double value(double x) const { double res = 0.; if ( firstGenerator().lower() <= x && x <= firstGenerator().upper() ) res += firstGenerator().value(x); if ( secondGenerator().lower() <= x && x <= secondGenerator().upper() ) res += secondGenerator().value(x); return res; } /** * Return the density's normalization */ double normalization() const { return firstGenerator().normalization() + secondGenerator().normalization(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { return r < fraction() ? firstGenerator()(r/fraction()) : secondGenerator()((r-fraction())/(1.-fraction())); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct the sum of two densities. */ template Generator > operator+(const Generator& first, const Generator& second) { return Generator >(first,second); } /** * \ingroup Matchbox * \author Simon Platzer * \brief Indicate that the argument density should be matched to the * previous one in a piecewise definition. */ template struct matcher { /** * The generator to be matched. */ Generator generator; /** * Construct from generator. */ matcher(const Generator& gen) : generator(gen) {} }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Indicate that the argument density should be matched to the * previous one in a piecewise definition. */ template matcher match(const Generator& gen) { return matcher(gen); } /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct the sum of two densities, matching the first * summand at its upper bound to the second at its lower bound. */ template Generator > > operator+(const Generator& first, const matcher& second) { double matching = first.value(first.upper())/ second.generator.value(second.generator.lower()); return Generator > >(first,matching*second.generator); } /** * \ingroup Matchbox * \author Simon Platzer * \brief A piecewise defined density. */ template struct Piecewise {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Placeholder when constructing piecewise defined densities. */ struct ToBeDefined {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate a piecewise defined density. */ template class Generator > { /** * The first generator. */ Generator theFirstGenerator; /** * The second generator. */ Generator theSecondGenerator; /** * The lower boundary. */ double theLower; /** * The transition value. */ double theIntermediate; /** * The upper boundary. */ double theUpper; /** * The fraction of the unit interval considered for the first * generator. */ double theFraction; public: /** * Construct from generators. */ Generator(const Generator& firstGen, const Generator& secondGen) : theFirstGenerator(firstGen), theSecondGenerator(secondGen), theLower(firstGen.lower()), theIntermediate(firstGen.upper()), theUpper(secondGen.upper()), theFraction(1.) { if ( firstGenerator().upper() != secondGenerator().lower() ) throw std::logic_error("[Generator] Invalid boundaries."); theFraction = firstGenerator().normalization() / normalization(); } /** * Return the first generator. */ const Generator& firstGenerator() const { return theFirstGenerator; } /** * Return the second generator. */ const Generator& secondGenerator() const { return theSecondGenerator; } /** * Return the lower bound of the density generated. */ double lower() const { return theLower; } /** * Return the transition value. */ double intermediate() const { return theIntermediate; } /** * Return the upper bound of the density generated. */ double upper() const { return theUpper; } /** * Return the fraction of the unit interval considered for the first * generator. */ double fraction() const { return theFraction; } /** * Return the density's value */ double value(double x) const { return x < intermediate() ? firstGenerator().value(x) : secondGenerator().value(x); } /** * Return the density's normalization */ double normalization() const { return firstGenerator().normalization() + secondGenerator().normalization(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { return r < fraction() ? firstGenerator()(r/fraction()) : secondGenerator()((r-fraction())/(1.-fraction())); } /** * Construct piecewise generators. */ template Generator,Density3> > operator,(const Generator& thirdGenerator) { return Generator,Density3> > (*this,thirdGenerator); } /** * Construct piecewise generators. */ template Generator,Rescale > > operator,(const matcher& thirdGenerator) { double matching = value(upper())/thirdGenerator.generator.value(upper()); return Generator,Rescale > > (*this,matching*thirdGenerator.generator); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate a piecewise defined density. */ template struct Generator > { /** * The first generator. */ Generator generator; /** * Construct from generator. */ Generator(const Generator& gen) : generator(gen) {} /** * Construct piecewise generators. */ template Generator > operator,(const Generator& secondGen) { return Generator > (generator,secondGen); } /** * Construct piecewise generators. */ template Generator > > operator,(const matcher& secondGen) { double matching = generator.value(generator.upper())/secondGen.generator.value(generator.upper()); return Generator > > (generator,matching*secondGen.generator); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate a piecewise defined density. */ template<> struct Generator > { /** * Construct piecewise generators. */ template Generator > operator,(const Generator& gen) { return Generator >(gen); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct a piecewise defined density. */ inline Generator > piecewise() { return Generator >(); } /** * \ingroup Matchbox * \author Simon Platzer * \brief A constant density. */ struct Flat {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate x flat. */ template<> class Generator { /** * The lower boundary. */ double theLower; /** * The upper boundary. */ double theUpper; public: /** * Construct from boundaries. */ Generator(double low, double up) : theLower(low), theUpper(up) {} /** * Return the lower bound of the density generated. */ double lower() const { return theLower; } /** * Return the upper bound of the density generated. */ double upper() const { return theUpper; } /** * Return the density's value */ double value(double x) const { return x>=lower() && x<=upper() ? 1. : 0.; } /** * Return the density's normalization */ double normalization() const { return upper()-lower(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { return lower() + r*(upper()-lower()); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct a constant density. */ inline Generator flat(double low, double up) { return Generator(low,up); } /** * \ingroup Matchbox * \author Simon Platzer * \brief A zero density. */ struct Zero {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate nothing. */ template<> class Generator { /** * The lower boundary. */ double theLower; /** * The upper boundary. */ double theUpper; public: /** * Construct from boundaries. */ Generator(double low, double up) : theLower(low), theUpper(up) {} /** * Return the lower bound of the density generated. */ double lower() const { return theLower; } /** * Return the upper bound of the density generated. */ double upper() const { return theUpper; } /** * Return the density's value */ double value(double x) const { return x>=lower() && x<=upper() ? Constants::epsilon : 0.; } /** * Return the density's normalization */ double normalization() const { return 0.; } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { return lower() + r*(upper()-lower()); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct a zero density. */ inline Generator zero(double low, double up) { return Generator(low,up); } /** * \ingroup Matchbox * \author Simon Platzer * \brief A density 1/|x-z| */ struct Inverse {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate x with density 1/|x-z| */ template<> class Generator { /** * The position of the pole */ double thePole; /** * The lower bound */ double theLower; /** * The upper bound */ double theUpper; /** * Scale for random numbers. */ double theScale; /** * Offset for random mnumbers. */ double theOffset; public: /** * Construct from pole and boundaries. */ Generator(double z, double l, double u) : thePole(z), theLower(l), theUpper(u), theScale(z < l ? log((u-z)/(l-z)) : log((z-l)/(z-u))), theOffset(z < l ? log(l-z) : log(z-u)) { if ( z >= l && z <= u ) throw std::logic_error("[Generator] Pole inside sampling interval."); } /** * Return the lower bound of the density generated. */ double lower() const { return theLower; } /** * Return the upper bound of the density generated. */ double upper() const { return theUpper; } /** * Return the position of the pole. */ double pole() const { return thePole; } /** * Return the scale for random numbers. */ double scale() const { return theScale; } /** * Return the offset for random mnumbers. */ double offset() const { return theOffset; } /** * Return the density's value */ double value(double x) const { return x>=lower() && x<=upper() ? 1/abs(x-pole()) : 0.; } /** * Return the density's normalization */ double normalization() const { return scale(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { return pole() + sign(upper()-pole())*exp(scale()*r+offset()); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct the density 1/|x-z| */ inline Generator inverse(double z, double lower, double upper) { return Generator(z,lower,upper); } /** * \ingroup Matchbox * \author Simon Platzer * \brief The density |(x-z)|^p */ struct Power {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate x with density |(x-z)|^p */ template<> class Generator { /** * The position of the pole */ double thePole; /** * The power */ double thePower; /** * The lower bound */ double theLower; /** * The upper bound */ double theUpper; /** * Scale for random numbers. */ double theScale; /** * Offset for random mnumbers. */ double theOffset; public: /** * Construct from pole, power and boundaries. */ Generator(double z, double p, double l, double u) : thePole(z), thePower(p), theLower(l), theUpper(u), theScale(z<=l ? (pow(u-z,1.+p)-pow(l-z,1.+p))/(1.+p) : (pow(z-l,1.+p)-pow(z-u,1.+p))/(1.+p)), theOffset(z<=l ? pow(l-z,1.+p)/(1.+p) : pow(z-u,1.+p)/(1.+p)) { if ( p == -1. ) throw std::logic_error("[Generator] Unit inverse. Consider using inverse()."); if ( z >= l && z <= u && p < 0. ) throw std::logic_error("[Generator] Pole inside sampling interval."); if ( z >= l && z <= u && p > 0. ) throw std::logic_error("[Generator] Zero inside sampling interval."); } /** * Return the lower bound of the density generated. */ double lower() const { return theLower; } /** * Return the upper bound of the density generated. */ double upper() const { return theUpper; } /** * Return the position of the pole. */ double pole() const { return thePole; } /** * Return the power. */ double power() const { return thePower; } /** * Return the scale for random numbers. */ double scale() const { return theScale; } /** * Return the offset for random mnumbers. */ double offset() const { return theOffset; } /** * Return the density's value */ double value(double x) const { return x>=lower() && x<=upper() ? pow(abs(x-pole()),power()) : 0.; } /** * Return the density's normalization */ double normalization() const { return scale(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { return pole() + sign(upper()-pole())*pow((1.+power())*(scale()*r+offset()),1./(1.+power())); } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct the density |(x-z)|^p */ inline Generator power(double z, double p, double lower, double upper) { return Generator(z,p,lower,upper); } /** * \ingroup Matchbox * \author Simon Platzer * \brief The density 1/((x-z)^2 + abs(w z)) */ struct BreitWigner {}; /** * \ingroup Matchbox * \author Simon Platzer * \brief Generate x with density 1/((x-z)^2 + abs(w z)) */ template<> class Generator { /** * The position of the pole */ double thePole; /** * The width */ double theWidth; /** * The lower bound */ double theLower; /** * The upper bound */ double theUpper; /** * Scale for random numbers. */ double theScale; /** * Offset for random mnumbers. */ double theOffset; /** * The square root of width times pole. */ double theSqrtWidth; public: /** * Construct from pole, width and boundaries. */ Generator(double z, double w, double l, double u) : thePole(z), theWidth(w), theLower(l), theUpper(u), theScale((atan((u-z)/sqrt(abs(w*z)))-atan((l-z)/sqrt(abs(w*z))))/sqrt(abs(w*z))), theOffset(atan((l-z)/sqrt(abs(w*z)))/sqrt(abs(w*z))), theSqrtWidth(sqrt(abs(w*z))) { if ( w == 0. ) throw std::logic_error("[Generator] Zero width. Consider using power()."); } /** * Return the lower bound of the density generated. */ double lower() const { return theLower; } /** * Return the upper bound of the density generated. */ double upper() const { return theUpper; } /** * Return the position of the pole. */ double pole() const { return thePole; } /** * Return the width. */ double width() const { return theWidth; } /** * Return the scale for random numbers. */ double scale() const { return theScale; } /** * Return the offset for random mnumbers. */ double offset() const { return theOffset; } /** * The square root of width times pole. */ double sqrtWidth() const { return theSqrtWidth; } /** * Return the density's value */ double value(double x) const { return x>=lower() && x<=upper() ? 1./(sqr(x-pole())+abs(width()*pole())) : 0.; } /** * Return the density's normalization */ double normalization() const { return scale(); } /** * Generate the return value according to the implemented density, * given a flat random number on the unit interval. */ double operator()(double r) const { double res = pole() + sqrtWidth()*tan(sqrtWidth()*(scale()*r+offset())); if ( res <= lower() ) return lower()*(1+std::numeric_limits::epsilon()); else if ( res >= upper() ) return upper()*(1-std::numeric_limits::epsilon()); else return res; } }; /** * \ingroup Matchbox * \author Simon Platzer * \brief Construct the density 1/((x-z)^2 + abs(w z)) */ inline Generator breitWigner(double z, double w, double lower, double upper) { return Generator(z,w,lower,upper); } } } #endif // HERWIG_RandomHelpers_H diff --git a/MatrixElement/Powheg/Makefile.am b/MatrixElement/Powheg/Makefile.am --- a/MatrixElement/Powheg/Makefile.am +++ b/MatrixElement/Powheg/Makefile.am @@ -1,17 +1,17 @@ pkglib_LTLIBRARIES = HwPowhegMEHadron.la HwPowhegMELepton.la -HwPowhegMEHadron_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 6:0:0 +HwPowhegMEHadron_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 7:0:1 HwPowhegMEHadron_la_SOURCES = \ MEqq2gZ2ffPowheg.cc MEqq2gZ2ffPowheg.h \ MEqq2W2ffPowheg.cc MEqq2W2ffPowheg.h \ MEPP2HiggsPowheg.cc MEPP2HiggsPowheg.h \ MEPP2WHPowheg.cc MEPP2WHPowheg.h \ MEPP2ZHPowheg.cc MEPP2ZHPowheg.h \ MEPP2VVPowheg.cc MEPP2VVPowheg.h \ VVKinematics.cc VVKinematics.h \ MEPP2GammaGammaPowheg.cc MEPP2GammaGammaPowheg.h \ MEPP2HiggsVBFPowheg.cc MEPP2HiggsVBFPowheg.h HwPowhegMELepton_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 1:0:0 HwPowhegMELepton_la_SOURCES = \ MEee2gZ2qqPowheg.cc MEee2gZ2qqPowheg.h \ MEee2gZ2llPowheg.cc MEee2gZ2llPowheg.h diff --git a/Models/General/HardProcessConstructor.cc b/Models/General/HardProcessConstructor.cc --- a/Models/General/HardProcessConstructor.cc +++ b/Models/General/HardProcessConstructor.cc @@ -1,647 +1,651 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the HardProcessConstructor class. // #include "HardProcessConstructor.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void HardProcessConstructor::persistentOutput(PersistentOStream & os) const { os << debug_ << subProcess_ << model_; } void HardProcessConstructor::persistentInput(PersistentIStream & is, int) { is >> debug_ >> subProcess_ >> model_; } AbstractClassDescription HardProcessConstructor::initHardProcessConstructor; // Definition of the static class description member. void HardProcessConstructor::Init() { static ClassDocumentation documentation ("Base class for implementation of the automatic generation of hard processes"); static Switch interfaceDebugME ("DebugME", "Print comparison with analytical ME", &HardProcessConstructor::debug_, false, false, false); static SwitchOption interfaceDebugMEYes (interfaceDebugME, "Yes", "Print the debug information", true); static SwitchOption interfaceDebugMENo (interfaceDebugME, "No", "Do not print the debug information", false); } void HardProcessConstructor::doinit() { Interfaced::doinit(); EGPtr eg = generator(); model_ = dynamic_ptr_cast(eg->standardModel()); if(!model_) throw InitException() << "HardProcessConstructor:: doinit() - " << "The model pointer is null!" << Exception::abortnow; if(!eg->eventHandler()) { throw InitException() << "HardProcessConstructor:: doinit() - " << "The eventHandler pointer was null therefore " << "could not get SubProcessHandler pointer " << Exception::abortnow; } string subProcessName = eg->preinitInterface(eg->eventHandler(), "SubProcessHandlers", "get",""); subProcess_ = eg->getObject(subProcessName); if(!subProcess_) { ostringstream s; s << "HardProcessConstructor:: doinit() - " << "There was an error getting the SubProcessHandler " << "from the current event handler. "; generator()->logWarning( Exception(s.str(), Exception::warning) ); } } GeneralHardME::ColourStructure HardProcessConstructor:: colourFlow(const tcPDVector & extpart) const { PDT::Colour ina = extpart[0]->iColour(); PDT::Colour inb = extpart[1]->iColour(); PDT::Colour outa = extpart[2]->iColour(); PDT::Colour outb = extpart[3]->iColour(); // incoming colour neutral if(ina == PDT::Colour0 && inb == PDT::Colour0) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour11to11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour11to33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour11to88; } else assert(false); } // incoming 3 3 else if(ina == PDT::Colour3 && inb == PDT::Colour3 ) { if( outa == PDT::Colour3 && outb == PDT::Colour3 ) { return GeneralHardME::Colour33to33; } else if( outa == PDT::Colour6 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33to61; } else if( outa == PDT::Colour0 && outb == PDT::Colour6 ) { return GeneralHardME::Colour33to16; } else assert(false); } // incoming 3bar 3bar else if(ina == PDT::Colour3bar && inb == PDT::Colour3bar ) { if( outa == PDT::Colour3bar && outb == PDT::Colour3bar ) { return GeneralHardME::Colour3bar3barto3bar3bar; } else if( outa == PDT::Colour6bar && outb == PDT::Colour0) { return GeneralHardME::Colour3bar3barto6bar1; } else if ( outa == PDT::Colour0 && outb == PDT::Colour6bar ) { return GeneralHardME::Colour3bar3barto16bar; } else assert(false); } // incoming 3 3bar else if(ina == PDT::Colour3 && inb == PDT::Colour3bar ) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33barto11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour33barto33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour33barto88; } else if( outa == PDT::Colour8 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33barto81; } else if( outa == PDT::Colour0 && outb == PDT::Colour8 ) { return GeneralHardME::Colour33barto18; } else if( outa == PDT::Colour6 && outb == PDT::Colour6bar) { return GeneralHardME::Colour33barto66bar; } else if( outa == PDT::Colour6bar && outb == PDT::Colour6) { return GeneralHardME::Colour33barto6bar6; } else assert(false); } // incoming 88 else if(ina == PDT::Colour8 && inb == PDT::Colour8 ) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour88to11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour88to33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour88to88; } else if( outa == PDT::Colour8 && outb == PDT::Colour0 ) { return GeneralHardME::Colour88to81; } else if( outa == PDT::Colour0 && outb == PDT::Colour8 ) { return GeneralHardME::Colour88to18; } else if( outa == PDT::Colour6 && outb == PDT::Colour6bar ) { return GeneralHardME::Colour88to66bar; } else assert(false); } // incoming 38 else if(ina == PDT::Colour3 && inb == PDT::Colour8 ) { if(outa == PDT::Colour3 && outb == PDT::Colour0) { return GeneralHardME::Colour38to31; } else if(outa == PDT::Colour0 && outb == PDT::Colour3) { return GeneralHardME::Colour38to13; } else if(outa == PDT::Colour3 && outb == PDT::Colour8) { return GeneralHardME::Colour38to38; } else if(outa == PDT::Colour8 && outb == PDT::Colour3) { return GeneralHardME::Colour38to83; } else if(outa == PDT::Colour3bar && outb == PDT::Colour6){ return GeneralHardME::Colour38to3bar6; } else if(outa == PDT::Colour6 && outb == PDT::Colour3bar){ return GeneralHardME::Colour38to63bar; } else assert(false); } // incoming 3bar8 else if(ina == PDT::Colour3bar && inb == PDT::Colour8 ) { if(outa == PDT::Colour3bar && outb == PDT::Colour0 ) { return GeneralHardME::Colour3bar8to3bar1; } else if(outa == PDT::Colour0 && outb == PDT::Colour3bar) { return GeneralHardME::Colour3bar8to13bar; } else if(outa == PDT::Colour3bar && outb == PDT::Colour8 ) { return GeneralHardME::Colour3bar8to3bar8; } else if(outa == PDT::Colour8 && outb == PDT::Colour3bar) { return GeneralHardME::Colour3bar8to83bar; } else assert(false); } // unknown colour flow else assert(false); return GeneralHardME::UNDEFINED; } void HardProcessConstructor::fixFSOrder(HPDiagram & diag) { tcPDPtr psa = getParticleData(diag.incoming.first); tcPDPtr psb = getParticleData(diag.incoming.second); tcPDPtr psc = getParticleData(diag.outgoing.first); tcPDPtr psd = getParticleData(diag.outgoing.second); //fix a spin order if( psc->iSpin() < psd->iSpin() ) { swap(diag.outgoing.first, diag.outgoing.second); if(diag.channelType == HPDiagram::tChannel) { diag.ordered.second = !diag.ordered.second; } return; } if( psc->iSpin() == psd->iSpin() && psc->id() < 0 && psd->id() > 0 ) { swap(diag.outgoing.first, diag.outgoing.second); if(diag.channelType == HPDiagram::tChannel) { diag.ordered.second = !diag.ordered.second; } return; } } void HardProcessConstructor::assignToCF(HPDiagram & diag) { if(diag.channelType == HPDiagram::tChannel) { if(diag.ordered.second) tChannelCF(diag); else uChannelCF(diag); } else if(diag.channelType == HPDiagram::sChannel) { sChannelCF(diag); } else if (diag.channelType == HPDiagram::fourPoint) { fourPointCF(diag); } else assert(false); } void HardProcessConstructor::tChannelCF(HPDiagram & diag) { PDT::Colour ina = getParticleData(diag.incoming.first )->iColour(); PDT::Colour inb = getParticleData(diag.incoming.second)->iColour(); PDT::Colour outa = getParticleData(diag.outgoing.first )->iColour(); PDT::Colour outb = getParticleData(diag.outgoing.second)->iColour(); vector cfv(1, make_pair(0, 1.)); if(diag.intermediate->iColour() == PDT::Colour0) { if(ina==PDT::Colour0) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(2, 1); } } else if(ina==PDT::Colour8) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(5, 1); } } } else if(diag.intermediate->iColour() == PDT::Colour8) { if(ina==PDT::Colour8&&outa==PDT::Colour8&& inb==PDT::Colour8&&outb==PDT::Colour8) { cfv.push_back(make_pair(1, -1.)); } } else if(diag.intermediate->iColour() == PDT::Colour3 || diag.intermediate->iColour() == PDT::Colour3bar) { if(outa == PDT::Colour0 || outb == PDT::Colour0) { if( outa != PDT::Colour6 && outb != PDT::Colour6 && outa != PDT::Colour6bar && outb != PDT::Colour6bar) { cfv[0] = make_pair(0,1.); } else { cfv[0] = make_pair(0,0.5); cfv.push_back(make_pair(1,0.5)); } } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour6bar) { cfv[0] = make_pair(4, 1.); for(unsigned int ix=5;ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6 || outa ==PDT::Colour6bar || outb==PDT::Colour6 || outb ==PDT::Colour6bar ) { assert(false); } } else if(diag.intermediate->iColour() == PDT::Colour6 || diag.intermediate->iColour() == PDT::Colour6bar) { if(ina==PDT::Colour8 && inb==PDT::Colour8) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); for(unsigned int ix=4;ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour3bar && outb==PDT::Colour6) { cfv[0] = make_pair(0,1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } } diag.colourFlow = cfv; } void HardProcessConstructor::uChannelCF(HPDiagram & diag) { PDT::Colour offshell = diag.intermediate->iColour(); PDT::Colour ina = getParticleData(diag.incoming.first )->iColour(); PDT::Colour inb = getParticleData(diag.incoming.second)->iColour(); PDT::Colour outa = getParticleData(diag.outgoing.first )->iColour(); PDT::Colour outb = getParticleData(diag.outgoing.second)->iColour(); vector cfv(1, make_pair(1, 1.)); if(offshell == PDT::Colour8) { - if( outa != outb ) { + if(outa == PDT::Colour0 && + outb == PDT::Colour0) { + cfv[0].first = 0; + } + else if( outa != outb ) { if(outa == PDT::Colour0 || outb == PDT::Colour0) { cfv[0].first = 0; } else { cfv[0].first = 0; cfv.push_back(make_pair(1, -1.)); } } else if(outa==PDT::Colour8&&ina==PDT::Colour8) { cfv[0]=make_pair(1, -1.); cfv.push_back(make_pair(2, 1.)); } } else if(offshell == PDT::Colour3 || offshell == PDT::Colour3bar) { if( outa == PDT::Colour0 || outb == PDT::Colour0 ) { if( outa != PDT::Colour6 && outb != PDT::Colour6 && outa != PDT::Colour6bar && outb != PDT::Colour6bar) { cfv[0] = make_pair(0,1.); } else { cfv[0] = make_pair(0,0.5); cfv.push_back(make_pair(1,0.5)); } } else if(outa==PDT::Colour3bar && outb==PDT::Colour6) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(0,1.); for(int ix=0; ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6bar && outb==PDT::Colour6) { cfv[0] = make_pair(4,1.); for(int ix=5; ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } } else if( offshell == PDT::Colour0 ) { if(ina==PDT::Colour0) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(3, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(2, 1); } } else if(ina==PDT::Colour8) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(4, 1); } } } else if(diag.intermediate->iColour() == PDT::Colour6 || diag.intermediate->iColour() == PDT::Colour6bar) { if(ina==PDT::Colour8 && inb==PDT::Colour8) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); for(unsigned int ix=8;ix<12;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour3bar && outa==PDT::Colour6) { cfv[0] = make_pair(4, 1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outa==PDT::Colour3bar) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } } diag.colourFlow = cfv; } void HardProcessConstructor::sChannelCF(HPDiagram & diag) { tcPDPtr pa = getParticleData(diag.incoming.first); tcPDPtr pb = getParticleData(diag.incoming.second); PDT::Colour ina = pa->iColour(); PDT::Colour inb = pb->iColour(); PDT::Colour offshell = diag.intermediate->iColour(); tcPDPtr pc = getParticleData(diag.outgoing.first); tcPDPtr pd = getParticleData(diag.outgoing.second); PDT::Colour outa = pc->iColour(); PDT::Colour outb = pd->iColour(); vector cfv(1); if(offshell == PDT::Colour8) { if(ina == PDT::Colour0 || inb == PDT::Colour0 || outa == PDT::Colour0 || outb == PDT::Colour0) { cfv[0] = make_pair(0, 1); } else { bool incol = ina == PDT::Colour8 && inb == PDT::Colour8; bool outcol = outa == PDT::Colour8 && outb == PDT::Colour8; bool intrip = ina == PDT::Colour3 && inb == PDT::Colour3bar; bool outtrip = outa == PDT::Colour3 && outb == PDT::Colour3bar; bool outsex = outa == PDT::Colour6 && outb == PDT::Colour6bar; bool outsexb = outa == PDT::Colour6bar && outb == PDT::Colour6; if(incol || outcol) { // Require an additional minus sign for a scalar/fermion // 33bar final state due to the way the vertex rules are defined. int prefact(1); if( ((pc->iSpin() == PDT::Spin1Half && pd->iSpin() == PDT::Spin1Half) || (pc->iSpin() == PDT::Spin0 && pd->iSpin() == PDT::Spin0 )) && (outa == PDT::Colour3 && outb == PDT::Colour3bar) ) prefact = -1; if(incol && outcol) { cfv[0].first = 0; cfv[0].second = -prefact; cfv.push_back(make_pair(2, prefact)); } else if(incol && outsex) { cfv[0].first = 4; cfv[0].second = prefact; for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(4+ix, prefact)); for(unsigned int ix=0;ix<4;++ix) cfv.push_back(make_pair(8+ix,-prefact)); } else { cfv[0].first = 0; cfv[0].second = -prefact; cfv.push_back(make_pair(1, prefact)); } } else if( ( intrip && !outtrip ) || ( !intrip && outtrip ) ) { if(!outsex) cfv[0] = make_pair(0, 1); else { cfv[0] = make_pair(0, 1.); for(unsigned int ix=0;ix<3;++ix) cfv.push_back(make_pair(ix+1, 1.)); } } else if((intrip && outsex) || (intrip && outsexb)) { cfv[0] = make_pair(0,1.); for(int ix=1; ix<4; ++ix) cfv.push_back(make_pair(ix,1.)); } else cfv[0] = make_pair(1, 1); } } else if(offshell == PDT::Colour0) { if( ina == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( outa == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(outa==PDT::Colour3 || outa==PDT::Colour3bar) { cfv[0] = make_pair(3, 1); } else if(outa==PDT::Colour8) { cfv[0] = make_pair(2, 1); } else assert(false); } else if(ina==PDT::Colour8) { if( outa == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(outa==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(outa==PDT::Colour8) { cfv[0] = make_pair(3, 1); } } } else if(offshell == PDT::Colour3 || offshell == PDT::Colour3bar) { if(outa == PDT::Colour6 || outa == PDT::Colour6bar || outb == PDT::Colour6bar || outb == PDT::Colour6) { cfv[0] = make_pair(6, 1.); cfv.push_back(make_pair(7,1.)); } else { if(outa == PDT::Colour0 || outb == PDT::Colour0) cfv[0] = make_pair(0, 1); else cfv[0] = make_pair(1, 1); } } else if( offshell == PDT::Colour6 || offshell == PDT::Colour6bar) { if((ina == PDT::Colour3 && inb == PDT::Colour3 && outa == PDT::Colour3 && outb == PDT::Colour3 ) || (ina == PDT::Colour3bar && inb == PDT::Colour3bar && outa == PDT::Colour3bar && outb == PDT::Colour3bar)) { cfv[0] = make_pair(2,0.5); cfv.push_back(make_pair(3,0.5)); } else if((ina == PDT::Colour3 && inb == PDT::Colour3 && ((outa == PDT::Colour6 && outb == PDT::Colour0)|| (outb == PDT::Colour6 && outa == PDT::Colour0))) || (ina == PDT::Colour3bar && inb == PDT::Colour3bar && ((outa == PDT::Colour6bar && outb == PDT::Colour0)|| (outb == PDT::Colour6bar && outa == PDT::Colour0)))) { cfv[0] = make_pair(0,0.5); cfv.push_back(make_pair(1,0.5)); } else assert(false); } else { if(outa == PDT::Colour0 || outb == PDT::Colour0) cfv[0] = make_pair(0, 1); else cfv[0] = make_pair(1, 1); } diag.colourFlow = cfv; } void HardProcessConstructor::fourPointCF(HPDiagram & diag) { // count the colours unsigned int noct(0),ntri(0),nsng(0),nsex(0); for(unsigned int ix=0;ix<4;++ix) { PDT::Colour col = getParticleData(diag.ids[ix])->iColour(); if(col==PDT::Colour0) ++nsng; else if(col==PDT::Colour3||col==PDT::Colour3bar) ++ntri; else if(col==PDT::Colour8) ++noct; else if(col==PDT::Colour6||col==PDT::Colour6bar) ++nsex; } if(nsng==4 || (ntri==2&&nsng==2) || (noct==3 && nsng==1) || (ntri==2 && noct==1 && nsng==1) ) { vector cfv(1,make_pair(0,1)); diag.colourFlow = cfv; } else if(noct==4) { // flows for SSVV, VVVV is handled in me class vector cfv(3); cfv[0] = make_pair(0, 1.); cfv[1] = make_pair(1,-2.); cfv[2] = make_pair(2, 1.); diag.colourFlow = cfv; } else if(ntri==2&&noct==2) { vector cfv(2); cfv[0] = make_pair(0, 1); cfv[1] = make_pair(1, 1); diag.colourFlow = cfv; } else if(nsex==2&&noct==2) { vector cfv; for(unsigned int ix=0;ix<4;++ix) cfv.push_back(make_pair(ix ,2.)); for(unsigned int ix=0;ix<8;++ix) cfv.push_back(make_pair(4+ix,1.)); diag.colourFlow = cfv; } else assert(false); } namespace { // Helper functor for find_if in duplicate function. class SameDiagramAs { public: SameDiagramAs(const HPDiagram & diag) : a(diag) {} bool operator()(const HPDiagram & b) const { return a == b; } private: HPDiagram a; }; } bool HardProcessConstructor::duplicate(const HPDiagram & diag, const HPDVector & group) const { //find if a duplicate diagram exists HPDVector::const_iterator it = find_if(group.begin(), group.end(), SameDiagramAs(diag)); return it != group.end(); } diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -1,1501 +1,1526 @@ Herwig News -*- outline -*- ================================================================================ +* Herwig 7.0.2 release: 2016-04-29 + +** Event reweighting + New option of calculating the weights for the effect of varying the scale used in both the default and dipole showers. This will be described in a forthcoming publication. + +** mergegrids mode + A main mode for the Herwig executable has been added which merges the integration grids from parallel runs. + +** NLO Diphoton production + The NLO matrix elements in the POWHEG approach for diphoton production as described in JHEP 1202 (2012) 130, arXiv:1106.3939 have been included as MEPP2GammaGammaPowheg. + +** BSM Hard process constructor + A missing Feynman diagram with a t-channel vector boson has been added to the matrix element for vv2ss + +** BSM Decay Modes calculation + The behaviour of the option to disable decay modes in BSM Models has been changed so that the partial width for the ignored modes is now calculated and included in the total width, but the branching ratio is set to zero. This is more physical than the previous option where the mode was totally ignored and hence not included in the calculation of the width. + +** Mass Generation + The behaviour of the GenericMassGenerator has been changed so that modes which have been disabled are only included in the calculation of the total width and not in the partial width used in the numerator of the weight used to select the off-shell mass. + +** Boost detection + Boost could not detect the compiler version for gcc-5.3 and gcc-6.1 + + + * Herwig 7.0.1 release: 2016-01-17 ** Version number written to log file The Herwig version number is now included in addition to ThePEG's version. ** Tau lifetimes A bug with lifetimes for hard process Taus is fixed. Thanks to ATLAS for the report! ** Shower FSR retries Rare events could take a long time due to an extremely large number of FSR retries. These are now capped at a configurable number. ** Dipole shower Reweighting for non-radiating events; fixes for shower profile handling; option to downgrade large-Q expansion for alphaS ** Matchbox builtins Added massive currents for q-qbar ** ShowerAlphaQCD can now use user-defined thresholds ** Input snippets W/Z/H on-shell now split into three files; 4-flavour scheme added ** UFO converter The converter now has experimental support for writing out param cards of its current settings. ** LEPJetAnalysis loading fixed ** Contrib HJets++ has moved to a stand-alone project, FxFx has been added * Herwig 7.0.0 (Herwig++ 3.0.0) release: 2015-12-04 ** Major new release A major new release of the Monte Carlo event generator Herwig++ (version 3.0) is now available. This release marks the end of distinguishing Herwig++ and HERWIG development and therefore constitutes the first major release of version 7 of the Herwig event generator family. The new version features a number of significant improvements to the event simulation, including: built-in NLO hard process calculation for all Standard Model processes, with matching to both angular ordered and dipole shower modules via variants of both subtractive (MC@NLO-type) and multiplicative (Powheg-type) algorithms; QED radiation and spin correlations in the angular ordered shower; a consistent treatment of perturbative uncertainties within the hard process and parton showering, as well as a vastly improved documentation. This version includes (for a more detailed overview and further references please see the release note arXiv:1512.01178): ** A long list of improvements and fixes for the Matchbox module *** includes MC@NLO and Powheg matching to both showers with truncated showering ** A long list of improvements and fixes for both of the shower modules *** includes improvements of numerics issues relevant to 100 TeV pp collisions ** NLO event simulation and Matchbox development *** Interfaces to a number of external libraries *** A new workflow for event generation *** Electroweak corrections to VV production ** Parton shower development *** QED radiation in the angular ordered shower *** Spin correlations in the angular ordered shower *** New scale choices in gluon branchings ** Improvements to event generation workflow *** Re-organized and streamlined input files for the new NLO development *** A unified treatment of shower and matching uncertainties *** New integrator modules featuring parallel integration ** New default tunes for both shower modules ** New contrib modules *** Electroweak Higgs plus jets production *** FxFx merging support *** Higgs boson pair production * Herwig++-2.7.1 release: 2014-07-07 ** New shower switches to select schemes for momentum reconstruction *** QTildeReconstructor:FinalStateReconOption has the following options: *** Default All momenta are rescaled in the rest frame. *** MostOffShell Put all particles on the new-mass shell and the most off-shell and recoiling system are rescaled to ensure 4-momentum is conserved. *** Recursive Recursively put the most off-shell particle which hasn't yet been rescaled on-shell by rescaling the particles and the recoiling system. *** RestMostOffShell The most off-shell is put on shell by rescaling it and the recoiling system, the recoiling system is then put on-shell in its rest frame. *** RestRecursive As above, but recursively treat the currently most-off shell (only makes a difference for more than 3 partons) ** Ticket #378: Hadronization of baryon number violating clusters involving diquarks Fixed by only considering non-diquarks to be combined in the ClusterFinder. ** UFO converter can now parse SLHA files for parameter settings The UFO converter code can now use SLHA files for modifying parameters. The first pass "ufo2herwig" produces the model to be compiled. For each parameter card, run "slha2herwig" to get the matching input file. ** Fix for systems using lib64 The repository is now initialized correctly on systems using lib64 as the library location. ** Efficiency optimization Better allocation of internal vector variables for a noticeable speed increase of 10-20% with LHC events. * Herwig++-2.7.0 release: 2013-10-28 ** UFO interface to Feynman rules generators Herwig++ now includes "ufo2herwig", a tool that automatically creates all required files to run a BSM model from a UFO directory. The conversion has been extensively tested against Feynrules models MSSM, NMSSM, RS, Technicolor, and less extensively with most of the other models in the Feynrules model database. We expect that following this release there will be no further hard-coded new physics models added to Herwig++ and that future models will be included using the UFO interface. ** Shower uncertainties A first set of scaling parameters to estimate shower uncertainties is provided for both the angular ordered as well as the dipole shower; they are Evolver:HardScaleFactor and ShowerAlphaQCD: RenormalizationScaleFactor. ** Rewrite of Matchbox NLO matching The NLO matching implementation has been rewritten and is now more flexible and consistent. Profile scales are provided for the hardest emission both for the dipole shower and matrix element correction matching. ** BLHA2 Interface and new processes Matchbox now features a generic BLHA2 interface to one-loop amplitude codes and now also includes W and W+jet production as well as Higss production in gluon fusion as builtin processes. ** Impoved dipole shower kinematics parametrization The kinematics parametrization for emissions in the dipole shower has been made more efficient. ** W and Z Powheg decays Decays of W and Z bosons now use the Powheg decayers by default. ** Improved treatment of beam remnants The handling of beam remnants has been improved in multiple contexts, leading to a much lower error rate at p+/p- collisions. An additional value "VeryHard" for ClusterFissioner:RemnantOption can be used to disable any special treatment of beam remnant clusters. ** New underlying event tune Herwig++ now uses tune UE-EE-5-MRST by default. Other related tunes can be obtained from the Herwig++ tunes page ** Improvements in BSM code The UFO development identified many sign fixes in rarely used BSM vertices; many improvements were made to general decayers, allowing four-body decays in BSM for the first time; Powheg is enabled in General two-body decayers; and the handling of colour sextets has been improved. ** A new HiggsPair matrix element in Contrib. ** A new matrix element for single top production. ** The Higgs mass is now set to 125.9 GeV (from PDG 2013 update). ** C++-11 testing To help with the coming transition to C++-11, we provide the new --enable-stdcxx11 configure flag. Please try to test builds with this flag enabled and let us know any problems, but do not use this in production code yet. In future releases, this flag will be on by default. ** Other changes *** Many new Rivet analyses have been included in the Tests directory. *** Cleaned Shower header structure; grouped shower parameters into one struct. *** The boolean Powheg flag in HwMEBase changed to an enumeration. * Herwig++-2.6.3 release: 2013-02-22 ** Decay vertex positioning in HepMC output Pseudo-vertices that Herwig++ inserts for technical reasons will now not contribute to the Lorentz positions of downstream vertices. Thanks to ATLAS for the bug report! ** Updated Rivet tests Herwig's library of Rivet test runs has been brought up-to-date with new analyses that were recently published by the Rivet collaboration. * Herwig++-2.6.2 release: 2013-01-30 ** Fixes for PDF and scale choices in POWHEG events Scale settings for MPI and the regular shower are now correct in POWHEG events. This should fix reported anomalies in POWHEG jet rates. NLO PDFs are now also set consistently in the example input files. ** Ticket #373: Branching ratio factors in cross-section If any decay modes are selectively disabled, setting the following post-handler will cause all reported cross-sections to include the branching ratio factor(s) from the previous stages correctly: create Herwig::BranchingRatioReweighter BRreweight insert LHCGenerator:EventHandler:PostDecayHandlers 0 BRreweight ** Anomalous vertices now possible in MEfftoVH ** Interactive shell does not quit on error ** Better warning messages for events from inconsistent LHEF files ** Possible division by zero error fixed in BSM branching ratio calculations ** Decayer and ME changes to improve checkpointing The checkpointing changes in ThePEG 1.8.2 are implemented here, too. Regular dump files are consistent now. * Herwig++-2.6.1 release: 2012-10-16 ** Configure switches The various switches to turn off compilation of BSM models have been unified into a single '--disable-models'. A new flag '--disable-dipole' can be used to turn off the compilation of the Dipole and Matchbox codes. ** Ticket #348: Search path for repository 'read' command The search path for the 'read' command is configurable on the command line with the -i and -I switches. By default, the installation location is now included in the search path, so that 'Herwig++ read LEP.in' will work in an empty directory. The current working directory will always be searched first. The rarely used "Herwig++ init" command has been made consistent with 'read' and 'run' and should now be used without the '-i' flag. ** Width treatment in BSM The width treatment in BSM decay chains has been greatly improved and is now switched on by default in the .model files. To get the old behaviour, use set /Herwig/NewPhysics/NewModel:WhichOffshell Selected ** New BSM models Little Higgs models with and without T-parity are now available. ** Resonance photon lifetime A lifetime bug affecting decays of pi0 to e+e-X was fixed. The virtual photon is not part of the event record anymore. ** Ticket #371: Hard diffraction FPE Herwig++ 2.6.0 introduced a bug into the diffraction code which would abort any runs. This is now fixed. ** O2AlphaS Support for setting quark masses different from the particle data objects as introduced in ThePEG 1.8.1 has been enabled. ** Matchbox Several improvements and bug fixes are included for Matchbox. Amplitudes relevant to pp -> Z+jet and crossed processes at NLO are now available, and various scale choices have been added in a more flexible way. All subtraction dipoles for massive quarks are now included. ** Dipole shower Parameters to perform scale variations in the shower have been added to estimate uncertainties. A bug in showering off gg -> h has been fixed. ** Minor fixes *** Two broken colour structures in GeneralHardME *** Susy Higgs mixing matrix *** BaryonFactorizedDecayer out-of-bounds access *** Mass values in SimpleLHCAnalysis * Herwig++-2.6.0 release: 2012-05-21 (tagged at SVN r7407) ** New NLO framework Matchbox, a flexible and very general framework for performing NLO calculations at fixed order or matched to parton showers is provided with this release. ** Dipole shower algorithm A first implementation of the coherent dipole shower algorithm by Plätzer and Gieseke (arXiv:0909.5593 and arXiv:1109.6256) is available. ** Alternative samplers and the ExSample library The ExSample library by Plätzer (arXiv:1108.6182) is shipped along with Herwig++ in an extended version. The extended version provides SamplerBase objects which can be used alternatively to the default ACDCSampler. ** New BSM models *** New colour sextet diquark model A colour sextet diquark model has been included, as described in Richardson and Winn (arXiv:1108.6154). *** Models reproducing the CDF t-tbar asymmetry Four models that can reproduce the reported t-tbar asymmetry have been included. *** Zprime A simple standard model extension by one additional heavy neutral vector boson. ** Interface to AlpGen, with MLM merging The Contrib directory contains a new interface to the AlpGen matrix element generator. AlpGen events must be preprocessed with the provided AlpGenToLH.exe tool before they can be used. More information can be found in the Herwig++ 2.6 release note. ** HiggsVBF Powheg Higgs boson production by vector boson fusion is available at NLO in the POWHEG scheme, as described in d'Errico, Richardson (arXiv:1106.2983). The Powheg DIS processes were available in Herwig++-2.5.2 already. ** Statistical colour reconnection Alternative mechanisms to minimize the colour length Sum(m_clu) before the hadronization stage, based on Metropolis and annealing algorithms. ** Energy extrapolation of underlying-event tunes To describe underlying-event data at different c.m. energies, the energy-dependent parameter pT_min will now be adjusted automatically, following a power-law. The new tune parameters are the value at 7000 GeV "MPIHandler:pTmin0", and MPIHandler:Power. ** Ticket #239: Reporting of minimum-bias cross-section When simulating minimum-bias events using the MEMinBias matrix element, the correct unitarized cross section can now be reported via the standard facilities; it is no longer necessary to extract it from the .log file of the run. The corresponding functionality is enabled by inserting a MPIXSecReweighter object as a post-subprocess handler: create Herwig::MPIXSecReweighter MPIXSecReweighter insert LHCHandler:PostSubProcessHandlers 0 MPIXSecReweighter ** Dependency on 'boost' Herwig++ now requires the boost headers to build; if not detected in standard locations, specify with the --with-boost configure option. ** Tests directory The Tests directory now contains input cards for almost all Rivet analyses. A full comparison run can be initiated with 'make tests'. ** Minor changes *** Default LHC energy now 8 TeV All LHC-based defaults have now been updated to use 8 TeV as the center-of-mass energy. *** Herwig::ExtraParticleID -> ThePEG::ParticleID The namespace for additional particles has been unified into ThePEG::ParticleID *** MEee2VectorMeson The e+e- -> vector meson matrix element has moved from Contrib into HwMELepton.so *** SUSY numerics fixes Better handling of rare numerical instabilities. *** YODA output for Rivet The built-in histogramming handler can now output data in the YODA format used by Rivet. *** Consistency checks in SLHA file reader Better warnings for inconsistent SusyLHA files *** better colour flow checking for development ** Bug fixes *** Extremely offshell W from top decay Numerical improvements for very off-shell W bosons coming from top decays. *** Ticket #367: problems in using SUSY + LHE Susy events from Les Houches event files are now handled better. *** Infinite loop in remnant decayer The remnant decayer will now abort after 100 tries. *** Fix to HiggsVBF LO diagrams The diagram structure of HiggsVBF LO matrix elements has been fixed. *** LEP thrust fix The calculation of the transverse momentum of a branching from the evolution variable in final-state radiation can now be changed. While formally a sub-leading choice this enables a better description of the thrust distribution in e+e- collisions at small values of the thrust. Currently the default behaviour, where the cut-off masses are used in the calculation, remains the same as previous versions. * Herwig++-2.5.2 release: 2011-11-01 (tagged at SVN r6928) ** Optional new jet vetoing model The jet vetoing model by Schofield and Seymour (arXiv:1103.4811) is available via Evolver:ColourEvolutionMethod, PartnerFinder:PartnerMethod and SplittingFunction:SplittingColourMethod. The default behaviour is unchanged. ** MPI tune Version 3 of the MPI tunes is now the default. Please note that the pT parameter is energy-dependent and needs to be modified when an LHC run is not at 7 TeV. The latest tunes are always available at http://projects.hepforge.org/herwig/trac/wiki/MB_UE_tunes ** MPI PDFs MPI PDFs can now be controlled independently. ** Initialization time speedup A new BSMModel base class was introduced between StandardModel and the BSM model classes. Together with a restructured decay mode initialization, this offers significantly faster startup times for BSM runs. ThreeBodyDecays can now always be switched on without a large speed penalty. ** Decay mode file Decay mode files in the SLHA format can now be read separately in any BSM model with 'set Model:DecayFileName filename' ** Powheg DIS Charged- and neutral-current DIS processes implementing the POWHEG method are now available. ** Diffraction models Xi cut implemented in PomeronFlux ** Ticket #352: Colour reconnection fixed in DIS ** Ticket #353: Improved numerical stability in chargino decays ** Ticket #358: Infinite loop in top events with pT cut in shower ** Ticket #361: Problem with duplicate 2-body modes in BSM ** Tickets #362 / #363: Crashes with baryon number violating models Particle decays in SUSY models with RPV now work correctly in the colour 8 -> 3,3,3 case. Colour reshuffling now works for RPV clusters. ** Improved Fastjet detection The configure step uses fastjet-config to make sure all header file paths are seen. ** Darwin 11 / OS X Lion A configure bug was fixed which prevented 'make check' from succeeding on OS X Lion. ** Vertex classes The specification of QED / QCD orders has been moved to the vertex constructors, to allow ThePEG consistency checks. WWHH vertices in MSSM and NMSSM were fixed. Some Leptoquark and UED vertices fixed. ** Hadronization Cleanup of obsolete code. * Herwig++-2.5.1 release: 2011-06-24 (tagged at SVN r6609) ** Example input files at 7 TeV All our example input files for LHC now have their beam energy set to 7 TeV instead of 14 TeV. ** Colour reconnection on by default The colour reconnection tunes are now the default setup. Version 2 of the tunes replaces the *-1 tunes, which had a problem with LEP event shapes. ** Run name tags Aded possibility to add a tag to the run name when running with the '-t' option. One run file can thus be run with different seeds and results stored in different output files. ** Floating point exceptions The new command line option -D enables floating point error checking. ** General improvements to WeakCurrent decays ** Remnant decayer Hardwired gluon mass was removed. ** WeakCurrentDecayConstructor Instead of specifying separate Particle1...Particle5 vectors for the decay modes, the new interface DecayModes can be filled with decay tags in the standard syntax. ** BSM: improvements to handling of vertex and model initialisation ** Powheg Higgs Option to use pT or mT as the scale in alphaS and for the factorization scale in the PDFs ** Ticket #337: Tau polarization wrong in charged Higgs decay ** Ticket #339: Colour flows in GeneralThreeBody Decayers for 3bar -> 8 3bar 1 ** Ticket #340: Crash for resonant zero-width particles ** Ticket #341: Varying scale for BSM processes The scale used is now ResonantProcessConstructor:ScaleFactor or TwoToTwoProcessConstructor:ScaleFactor multiplied by sHat. ** Ticket #346: Chargino decays Chargino decayers now automatically switch between the mesonic decays for mass differences less than 2 GeV and the normal partonic decays above 2 GeV. ** Ticket #349: Stop by default on input file errors The '--exitonerror' flag is now the default behaviour for the Herwig++ binary. To switch back to the old behaviour, '--noexitonerror' is required. ** Ticket #351: Four-body stop decays ** Tested with gcc-4.6 * Herwig++-2.5.0 release: 2011-02-08 (tagged at SVN r6274) ** Uses ThePEG-1.7.0 Herwig++ 2.5.0 requires ThePEG 1.7.0 to benefit from various improvements, particularly: handling of diffractive processes; respecting LD_LIBRARY_PATH when loading dynamic libraries, including LHAPDF; improvements to repository commands for decay modes. See ThePEG's NEWS file for more details. ** POWHEG improvements *** New POWHEG processes Simulation at NLO accuracy using the POWHEG method is now available for hadronic diboson production (pp to WW,WZ,ZZ), Higgs decays to heavy quarks, and e+e- to two jets or ttbar, including full mass dependence. *** Input file changes The input files for setting up POWHEG process simulation have been simplified. See the example files LHC-Powheg.in and TVT-Powheg.in for the improved command list. *** Structural changes The POWHEG backend in the shower code has been restructured to make future additions easier: PowhegEvolver has merged with Evolver; both the matrix element corrections and real corrections in the POWHEG scheme are implemented directly in the ME or Decayer classes. ** New processes at leading order *** Photon initiated processes We have added a matrix element for dijet production in gamma hadron collisions. *** Bottom and charm in heavy quark ME The option of bottom and charm quarks is now supported for heavy quark production in MEHeavyQuark. ** Colour reconnection The cluster hadronization model has been extended by an option to reconnect coloured constituents between clusters with a given probability. This new model is different from the colour reconnection model used in FORTRAN HERWIG, and improves the description of minimum bias and underlying event data. ** Diffractive Processes Both single and double diffractive processes are now supported in Herwig++. The Pomeron PDF is implemented using a fit to HERA data, and a pion PDF can be used to model reggeon flux. ** BSM physics *** New models We have added new BSM models, particularly ADD-type extra dimension models and the next-to-minimal supersymmetric standard model (NMSSM). Effects of leptoquarks can as well be simulated. *** Vertex additions We have added flavour changing stop interactions (stop - neutralino - charm) and gravitino interactions with particular emphasis on numerical stability for very light gravitinos. Tri-linear Higgs and Higgs-Higgs/Vector-Vector four-vertices are available as well. *** Input file changes The SUSY model can now also extract the SLHA information from the header of a Les Houches event file: replace the SLHA file name in the example input files with the LH file name. *** Structure The backend structure of the HardProcessConstructor has changed, to allow easier inclusion of new process constructors. Some 2->3 BSM scattering processes involving neutral higgs bosons are now included. The spin handling has been improved in the background. ** Shower splitting code reorganized The selection of spin structures has been decoupled from the choice of colour structure. This gives more flexibility in implementing new splittings. Selected splittings can be disabled in the input files. ** B mixing B mixing, and indirect CP violation in the B meson system are included now. ** Looptools The Looptools directory has been updated to reflect T.Hahn's Looptools 2.6. ** Contrib changes The ROOT interface has been removed as deprecated. The MCPWNLO code has temporarily been removed from the Contrib directory as a major review of this code is required. Additionally, there are various fixes to all other codes shipped in Contrib. ** DIS improvements The momentum reshuffling in DIS events has been improved. ** mu and nu beams mu, nu_e and nu_mu and their antiparticles are now available as beam particles. They are all supported in the DIS matrix elements. mu+ mu- collisions are supported in the general matrix element code for BSM models, but not yet in the hard-coded matrix elements for lepton-lepton scattering. ** Structural changes *** Inline code Inline code has been merged into the header files, .icc files were removed. *** Silent build By default, Herwig++ now builds with silent build rules. To get the old behaviour, run 'make V=1'. *** Debug level The debug level on the command line will now always have priority. *** Event counter The event counter has been simplified. *** Interpolator persistency Interpolators can now be written persistently. ** Ticket #307: Momentum violation check in BasicConsistency Added parameters AbsoluteMomentumTolerance and RelativeMomentumTolerance ** Example POWHEG input files The example input files for Powheg processes now set the NLO alpha_S correctly, and are run as part of 'make check'. ** Truncated shower A problem which lead to the truncated shower not being applied in some cases has been fixed. ** Fixes to numerical problems Minor problems with values close to zero were fixed in several locations. ** Remove duplicated calculation of event shapes An accidental duplication in the calculation of event shapes was removed, they are now only calculated once per event. Several other minor issues in the event shape calculations have also been fixed. ** MRST PDFs fixed An initialization problem in the internal MRST PDFs was fixed. ** Vertex scale choice The scale in the Vertex classes can now be zero where possible. ** Treatment of -N flag The Herwig++ main program now correctly treats the -N flag as optional. ** Numerical stability improved The numerical stability in the 'RunningMass' and 'QTildeReconstructor' classes has been improved. The stability of the boosts in the SOPTHY code for the simulation of QED radiation has been improved. The accuracy of boosts in the z-direction has been improved to fix problems with extremely high p_T partons. ** Bugfix in initial state splittings A bug in the implementation of the PDF weight in initial-state qbar -> qbar g splittings has been fixed. ** Bugfix in chargino neutralino vertices A bug in the 'chi+- chi0 W-+' and charged Higgs-sfermions vertices has been fixed. ** Remove uninitialized variables written to repository A number of uninitialised variables which were written to the repository have been initialised to zero to avoid problems on some systems. ** Fix to QED radiation in hadronic collisions The longitudinal boost of the centre-of-mass frame in hadronic collisions is correctly accounted for now in the generation of QED radiation. ** Fix to numerical problems in two-body decays Numerical problems have been fixed, which appeared in the rare case that the three-momenta of the decay products in two-body decays are zero in the rest frame of the decay particle. ** A problem with forced splittings in the Remnant was fixed. ** ME correction for W+- decays applied properly The matrix element correction for QCD radiation in W+- decays which was not being applied is now correctly used. ** Top quark decays from SLHA file The presence of top quark decay modes in SLHA files is now handled correctly. ** Exceptional shower reconstruction kinematics Additional protection against problems due to the shower reconstruction leading to partons with x>1 has been added. ** Ordering of particles in BSM processes Changes have been made to allow arbitrary ordering of the outgoing particles in BSM processes. ** Bugfixes in tau decays Two bugs involving tau decays have been fixed. The wrong masses were used in the 'KPiCurrent' class for the scalar form factors and a mistake in the selection of decay products lead to tau- --> pi0 K- being generated instead of tau- --> eta K-. ** Avoid crashes in baryon number violating processes. To avoid crashes, better protection has been introduced for the case where diquarks cannot be formed from the quarks in a baryon-number violating process. In addition, the parents of the baryon-number violating clusters have been changed to avoid problems with the conversion of the events to HepMC. ** QED radiation in W- decays A bug in the 'QEDRadiationHandler' class which resulted in no QED radiation being generated in W- decays has been fixed. ** A number of minor fixes to the SUSY models have been made. ** Partial width calculations in BSM models A fix for the direction of the incoming particle in the calculation of two-body partial widths in BSM models has been made. ** LoopTools improvements The LoopTools cache is now cleared more frequently to reduce the amount of memory used by the particle. ** Negative gluino masses are now correctly handled. ** A problem with mixing matrices which are not square has been fixed. ** Removed duplicate diagram The 'MEee2gZ2ll' class has been fixed to only include the photon exchange diagram once rather than twice as previously. ** Fix for duplicate particles in DecayConstructor A problem has been fixed which occurred if the same particle was included in the list of DecayConstructor:DecayParticles. ** Fixes for UED model vertices A number of minor problems in the vertices for the UED model have been fixed. ** Include missing symmetry factor The missing identical-particle symmetry factor in 'MEPP2GammaGamma' has been included. ** Fix floating point problem in top decays A floating point problem in the matrix element correction for top decays has been fixed. * Herwig++-2.4.2 release: 2009-12-11 (tagged at SVN r5022) ** Ticket #292: Tau decay numerical instability The momentum assignment in tau decays contained numerical instabilities which have been fixed by postponing the tau decay until after the parton shower. A new interface setting DecayHandler:Excluded is available to prevent decays in the shower step. This is enabled by default for tau only. ** Ticket #290: Missing MSSM colour structure The missing colour structure for gluino -> gluon neutralino was added. ** Ticket #294: Zero momentum in some decays Some rare phase space points lead to zero momentum in two-body decays. This has been fixed. ** Ticket #295: Stability of QED radiation for lepton collider processes The numerical stability of QED radiation momenta was improved further. ** Ticket #296: K0 oscillation vertex was wrong The oscillation from K0 to K0_L/S now takes place at the production vertex of K0. ** Ticket #289: Undefined variables in repository On some system configurations, undefined variables were written to the repository. These have been fixed. ** Fixed QED radiation for hadron processes The longitudinal boost of the centre-of-mass frame in hadronic collisions is correctly accounted for now. ** Numerical stability fixes Small fixes in RunningMass and QTildeReconstructor. ** Powheg example input files The example input files for Powheg processes now set the NLO alpha_S correctly, and are run as part of 'make check'. ** OS X builds for Snow Leopard Snow Leopard machines will now be recognized as a 64bit architecture. * Herwig++-2.4.1 release: 2009-11-19 (tagged at SVN r4932) ** Uses ThePEG-1.6.0 Herwig++ now requires ThePEG-1.6.0 to benefit from the improved helicity code there. If you have self-written vertex classes, see ThePEG's NEWS file for conversion instructions. ** Vertex improvements ThePEG's new helicity code allowed major simplification of the vertex implementations for all Standard Model and BSM physics models. ** New Transplanckian scattering model An example configuration is in LHC-TRP.in ** BSM ModelGenerator as branching ratio calculator The BSM ModelGenerator has a new switch to output the branching ratios for a given SLHA file in SLHA format, which can then be used elsewhere. ** BSM debugging: HardProcessConstructor New interface 'Excluded' to exclude certain particles from intermediate lines. ** Chargino-Neutralino-W vertex fixed ** Spin correlations are now switched on by default for all perturbative decays. ** Ticket #276: Scale choice in BSM models' HardProcessConstructor New interface 'ScaleChoice' to choose process scale between - sHat (default for colour neutral intermediates) and - transverse mass (default for all other processes). ** Ticket #287: Powheg process scale choice The default choice is now the mass of the colour-singlet system. ** Ticket #278: QED radiation for BSM Soft QED radiation is now enabled in BSM decays and all perturbative decays by default. ** Ticket #279: Full 1-loop QED radiation for Z decays Soft QED radiation in Z decays is now fully 1-loop by default. ** Ticket #280: Redirect all files to stdout This is now implemented globally. The files previously ending in -UE.out and -BSMinfo.out are now appended to the log file. They now also obey the EventGenerator:UseStdout flag. ** Ticket #270: LaTeX output updated After each run, a LaTeX file is produced that contains the full list of citations. Please include the relevant ones in publications. ** Ticket #256: Mac OS X problems An initialization problem that affected only some configurations has been identified and fixed. ** Tests directory added This contains many .in files, to exercise most matrix elements. ** Minor fixes *** Prevent rare x>1 partons in shower reconstruction. *** SUSY-LHA parameter EXTPAR can be used to set tan beta *** Improved Fastjet detection at configure time * Herwig++-2.4.0 release: 2009-09-01 (tagged at SVN r4616) ** New matrix elements We have added a built-in implementation of several new matrix elements: PP --> WW / WZ / ZZ PP --> W gamma / Z gamma PP --> VBF Higgs PP --> Higgs tt / Higgs bb e+e- --> WW / ZZ gamma gamma --> ff / WW ** Base code improvements *** Ticket #257: Remnant handling A problem with forced splittings in the Remnant was fixed. *** Ticket #264: Soft matrix element correction A problem with emissions form antiquarks was fixed. ** PDF sets *** New default set MRST LO** is the new default PDF set. LO* is also available built-in. *** Shower PDFs can be set separately from the hard process Use the 'ShowerHandler:PDF' interface. ** Parameter tunes Shower, hadronization and underlying event parameters were retuned against LEP and Tevatron data respectively. ** BSM module improvements *** Ticket #259: read error for some UED models Arbitrary ordering of outgoing lines in the process description is now possible. *** Ticket #266: branching ratio sums The warning threshold for branching ratios not summing to 1 has been relaxed. It is now a user interface parameter. *** Ticket #267: Top decay modes Top decay modes listed in SLHA files are now handled correctly. ** QED radiation *** Ticket #241: Soft QED radiation is now enabled by default *** Ticket #265: Radiation off W+ and W- is now handled correctly ** Interfaces *** Ticket #243: Fastjet Fastjet is now the only supported jet finder code. All example analyses have been converted to use Fastjet. *** KtJet and CLHEP interfaces have been removed. *** New interfaces to AcerDet and PGS available in Contrib *** MCPWnlo distributed in Contrib *** HepMC and Rivet interfaces moved to ThePEG ** Ticket #239: Inelastic cross-section for MinBias This information is now available in the ...-UE.out files. ** Technical changes *** Ticket #186 Configure now looks for ThePEG in the --prefix location first. *** Configure information Important configuration information is listed at the end of the 'configure' run and in the file 'config.thepeg'. Please provide this file in any bug reports. *** New ZERO object The ZERO object can be used to set any dimensionful quantity to zero. This avoids explicit constructs like 0.0*GeV. *** Exception specifiers removed Client code changes are needed in doinit() etc., simply remove the exception specifier after the function name. *** Ticket #263: Tau polarizations can be forced in TauDecayer * Herwig++-2.3.2 release: 2009-05-08 (tagged at SVN r4249) ** SUSY enhancements *** Ticket #245: Select inclusive / exclusive production Using the new 'HardProcessConstructor:Processes' switch options 'SingleParticleInclusive', 'TwoParticleInclusive' or 'Exclusive' *** Improved three-body decay generation Several problems were fixed, incl. tickets #249 #250 #251 Thanks to J.Tattersall and K.Rolbiecki for the stress-testing! *** Looptools fix Release 2.3.1 had broken the Looptools initialization. *** Improved warning message texts ** Ticket #237: Values of q2last can now be zero where possible. ** Ticket #240: The Herwig++ main program now correctly treats the -N flag as optional. ** Ticket #246: Extreme pT partons fixed by improving accuracy of z boosts. ** DIS Improved parton shower momentum reshuffling. ** Minimum Bias events The zero-momentum interacting particle used for bookkeeping is now labelled as a pomeron. ** User Makefile Makefile-UserModules does not enable -pedantic anymore. User's ROOT code will not compile otherwise. ** Build system Small fixes in the build system. * Herwig++-2.3.1 release: 2009-03-31 (tagged at SVN r4140) ** Initial state showers The PDF veto was wrongly applied to qbar->qbar g splittings. ** User interaction The Makefile-UserModules now includes the Herwig version number. The -N flag to 'Herwig++ run' is optional now, as was always intended. ** Contrib The contrib directory is now included in the tarball. The omission was accidental. ** Numerical accuracy Minor problems with values close to zero were fixed in several locations. ** LEP event shapes An accidental duplication was removed, they are now only calculated once per event. ** MRST PDF code Initialization problem fixed. ** Mac OS X The configure script was improved to detect libraries better. ** Libtool Updated to version 2.2.6 * Herwig++-2.3.0 release: 2008-12-02 (tagged at SVN r3939) ** Major release, with many new features and bug fixes ** Extension to lepton-hadron collisions ** Inclusion of several processes accurate at next-to-leading order in the POsitive Weight Hardest Emission Generator (POWHEG) scheme ** Inclusion of three-body decays and finite-width effects in BSM processes ** New procedure for reconstructing kinematics of the parton shower based on the colour structure of the hard scattering process ** New model for baryon decays including excited baryon multiplets ** Addition of a soft component to the multiple scattering model of the underlying event and the option to choose more than one hard scattering explicitly ** New matrix elements for DIS and e+e- processes ** New /Contrib directory added containing external modules that will hopefully be of use to some users but are not expected to be needed by most users and are not supported at the same level as the main Herwig++ code ** Minor changes to improve the physics simulation: *** IncomingPhotonEvolver added to allow the simulation of partonic processes with incoming photons in hadron collisions *** KTRapidityCut added to allow cuts on the p_T and rapidity, rather than just the p_T and pseudorapidity used in SimpleKTCut. This is now used by default for cuts on massive particles such as the $W^\pm$, $Z^0$ and Higgs bosons and the top quark *** Several changes to the decayers of B mesons both to resolve problems with the modelling of partonic decays and improve agreement with $\Upsilon(4s)$ data *** Changes to allow values other than transverse mass of final-state particles as maximum transverse momentum for radiation in parton shower either SCALUP for Les Houches events or the scale of the hard process for internally generated hard processes *** Changed defaults for intrinsic transverse momentum in hadron collisions to 1.9GeV, 2.1GeV and 2.2GeV for the Tevatron and LHC at 10 TeV and 14 TeV, respectively *** Pdfinfo object is now created in the HepMC interface However in order to support all versions of HepMC containing this feature the PDF set is not specified as not all versions contain this information *** New option of only decaying particles with lifetimes below user specified value *** New options for the cut-off in the shower and some obsolete parameters removed *** Added option of switching off certain decay modes in BSM models *** Added a Matcher for Higgs boson to allow cuts to be placed on it *** Diffractive particles deleted from default input files they were not previously used ** Technical changes: *** Some AnalysisHandler classes comparing to LEP data have been renamed e.g. MultiplicityCount becomes LEPMultiplicityCount to avoid confusion with those supplied in /Contrib for observables at the Upsilon(4s) resonance *** Reorganisation to remove the majority of the .icc files by moving inlined functions to headers in an effort to improve compile time *** Restructured the decay libraries to reduce the amount of memory allocation and de-allocation which improves run-time performance *** The switch to turn off LoopTools has been removed because LoopTools is now used by several core modules. As LoopTools does not work on 64-bit platforms with g77 this build option is not supported *** Removed support for obsolete version of HepMC supplied with CLHEP and improved the support for different units options with HepMC *** EvtGen interface has been removed until it is more stable *** Support for ROOT has been removed it was not previously used *** CKKW infrastructure has been removed from the release until a concrete implementation is available *** Default optimisation has been increased from -O2 to -O3 *** Handling of the fortran compiler has been improved mainly due to improvements in the autotools *** Use of FixedAllocator for Particle objects in ThePEG has been removed as it had no performance benefits ** Bugs fixed: *** Problems with the mother/daughter relations in the hard process and diagram selection in W+- and Z0 production in association with a hard jet *** In general matrix element code for fermion-vector to fermion-scalar where the outgoing fermion is coloured and the scalar neutral *** In the selection of diagrams in some associated squark gaugino processes *** h0->mu+mu- was being generated when h0->tau+tau- *** Normalisation in the Histogram class for non unit-weight events *** Protection against negative PDF values has been improved these can occur when using NLO PDF sets *** Lifetime for BSM particles is now automatically calculated at the same time as the width *** Hadrons containing a top quark now treated like hadrons containing BSM particles in order to support this possibility *** Several ambiguous uses of unsigned int *** Several variables that may have been used undefined *** Several memory leaks at initialisation *** The configuration now aborts if no fortran compiler is found as this is required to compile Looptools *** Several minor floating point errors that did not affect results * Herwig++-2.2.1 release: 2008-07-09 (tagged at SVN r3434) ** Ticket #181: BSM shower with a decay close to threshold Now fixed. ** Ticket #191: Split SUSY crash Improved error message. ** Ticket #192: using SCALUP as the pT veto in the shower Now implemented. ** Ticket #194: production processes of ~chi_1(2)- Fixed bug in the diagram creation. ** Removed unused particles DiffractiveParticles.in was removed, they were never produced. ** Hadronization Top quark clusters now possible, handled as 'exotic' clusters. ** Improved handling of decay modes See ThePEG-1.3.0. 'defaultparticle' command is now obsolete. ** Multi-Parton interactions Increased phase space sampling to have less than 1% uncertainty on average multiplicity. ** New libtool version gfortran is now used as default if it is available. Set FC=g77 to override this. ** Fixed several memory leaks ** Memory allocation Now using plain 'new' and 'delete'. * Herwig++-2.2.0 release: 2008-04-18 (tagged at SVN r3195) ** Major release: now as stand-alone library Herwig++ is now a stand-alone dlopen() plugin to ThePEG. No compile-time linking to Herwig code is required. The Herwig++ binary is a simple executable steering ThePEG, which can be replaced by other frontends (such as setupThePEG / runThePEG). ** New matrix elements p p -> W + jet / Z + jet / W + higgs / Z + higgs e+ e- -> Z + higgs ** Looptools Updated to version 2.2. ** Ticket #141: segfault from using 'run' command Fixed by using default allocators in Herwig++, and the Repository::cleanup() method in ThePEG 1.2.0. ** Ticket #157: broken gsl library path on some 64bit systems Paths with lib64 are correctly identified now. ** Ticket #159: p_t spectrum of ttbar pair Fixed identical particle multiplier in Sudakov form factor. ** Ticket #161: glibc segfault Rare segfault in MPI handler fixed. ** Ticket #165: rare infinite loop in four-body decay All 4-body decays without dedicated decayers now use the Mambo algorithm. A loop guard has been introduced to 3-body decays to avoid infinite retries. ** Ticket #166: rare infinite loop in top ME correction These very rare events (O(1) in 10^7) close to mass threshold now are discarded. ** Higgs width fixes ** SatPDF Optionally, the PDF extrapolation behaviour outside a given range can now be specified. ** gcc 4.3 Herwig++-2.2 compiles cleanly with the new gcc 4.3 series. * Herwig++-2.1.4 release: 2008-03-03 (tagged at SVN r3024) ** Ticket #152: Vertex positions All vertex positions of unphysical particles are set to zero until a fix for the previous nonsensical values can be implemented. * Herwig++-2.1.3 release: 2008-02-25 (tagged at SVN r2957) ** Ticket #129: Baryon decays Fix for baryon decay modes. ** Ticket #131: HepMC Check if IO_GenEvent exists ** Ticket #134: Hadronization Smearing of hadron directions in cluster decay fixed. ** Ticket #137: HepMC HepMC conversion allows specification of energy and length units to be used. ** Ticket #139: Neutral kaons Ratio K_L / K_S corrected. ** Ticket #140 / #141: Crash on shutdown Event generation from the 'read' stage or an interface now shuts down cleanly. Fixes a crash bug introduced in 2.1.1 which affected external APIs to ThePEG / Herwig. ** Ticket #146: BSM models can be disabled To save build time, some or all of the BSM models can be disabled using the '--enable-models' configure switch. ** Reorganised .model files The .model files now include the model-specific particles, too. ** Re-tune Re-tuned hadronization parameters to LEP data. ** Other fixes in QSPAC implementation in Shower; Multi-parton interaction tuning; MRST initialization * Herwig++-2.1.2 release: 2008-01-05 (tagged at SVN r2694) ** Ticket #127 Thanks to a patch submitted by Fred Stober, HepMCFile now can output event files in all supported formats. ** Ticket #128 Fixed incorrect value of pi in histogram limits. ** Other fixes in CKKW Qtilde clusterers, BSM width cut, SUSY mixing matrices. * Herwig++-2.1.1 release: 2007-12-08 (tagged at SVN r2589) ** Bug #123 Fixed a bug with particle lifetimes which resulted in nan for some vertex positions. ** Secondary scatters Fixed bug which gave intrinsic pT to secondary scatters. ** gcc abs bug detection configure now checks for and works around http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34130 ** CKKW reweighting Fixed wrong check for top quarks. ** MPIHandler Fixed call order ambiguity. * Herwig++-2.1.0 release: 2007-11-20 (tagged at SVN r2542) ** Major new release Herwig++-2.1 includes significant improvements, including multi-parton interactions, BSM physics and a new hadronic decay model, tuned to LEP data. For an overview of the changes, please see the release note arXiv:0711.3137 * Herwig++-2.0.3 release: 2007-08-21 (tagged at SVN r2101) ** Bug #90 nan in top decay ME corrections fixed. ** unlisted Colour flow fix in LightClusterDecayer ** unlisted Updated version of MultiplicityCount analysis handler. * Herwig++-2.0.2 release: 2007-07-06 (tagged at SVN r1716) ** Bug #80 Separation of HepMC from CLHEP is handled properly now. ** Bug #83 Workaround for OS X header problem ** unlisted Veto on very hard emissions from Shower. ** unlisted Detailed documentation in .in files * Herwig++-2.0.1 release: 2006-12-05 (tagged at SVN r1195) ** Bug #54 ClusterFissioner vertex calculation fixed. ** Bug #57 Crash when showering W+jet events supplied by Les Houches interface. ** Bug #59 Fix for #57 applied to LHC events. ** Bug #60 Segfault when PDF is set to NoPDF. ** Bug #61 Missing weight factor for I=0 mesons ** Bug #62 Spinor vertex calculations broken when spinor rep is not default rep. ** Bug #63 Top decay never produces tau. ** Bug #69 TTbar and HiggsJet analysis handlers fixed. ** unlisted Reorganization of Hadronization module gives 30% speedup. Thanks to Vincenzo Innocente at CMS for his profiling work! ** unlisted cleaner automake files in include/ and src/ ** unlisted Hw64 hadron selection algorithm 'abortnow' fixed. ** unlisted Top/LeptonDalitzAnalysis removed (only worked with modified code). ** unlisted removed f'_0 from particle list, decays were not handled * Herwig++-2.0.0 release: 2006-09-28 (tagged at SVN r1066) ** Full simulation of hadron collisions diff --git a/README b/README --- a/README +++ b/README @@ -1,18 +1,18 @@ ======== Herwig 7 ======== -This is the release of Herwig 7.0.1, a multi purpose event +This is the release of Herwig 7.0.2, a multi purpose event generator for high energy physics. The Herwig++ distribution contains an adapted version of LoopTools 2.6 . Please contact to be added to our list of users. This will allow you to make full use of the Wiki and bug tracker at http://projects.hepforge.org/herwig/trac/ BUILD AND INSTALL ================= Please refer to https://herwig.hepforge.org/tutorials/index.html for detailed instructions. diff --git a/Sampling/Makefile.am b/Sampling/Makefile.am --- a/Sampling/Makefile.am +++ b/Sampling/Makefile.am @@ -1,40 +1,40 @@ SUBDIRS = CellGrids pkglib_LTLIBRARIES = HwSampling.la -HwSampling_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0 +HwSampling_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0 HwSampling_la_SOURCES = \ GeneralStatistics.h GeneralStatistics.cc \ MultiIterationStatistics.h MultiIterationStatistics.cc \ BinSampler.h BinSampler.cc \ GeneralSampler.h GeneralSampler.cc \ MonacoSampler.h MonacoSampler.cc \ Remapper.h Remapper.cc \ exsample/cell.icc \ exsample/generator.h \ exsample/linear_interpolator.icc \ exsample/config.h \ exsample/selectors.h \ exsample/adaption_info.h \ exsample/selectors.icc \ exsample/adaption_info.icc \ exsample/exponential_generator.h \ exsample/exponential_generator.icc \ exsample/generator.icc \ exsample/statistics.h \ exsample/linear_interpolator.h \ exsample/cell.h \ exsample/utility.h \ exsample/binary_tree.h \ exsample/statistics.icc HwSampling_la_LIBADD = \ CellGrids/libHwCellGrids.la EXTRA_DIST = herwig-mergegrids.py install-exec-local: $(install_sh_SCRIPT) $(srcdir)/herwig-mergegrids.py $(DESTDIR)$(bindir)/herwig-mergegrids uninstall-local: rm -f $(DESTDIR)$(bindir)/herwig-mergegrids diff --git a/Sampling/exsample/cell.h b/Sampling/exsample/cell.h --- a/Sampling/exsample/cell.h +++ b/Sampling/exsample/cell.h @@ -1,304 +1,306 @@ // -*- C++ -*- // // cell.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions // // Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de // // ExSample is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // #ifndef EXSAMPLE_cell_h_included #define EXSAMPLE_cell_h_included #include "utility.h" #include "adaption_info.h" #include "statistics.h" namespace exsample { /// \brief Information contained in a leaf cell class cell_info { public: /// the default constructor cell_info(); /// construct from boundaries and adaption info cell_info(const std::vector& ll, const std::vector& ur, const adaption_info& ainfo); /// construct from boundaries, flags for variables to be sampled, /// and adaption info cell_info(const std::vector& ll, const std::vector& ur, const std::vector& sampled_variables, const adaption_info& ainfo); public: /// generate a flat trial point in this cell template void select(Random&, std::vector&); /// generate a flat trial point in this cell /// only for the variables falgged as true template void select(Random&, std::vector&, const std::vector&); /// indicate a function value for the given point void selected(const std::vector&, double, const adaption_info&); /// indicate that a point has been /// accepted in this cell void accept() { ++accepted_; } /// reject a previously accepted event void reject() { --accepted_; } public: /// return true, if below efficiency threshold bool bad(const adaption_info& ainfo) const { return ((static_cast(accepted_)/static_cast(attempted_)) < ainfo.efficiency_threshold); } /// suggest a split and indicate wether it is worth /// to be performed std::pair get_split(const adaption_info&, bool&) const; /// explore this cell performing a flat sampling, /// updating the given statistics object and pre-filling /// the efficiency histogram by a trial unweighting template void explore(Random&, const adaption_info&, Function*, statistics*, - SlaveStatistics& opt); + SlaveStatistics& opt, double detuning = 1.0); /// explore this cell in a more refined way, which /// is however not suited for already calculating integrals /// and stuff template - void explore(Random&, const adaption_info&, Function*); + void explore(Random&, const adaption_info&, Function*, + double detuning = 1.0); public: /// get the current overestimate double overestimate() const { return overestimate_; } /// return the position of the last maximum const std::vector& last_max_position() const { return last_max_position_; } /// set the current overestimate and maximum position void overestimate(double v, const std::vector& pos) { overestimate_ = v; last_max_position_ = pos; } /// get the volume double volume() const { return volume_; } /// get the lower left corner const std::vector& lower_left() const { return lower_left_; } /// get the upper right corner const std::vector& upper_right() const { return upper_right_; } /// get the number of attempted events unsigned long attempted() const { return attempted_; } /// get the number of accepted events unsigned long accepted() const { return accepted_; } public: /// return the number of missing events /// for the given parameter bin id int parametric_missing(const bit_container& id) const; /// set the number of missing events /// for the given parameter bin id void parametric_missing(const bit_container& id, int n); /// increase to the number of missing events /// for the given parameter bin id void increase_parametric_missing(const bit_container& id); /// decrease to the number of missing events /// for the given parameter bin id void decrease_parametric_missing(const bit_container& id); /// return true, if the cell is compensating in /// at least one parameter bin bool parametric_compensating() const { return !parametric_missing_map_.empty(); } /// return true, if the cell contains the /// indicated parameter point bool contains_parameter(const std::vector& point, const std::vector& sampled) const; public: /// put to ostream template void put(OStream& os) const; /// get from istream template void get(IStream& is); private: /// the value of the overestimate in this cell double overestimate_; /// the volume of this cell double volume_; /// the lower left corner of this cell std::vector lower_left_; /// the upper right corner of this cell std::vector upper_right_; /// midpoint of this cell std::vector mid_point_; /// the position of the last encountered /// maximum in this cell std::vector last_max_position_; /// left-right statistics of average weight std::vector > avg_weight_; /// the number of attempts in this cell unsigned long attempted_; /// the number of accepted events in this cell unsigned long accepted_; /// an optional map of parameter bin ids /// to the number of missing events std::map,int> parametric_missing_map_; }; /// \brief the general cell class class cell { public: /// default constructor cell(); /// construct from boundaries and adaption info cell(const std::vector& ll, const std::vector& ur, const adaption_info& ainfo); /// construct from boundaries, flags for variables to be sampled, /// and adaption info cell(const std::vector& ll, const std::vector& ur, const std::vector& sampled_variables, const adaption_info& ainfo); /// copy constructor cell(const cell& x); /// assignment cell& operator=(const cell& x); public: /// split this cell, exploring the /// child not containing the current overestimate template std::pair split(std::pair split_d, Random& rnd_gen, Function* f, const adaption_info& ainfo, const std::vector& sampled = - std::vector()); + std::vector(), + double detuning = 1.0); public: /// return the split dimension std::size_t split_dimension() const { return split_dimension_; } /// return the split value double split_point() const { return split_point_; } /// return the integral double integral() const { return integral_; } /// access the integral double& integral() { return integral_; } /// set the integral void integral(double v) { integral_ = v; } /// access the number of missing events int& missing_events() { return missing_events_; } /// return the number of missing events int missing_events() const { return missing_events_; } /// set the number of missing events void missing_events(int n) { missing_events_ = n; } /// access the cell_info object cell_info& info() { assert(cell_info_); return *cell_info_; } /// return the cell_info object const cell_info& info() const { assert(cell_info_); return *cell_info_; } public: /// put to ostream template void put(OStream& os) const; /// get from istream template void get(IStream& is); private: /// the dimension along this cell /// was split std::size_t split_dimension_; /// the value, where this cell was split double split_point_; /// the integral of the absolute value /// of the overestimate over all the /// children cells double integral_; /// the number of missing events in this cell int missing_events_; /// a pointer to the cell info object, /// if this is a leaf cell boost::scoped_ptr cell_info_; }; } #include "cell.icc" #endif // EXSAMPLE_cell_h_included diff --git a/Sampling/exsample/cell.icc b/Sampling/exsample/cell.icc --- a/Sampling/exsample/cell.icc +++ b/Sampling/exsample/cell.icc @@ -1,487 +1,490 @@ // -*- C++ -*- // // cell.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions // // Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de // // ExSample is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // namespace exsample { template void cell_info::select (Random& rnd_gen, std::vector& p) { std::transform(lower_left_.begin(),lower_left_.end(), upper_right_.begin(),p.begin(), rnd_gen); ++attempted_; } template void cell_info::select (Random& rnd_gen, std::vector& p, const std::vector& sample) { conditional_transform(lower_left_.begin(),lower_left_.end(), upper_right_.begin(),sample.begin(), p.begin(),rnd_gen); ++attempted_; } template void cell_info::explore(Random& rnd_gen, const adaption_info& ainfo, Function* function, statistics* stats, - SlaveStatistics& opt) { + SlaveStatistics& opt, + double detuning) { function->start_presampling(); unsigned long n_sampled = 0; std::vector ll = lower_left_; std::vector ur = upper_right_; double val = 0.; std::vector pos (ll.size()); std::vector< std::pair > > vals; unsigned long ivalnonzero = 0; while (n_sampled < ainfo.presampling_points) { std::transform(ll.begin(),ll.end(), ur.begin(),pos.begin(), rnd_gen); - val = function->evaluate(pos); + val = function->evaluate(pos) * detuning; vals.push_back( std::pair > (val,pos) ); if ( val != 0 ) ivalnonzero++; ++n_sampled; } while ( ivalnonzero > 0 ) { double avg = 0; double err = 0; double maxval = 0; std::vector maxpos (ll.size()); unsigned long imax; for ( unsigned long ival=0; ival < vals.size(); ival++ ) { val = std::abs(vals[ival].first); if ( val == 0 ) continue; avg += val; err += sqr(val); if ( val > maxval ) { maxval = val; maxpos = vals[ival].second; imax = ival; } } avg /= ivalnonzero; err /= ivalnonzero; err = sqrt(err-sqr(avg)); if ( maxval <= avg+sqrt(ivalnonzero/2.)*err ) { overestimate_ = maxval; last_max_position_ = maxpos; break; } vals.erase(vals.begin()+imax); ivalnonzero--; } for ( unsigned long ival=0; ival < vals.size(); ival++ ) { val = vals[ival].first; stats->presampled(val); opt.select(val); selected(pos,std::abs(val),ainfo); } function->stop_presampling(); } template void cell_info::explore (Random& rnd_gen, - const adaption_info& ainfo, Function* function) { + const adaption_info& ainfo, Function* function, + double detuning) { function->start_presampling(); unsigned long n_sampled = 0; std::vector ll = lower_left_; std::vector ur = upper_right_; double val = 0.; std::vector pos (ll.size()); std::vector< std::pair > > vals; while (n_sampled < ainfo.presampling_points) { std::transform(ll.begin(),ll.end(), ur.begin(),pos.begin(), rnd_gen); - val = function->evaluate(pos); + val = function->evaluate(pos) * detuning; if ( std::abs(val) > 0 ) vals.push_back( std::pair > (std::abs(val),pos) ); ++n_sampled; } while ( vals.size() > 0 ) { double avg = 0; double err = 0; double maxval = 0; std::vector maxpos (ll.size()); unsigned long imax; for ( unsigned long ival=0; ival < vals.size(); ival++ ) { double thisval = vals[ival].first; avg += thisval; err += sqr(thisval); if ( thisval > maxval ) { maxval = thisval; maxpos = vals[ival].second; imax = ival; } } avg /= vals.size(); err /= vals.size(); err = sqrt(err-sqr(avg)); if ( maxval <= avg+sqrt(vals.size()/2.)*err ) { overestimate_ = maxval; last_max_position_ = maxpos; break; } vals.erase(vals.begin()+imax); } function->stop_presampling(); } template void cell_info::put (OStream& os) const { os << overestimate_; ostream_traits::separator(os); os << volume_; ostream_traits::separator(os); os << lower_left_.size(); ostream_traits::separator(os); for (std::size_t k = 0; k < lower_left_.size(); ++k) { os << lower_left_[k]; ostream_traits::separator(os); } for (std::size_t k = 0; k < upper_right_.size(); ++k) { os << upper_right_[k]; ostream_traits::separator(os); } for (std::size_t k = 0; k < mid_point_.size(); ++k) { os << mid_point_[k]; ostream_traits::separator(os); } for (std::size_t k = 0; k < last_max_position_.size(); ++k) { os << last_max_position_[k]; ostream_traits::separator(os); } for (std::size_t k = 0; k < avg_weight_.size(); ++k) { os << avg_weight_[k].first; ostream_traits::separator(os); os << avg_weight_[k].second; ostream_traits::separator(os); } os << attempted_; ostream_traits::separator(os); os << accepted_; ostream_traits::separator(os); os << parametric_missing_map_.size(); ostream_traits::separator(os); for ( std::map,int>::const_iterator p = parametric_missing_map_.begin(); p != parametric_missing_map_.end(); ++p ) { p->first.put(os); os << p->second; ostream_traits::separator(os); } } template void cell_info::get (IStream& is) { std::size_t dim; is >> overestimate_ >> volume_ >> dim; lower_left_.resize(dim); for (std::size_t k = 0; k < lower_left_.size(); ++k) { is >> lower_left_[k]; } upper_right_.resize(dim); for (std::size_t k = 0; k < upper_right_.size(); ++k) { is >> upper_right_[k]; } mid_point_.resize(dim); for (std::size_t k = 0; k < mid_point_.size(); ++k) { is >> mid_point_[k]; } last_max_position_.resize(dim); for (std::size_t k = 0; k < last_max_position_.size(); ++k) { is >> last_max_position_[k]; } avg_weight_.resize(dim); for (std::size_t k = 0; k < avg_weight_.size(); ++k) { is >> avg_weight_[k].first >> avg_weight_[k].second; } is >> attempted_ >> accepted_ >> dim; for ( size_t k = 0; k < dim; ++k ) { bit_container in; in.get(is); is >> parametric_missing_map_[in]; } } template std::pair cell::split (std::pair split_d, Random& rnd_gen, Function* function, const adaption_info& ainfo, - const std::vector& sampled) { + const std::vector& sampled, + double detuning) { assert(!missing_events() && !info().parametric_compensating()); split_dimension_ = split_d.first; split_point_ = split_d.second; std::vector lower_left1 = info().lower_left(); std::vector upper_right1 = info().upper_right(); std::vector lower_left2 = info().lower_left(); std::vector upper_right2 = info().upper_right(); upper_right1[split_dimension_] = split_point_; lower_left2[split_dimension_] = split_point_; std::pair children; if (sampled.empty()) children = std::pair(cell(lower_left1,upper_right1,ainfo), cell(lower_left2,upper_right2,ainfo)); else children = std::pair (cell(lower_left1,upper_right1,sampled,ainfo), cell(lower_left2,upper_right2,sampled,ainfo)); if (info().last_max_position()[split_dimension_] <= split_point_) { children.first.info().overestimate(info().overestimate(),info().last_max_position()); - children.second.info().explore(rnd_gen,ainfo,function); + children.second.info().explore(rnd_gen,ainfo,function,detuning); } else { children.second.info().overestimate(info().overestimate(),info().last_max_position()); - children.first.info().explore(rnd_gen,ainfo,function); + children.first.info().explore(rnd_gen,ainfo,function,detuning); } cell_info_.reset(0); children.first.integral(children.first.info().volume() * children.first.info().overestimate()); children.second.integral(children.second.info().volume() * children.second.info().overestimate()); return children; } template void cell::put (OStream& os) const { os << split_dimension_; ostream_traits::separator(os); os << split_point_; ostream_traits::separator(os); os << integral_; ostream_traits::separator(os); os << missing_events_; ostream_traits::separator(os); if (cell_info_) { os << "has_cell_info"; ostream_traits::separator(os); cell_info_->put(os); } else { os << "has_no_cell_info"; ostream_traits::separator(os); } } template void cell::get (IStream& is) { std::string info_tag; is >> split_dimension_ >> split_point_ >> integral_ >> missing_events_ >> info_tag; if (info_tag == "has_cell_info") { cell_info_.reset(new cell_info()); cell_info_->get(is); } } inline cell_info::cell_info() : overestimate_(0.), volume_(0.), lower_left_(), upper_right_(), mid_point_(), last_max_position_(), avg_weight_(), attempted_(0), accepted_(0) {} inline cell_info::cell_info(const std::vector& ll, const std::vector& ur, const adaption_info& ainfo) : overestimate_(0.), volume_(), lower_left_(ll), upper_right_(ur), mid_point_(), last_max_position_(), avg_weight_(std::vector > (ainfo.dimension,std::make_pair(0.,0.))), attempted_(0), accepted_(0) { std::vector delta; std::transform(ur.begin(),ur.end(), ll.begin(),std::back_inserter(delta), std::minus()); volume_ = std::accumulate(delta.begin(),delta.end(),1.,std::multiplies()); std::transform(ur.begin(),ur.end(), ll.begin(),std::back_inserter(mid_point_), std::plus()); for (std::size_t k = 0; k < ainfo.dimension; ++k) mid_point_[k] /= 2.; } inline cell_info::cell_info(const std::vector& ll, const std::vector& ur, const std::vector& sampled_variables, const adaption_info& ainfo) : overestimate_(0.), volume_(), lower_left_(ll), upper_right_(ur), mid_point_(), last_max_position_(), avg_weight_(std::vector > (ainfo.dimension,std::make_pair(0.,0.))), attempted_(0), accepted_(0) { std::vector delta; conditional_transform(ur.begin(),ur.end(), ll.begin(),sampled_variables.begin(), std::back_inserter(delta), std::minus()); volume_ = std::accumulate(delta.begin(),delta.end(),1.,std::multiplies()); std::transform(ur.begin(),ur.end(), ll.begin(),std::back_inserter(mid_point_), std::plus()); for (std::size_t k = 0; k < ainfo.dimension; ++k) mid_point_[k] /= 2.; } inline int cell_info::parametric_missing(const bit_container& id) const { std::map,int>::const_iterator mit = parametric_missing_map_.find(id); if (mit == parametric_missing_map_.end()) return 0; return mit->second; } inline void cell_info::parametric_missing(const bit_container& id, int n) { if (n == 0) { std::map,int>::iterator mit = parametric_missing_map_.find(id); if (mit != parametric_missing_map_.end()) parametric_missing_map_.erase(mit); return; } parametric_missing_map_[id] = n; } inline void cell_info::increase_parametric_missing(const bit_container& id) { std::map,int>::iterator mit = parametric_missing_map_.find(id); if (mit != parametric_missing_map_.end()) { mit->second += 1; if (mit->second == 0) parametric_missing_map_.erase(mit); } else parametric_missing_map_[id] = 1; } inline void cell_info::decrease_parametric_missing(const bit_container& id) { std::map,int>::iterator mit = parametric_missing_map_.find(id); if (mit != parametric_missing_map_.end()) { mit->second -= 1; if (mit->second == 0) parametric_missing_map_.erase(mit); } else assert(false); } inline void cell_info::selected(const std::vector& p, double weight, const adaption_info& ainfo) { for (std::size_t k = 0; k < p.size(); ++k) { if (ainfo.adapt[k]) { if (p[k] < mid_point_[k]) avg_weight_[k].first += weight; else avg_weight_[k].second += weight; } } } inline std::pair cell_info::get_split (const adaption_info& ainfo, bool& worth) const { std::size_t split_d = 0; double gain = 0.; for (std::size_t k = 0; k < ainfo.dimension; ++k) { double xgain = 0.; double left = avg_weight_[k].first; double right = avg_weight_[k].second; if (left+right > 0.) { xgain = std::abs(left-right)/(left+right); } if (xgain > gain) { gain = xgain; split_d = k; } } worth = (gain >= ainfo.gain_threshold); return std::make_pair(split_d,mid_point_[split_d]); } inline bool cell_info::contains_parameter (const std::vector& point, const std::vector& sampled) const { std::vector::const_iterator p = point.begin(); std::vector::const_iterator l = lower_left_.begin(); std::vector::const_iterator u = upper_right_.begin(); std::vector::const_iterator f = sampled.begin(); for (; p < point.end(); ++p, ++f, ++l, ++u) if (!(*f)) { if (((*l) > (*p)) || ((*u) < (*p))) return false; } return true; } inline cell::cell() : split_dimension_(0), split_point_(0.), integral_(0.), missing_events_(0), cell_info_(0) {} inline cell::cell(const std::vector& ll, const std::vector& ur, const adaption_info& ainfo) : split_dimension_(0), split_point_(0.), integral_(0.), missing_events_(0), cell_info_(new cell_info(ll,ur,ainfo)) {} inline cell::cell(const std::vector& ll, const std::vector& ur, const std::vector& sampled_variables, const adaption_info& ainfo) : split_dimension_(0), split_point_(0.), integral_(0.), missing_events_(0), cell_info_(new cell_info(ll,ur,sampled_variables,ainfo)) {} inline cell::cell(const cell& x) : split_dimension_(x.split_dimension_), split_point_(x.split_point_), integral_(x.integral_), missing_events_(x.missing_events_), cell_info_(0) { if (x.cell_info_) cell_info_.reset(new cell_info(*x.cell_info_)); } inline cell& cell::operator=(const cell& x) { if (this == &x) return *this; split_dimension_ = x.split_dimension_; split_point_ = x.split_point_; integral_ = x.integral_; missing_events_ = x.missing_events_; if (x.cell_info_) cell_info_.reset(new cell_info(*x.cell_info_)); return *this; } } diff --git a/Sampling/exsample/exponential_generator.h b/Sampling/exsample/exponential_generator.h --- a/Sampling/exsample/exponential_generator.h +++ b/Sampling/exsample/exponential_generator.h @@ -1,243 +1,249 @@ // -*- C++ -*- // // exponential_generator.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions // // Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de // // ExSample is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // #ifndef EXSAMPLE_exponential_generator_h_included #define EXSAMPLE_exponential_generator_h_included #include "cell.h" #include "selectors.h" #include "statistics.h" #include "linear_interpolator.h" #include "binary_tree.h" namespace exsample { /// \brief Exception thrown, if the exponential_generator has just changed its /// state. The attempt of generating an event should be repeated. struct exponential_regenerate{}; /// \brief The generator for sudakov-type distributions. template class exponential_generator { public: /// default constructor exponential_generator() : function_(0), check_events_(0), adaption_info_(), root_cell_(), rnd_gen_(), did_split_(false), initialized_(false), evolution_variable_(0), evolution_cutoff_(0.), sample_variables_(), sample_other_variables_(), parameter_splits_(), last_cell_(), last_point_(), last_value_(0.), last_parameter_bin_(), exponents_(), last_exponent_integrand_(), last_exponent_(), compensating_(false), integral_accessor_(), missing_accessor_(), parametric_selector_(), exponent_selector_(), parametric_sampler_(), attempts_(0), accepts_(0), - splits_(0), docompensate_(false) {} + splits_(0), docompensate_(false), detuning_(1.0) {} public: /// initialize this generator void initialize(); /// finalize this generator void finalize() {} /// generate an event, returning /// the sign of the weight or zero /// for an event below the evolution cutoff double generate(); /// generate an event, returning /// the sign of the weight or zero /// for an event below the evolution cutoff double generate(double cutoff) { double oldcut = evolution_cutoff_; evolution_cutoff_ = cutoff; double w = 0.0; try { w = generate(); } catch(...) { evolution_cutoff_ = oldcut; throw; } evolution_cutoff_ = oldcut; return w; } /// return the last sampled phase space point const std::vector& last_point() const { return last_point_; } /// return the last evaluated function double last_value() const { return last_value_; } /// indicate that the last generated point has been rejected void reject() { last_cell_->info().reject(); } public: /// return true, if this generator has been initialized bool initialized() const { return initialized_; } /// return true, if at least one split has been performed bool did_split() const { return did_split_; } /// access the function Function& function() { return *function_; } /// set the function void function(Function * f) { function_ = f; } /// access the adaption_info object adaption_info& sampling_parameters() { return adaption_info_; } /// indicate, if compensation should be applied void docompensate(bool yes = true) { docompensate_ = yes; } + /// set the detuning parameter + void detuning(double val) { detuning_ = val; } + public: /// put to ostream template void put(OStream& os) const; /// get from istream template void get(IStream& is); private: /// check for and possibly split /// the last selected cell bool split(); /// get the projection of the density integrating over every /// variable to be sampled, except the evolution variable for the /// indicated parameter point. the k'th entry in /// last_exponent_integrand_ is the value in the evolution /// variable bin from evolution_splits_[k] to /// evolution_splits_[k+1] void get_exponent(); /// compensate void compensate(); /// get all parameter points to build /// all possible sub tree hashes std::set > parameter_points(); /// get all parameter points to build /// all possible sub tree hashes void recursive_parameter_points(std::set >&, std::vector&, size_t); /// function to be sampled Function * function_; /// the number of events after which /// a cell is checked for splits unsigned long check_events_; /// the adaption info object adaption_info adaption_info_; /// the root cell binary_tree root_cell_; /// the random number generator to be used rnd_generator rnd_gen_; /// wether a split has already been performed bool did_split_; /// wether this generator has been initialized bool initialized_; /// the position of the evolution variable std::size_t evolution_variable_; /// the cutoff on the evolution variable double evolution_cutoff_; /// flags of variables to be sampled /// including the evolution variable std::vector sample_variables_; /// flags of variables to be sampled /// excluding the evolution variable std::vector sample_other_variables_; /// the splits in any parameter done so far /// (including the evolution variable) std::map > parameter_splits_; /// the last selected cell binary_tree::iterator last_cell_; /// the last sampled phasespace point std::vector last_point_; /// the last function value double last_value_; /// the last parameter bin id bit_container last_parameter_bin_; /// map parameter bin ids to exponent interpolations std::map,linear_interpolator > exponents_; /// the last exponent integrand std::vector last_exponent_integrand_; /// the last exponent std::map,linear_interpolator >::iterator last_exponent_; /// wether or not we are compensating bool compensating_; /// the integral accessor to be used integral_accessor integral_accessor_; /// the missing events accessor to be used parametric_missing_accessor missing_accessor_; /// the parametric selector to be used parametric_selector parametric_selector_; /// the parametric selector to be used for parameter bins parametric_selector exponent_selector_; /// the parametric sampler to be used parametric_sampling_selector > parametric_sampler_; /// the number of trials in the veto loo so far unsigned long attempts_; /// the number of accepted events so far unsigned long accepts_; /// number of splits done unsigned long splits_; /// true, if compensation should be applied bool docompensate_; + /// a detuning factor to be applied to the overestimate + double detuning_; + }; } #include "exponential_generator.icc" #endif // EXSAMPLE_exponential_generator_h_included diff --git a/Sampling/exsample/exponential_generator.icc b/Sampling/exsample/exponential_generator.icc --- a/Sampling/exsample/exponential_generator.icc +++ b/Sampling/exsample/exponential_generator.icc @@ -1,380 +1,386 @@ // -*- C++ -*- // // exponential_generator.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions // // Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de // // ExSample is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // namespace exsample { template void exponential_generator::initialize() { adaption_info_.dimension = function_->dimension(); adaption_info_.lower_left = function_->support().first; adaption_info_.upper_right = function_->support().second; if (adaption_info_.adapt.empty()) adaption_info_.adapt = std::vector(adaption_info_.dimension,true); evolution_variable_ = function_->evolution_variable(); evolution_cutoff_ = function_->evolution_cutoff(); sample_variables_ = function_->variable_flags(); sample_other_variables_ = sample_variables_; sample_other_variables_[evolution_variable_] = false; last_point_.resize(adaption_info_.dimension); parametric_selector_ = parametric_selector(&last_point_,sample_other_variables_); exponent_selector_ = parametric_selector(&last_point_,sample_variables_); missing_accessor_ = parametric_missing_accessor(&last_parameter_bin_); parametric_sampler_ = parametric_sampling_selector > (&last_point_,&last_parameter_bin_,sample_other_variables_,rnd_gen_); if (initialized_) return; splits_ = 0; for ( std::size_t k = 0; k < adaption_info_.dimension; ++k ) { if ( sample_other_variables_[k] ) continue; parameter_splits_[k].push_back(adaption_info_.lower_left[k]); parameter_splits_[k].push_back(adaption_info_.upper_right[k]); } root_cell_ = binary_tree(cell(adaption_info_.lower_left, adaption_info_.upper_right, sample_other_variables_, adaption_info_)); - root_cell_.value().info().explore(rnd_gen_,adaption_info_,function_); + root_cell_.value().info().explore(rnd_gen_,adaption_info_,function_,detuning_); root_cell_.value().integral(root_cell_.value().info().volume() * root_cell_.value().info().overestimate()); last_exponent_integrand_.resize(1); check_events_ = adaption_info_.presampling_points; initialized_ = true; } template bool exponential_generator::split () { if (adaption_info_.freeze_grid <= accepts_) return false; if (compensating_) return false; if (!(*last_cell_).info().bad(adaption_info_)) return false; bool dosplit = false; std::pair sp = (*last_cell_).info().get_split(adaption_info_,dosplit); if (!dosplit) return false; if (!adaption_info_.adapt[sp.first]) return false; if (splits_ == parameter_hash_bits/2) return false; ++splits_; - last_cell_.node().split((*last_cell_).split(sp,rnd_gen_,function_,adaption_info_,sample_other_variables_)); + last_cell_.node().split((*last_cell_).split(sp,rnd_gen_,function_,adaption_info_, + sample_other_variables_,detuning_)); if ( !sample_other_variables_[sp.first] ) { if ( std::find(parameter_splits_[sp.first].begin(),parameter_splits_[sp.first].end(),sp.second) == parameter_splits_[sp.first].end() ) { parameter_splits_[sp.first].push_back(sp.second); std::sort(parameter_splits_[sp.first].begin(),parameter_splits_[sp.first].end()); if ( sp.first == evolution_variable_ ) { last_exponent_integrand_.push_back(0.); } } } did_split_ = true; last_point_ = function_->parameter_point(); root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus()); exponents_.clear(); get_exponent(); return true; } template void exponential_generator::get_exponent () { last_parameter_bin_.reset(); root_cell_.subtree_hash (exponent_selector_,last_parameter_bin_); last_exponent_ = exponents_.find(last_parameter_bin_); if (last_exponent_ != exponents_.end()) return; exponents_[last_parameter_bin_] = linear_interpolator(); last_exponent_ = exponents_.find(last_parameter_bin_); double old_evo = last_point_[evolution_variable_]; std::vector::iterator exp_it = last_exponent_integrand_.begin(); for (std::vector::iterator esp = parameter_splits_[evolution_variable_].begin(); esp < boost::prior(parameter_splits_[evolution_variable_].end()); ++esp, ++exp_it) { last_point_[evolution_variable_] = (*esp + *boost::next(esp))/2.; *exp_it = root_cell_.accumulate(parametric_selector_,integral_accessor_,std::plus()); } exp_it = boost::prior(last_exponent_integrand_.end()); double total = 0.; for (std::vector::iterator esp = boost::prior(parameter_splits_[evolution_variable_].end()); esp > parameter_splits_[evolution_variable_].begin(); --esp, --exp_it) { last_exponent_->second.set_interpolation(*esp,total); total += (*exp_it) * ((*esp) - (*boost::prior(esp))); } last_exponent_->second.set_interpolation(parameter_splits_[evolution_variable_].front(),total); last_point_[evolution_variable_] = old_evo; } template std::set > exponential_generator::parameter_points() { std::set > res; std::vector pt(adaption_info_.dimension,0.); recursive_parameter_points(res,pt,0); return res; } template void exponential_generator:: recursive_parameter_points(std::set >& res, std::vector& pt, size_t current) { if ( current == adaption_info_.dimension ) { res.insert(pt); return; } if ( sample_variables_[current] ) { recursive_parameter_points(res,pt,current+1); return; } for ( std::vector::const_iterator sp = parameter_splits_[current].begin(); sp != boost::prior(parameter_splits_[current].end()); ++sp ) { pt[current] = (*sp + *boost::next(sp))/2.; recursive_parameter_points(res,pt,current+1); } } template void exponential_generator::compensate() { if (!did_split_ || !docompensate_) { assert(did_split_ || last_cell_ == root_cell_.begin()); exponents_.clear(); last_cell_->info().overestimate(last_value_,last_point_); last_cell_->integral(last_cell_->info().volume() * last_cell_->info().overestimate()); last_point_ = function_->parameter_point(); get_exponent(); return; } std::vector themaxpoint = last_point_; std::set > id_points = parameter_points(); for ( std::set >::const_iterator id = id_points.begin(); id != id_points.end(); ++id ) { last_point_ = *id; get_exponent(); } std::map,linear_interpolator > old_exponents = exponents_; double old_oe = last_cell_->info().overestimate(); last_cell_->info().overestimate(last_value_,themaxpoint); last_cell_->integral(last_cell_->info().volume() * last_cell_->info().overestimate()); exponents_.clear(); for ( std::set >::const_iterator id = id_points.begin(); id != id_points.end(); ++id ) { last_point_ = *id; get_exponent(); std::map,linear_interpolator >::iterator old_exp = old_exponents.find(last_parameter_bin_); std::map,linear_interpolator >::iterator new_exp = exponents_.find(last_parameter_bin_); assert(old_exp != old_exponents.end() && new_exp != exponents_.end()); double old_norm = 1. - std::exp(-(old_exp->second)(adaption_info_.lower_left[evolution_variable_])); double new_norm = 1. - std::exp(-(new_exp->second)(adaption_info_.lower_left[evolution_variable_])); for (binary_tree::iterator it = root_cell_.begin(); it != root_cell_.end(); ++it) { if ( !it->info().contains_parameter(last_point_,sample_variables_) ) continue; double old_int = 0.; double new_int = 0.; for ( std::vector::const_iterator sp = parameter_splits_[evolution_variable_].begin(); sp != boost::prior(parameter_splits_[evolution_variable_].end()); ++sp ) { if ( *sp >= it->info().lower_left()[evolution_variable_] && *sp < it->info().upper_right()[evolution_variable_] ) { double xl = *sp; double xxl = *boost::next(sp); double old_al = (old_exp->second.interpolation()[xxl] - old_exp->second.interpolation()[xl]) / (xxl-xl); double old_bl = (xxl * old_exp->second.interpolation()[xl] - xl * old_exp->second.interpolation()[xxl]) / (xxl-xl); double new_al = (new_exp->second.interpolation()[xxl] - new_exp->second.interpolation()[xl]) / (xxl-xl); double new_bl = (xxl * new_exp->second.interpolation()[xl] - xl * new_exp->second.interpolation()[xxl]) / (xxl-xl); if ( std::abs(old_al) > std::numeric_limits::epsilon() ) { old_int += (exp(-(old_al*xl+old_bl)) - exp(-(old_al*xxl+old_bl)))/old_al; } else { old_int += (xxl-xl)*exp(-old_bl); } if ( std::abs(new_al) > std::numeric_limits::epsilon() ) { new_int += (exp(-(new_al*xl+new_bl)) - exp(-(new_al*xxl+new_bl)))/new_al; } else { new_int += (xxl-xl)*exp(-new_bl); } } } double scaling; if (it != last_cell_) { if (old_int > std::numeric_limits::epsilon() && new_int > std::numeric_limits::epsilon()) scaling = ((old_norm * new_int) / (new_norm * old_int)) - 1.; else scaling = 0.; } else { if (old_int > std::numeric_limits::epsilon() && new_int > std::numeric_limits::epsilon()) scaling = ((last_value_ * old_norm * new_int) / (old_oe * new_norm * old_int)) - 1.; else scaling = 0.; } it->info().parametric_missing(last_parameter_bin_, it->info().parametric_missing(last_parameter_bin_) + static_cast(round(scaling * it->info().attempted()))); if (it->info().parametric_missing(last_parameter_bin_) != 0) { compensating_ = true; } } } last_point_ = function_->parameter_point(); } template double exponential_generator::generate () { if (compensating_) { compensating_ = false; for (binary_tree::iterator it = root_cell_.begin(); it != root_cell_.end(); ++it) if (it->info().parametric_compensating()) { compensating_ = true; break; } parametric_sampler_.compensate(compensating_); } last_point_ = function_->parameter_point(); if (last_point_[evolution_variable_] < evolution_cutoff_) { return 0.; } unsigned long n_hit_miss = 0; unsigned long n_select = 0; double minus_log_r; root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus()); get_exponent(); while (true) { n_select = 0; minus_log_r = -std::log(rnd_gen_()) + last_exponent_->second(last_point_[evolution_variable_]); if (!last_exponent_->second.invertible(minus_log_r)) { return 0.; } try { last_point_[evolution_variable_] = last_exponent_->second.unique_inverse(minus_log_r); } catch (constant_interpolation& c) { last_point_[evolution_variable_] = rnd_gen_(c.range.first,c.range.second); } assert(!std::isnan(last_point_[evolution_variable_]) && !std::isinf(last_point_[evolution_variable_])); if (last_point_[evolution_variable_] < evolution_cutoff_) { return 0.; } ++attempts_; if (compensating_) { root_cell_.tree_accumulate(missing_accessor_,std::plus()); } if (parameter_splits_[evolution_variable_].size() > 2) root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus()); if (did_split_) while ((last_cell_ = root_cell_.select(parametric_sampler_)) == root_cell_.end()) { root_cell_.tree_accumulate(missing_accessor_,std::plus()); if(++n_select > adaption_info_.maxtry) throw selection_maxtry(); } else last_cell_ = root_cell_.begin(); last_cell_->info().select(rnd_gen_,last_point_,sample_other_variables_); last_value_ = function_->evaluate(last_point_); assert(last_value_ >= 0.); last_cell_->info().selected(last_point_,last_value_,adaption_info_); if (last_value_ > last_cell_->info().overestimate()) { if ( std::abs(last_value_)/last_cell_->info().overestimate() > 2. ) { last_value_ = last_cell_->info().overestimate()* (1.+exp(2.*(2.-std::abs(last_value_)/last_cell_->info().overestimate()))); } compensate(); throw exponential_regenerate(); } if (last_cell_->info().attempted() % check_events_ == 0) { if (split()) { throw exponential_regenerate(); } } - if (last_value_/last_cell_->info().overestimate() > rnd_gen_()) + if (last_value_/last_cell_->info().overestimate() > rnd_gen_()) { + function_->accept(last_point_,last_value_,last_cell_->info().overestimate()); break; + } + if ( last_value_ != 0.0 ) { + function_->veto(last_point_,last_value_,last_cell_->info().overestimate()); + } if(++n_hit_miss > adaption_info_.maxtry) throw hit_and_miss_maxtry(); } if (last_value_ == 0.) return 0.; ++accepts_; ++check_events_; last_cell_->info().accept(); return 1.; } template template void exponential_generator::put (OStream& os) const { os << check_events_; ostream_traits::separator(os); adaption_info_.put(os); root_cell_.put(os); os << did_split_; ostream_traits::separator(os); os << initialized_; ostream_traits::separator(os); os << evolution_variable_; ostream_traits::separator(os); os << evolution_cutoff_; ostream_traits::separator(os); os << sample_variables_; ostream_traits::separator(os); os << sample_other_variables_; ostream_traits::separator(os); os << parameter_splits_; ostream_traits::separator(os); // last_cell_ is selected new so we ignore it here os << last_point_; ostream_traits::separator(os); os << last_value_; ostream_traits::separator(os); last_parameter_bin_.put(os); os << exponents_.size(); ostream_traits::separator(os); for ( std::map,linear_interpolator >::const_iterator ex = exponents_.begin(); ex != exponents_.end() ; ++ex ) { ex->first.put(os); ex->second.put(os); } os << last_exponent_integrand_; ostream_traits::separator(os); os << compensating_; ostream_traits::separator(os); os << attempts_; ostream_traits::separator(os); os << accepts_; ostream_traits::separator(os); os << splits_; ostream_traits::separator(os); os << docompensate_; ostream_traits::separator(os); } template template void exponential_generator::get (IStream& is) { is >> check_events_; adaption_info_.get(is); root_cell_.get(is); is >> did_split_ >> initialized_ >> evolution_variable_ >> evolution_cutoff_ >> sample_variables_ >> sample_other_variables_ >> parameter_splits_; // last_cell_ is selected new so we ignore it here is >> last_point_ >> last_value_; last_parameter_bin_.get(is); size_t dim; is >> dim; for ( size_t k = 0; k < dim ; ++k ) { bit_container key; key.get(is); exponents_[key].get(is); } is >> last_exponent_integrand_; last_exponent_ = exponents_.find(last_parameter_bin_); is >> compensating_ >> attempts_ >> accepts_ >> splits_ >> docompensate_; } } diff --git a/Shower/Base/SudakovFormFactor.cc b/Shower/Base/SudakovFormFactor.cc --- a/Shower/Base/SudakovFormFactor.cc +++ b/Shower/Base/SudakovFormFactor.cc @@ -1,326 +1,344 @@ // -*- C++ -*- // // SudakovFormFactor.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SudakovFormFactor class. // #include "SudakovFormFactor.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ShowerKinematics.h" #include "ShowerParticle.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Shower/ShowerHandler.h" using namespace Herwig; DescribeAbstractClass describeSudakovFormFactor ("Herwig::SudakovFormFactor",""); void SudakovFormFactor::persistentOutput(PersistentOStream & os) const { os << splittingFn_ << alpha_ << pdfmax_ << particles_ << pdffactor_ << a_ << b_ << ounit(c_,GeV) << ounit(kinCutoffScale_,GeV) << cutOffOption_ << ounit(vgcut_,GeV) << ounit(vqcut_,GeV) << ounit(pTmin_,GeV) << ounit(pT2min_,GeV2) << theFactorizationScaleFactor << theRenormalizationScaleFactor; } void SudakovFormFactor::persistentInput(PersistentIStream & is, int) { is >> splittingFn_ >> alpha_ >> pdfmax_ >> particles_ >> pdffactor_ >> a_ >> b_ >> iunit(c_,GeV) >> iunit(kinCutoffScale_,GeV) >> cutOffOption_ >> iunit(vgcut_,GeV) >> iunit(vqcut_,GeV) >> iunit(pTmin_,GeV) >> iunit(pT2min_,GeV2) >> theFactorizationScaleFactor >> theRenormalizationScaleFactor; } void SudakovFormFactor::Init() { static ClassDocumentation documentation ("The SudakovFormFactor class is the base class for the implementation of Sudakov" " form factors in Herwig"); static Reference interfaceSplittingFunction("SplittingFunction", "A reference to the SplittingFunction object", &Herwig::SudakovFormFactor::splittingFn_, false, false, true, false); static Reference interfaceAlpha("Alpha", "A reference to the Alpha object", &Herwig::SudakovFormFactor::alpha_, false, false, true, false); static Parameter interfacePDFmax ("PDFmax", "Maximum value of PDF weight. ", &SudakovFormFactor::pdfmax_, 35.0, 1.0, 100000.0, false, false, Interface::limited); static Switch interfacePDFFactor ("PDFFactor", "Include additional factors in the overestimate for the PDFs", &SudakovFormFactor::pdffactor_, 0, false, false); static SwitchOption interfacePDFFactorOff (interfacePDFFactor, "Off", "Don't include any factors", 0); static SwitchOption interfacePDFFactorOverZ (interfacePDFFactor, "OverZ", "Include an additional factor of 1/z", 1); static SwitchOption interfacePDFFactorOverOneMinusZ (interfacePDFFactor, "OverOneMinusZ", "Include an additional factor of 1/(1-z)", 2); static SwitchOption interfacePDFFactorOverZOneMinusZ (interfacePDFFactor, "OverZOneMinusZ", "Include an additional factor of 1/z/(1-z)", 3); static Switch interfaceCutOffOption ("CutOffOption", "The type of cut-off to use to end the shower", &SudakovFormFactor::cutOffOption_, 0, false, false); static SwitchOption interfaceCutOffOptionDefault (interfaceCutOffOption, "Default", "Use the standard Herwig cut-off on virtualities with the minimum" " virtuality depending on the mass of the branching particle", 0); static SwitchOption interfaceCutOffOptionFORTRAN (interfaceCutOffOption, "FORTRAN", "Use a FORTRAN-like cut-off on virtualities", 1); static SwitchOption interfaceCutOffOptionpT (interfaceCutOffOption, "pT", "Use a cut on the minimum allowed pT", 2); static Parameter interfaceaParameter ("aParameter", "The a parameter for the kinematic cut-off", &SudakovFormFactor::a_, 0.3, -10.0, 10.0, false, false, Interface::limited); static Parameter interfacebParameter ("bParameter", "The b parameter for the kinematic cut-off", &SudakovFormFactor::b_, 2.3, -10.0, 10.0, false, false, Interface::limited); static Parameter interfacecParameter ("cParameter", "The c parameter for the kinematic cut-off", &SudakovFormFactor::c_, GeV, 0.3*GeV, 0.1*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceKinScale ("cutoffKinScale", "kinematic cutoff scale for the parton shower phase" " space (unit [GeV])", &SudakovFormFactor::kinCutoffScale_, GeV, 2.3*GeV, 0.001*GeV, 10.0*GeV,false,false,false); static Parameter interfaceGluonVirtualityCut ("GluonVirtualityCut", "For the FORTRAN cut-off option the minimum virtuality of the gluon", &SudakovFormFactor::vgcut_, GeV, 0.85*GeV, 0.1*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceQuarkVirtualityCut ("QuarkVirtualityCut", "For the FORTRAN cut-off option the minimum virtuality added to" " the mass for particles other than the gluon", &SudakovFormFactor::vqcut_, GeV, 0.85*GeV, 0.1*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfacepTmin ("pTmin", "The minimum pT if using a cut-off on the pT", &SudakovFormFactor::pTmin_, GeV, 1.0*GeV, ZERO, 10.0*GeV, false, false, Interface::limited); } bool SudakovFormFactor::alphaSVeto(Energy2 pt2) const { - pt2 *= sqr(renormalizationScaleFactor()); - return UseRandom::rnd() > ThePEG::Math::powi(alpha_->ratio(pt2), - splittingFn_->interactionOrder()); + double ratio=alphaSVetoRatio(pt2,1.); + return UseRandom::rnd() > ratio; } -bool SudakovFormFactor:: -PDFVeto(const Energy2 t, const double x, +double SudakovFormFactor::alphaSVetoRatio(Energy2 pt2, double factor) const { + factor *= renormalizationScaleFactor(); + return ThePEG::Math::powi(alpha_->ratio(pt2, factor), + splittingFn_->interactionOrder()); +} + + +bool SudakovFormFactor::PDFVeto(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, Ptr::transient_const_pointer beam) const { + double ratio=PDFVetoRatio(t,x,parton0,parton1,beam,1.); + return UseRandom::rnd() > ratio; +} + +double SudakovFormFactor::PDFVetoRatio(const Energy2 t, const double x, + const tcPDPtr parton0, const tcPDPtr parton1, + Ptr::transient_const_pointer beam,double factor) const { assert(pdf_); - Energy2 theScale = t * sqr(factorizationScaleFactor()); + Energy2 theScale = t * sqr(factorizationScaleFactor()*factor); if (theScale < sqr(freeze_)) theScale = sqr(freeze_); double newpdf(0.0), oldpdf(0.0); - //different treatment of MPI ISR is done via CascadeHandler::resetPDFs() + newpdf=pdf_->xfx(beam,parton0,theScale,x/z()); oldpdf=pdf_->xfx(beam,parton1,theScale,x); + if(newpdf<=0.) return 0.; + if(oldpdf<=0.) return 1.; - if(newpdf<=0.) return true; - if(oldpdf<=0.) return false; double ratio = newpdf/oldpdf; + double maxpdf = pdfmax_; - double maxpdf(pdfmax_); switch (pdffactor_) { case 1: maxpdf /= z(); break; case 2: maxpdf /= 1.-z(); break; case 3: maxpdf /= (z()*(1.-z())); break; } - // ratio / PDFMax must be a probability <= 1.0 if (ratio > maxpdf) { - generator()->log() << "PDFVeto warning: Ratio > " << name() - << ":PDFmax (by a factor of " - << ratio/maxpdf <<") for " - << parton0->PDGName() << " to " - << parton1->PDGName() << "\n"; + generator()->log() << "PDFVeto warning: Ratio > " << name() + << ":PDFmax (by a factor of " + << ratio/maxpdf <<") for " + << parton0->PDGName() << " to " + << parton1->PDGName() << "\n"; } - return ratio < UseRandom::rnd()*maxpdf; + return ratio/maxpdf ; } + + + + + + + void SudakovFormFactor::addSplitting(const IdList & in) { bool add=true; for(unsigned int ix=0;ix::iterator it=particles_.begin(); it!=particles_.end();++it) { if(it->size()==in.size()) { bool match=true; for(unsigned int iy=0;iy::iterator itemp=it; --itemp; particles_.erase(it); it = itemp; } } } } Energy2 SudakovFormFactor::guesst(Energy2 t1,unsigned int iopt, const IdList &ids, double enhance,bool ident) const { unsigned int pdfopt = iopt!=1 ? 0 : pdffactor_; double c = 1./((splittingFn_->integOverP(zlimits_.second,ids,pdfopt) - splittingFn_->integOverP(zlimits_.first ,ids,pdfopt))* alpha_->overestimateValue()/Constants::twopi*enhance); assert(iopt<=2); if(iopt==1) { c/=pdfmax_; //symmetry of FS gluon splitting if(ident) c*=0.5; } else if(iopt==2) c*=-1.; if(splittingFn_->interactionOrder()==1) { double r = UseRandom::rnd(); if(iopt!=2 || c*log(r)interactionOrder()-1); c/=Math::powi(alpha_->overestimateValue()/Constants::twopi,nm); return t1 / pow (1. - nm*c*log(UseRandom::rnd()) * Math::powi(t1*UnitRemoval::InvE2,nm) ,1./double(nm)); } } double SudakovFormFactor::guessz (unsigned int iopt, const IdList &ids) const { unsigned int pdfopt = iopt!=1 ? 0 : pdffactor_; double lower = splittingFn_->integOverP(zlimits_.first,ids,pdfopt); return splittingFn_->invIntegOverP (lower + UseRandom::rnd()*(splittingFn_->integOverP(zlimits_.second,ids,pdfopt) - lower),ids,pdfopt); } void SudakovFormFactor::doinit() { Interfaced::doinit(); pT2min_ = cutOffOption()==2 ? sqr(pTmin_) : ZERO; } const vector & SudakovFormFactor::virtualMasses(const IdList & ids) { static vector output; output.clear(); if(cutOffOption() == 0) { for(unsigned int ix=0;ixmass()); Energy kinCutoff= kinematicCutOff(kinScale(),*std::max_element(output.begin(),output.end())); for(unsigned int ix=0;ixmass()); output.back() += ids[ix]->id()==ParticleID::g ? vgCut() : vqCut(); } } else if(cutOffOption() == 2) { for(unsigned int ix=0;ixmass()); } else { throw Exception() << "Unknown option for the cut-off" << " in SudakovFormFactor::virtualMasses()" << Exception::runerror; } return output; } diff --git a/Shower/Base/SudakovFormFactor.h b/Shower/Base/SudakovFormFactor.h --- a/Shower/Base/SudakovFormFactor.h +++ b/Shower/Base/SudakovFormFactor.h @@ -1,693 +1,718 @@ // -*- C++ -*- // // SudakovFormFactor.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_SudakovFormFactor_H #define HERWIG_SudakovFormFactor_H // // This is the declaration of the SudakovFormFactor class. // #include "ThePEG/Interface/Interfaced.h" #include "Herwig/Shower/SplittingFunctions/SplittingFunction.h" #include "Herwig/Shower/Couplings/ShowerAlpha.h" #include "Herwig/Shower/SplittingFunctions/SplittingGenerator.fh" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ThePEG/EventRecord/RhoDMatrix.h" #include "ThePEG/EventRecord/SpinInfo.h" #include "ShowerKinematics.fh" #include "SudakovFormFactor.fh" namespace Herwig { using namespace ThePEG; /** * A typedef for the BeamParticleData */ typedef Ptr::transient_const_pointer tcBeamPtr; /** \ingroup Shower * * This is the definition of the Sudakov form factor class. In general this * is the base class for the implementation of Sudakov form factors in Herwig. * The methods generateNextTimeBranching(), generateNextDecayBranching() and * generateNextSpaceBranching need to be implemented in classes inheriting from this * one. * * In addition a number of methods are implemented to assist with the calculation * of the form factor using the veto algorithm in classes inheriting from this one. * * In general the Sudakov form-factor, for final-state radiation, is given * by * \f[\Delta_{ba}(\tilde{q}_{i+1},\tilde{q}_i)= * \exp\left\{ * -\int^{\tilde{q}^2_i}_{\tilde{q}^2_{i+1}} * \frac{{\rm d}\tilde{q}^2}{\tilde{q}^2} * \int\frac{\alpha_S(z,\tilde{q})}{2\pi} * P_{ba}(z,\tilde{q})\Theta(p_T) * \right\}. * \f] * We can solve this to obtain the next value of the scale \f$\tilde{q}_{i+1}\f$ * given the previous value \f$\tilde{q}_i\f$ * in the following way. First we obtain a simplified form of the integrand * which is greater than or equal to the true integrand for all values of * \f$\tilde{q}\f$. * * In practice it is easiest to obtain this over estimate in pieces. The ShowerAlpha * object contains an over estimate for \f$\alpha_S\f$, the splitting function * contains both an over estimate of the spltting function and its integral * which is needed to compute the over estimate of the \f$\tilde{q}\f$ integrand, * together with an over estimate of the limit of the \f$z\f$ integral. * * This gives an overestimate of the integrand * \f[g(\tilde{q}^2) = \frac{c}{\tilde{q}^2}, \f] * where because the over estimates are chosen to be independent of \f$\tilde{q}\f$ the * parameter * \f[c = \frac{\alpha_{\rm over}}{2\pi}\int^{z_1}_{z_0}P_{\rm over}(z),\f] * is a constant independent of \f$\tilde{q}\f$. * * The guesst() member can then be used to generate generate the value of * \f$\tilde{q}^2\f$ according to this result. This is done by solving the Sudakov * form factor, with the over estimates, is equal to a random number * \f$r\f$ in the interval \f$[0,1]\f$. This gives * \f[\tilde{q}^2_{i+1}=G^{-1}\left[G(\tilde{q}^2_i)+\ln r\right],\f] * where \f$G(\tilde{q}^2)=c\ln(\tilde{q}^2)\f$ is the infinite integral * of \f$g(\tilde{q}^2)\f$ and \f$G^{-1}(x)=\exp\left(\frac{x}c\right)\f$ * is its inverse. * It this case we therefore obtain * \f[\tilde{q}^2_{i+1}=\tilde{q}^2_ir^{\frac1c}.\f] * The value of \f$z\f$ can then be calculated in a similar way * \f[z = I^{-1}\left[I(z_0)+r\left(I(z_1)-I(z_0)\right)\right],\f] * using the guessz() member, * where \f$I=\int P(z){\rm d}z\f$ and \f$I^{-1}\f$ is its inverse. * * The veto algorithm then uses rejection using the ratio of the * true value to the overestimated one to obtain the original distribution. * This is accomplished using the * - alphaSVeto() member for the \f$\alpha_S\f$ veto * - SplittingFnVeto() member for the veto on the value of the splitting function. * in general there must also be a chech that the emission is in the allowed * phase space but this is left to the inheriting classes as it will depend * on the ordering variable. * * The Sudakov form factor for the initial-scale shower is different because * it must include the PDF which guides the backward evolution. * It is given by * \f[\Delta_{ba}(\tilde{q}_{i+1},\tilde{q}_i)= * \exp\left\{ * -\int^{\tilde{q}^2_i}_{\tilde{q}^2_{i+1}} * \frac{{\rm d}\tilde{q}^2}{\tilde{q}^2} * \int\frac{\alpha_S(z,\tilde{q})}{2\pi} * P_{ba}(z,\tilde{q})\frac{x'f_a(\frac{x}z,\tilde{q}^2)}{xf_b(x,\tilde{q^2})} * \right\}, * \f] * where \f$x\f$ is the fraction of the beam momentum the parton \f$b\f$ had before * the backward evolution. * This can be solve in the same way as for the final-state branching but the constant * becomes * \f[c = \frac{\alpha_{\rm over}}{2\pi}\int^{z_1}_{z_0}P_{\rm over}(z)PDF_{\rm max},\f] * where * \f[PDF_{\rm max}=\max\frac{x'f_a(\frac{x}z,\tilde{q}^2)}{xf_b(x,\tilde{q^2})},\f] * which can be set using an interface. * In addition the PDFVeto() member then is needed to implement the relevant veto. * * @see SplittingGenerator * @see SplittingFunction * @see ShowerAlpha * @see \ref SudakovFormFactorInterfaces "The interfaces" * defined for SudakovFormFactor. */ class SudakovFormFactor: public Interfaced { /** * The SplittingGenerator is a friend to insert the particles in the * branchings at initialisation */ friend class SplittingGenerator; public: /** * The default constructor. */ SudakovFormFactor() : pdfmax_(35.0), pdffactor_(0), cutOffOption_(0), a_(0.3), b_(2.3), c_(0.3*GeV), kinCutoffScale_( 2.3*GeV ), vgcut_(0.85*GeV), vqcut_(0.85*GeV), pTmin_(1.*GeV), pT2min_(ZERO), z_( 0.0 ),phi_(0.0), pT_(), theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0) {} /** * Members to generate the scale of the next branching */ //@{ /** * Return the scale of the next time-like branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param ids The PDG codes of the particles in the splitting * @param enhance The radiation enhancement factor * @param maxQ2 The maximum \f$Q^2\f$ for the emission */ virtual ShoKinPtr generateNextTimeBranching(const Energy startingScale, const IdList &ids, const RhoDMatrix & rho, double enhance, Energy2 maxQ2)=0; /** * Return the scale of the next space-like decay branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param stoppingScale stopping scale for the evolution * @param minmass The minimum mass allowed for the spake-like particle. * @param ids The PDG codes of the particles in the splitting * defined. * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale, const Energy stoppingScale, const Energy minmass, const IdList &ids, const RhoDMatrix & rho, double enhance)=0; /** * Return the scale of the next space-like branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param ids The PDG codes of the particles in the splitting * @param x The fraction of the beam momentum * defined. * @param beam The beam particle * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextSpaceBranching(const Energy startingScale, const IdList &ids,double x, const RhoDMatrix & rho, double enhance, tcBeamPtr beam)=0; //@} /** * Generate the azimuthal angle of the branching for forward evolution * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiForward(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho)=0; /** * Generate the azimuthal angle of the branching for backward evolution * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiBackward(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho)=0; /** * Generate the azimuthal angle of the branching for ISR in decays * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiDecay(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho)=0; /** * Methods to provide public access to the private member variables */ //@{ /** * Return the pointer to the SplittingFunction object. */ tSplittingFnPtr splittingFn() const { return splittingFn_; } /** * Return the pointer to the ShowerAlpha object. */ tShowerAlphaPtr alpha() const { return alpha_; } /** * The type of interaction */ inline ShowerInteraction::Type interactionType() const {return splittingFn_->interactionType();} //@} public: /** * Methods to access the kinematic variables for the branching */ //@{ /** * The energy fraction */ double z() const { return z_; } /** * The azimuthal angle */ double phi() const { return phi_; } /** * The transverse momentum */ Energy pT() const { return pT_; } //@} /** * Access the maximum weight for the PDF veto */ double pdfMax() const { return pdfmax_;} /** * Method to return the evolution scale given the * transverse momentum, \f$p_T\f$ and \f$z\f$. */ virtual Energy calculateScale(double z, Energy pt, IdList ids,unsigned int iopt)=0; /** * Method to create the ShowerKinematics object for a final-state branching */ virtual ShoKinPtr createFinalStateBranching(Energy scale,double z, double phi, Energy pt)=0; /** * Method to create the ShowerKinematics object for an initial-state branching */ virtual ShoKinPtr createInitialStateBranching(Energy scale,double z, double phi, Energy pt)=0; /** * Method to create the ShowerKinematics object for a decay branching */ virtual ShoKinPtr createDecayBranching(Energy scale,double z, double phi, Energy pt)=0; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** * Methods to implement the veto algorithm to generate the scale of * the next branching */ //@{ /** * Value of the energy fraction for the veto algorithm * @param iopt The option for calculating z * @param ids The PDG codes of the particles in the splitting * - 0 is final-state * - 1 is initial-state for the hard process * - 2 is initial-state for particle decays */ double guessz (unsigned int iopt, const IdList &ids) const; /** * Value of the scale for the veto algorithm * @param t1 The starting valoe of the scale * @param iopt The option for calculating t * @param ids The PDG codes of the particles in the splitting * - 0 is final-state * - 1 is initial-state for the hard process * - 2 is initial-state for particle decays * @param enhance The radiation enhancement factor * @param identical Whether or not the outgoing particles are identical */ Energy2 guesst (Energy2 t1,unsigned int iopt, const IdList &ids, double enhance, bool identical) const; /** * Veto on the PDF for the initial-state shower * @param t The scale * @param x The fraction of the beam momentum * @param parton0 Pointer to the particleData for the * new parent (this is the particle we evolved back to) * @param parton1 Pointer to the particleData for the * original particle * @param beam The BeamParticleData object */ bool PDFVeto(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, tcBeamPtr beam) const; + /** + * The PDF veto ratio + */ + double PDFVetoRatio(const Energy2 t, const double x, + const tcPDPtr parton0, const tcPDPtr parton1, + tcBeamPtr beam,double factor) const; /** * The veto on the splitting function. * @param t The scale * @param ids The PDG codes of the particles in the splitting * @param mass Whether or not to use the massive splitting functions * @return true if vetoed */ bool SplittingFnVeto(const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix & rho) const { return UseRandom::rnd()>splittingFn_->ratioP(z_, t, ids,mass,rho); } + + /** + * The Splitting function veto ratio + */ + + double SplittingFnVetoRatio(const Energy2 t, + const IdList &ids, + const bool mass, + const RhoDMatrix & rho) const { + return splittingFn_->ratioP(z_, t, ids,mass,rho); + } /** * The veto on the coupling constant * @param pt2 The value of ther transverse momentum squared, \f$p_T^2\f$. * @return true if vetoed */ bool alphaSVeto(Energy2 pt2) const; + + /** + * The alpha S veto ratio + */ + + double alphaSVetoRatio(Energy2 pt2,double factor) const; + + //@} /** * Methods to set the kinematic variables for the branching */ //@{ /** * The energy fraction */ void z(double in) { z_=in; } /** * The azimuthal angle */ void phi(double in) { phi_=in; } /** * The transverse momentum */ void pT(Energy in) { pT_=in; } //@} /** * Set/Get the limits on the energy fraction for the splitting */ //@{ /** * Get the limits */ pair zLimits() const { return zlimits_;} /** * Set the limits */ void zLimits(pair in) { zlimits_=in; } //@} /** * Set the particles in the splittings */ void addSplitting(const IdList &); /** * Delete the particles in the splittings */ void removeSplitting(const IdList &); /** * Access the potential branchings */ const vector & particles() const { return particles_; } public: /** * @name Methods for the cut-off */ //@{ /** * The option being used */ unsigned int cutOffOption() const { return cutOffOption_; } /** * The kinematic scale */ Energy kinScale() const {return kinCutoffScale_;} /** * The virtuality cut-off on the gluon \f$Q_g=\frac{\delta-am_q}{b}\f$ * @param scale The scale \f$\delta\f$ * @param mq The quark mass \f$m_q\f$. */ Energy kinematicCutOff(Energy scale, Energy mq) const {return max((scale -a_*mq)/b_,c_);} /** * The virtualilty cut-off for gluons */ Energy vgCut() const { return vgcut_; } /** * The virtuality cut-off for everything else */ Energy vqCut() const { return vqcut_; } /** * The minimum \f$p_T\f$ for the branching */ Energy pTmin() const { return pTmin_; } /** * The square of the minimum \f$p_T\f$ */ Energy2 pT2min() const { return pT2min_; } /** * Calculate the virtual masses for a branchings */ const vector & virtualMasses(const IdList & ids); //@} /** * Set the PDF */ void setPDF(tcPDFPtr pdf, Energy scale) { pdf_ = pdf; freeze_ = scale; } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SudakovFormFactor & operator=(const SudakovFormFactor &); private: /** * Pointer to the splitting function for this Sudakov form factor */ SplittingFnPtr splittingFn_; /** * Pointer to the coupling for this Sudakov form factor */ ShowerAlphaPtr alpha_; /** * Maximum value of the PDF weight */ double pdfmax_; /** * List of the particles this Sudakov is used for to aid in setting up * interpolation tables if needed */ vector particles_; /** * Option for the inclusion of a factor \f$1/(1-z)\f$ in the PDF estimate */ unsigned pdffactor_; private: /** * Option for the type of cut-off to be applied */ unsigned int cutOffOption_; /** * Parameters for the default Herwig cut-off option, i.e. the parameters for * the \f$Q_g=\max(\frac{\delta-am_q}{b},c)\f$ kinematic cut-off */ //@{ /** * The \f$a\f$ parameter */ double a_; /** * The \f$b\f$ parameter */ double b_; /** * The \f$c\f$ parameter */ Energy c_; /** * Kinematic cutoff used in the parton shower phase space. */ Energy kinCutoffScale_; //@} /** * Parameters for the FORTRAN-like cut-off */ //@{ /** * The virtualilty cut-off for gluons */ Energy vgcut_; /** * The virtuality cut-off for everything else */ Energy vqcut_; //@} /** * Parameters for the \f$p_T\f$ cut-off */ //@{ /** * The minimum \f$p_T\f$ for the branching */ Energy pTmin_; /** * The square of the minimum \f$p_T\f$ */ Energy2 pT2min_; //@} private: /** * Member variables to keep the shower kinematics information * generated by a call to generateNextTimeBranching or generateNextSpaceBranching */ //@{ /** * The energy fraction */ double z_; /** * The azimuthal angle */ double phi_; /** * The transverse momentum */ Energy pT_; //@} /** * The limits of \f$z\f$ in the splitting */ pair zlimits_; /** * Stuff for the PDFs */ //@{ /** * PDf */ tcPDFPtr pdf_; /** * Freezing scale */ Energy freeze_; //@} public: /** * Get the factorization scale factor */ double factorizationScaleFactor() const { return theFactorizationScaleFactor; } /** * Set the factorization scale factor */ void factorizationScaleFactor(double f) { theFactorizationScaleFactor = f; } /** * Get the renormalization scale factor */ double renormalizationScaleFactor() const { return theRenormalizationScaleFactor; } /** * Set the renormalization scale factor */ void renormalizationScaleFactor(double f) { theRenormalizationScaleFactor = f; } private: /** * The factorization scale factor. */ double theFactorizationScaleFactor; /** * The renormalization scale factor. */ double theRenormalizationScaleFactor; }; } #endif /* HERWIG_SudakovFormFactor_H */ diff --git a/Shower/Couplings/ShowerAlpha.h b/Shower/Couplings/ShowerAlpha.h --- a/Shower/Couplings/ShowerAlpha.h +++ b/Shower/Couplings/ShowerAlpha.h @@ -1,150 +1,150 @@ // -*- C++ -*- // // ShowerAlpha.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ShowerAlpha_H #define HERWIG_ShowerAlpha_H // // This is the declaration of the ShowerAlpha class. // #include "ThePEG/Interface/Interfaced.h" #include "ShowerAlpha.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This class is the abstract class from which all types of running couplings * used in the Showering derive from. * The main purpose of this class, and the ones that derive from it, is * to allow systematic uncertainties for the initial-state radiation and, * independently, the final-state radiation effects, to be evaluated. * * This is achieved by allowing a multiplicative factor, * which is 1.0 for the "central value", * for the scale argument, \f$\mu^2\f$, of the running coupling. This * factor, \f$f\f$ is given by the scaleFactor() member and the coupling * returned by the value() member is such that * \f[\alpha(\mu^2)\to \alpha(f\times\mu^2).\f] * This scale factor is a parameter which is settable by the user, via the * interface. * Although, of course, it is not clear my how much we should scale * in order to get a \f$1\sigma\f$ systematic error (but factors: * 1/2 and 2 are quite common), this method provides a double side error, * and it appears more sensible than the rough and one-sided evaluation * obtained * via turning off the I.S.R. and/or F.S.R. (possibilities which are, * anyway, provided by Herwig). * * @see \ref ShowerAlphaInterfaces "The interfaces" * defined for ShowerAlpha. */ class ShowerAlpha: public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ ShowerAlpha() : _scaleFactor( 1.0 ) {} //@} public: /** * Methods to return the coupling and the scaleFactor */ //@{ /** * Pure virtual method that is supposed to return the * running alpha value evaluated at the input scale. * @param scale The scale * @return The coupling */ virtual double value(const Energy2 scale) const = 0; /** * Virtual method, which * should be overridden in a derived class to provide an * overestimate approximation of the alpha value. */ virtual double overestimateValue() const = 0; /** * Virtual method which returns the ratio of the running alpha * value at the input scale to the overestimated value. * @param scale The scale * @return The ratio */ - virtual double ratio(const Energy2 scale) const = 0; + virtual double ratio(const Energy2 scale,double factor=1.) const = 0; /** * It returns the factor that multiplies the * scale argument, \f$\mu^2\f$, of the running coupling. * This is supposed to be 1.0 in normal conditions (central values) * whereas different values can be useful for systematics evaluation * for Initial State radiation or Final State radiation effects. */ double scaleFactor() const {return _scaleFactor;} /** * Initialize this coupling. */ virtual void initialize () {} //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerAlpha & operator=(const ShowerAlpha &); private: /** * The scale factor */ double _scaleFactor; }; } #endif /* HERWIG_ShowerAlpha_H */ diff --git a/Shower/Couplings/ShowerAlphaQCD.cc b/Shower/Couplings/ShowerAlphaQCD.cc --- a/Shower/Couplings/ShowerAlphaQCD.cc +++ b/Shower/Couplings/ShowerAlphaQCD.cc @@ -1,453 +1,453 @@ // -*- C++ -*- // // ShowerAlphaQCD.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerAlphaQCD class. // #include "ShowerAlphaQCD.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Config/Constants.h" using namespace Herwig; DescribeClass describeShowerAlphaQCD("Herwig::ShowerAlphaQCD","HwShower.so"); IBPtr ShowerAlphaQCD::clone() const { return new_ptr(*this); } IBPtr ShowerAlphaQCD::fullclone() const { return new_ptr(*this); } void ShowerAlphaQCD::persistentOutput(PersistentOStream & os) const { os << _asType << _asMaxNP << ounit(_qmin,GeV) << _nloop << _lambdaopt << _thresopt << ounit(_lambdain,GeV) << _alphain << _inopt << _tolerance << _maxtry << _alphamin << ounit(_thresholds,GeV) << ounit(_lambda,GeV) << _val0 << ounit(_optInputScale,GeV) << ounit(_quarkMasses,GeV); } void ShowerAlphaQCD::persistentInput(PersistentIStream & is, int) { is >> _asType >> _asMaxNP >> iunit(_qmin,GeV) >> _nloop >> _lambdaopt >> _thresopt >> iunit(_lambdain,GeV) >> _alphain >> _inopt >> _tolerance >> _maxtry >> _alphamin >> iunit(_thresholds,GeV) >> iunit(_lambda,GeV) >> _val0 >> iunit(_optInputScale,GeV) >> iunit(_quarkMasses,GeV); } void ShowerAlphaQCD::Init() { static ClassDocumentation documentation ("This (concrete) class describes the QCD alpha running."); static Switch intAsType ("NPAlphaS", "Behaviour of AlphaS in the NP region", &ShowerAlphaQCD::_asType, 1, false, false); static SwitchOption intAsTypeZero (intAsType, "Zero","zero below Q_min", 1); static SwitchOption intAsTypeConst (intAsType, "Const","const as(qmin) below Q_min", 2); static SwitchOption intAsTypeLin (intAsType, "Linear","growing linearly below Q_min", 3); static SwitchOption intAsTypeQuad (intAsType, "Quadratic","growing quadratically below Q_min", 4); static SwitchOption intAsTypeExx1 (intAsType, "Exx1", "quadratic from AlphaMaxNP down to as(Q_min)", 5); static SwitchOption intAsTypeExx2 (intAsType, "Exx2", "const = AlphaMaxNP below Q_min", 6); // default such that as(qmin) = 1 in the current parametrization. // min = Lambda3 static Parameter intQmin ("Qmin", "Q < Qmin is treated with NP parametrization as of (unit [GeV])," " if negative it is solved for at initialisation such that alpha_S(Qmin)=AlphaMaxNP", &ShowerAlphaQCD::_qmin, GeV, 0.630882*GeV, 0.330445*GeV, 100.0*GeV,false,false,false); static Parameter interfaceAlphaMaxNP ("AlphaMaxNP", "Max value of alpha in NP region, only relevant if NPAlphaS = 5,6", &ShowerAlphaQCD::_asMaxNP, 1.0, 0., 100.0, false, false, Interface::limited); static Parameter interfaceNumberOfLoops ("NumberOfLoops", "The number of loops to use in the alpha_S calculation", &ShowerAlphaQCD::_nloop, 3, 1, 3, false, false, Interface::limited); static Switch interfaceLambdaOption ("LambdaOption", "Option for the calculation of the Lambda used in the simulation from the input" " Lambda_MSbar", &ShowerAlphaQCD::_lambdaopt, false, false, false); static SwitchOption interfaceLambdaOptionfalse (interfaceLambdaOption, "Same", "Use the same value", false); static SwitchOption interfaceLambdaOptionConvert (interfaceLambdaOption, "Convert", "Use the conversion to the Herwig scheme from NPB349, 635", true); static Parameter interfaceLambdaQCD ("LambdaQCD", "Input value of Lambda_MSBar", &ShowerAlphaQCD::_lambdain, MeV, 0.208364*GeV, 100.0*MeV, 500.0*MeV, false, false, Interface::limited); static Parameter interfaceAlphaMZ ("AlphaMZ", "The input value of the strong coupling at the Z mass ", &ShowerAlphaQCD::_alphain, 0.118, 0.1, 0.2, false, false, Interface::limited); static Switch interfaceInputOption ("InputOption", "Option for inputing the initial value of the coupling", &ShowerAlphaQCD::_inopt, true, false, false); static SwitchOption interfaceInputOptionAlphaMZ (interfaceInputOption, "AlphaMZ", "Use the value of alpha at MZ to calculate the coupling", true); static SwitchOption interfaceInputOptionLambdaQCD (interfaceInputOption, "LambdaQCD", "Use the input value of Lambda to calculate the coupling", false); static Parameter interfaceTolerance ("Tolerance", "The tolerance for discontinuities in alphaS at thresholds.", &ShowerAlphaQCD::_tolerance, 1e-10, 1e-20, 1e-4, false, false, Interface::limited); static Parameter interfaceMaximumIterations ("MaximumIterations", "The maximum number of iterations for the Newton-Raphson method to converge.", &ShowerAlphaQCD::_maxtry, 100, 10, 1000, false, false, Interface::limited); static Switch interfaceThresholdOption ("ThresholdOption", "Whether to use the consistuent or normal masses for the thresholds", &ShowerAlphaQCD::_thresopt, true, false, false); static SwitchOption interfaceThresholdOptionCurrent (interfaceThresholdOption, "Current", "Use the current masses", true); static SwitchOption interfaceThresholdOptionConstituent (interfaceThresholdOption, "Constituent", "Use the constitent masses.", false); static Command interfaceValue ("Value", "", &ShowerAlphaQCD::value, false); static Command interfacecheck ("check", "check", &ShowerAlphaQCD::check, false); static Parameter interfaceInputScale ("InputScale", "An optional input scale. MZ will be used if not set.", &ShowerAlphaQCD::_optInputScale, GeV, ZERO, ZERO, 0*GeV, false, false, Interface::lowerlim); static ParVector interfaceQuarkMasses ("QuarkMasses", "The quark masses to be used instead of the masses set in the particle data.", &ShowerAlphaQCD::_quarkMasses, GeV, -1, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); } void ShowerAlphaQCD::doinit() { ShowerAlpha::doinit(); // calculate the value of 5-flavour lambda // evaluate the initial // value of Lambda from alphas if needed using Newton-Raphson if(_inopt) { _lambda[2]=computeLambda(_optInputScale == ZERO ? getParticleData(ParticleID::Z0)->mass() : _optInputScale, _alphain,5); } // otherwise it was an input parameter else{_lambda[2]=_lambdain;} // convert lambda to the Monte Carlo scheme if needed using Constants::pi; if(_lambdaopt) _lambda[2] *=exp(0.5*(67.-3.*sqr(pi)-50./3.)/23.)/sqrt(2.); // compute the threshold matching // top threshold for(int ix=1;ix<4;++ix) { if ( _quarkMasses.empty() ) { if(_thresopt) _thresholds[ix]=getParticleData(ix+3)->mass(); else _thresholds[ix]=getParticleData(ix+3)->constituentMass(); } else { // starting at zero rather than one, cf the other alphas's _thresholds[ix] = _quarkMasses[ix+2]; } } // compute 6 flavour lambda by matching at top mass using Newton Raphson _lambda[3]=computeLambda(_thresholds[3],alphaS(_thresholds[3],_lambda[2],5),6); // bottom threshold // compute 4 flavour lambda by matching at bottom mass using Newton Raphson _lambda[1]=computeLambda(_thresholds[2],alphaS(_thresholds[2],_lambda[2],5),4); // charm threshold // compute 3 flavour lambda by matching at charm mass using Newton Raphson _lambda[0]=computeLambda(_thresholds[1],alphaS(_thresholds[1],_lambda[1],4),3); // if qmin less than zero solve for alphaS(_qmin) = 1. if(_qmin() << "The value of Qmin is less than Lambda_3 in" << " ShowerAlphaQCD::doinit " << Exception::abortnow; Energy high = 10*GeV; while (value(sqr(high))>_asMaxNP) high *=2.; double as; do { _qmin = 0.5*(low+high); as = value(sqr(_qmin)); if(_asMaxNP>as) high = _qmin; else if(_asMaxNP _tolerance ); } // final threshold is qmin _thresholds[0]=_qmin; // value of alphaS at threshold pair nflam = getLamNfTwoLoop(_qmin); _val0 = alphaS(_qmin, nflam.second, nflam.first); // compute the maximum value of as if ( _asType < 5 ) _alphamin = _val0; else _alphamin = max(_asMaxNP, _val0); // check consistency lambda_3 < qmin if(_lambda[0]>_qmin) Throw() << "The value of Qmin is less than Lambda_3 in" << " ShowerAlphaQCD::doinit " << Exception::abortnow; } string ShowerAlphaQCD::check(string args) { doinit(); istringstream argin(args); double Q_low, Q_high; long n_steps; argin >> Q_low >> Q_high >> n_steps; string fname; argin >> fname; cout << "checking alpha_s in range [" << Q_low << "," << Q_high << "] GeV in " << n_steps << " steps.\nResults are written to " << fname << "\n"; double step_width = (Q_high-Q_low)/n_steps; ofstream out (fname.c_str()); for (long k = 0; k <= n_steps; ++k) { Energy Q = Q_low*GeV + k*step_width*GeV; out << (Q/GeV) << " " << value(Q*Q) << "\n"; } return "alpha_s check finished"; } double ShowerAlphaQCD::value(const Energy2 scale) const { Energy q = scaleFactor()*sqrt(scale); double val(0.); // normal case if (q >= _qmin) { pair nflam = getLamNfTwoLoop(q); val = alphaS(q, nflam.second, nflam.first); } // special handling if the scale is less than Qmin else { switch (_asType) { case 1: // flat, zero; the default type with no NP effects. val = 0.; break; case 2: // flat, non-zero alpha_s = alpha_s(q2min). val = _val0; break; case 3: // linear in q val = _val0*q/_qmin; break; case 4: // quadratic in q val = _val0*sqr(q/_qmin); break; case 5: // quadratic in q, starting off at asMaxNP, ending on as(qmin) val = (_val0 - _asMaxNP)*sqr(q/_qmin) + _asMaxNP; break; case 6: // just asMaxNP and constant val = _asMaxNP; break; } } return val; } double ShowerAlphaQCD::overestimateValue() const { return _alphamin; } -double ShowerAlphaQCD::ratio(const Energy2 scale) const { - Energy q = scaleFactor()*sqrt(scale); +double ShowerAlphaQCD::ratio(const Energy2 scale, double factor) const { + Energy q = scaleFactor()*factor*sqrt(scale); double val(0.); // normal case if (q >= _qmin) { pair nflam = getLamNfTwoLoop(q); val = alphaS(q, nflam.second, nflam.first); } // special handling if the scale is less than Qmin else { switch (_asType) { case 1: // flat, zero; the default type with no NP effects. val = 0.; break; case 2: // flat, non-zero alpha_s = alpha_s(q2min). val = _val0; break; case 3: // linear in q val = _val0*q/_qmin; break; case 4: // quadratic in q val = _val0*sqr(q/_qmin); break; case 5: // quadratic in q, starting off at asMaxNP, ending on as(qmin) val = (_val0 - _asMaxNP)*sqr(q/_qmin) + _asMaxNP; break; case 6: // just asMaxNP and constant val = _asMaxNP; break; } } // denominator return val/_alphamin; } string ShowerAlphaQCD::value (string scale) { istringstream readscale(scale); double inScale; readscale >> inScale; Energy theScale = inScale * GeV; initialize(); ostringstream showvalue (""); showvalue << "alpha_s (" << theScale/GeV << " GeV) = " << value (sqr(theScale)); return showvalue.str(); } pair ShowerAlphaQCD::getLamNfTwoLoop(Energy q) const { short nf = 6; // get lambda and nf according to the thresholds if (q < _thresholds[1]) nf = 3; else if (q < _thresholds[2]) nf = 4; else if (q < _thresholds[3]) nf = 5; return pair(nf, _lambda[nf-3]); } Energy ShowerAlphaQCD::computeLambda(Energy match, double alpha, unsigned int nflav) const { Energy lamtest=200.0*MeV; double xtest; unsigned int ntry=0; do { ++ntry; xtest = log(sqr(match/lamtest)); xtest += (alpha-alphaS(match,lamtest,nflav))/derivativealphaS(match,lamtest,nflav); Energy newLambda = match/exp(0.5*xtest); lamtest = newLambda _tolerance && ntry < _maxtry); return lamtest; } double ShowerAlphaQCD::derivativealphaS(Energy q, Energy lam, int nf) const { using Constants::pi; double lx = log(sqr(q/lam)); double b0 = 11. - 2./3.*nf; double b1 = 51. - 19./3.*nf; double b2 = 2857. - 5033./9.*nf + 325./27.*sqr(nf); if(_nloop==1) return -4.*pi/(b0*sqr(lx)); else if(_nloop==2) return -4.*pi/(b0*sqr(lx))*(1.+2.*b1/sqr(b0)/lx*(1.-2.*log(lx))); else return -4.*pi/(b0*sqr(lx))* (1. + 2.*b1/sqr(b0)/lx*(1.-2.*log(lx)) + 4.*sqr(b1)/(sqr(sqr(b0))*sqr(lx))*(1. - 2.*log(lx) + 3.*(sqr(log(lx) - 0.5)+b2*b0/(8.*sqr(b1))-1.25))); } double ShowerAlphaQCD::alphaS(Energy q, Energy lam, int nf) const { using Constants::pi; double lx(log(sqr(q/lam))); double b0 = 11. - 2./3.*nf; double b1 = 51. - 19./3.*nf; double b2 = 2857. - 5033./9.*nf + 325./27.*sqr(nf); // one loop if(_nloop==1) {return 4.*pi/(b0*lx);} // two loop else if(_nloop==2) { return 4.*pi/(b0*lx)*(1.-2.*b1/sqr(b0)*log(lx)/lx); } // three loop else {return 4.*pi/(b0*lx)*(1.-2.*b1/sqr(b0)*log(lx)/lx + 4.*sqr(b1)/(sqr(sqr(b0))*sqr(lx))* (sqr(log(lx) - 0.5) + b2*b0/(8.*sqr(b1)) - 5./4.));} } diff --git a/Shower/Couplings/ShowerAlphaQCD.h b/Shower/Couplings/ShowerAlphaQCD.h --- a/Shower/Couplings/ShowerAlphaQCD.h +++ b/Shower/Couplings/ShowerAlphaQCD.h @@ -1,308 +1,308 @@ // -*- C++ -*- // // ShowerAlphaQCD.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ShowerAlphaQCD_H #define HERWIG_ShowerAlphaQCD_H // // This is the declaration of the ShowerAlphaQCD class. // #include "ShowerAlpha.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This concrete class provides the definition of the * pure virtual function value() and overestimateValue() for the * strong coupling. * * A number of different options for the running of the coupling * and its initial definition are supported. * * @see \ref ShowerAlphaQCDInterfaces "The interfaces" * defined for ShowerAlphaQCD. */ class ShowerAlphaQCD: public ShowerAlpha { public: /** * The default constructor. */ ShowerAlphaQCD() : ShowerAlpha(), _qmin(0.630882*GeV), _asType(1), _asMaxNP(1.0), _thresholds(4), _lambda(4), _nloop(3),_lambdaopt(false),_thresopt(false), _lambdain(0.208364*GeV),_alphain(0.118),_inopt(true),_tolerance(1e-10), _maxtry(100),_alphamin(0.),_val0(1.), _optInputScale(ZERO) {} public: /** * Methods to return the coupling */ //@{ /** * It returns the running coupling value evaluated at the input scale * multiplied by the scale factor scaleFactor(). * @param scale The scale * @return The coupling */ virtual double value(const Energy2 scale) const; /** * It returns the running coupling value evaluated at the input scale * multiplied by the scale factor scaleFactor(). */ virtual double overestimateValue() const; /** * Return the ratio of the coupling at the scale to the overestimated value */ - virtual double ratio(const Energy2 scale) const; + virtual double ratio(const Energy2 scale,double factor =1.) const; /** * Initialize this coupling. */ virtual void initialize() { doinit(); } /** * A command to initialize the coupling and write * its value at the scale given by the argument (in GeV) */ string value(string); /** * Match thresholds and write alpha_s * specified file; arguments are * Q_low/GeV Q_high/GeV n_steps filename */ string check(string args); //@} /** * Get the value of \f$\Lambda_{\rm QCd}\f$ * @param nf number of flavours */ Energy lambdaQCD(unsigned int nf) { if (nf <= 3) return _lambda[0]; else if (nf==4 || nf==5) return _lambda[nf-3]; else return _lambda[3]; } /** * Return the quark masses to be used; if not empty these masses * should be considered instead of the ones set in the particle data * objects. */ const vector& quarkMasses() const { return _quarkMasses; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * Member functions which calculate the coupling */ //@{ /** * The 1,2,3-loop parametrization of \f$\alpha_S\f$. * @param q The scale * @param lam \f$\Lambda_{\rm QCD}\f$ * @param nf The number of flavours */ double alphaS(Energy q, Energy lam, int nf) const; /** * The derivative of \f$\alpha_S\f$ with respect to \f$\ln(Q^2/\Lambda^2)\f$ * @param q The scale * @param lam \f$\Lambda_{\rm QCD}\f$ * @param nf The number of flavours */ double derivativealphaS(Energy q, Energy lam, int nf) const; /** * Compute the value of \f$Lambda\f$ needed to get the input value of * the strong coupling at the scale given for the given number of flavours * using the Newton-Raphson method * @param match The scale for the coupling * @param alpha The input coupling * @param nflav The number of flavours */ Energy computeLambda(Energy match, double alpha, unsigned int nflav) const; /** * Return the value of \f$\Lambda\f$ and the number of flavours at the scale. * @param q The scale * @return The number of flavours at the scale and \f$\Lambda\f$. */ pair getLamNfTwoLoop(Energy q) const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerAlphaQCD & operator=(const ShowerAlphaQCD &); private: /** * Minimum value of the scale */ Energy _qmin; /** * Parameter controlling the behaviour of \f$\alpha_S\f$ in the * non-perturbative region. */ int _asType; /** * Another parameter, a possible (maximum) value of alpha in the * non-perturbative region. */ double _asMaxNP; /** * Thresholds for the different number of flavours */ vector _thresholds; /** * \f$\Lambda\f$ for the different number of flavours */ vector _lambda; /** * Option for the number of loops */ unsigned int _nloop; /** * Option for the translation between \f$\Lambda_{\bar{MS}}\f$ and * \f$\Lambda_{\rm Herwig}\f$ */ bool _lambdaopt; /** * Option for the threshold masses */ bool _thresopt; /** * Input value of Lambda */ Energy _lambdain; /** * Input value of \f$alpha_S(M_Z)\f$ */ double _alphain; /** * Option for the calculation of Lambda from input parameters */ bool _inopt; /** * Tolerance for discontinuities at the thresholds */ double _tolerance; /** * Maximum number of iterations for the Newton-Raphson method to converge */ unsigned int _maxtry; /** * The minimum value of the coupling */ double _alphamin; /** * Value of \f$\alpha_S\f$ at the minimum scale */ double _val0; /** * An optional input scale to be used for the input alphas; if zero MZ will * be used out of the particle data object. */ Energy _optInputScale; /** * The quark masses to be used; if not empty these masses should be * considered instead of the ones set in the particle data objects. */ vector _quarkMasses; }; } #endif /* HERWIG_ShowerAlphaQCD_H */ diff --git a/Shower/Couplings/ShowerAlphaQED.cc b/Shower/Couplings/ShowerAlphaQED.cc --- a/Shower/Couplings/ShowerAlphaQED.cc +++ b/Shower/Couplings/ShowerAlphaQED.cc @@ -1,88 +1,88 @@ // -*- C++ -*- // // ShowerAlphaQED.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerAlphaQED class. // #include "ShowerAlphaQED.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void ShowerAlphaQED::persistentOutput(PersistentOStream & os) const { os << _alpha << couplingSource_; } void ShowerAlphaQED::persistentInput(PersistentIStream & is, int) { is >> _alpha >> couplingSource_; } ClassDescription ShowerAlphaQED::initShowerAlphaQED; // Definition of the static class description member. void ShowerAlphaQED::Init() { static ClassDocumentation documentation ("This (concrete) class describes the QED alpha running."); static Parameter interfaceAlpha ("Alpha", "The value of alpha_EM", &ShowerAlphaQED::_alpha, 1./137., 0., 1., false, false, Interface::limited); static Switch interfaceCouplingSource ("CouplingSource", "Where to get the coupling from", &ShowerAlphaQED::couplingSource_, 0, false, false); static SwitchOption interfaceCouplingSourceLocal (interfaceCouplingSource, "Local", "Use the local value", 0); static SwitchOption interfaceCouplingSourceThompson (interfaceCouplingSource, "Thompson", "Use the Thompson value from the StamdardModel object", 1); static SwitchOption interfaceCouplingSourceMZ (interfaceCouplingSource, "MZ", "Use the value at MZ from the StandardModel object", 2); } double ShowerAlphaQED::value(const Energy2) const { return _alpha; } double ShowerAlphaQED::overestimateValue() const { return _alpha; } -double ShowerAlphaQED::ratio(const Energy2) const { +double ShowerAlphaQED::ratio(const Energy2,double ) const { return 1.; } void ShowerAlphaQED::doinit() throw(InitException) { ShowerAlpha::doinit(); if(couplingSource_==1) _alpha=generator()->standardModel()->alphaEM(); else if(couplingSource_==2) _alpha=generator()->standardModel()->alphaEMMZ(); } diff --git a/Shower/Couplings/ShowerAlphaQED.h b/Shower/Couplings/ShowerAlphaQED.h --- a/Shower/Couplings/ShowerAlphaQED.h +++ b/Shower/Couplings/ShowerAlphaQED.h @@ -1,193 +1,193 @@ // -*- C++ -*- // // ShowerAlphaQED.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ShowerAlphaQED_H #define HERWIG_ShowerAlphaQED_H // // This is the declaration of the ShowerAlphaQED class. // #include "ShowerAlpha.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This concrete class provides the definition of the * pure virtual function value(scale) for \f$\alpha_{\rm QED}\f$. * N.B. as we always use \f$\alpha(0)\f$ for the radiation of photons * this class is very simple. * * @see ShowerAlpha * @see ShowerAlphaQCD * * @see \ref ShowerAlphaQEDInterfaces "The interfaces" * defined for ShowerAlphaQED. */ class ShowerAlphaQED: public ShowerAlpha { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ ShowerAlphaQED() : ShowerAlpha(), _alpha(1./137.), couplingSource_(1) {} //@} public: /** * Methods to return the coupling. * The methods are equivalent to the QCD ones * and are necessary to make use of the virtuality of ShowerAlpha * at other places. */ //@{ /** * It returns the running coupling value evaluated at the input scale * multiplied by the scale factor scaleFactor(). * @param scale The scale * @return The coupling */ virtual double value(const Energy2 scale) const; /** * It returns the overestimiate of the coupling * multiplied by the scale factor scaleFactor(). */ virtual double overestimateValue() const; /** * Return the ratio of the coupling at the scale to the overestimated value */ - virtual double ratio(const Energy2 scale) const; + virtual double ratio(const Energy2 scale,double factor=1.) 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);} //@} protected: /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit() throw(InitException); private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initShowerAlphaQED; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerAlphaQED & operator=(const ShowerAlphaQED &); private: /** * The value of the coupling, as we are producing real photons * this is always \f$\alpha(q^2=0)\f$. */ double _alpha; /** * Source of coupling value */ unsigned int couplingSource_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of ShowerAlphaQED. */ template <> struct BaseClassTrait { /** Typedef of the first base class of ShowerAlphaQED. */ typedef Herwig::ShowerAlpha NthBase; }; /** This template specialization informs ThePEG about the name of * the ShowerAlphaQED 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::ShowerAlphaQED"; } /** * The name of a file containing the dynamic library where the class * ShowerAlphaQED is implemented. It may also include several, space-separated, * libraries if the class ShowerAlphaQED 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 "HwShower.so"; } }; /** @endcond */ } #endif /* HERWIG_ShowerAlphaQED_H */ diff --git a/Shower/Default/QTildeSudakov.cc b/Shower/Default/QTildeSudakov.cc --- a/Shower/Default/QTildeSudakov.cc +++ b/Shower/Default/QTildeSudakov.cc @@ -1,927 +1,1055 @@ // -*- C++ -*- // // QTildeSudakov.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the QTildeSudakov class. // #include "QTildeSudakov.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/Shower/Default/FS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/Default/IS_QTildeShowerKinematics1to2.h" #include "Herwig/Shower/Default/Decay_QTildeShowerKinematics1to2.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Shower/Base/ShowerVertex.h" #include "Herwig/Shower/Base/ShowerParticle.h" #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/Shower/Base/Evolver.h" #include "Herwig/Shower/Base/PartnerFinder.h" #include "Herwig/Shower/Base/ShowerModel.h" #include "Herwig/Shower/Base/KinematicsReconstructor.h" using namespace Herwig; DescribeNoPIOClass describeQTildeSudakov ("Herwig::QTildeSudakov","HwShower.so"); void QTildeSudakov::Init() { static ClassDocumentation documentation ("The QTildeSudakov class implements the Sudakov form factor for ordering it" " qtilde"); } bool QTildeSudakov::guessTimeLike(Energy2 &t,Energy2 tmin,double enhance) { Energy2 told = t; // calculate limits on z and if lower>upper return if(!computeTimeLikeLimits(t)) return false; // guess values of t and z t = guesst(told,0,ids_,enhance,ids_[1]==ids_[2]); z(guessz(0,ids_)); // actual values for z-limits if(!computeTimeLikeLimits(t)) return false; if(tupper return if(!computeSpaceLikeLimits(t,x)) return false; // guess values of t and z t = guesst(told,1,ids_,enhance,ids_[1]==ids_[2]); z(guessz(1,ids_)); // actual values for z-limits if(!computeSpaceLikeLimits(t,x)) return false; if(t zLimits().second) return true; Energy2 q2 = z()*(1.-z())*t; if(ids_[0]->id()!=ParticleID::g && ids_[0]->id()!=ParticleID::gamma ) q2 += masssquared_[0]; if(q2>maxQ2) return true; // compute the pts Energy2 pt2 = z()*(1.-z())*q2 - masssquared_[1]*(1.-z()) - masssquared_[2]*z(); // if pt2<0 veto if(pt2 min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax); - do { - if(!guessTimeLike(t,tmin,enhance)) break; + // no shower variations to calculate + + + + if(ShowerHandler::currentHandler()->showerVariations().empty()){ + // Without variations do the usual Veto algorithm + // No need for more if-statements in this loop. + do { + if(!guessTimeLike(t,tmin,enhance)) break; + } + while(PSVeto(t,maxQ2) || + SplittingFnVeto(z()*(1.-z())*t,ids,true,rho) || + alphaSVeto(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t)); } - while(PSVeto(t,maxQ2) || SplittingFnVeto(z()*(1.-z())*t,ids,true,rho) || - alphaSVeto(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t)); + else{ + bool alphaRew(true),PSRew(true),SplitRew(true); + do { + if(!guessTimeLike(t,tmin,enhance)) break; + PSRew=PSVeto(t,maxQ2); + if (PSRew) continue; + SplitRew=SplittingFnVeto(z()*(1.-z())*t,ids,true,rho); + alphaRew=alphaSVeto(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t); + double factor=alphaSVetoRatio(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,1.)* + SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,rho); + + ShowerHandlerPtr ch = ShowerHandler::currentHandler(); + + if( !(SplitRew || alphaRew) ) { + //Emission + q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; + if (q_ <= ZERO) break; + } + + for ( map::const_iterator var = + ch->showerVariations().begin(); + var != ch->showerVariations().end(); ++var ) { + if ( ( ch->firstInteraction() && var->second.firstInteraction ) || + ( !ch->firstInteraction() && var->second.secondaryInteractions ) ) { + + double newfactor = alphaSVetoRatio(splittingFn()->angularOrdered() ? + sqr(z()*(1.-z()))*t : + z()*(1.-z())*t,var->second.renormalizationScaleFactor) + * SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,rho); + + double varied; + if ( SplitRew || alphaRew ) { + // No Emission + varied = (1. - newfactor) / (1. - factor); + } else { + // Emission + varied = newfactor / factor; + } + + map::iterator wi = ch->currentWeights().find(var->first); + if ( wi != ch->currentWeights().end() ) + wi->second *= varied; + else { + assert(false); + //ch->currentWeights()[var->first] = varied; + } + } + } + + } + while(PSRew || SplitRew || alphaRew); + } q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if(q_ < ZERO) return ShoKinPtr(); // return the ShowerKinematics object return createFinalStateBranching(q_,z(),phi(),pT()); } ShoKinPtr QTildeSudakov:: generateNextSpaceBranching(const Energy startingQ, const IdList &ids, double x, const RhoDMatrix & rho, double enhance, Ptr::transient_const_pointer beam) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to the method. q_ = ZERO; z(0.); phi(0.); // perform the initialization Energy2 tmax(sqr(startingQ)),tmin; initialize(ids,tmin); // check max > min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax),pt2(ZERO); - do { - if(!guessSpaceLike(t,tmin,x,enhance)) break; - pt2=sqr(1.-z())*t-z()*masssquared_[2]; + // no shower variations + if(ShowerHandler::currentHandler()->showerVariations().empty()) { + // Without variations do the usual Veto algorithm + // No need for more if-statements in this loop. + do { + if(!guessSpaceLike(t,tmin,x,enhance)) break; + pt2=sqr(1.-z())*t-z()*masssquared_[2]; + } + while(pt2 < pT2min()|| + z() > zLimits().second|| + SplittingFnVeto((1.-z())*t/z(),ids,true,rho)|| + alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t)|| + PDFVeto(t,x,ids[0],ids[1],beam)); } - while(z() > zLimits().second || - SplittingFnVeto((1.-z())*t/z(),ids,true,rho) || - alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t) || - PDFVeto(t,x,ids[0],ids[1],beam) || pt2 < pT2min() ); + // shower variations + else{ + bool alphaRew(true),PDFRew(true),ptRew(true),zRew(true),SplitRew(true); + do { + if(!guessSpaceLike(t,tmin,x,enhance)) break; + pt2=sqr(1.-z())*t-z()*masssquared_[2]; + ptRew=pt2 < pT2min(); + zRew=z() > zLimits().second; + if (ptRew||zRew) continue; + SplitRew=SplittingFnVeto((1.-z())*t/z(),ids,true,rho); + alphaRew=alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t); + PDFRew=PDFVeto(t,x,ids[0],ids[1],beam); + double factor=PDFVetoRatio(t,x,ids[0],ids[1],beam,1.)* + alphaSVetoRatio(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t,1.)* + SplittingFnVetoRatio((1.-z())*t/z(),ids,true,rho); + + ShowerHandlerPtr ch = ShowerHandler::currentHandler(); + + if( !(PDFRew || SplitRew || alphaRew) ) { + //Emission + q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; + if (q_ <= ZERO) break; + } + + for ( map::const_iterator var = + ch->showerVariations().begin(); + var != ch->showerVariations().end(); ++var ) { + if ( ( ch->firstInteraction() && var->second.firstInteraction ) || + ( !ch->firstInteraction() && var->second.secondaryInteractions ) ) { + + + + double newfactor = PDFVetoRatio(t,x,ids[0],ids[1],beam,var->second.factorizationScaleFactor)* + alphaSVetoRatio(splittingFn()->angularOrdered() ? + sqr(1.-z())*t : (1.-z())*t,var->second.renormalizationScaleFactor) + *SplittingFnVetoRatio((1.-z())*t/z(),ids,true,rho); + + double varied; + if( PDFRew || SplitRew || alphaRew) { + // No Emission + varied = (1. - newfactor) / (1. - factor); + } else { + // Emission + varied = newfactor / factor; + } + + + map::iterator wi = ch->currentWeights().find(var->first); + if ( wi != ch->currentWeights().end() ) + wi->second *= varied; + else { + assert(false); + //ch->currentWeights()[var->first] = varied; + } + } + } + + } + while( PDFRew || SplitRew || alphaRew); + } + if(t > ZERO && zLimits().first < zLimits().second) q_ = sqrt(t); else return ShoKinPtr(); pT(sqrt(pt2)); // create the ShowerKinematics and return it return createInitialStateBranching(q_,z(),phi(),pT()); } void QTildeSudakov::initialize(const IdList & ids, Energy2 & tmin) { ids_=ids; tmin = cutOffOption() != 2 ? ZERO : 4.*pT2min(); masses_ = virtualMasses(ids); masssquared_.clear(); for(unsigned int ix=0;ix0) tmin=max(masssquared_[ix],tmin); } } ShoKinPtr QTildeSudakov::generateNextDecayBranching(const Energy startingScale, const Energy stoppingScale, const Energy minmass, const IdList &ids, const RhoDMatrix & rho, double enhance) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to this method. q_ = Constants::MaxEnergy; z(0.); phi(0.); // perform initialisation Energy2 tmax(sqr(stoppingScale)),tmin; initialize(ids,tmin); tmin=sqr(startingScale); // check some branching possible if(tmax<=tmin) return ShoKinPtr(); // perform the evolution Energy2 t(tmin),pt2(-MeV2); do { if(!guessDecay(t,tmax,minmass,enhance)) break; pt2 = sqr(1.-z())*(t-masssquared_[0])-z()*masssquared_[2]; } while(SplittingFnVeto((1.-z())*t/z(),ids,true,rho)|| alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t ) || pt2masssquared_[0]-sqr(minmass)); if(t > ZERO) { q_ = sqrt(t); pT(sqrt(pt2)); } else return ShoKinPtr(); phi(0.); // create the ShowerKinematics object return createDecayBranching(q_,z(),phi(),pT()); } bool QTildeSudakov::guessDecay(Energy2 &t,Energy2 tmax, Energy minmass, double enhance) { // previous scale Energy2 told = t; // overestimated limits on z if(tmax limits=make_pair(sqr(minmass/masses_[0]), 1.-sqrt(masssquared_[2]+pT2min()+ 0.25*sqr(masssquared_[2])/tm2)/tm +0.5*masssquared_[2]/tm2); zLimits(limits); if(zLimits().secondtmax||zLimits().second limits; if(ids_[0]->id()==ParticleID::g||ids_[0]->id()==ParticleID::gamma) { // no emission possible if(t<16.*(masssquared_[1]+pT2min())) { t=-1.*GeV2; return false; } // overestimate of the limits limits.first = 0.5*(1.-sqrt(1.-4.*sqrt((masssquared_[1]+pT2min())/t))); limits.second = 1.-limits.first; } // special case for radiated particle is gluon else if(ids_[2]->id()==ParticleID::g||ids_[2]->id()==ParticleID::gamma) { limits.first = sqrt((masssquared_[1]+pT2min())/t); limits.second = 1.-sqrt((masssquared_[2]+pT2min())/t); } else if(ids_[1]->id()==ParticleID::g||ids_[1]->id()==ParticleID::gamma) { limits.second = sqrt((masssquared_[2]+pT2min())/t); limits.first = 1.-sqrt((masssquared_[1]+pT2min())/t); } else { limits.first = (masssquared_[1]+pT2min())/t; limits.second = 1.-(masssquared_[2]+pT2min())/t; } if(limits.first>=limits.second) { t=-1.*GeV2; return false; } zLimits(limits); return true; } bool QTildeSudakov::computeSpaceLikeLimits(Energy2 & t, double x) { if (t < 1e-20 * GeV2) { t=-1.*GeV2; return false; } pair limits; // compute the limits limits.first = x; double yy = 1.+0.5*masssquared_[2]/t; limits.second = yy - sqrt(sqr(yy)-1.+pT2min()/t); // return false if lower>upper zLimits(limits); if(limits.second(particle.parents()[0]) : tShowerParticlePtr(); } else { mother = particle.children().size()==2 ? dynamic_ptr_cast(&particle) : tShowerParticlePtr(); } tShowerParticlePtr partner; while(mother) { tPPtr otherChild; if(forward) { for (unsigned int ix=0;ixchildren().size();++ix) { if(mother->children()[ix]!=child) { otherChild = mother->children()[ix]; break; } } } else { otherChild = mother->children()[1]; } tShowerParticlePtr other = dynamic_ptr_cast(otherChild); if((inter==ShowerInteraction::QCD && otherChild->dataPtr()->coloured()) || (inter==ShowerInteraction::QED && otherChild->dataPtr()->charged())) { partner = other; break; } if(forward && !other->isFinalState()) { partner = dynamic_ptr_cast(mother); break; } child = mother; if(forward) { mother = ! mother->parents().empty() ? dynamic_ptr_cast(mother->parents()[0]) : tShowerParticlePtr(); } else { if(mother->children()[0]->children().size()!=2) break; tShowerParticlePtr mtemp = dynamic_ptr_cast(mother->children()[0]); if(!mtemp) break; else mother=mtemp; } } if(!partner) { if(forward) { partner = dynamic_ptr_cast( child)->partner(); } else { if(mother) { tShowerParticlePtr parent; if(!mother->children().empty()) { parent = dynamic_ptr_cast(mother->children()[0]); } if(!parent) { parent = dynamic_ptr_cast(mother); } partner = parent->partner(); } else { partner = dynamic_ptr_cast(&particle)->partner(); } } } return partner; } pair softPhiMin(double phi0, double phi1, double A, double B, double C, double D) { double c01 = cos(phi0 - phi1); double s01 = sin(phi0 - phi1); double s012(sqr(s01)), c012(sqr(c01)); double A2(A*A), B2(B*B), C2(C*C), D2(D*D); if(abs(B/A)<1e-10 && abs(D/C)<1e-10) return make_pair(phi0,phi0+Constants::pi); double root = sqr(B2)*C2*D2*sqr(s012) + 2.*A*B2*B*C2*C*D*c01*s012 + 2.*A*B2*B*C*D2*D*c01*s012 + 4.*A2*B2*C2*D2*c012 - A2*B2*C2*D2*s012 - A2*B2*sqr(D2)*s012 - sqr(B2)*sqr(C2)*s012 - sqr(B2)*C2*D2*s012 - 4.*A2*A*B*C*D2*D*c01 - 4.*A*B2*B*C2*C*D*c01 + sqr(A2)*sqr(D2) + 2.*A2*B2*C2*D2 + sqr(B2)*sqr(C2); if(root<0.) return make_pair(phi0,phi0+Constants::pi); root = sqrt(root); double denom = (-2.*A*B*C*D*c01 + A2*D2 + B2*C2); double denom2 = (-B*C*c01 + A*D); double num = B2*C*D*s012; return make_pair(atan2(B*s01*(-C*(num + root) / denom + D) / denom2, -(num + root ) / denom) + phi0, atan2(B*s01*(-C*(num - root) / denom + D) / denom2, -(num - root ) / denom) + phi0); } } double QTildeSudakov::generatePhiForward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho) { // no correlations, return flat phi if(! ShowerHandler::currentHandler()->evolver()->correlations()) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy2 t = z*(1.-z)*sqr(kinematics->scale()); Energy pT = kinematics->pT(); // if soft correlations Energy2 pipj,pik; bool canBeSoft[2] = {ids[1]->id()==ParticleID::g || ids[1]->id()==ParticleID::gamma, ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma }; vector pjk(3,ZERO); vector Ek(3,ZERO); Energy Ei,Ej; Energy2 m12(ZERO),m22(ZERO); InvEnergy2 aziMax(ZERO); bool softAllowed = ShowerHandler::currentHandler()->evolver()->softCorrelations()&& (canBeSoft[0] || canBeSoft[1]); if(softAllowed) { // find the partner for the soft correlations tShowerParticlePtr partner=findCorrelationPartner(particle,true,splittingFn()->interactionType()); // remember we want the softer gluon bool swapOrder = !canBeSoft[1] || (canBeSoft[0] && canBeSoft[1] && z < 0.5); double zFact = !swapOrder ? (1.-z) : z; // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); Boost beta_bb; if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) { beta_bb = -(pVect + nVect).boostVector(); } else if(particle.showerBasis()->frame()==ShowerBasis::Rest) { beta_bb = -pVect.boostVector(); } else assert(false); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis; if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) { axis = pVect.vect().unit(); } else if(particle.showerBasis()->frame()==ShowerBasis::Rest) { axis = nVect.vect().unit(); } else assert(false); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect, m2 = pVect.m2(); double alpha0 = particle.showerParameters().alpha; double beta0 = 0.5/alpha0/pn* (sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt)); Lorentz5Momentum qperp0(particle.showerParameters().ptx, particle.showerParameters().pty,ZERO,ZERO); assert(partner); Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; // compute the two phi independent dot products pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn ) +0.5*sqr(pT)/zFact; Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; Energy2 dot3 = pj*qperp0; pipj = alpha0*dot1+beta0*dot2+dot3; // compute the constants for the phi dependent dot product pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*dot2/pn/zFact/alpha0; pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT; pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT; m12 = sqr(particle.dataPtr()->mass()); m22 = sqr(partner->dataPtr()->mass()); if(swapOrder) { pjk[1] *= -1.; pjk[2] *= -1.; } Ek[0] = zFact*(alpha0*pVect.t()-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0; Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT; Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT; if(swapOrder) { Ek[1] *= -1.; Ek[2] *= -1.; } Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2])); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); double phi0 = atan2(-pjk[2],-pjk[1]); if(phi0<0.) phi0 += Constants::twopi; double phi1 = atan2(-Ek[2],-Ek[1]); if(phi1<0.) phi1 += Constants::twopi; double xi_min = pik/Ei/(Ek[0]+mag2), xi_max = pik/Ei/(Ek[0]-mag2), xi_ij = pipj/Ei/Ej; if(xi_min>xi_max) swap(xi_min,xi_max); if(xi_min>xi_ij) softAllowed = false; Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { double A = (pipj*Ek[0]- Ej*pik)/Ej/sqr(Ej); double B = -sqrt(sqr(pipj)*(sqr(Ek[1])+sqr(Ek[2])))/Ej/sqr(Ej); double C = pjk[0]/sqr(Ej); double D = -sqrt(sqr(pjk[1])+sqr(pjk[2]))/sqr(Ej); pair minima = softPhiMin(phi0,phi1,A,B,C,D); aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + max(Ej*(A+B*cos(minima.first -phi1))/(C+D*cos(minima.first -phi0)), Ej*(A+B*cos(minima.second-phi1))/(C+D*cos(minima.second-phi0)))); } else assert(false); } // if spin correlations vector > wgts; if(ShowerHandler::currentHandler()->evolver()->spinCorrelations()) { // calculate the weights wgts = splittingFn()->generatePhiForward(z,t,ids,rho); } else { wgts = vector >(1,make_pair(0,1.)); } // generate the azimuthal angle double phi,wgt; static const Complex ii(0.,1.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); // first the spin correlations bit (gives 1 if correlations off) Complex spinWgt = 0.; for(unsigned int ix=0;ix1e-10) { generator()->log() << "Forward spin weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ixlog() << wgts[ix].first << " " << wgts[ix].second << "\n"; } // soft correlations bit double aziWgt = 1.; if(softAllowed) { Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi); if(pipj*Eg>pik*Ej) { if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { aziWgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax); } if(aziWgt-1.>1e-10||aziWgt<-1e-10) { generator()->log() << "Forward soft weight problem " << aziWgt << " " << aziWgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } } else { aziWgt = 0.; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi in forward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double QTildeSudakov::generatePhiBackward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho) { // no correlations, return flat phi if(! ShowerHandler::currentHandler()->evolver()->correlations()) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy2 t = (1.-z)*sqr(kinematics->scale())/z; Energy pT = kinematics->pT(); // if soft correlations bool softAllowed = ShowerHandler::currentHandler()->evolver()->softCorrelations() && (ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma); Energy2 pipj,pik,m12(ZERO),m22(ZERO); vector pjk(3,ZERO); Energy Ei,Ej,Ek; InvEnergy2 aziMax(ZERO); if(softAllowed) { // find the partner for the soft correlations tShowerParticlePtr partner=findCorrelationPartner(particle,false,splittingFn()->interactionType()); double zFact = (1.-z); // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); assert(particle.showerBasis()->frame()==ShowerBasis::BackToBack); Boost beta_bb = -(pVect + nVect).boostVector(); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis = pVect.vect().unit(); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect; Energy2 m2 = pVect.m2(); double alpha0 = particle.x(); double beta0 = -0.5/alpha0/pn*sqr(alpha0)*m2; Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; double beta2 = 0.5*(1.-zFact)*(sqr(alpha0*zFact/(1.-zFact))*m2+sqr(pT))/alpha0/zFact/pn; // compute the two phi independent dot products Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; pipj = alpha0*dot1+beta0*dot2; pik = alpha0*(alpha0*zFact/(1.-zFact)*m2+pn*(beta2+zFact/(1.-zFact)*beta0)); // compute the constants for the phi dependent dot product pjk[0] = alpha0*zFact/(1.-zFact)*dot1+beta2*dot2; pjk[1] = pj.x()*pT; pjk[2] = pj.y()*pT; m12 = ZERO; m22 = sqr(partner->dataPtr()->mass()); Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { Ek = alpha0*zFact/(1.-zFact)*pVect.t()+beta2*nVect.t(); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); if(pipj*Ek> Ej*pik) { aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik + (pipj*Ek- Ej*pik)/(pjk[0]-mag)); } else { aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik); } } else { assert(ShowerHandler::currentHandler()->evolver()->softCorrelations()==0); } } // if spin correlations vector > wgts; if(ShowerHandler::currentHandler()->evolver()->spinCorrelations()) { // get the spin density matrix and the mapping // get the weights wgts = splittingFn()->generatePhiBackward(z,t,ids,rho); } else { wgts = vector >(1,make_pair(0,1.)); } // generate the azimuthal angle double phi,wgt; static const Complex ii(0.,1.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); Complex spinWgt = 0.; for(unsigned int ix=0;ix1e-10) { generator()->log() << "Backward weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << z << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ixlog() << wgts[ix].first << " " << wgts[ix].second << "\n"; } // soft correlations bit double aziWgt = 1.; if(softAllowed) { Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { aziWgt = max(ZERO,0.5/pik/Ek*(Ei-m12*Ek/pik + pipj*Ek/dot - Ej*pik/dot)/aziMax); } if(aziWgt-1.>1e-10||aziWgt<-1e-10) { generator()->log() << "Backward soft weight problem " << aziWgt << " " << aziWgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi in backward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double QTildeSudakov::generatePhiDecay(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix &) { // only soft correlations in this case // no correlations, return flat phi if( !(ShowerHandler::currentHandler()->evolver()->softCorrelations() && (ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma ))) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy pT = kinematics->pT(); // if soft correlations // find the partner for the soft correlations tShowerParticlePtr partner = findCorrelationPartner(particle,true,splittingFn()->interactionType()); double zFact(1.-z); // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); assert(particle.showerBasis()->frame()==ShowerBasis::Rest); Boost beta_bb = -pVect.boostVector(); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis = nVect.vect().unit(); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect; Energy2 m2 = pVect.m2(); double alpha0 = particle.showerParameters().alpha; double beta0 = 0.5/alpha0/pn* (sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt)); Lorentz5Momentum qperp0(particle.showerParameters().ptx, particle.showerParameters().pty,ZERO,ZERO); Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; // compute the two phi independent dot products Energy2 pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn ) +0.5*sqr(pT)/zFact; Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; Energy2 dot3 = pj*qperp0; Energy2 pipj = alpha0*dot1+beta0*dot2+dot3; // compute the constants for the phi dependent dot product vector pjk(3,ZERO); pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*dot2/pn/zFact/alpha0; pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT; pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT; Energy2 m12 = sqr(particle.dataPtr()->mass()); Energy2 m22 = sqr(partner->dataPtr()->mass()); Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); InvEnergy2 aziMax; vector Ek(3,ZERO); Energy Ei,Ej; if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { Ek[0] = zFact*(alpha0*pVect.t()+-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0; Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT; Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT; Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2])); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + pipj*(Ek[0]+mag2)/(pjk[0]-mag) - Ej*pik/(pjk[0]-mag) ); } else assert(ShowerHandler::currentHandler()->evolver()->softCorrelations()==0); // generate the azimuthal angle double phi,wgt(0.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { wgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { if(qperp0.m2()==ZERO) { wgt = 1.; } else { Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi); wgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax); } } if(wgt-1.>1e-10||wgt<-1e-10) { generator()->log() << "Decay soft weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi\n"; } // return the azimuthal angle return phi; } Energy QTildeSudakov::calculateScale(double zin, Energy pt, IdList ids, unsigned int iopt) { Energy2 tmin; initialize(ids,tmin); // final-state branching if(iopt==0) { Energy2 scale=(sqr(pt)+masssquared_[1]*(1.-zin)+masssquared_[2]*zin); if(ids[0]->id()!=ParticleID::g) scale -= zin*(1.-zin)*masssquared_[0]; scale /= sqr(zin*(1-zin)); return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else if(iopt==1) { Energy2 scale=(sqr(pt)+zin*masssquared_[2])/sqr(1.-zin); return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else if(iopt==2) { Energy2 scale = (sqr(pt)+zin*masssquared_[2])/sqr(1.-zin)+masssquared_[0]; return scale<=ZERO ? sqrt(tmin) : sqrt(scale); } else { throw Exception() << "Unknown option in QTildeSudakov::calculateScale() " << "iopt = " << iopt << Exception::runerror; } } ShoKinPtr QTildeSudakov::createFinalStateBranching(Energy scale,double z, double phi, Energy pt) { ShoKinPtr showerKin = new_ptr(FS_QTildeShowerKinematics1to2()); showerKin->scale(scale); showerKin->z(z); showerKin->phi(phi); showerKin->pT(pt); showerKin->SudakovFormFactor(this); return showerKin; } ShoKinPtr QTildeSudakov::createInitialStateBranching(Energy scale,double z, double phi, Energy pt) { ShoKinPtr showerKin = new_ptr(IS_QTildeShowerKinematics1to2()); showerKin->scale(scale); showerKin->z(z); showerKin->phi(phi); showerKin->pT(pt); showerKin->SudakovFormFactor(this); return showerKin; } ShoKinPtr QTildeSudakov::createDecayBranching(Energy scale,double z, double phi, Energy pt) { ShoKinPtr showerKin = new_ptr(Decay_QTildeShowerKinematics1to2()); showerKin->scale(scale); showerKin->z(z); showerKin->phi(phi); showerKin->pT(pt); showerKin->SudakovFormFactor(this); return showerKin; } diff --git a/Shower/Makefile.am b/Shower/Makefile.am --- a/Shower/Makefile.am +++ b/Shower/Makefile.am @@ -1,50 +1,50 @@ SUBDIRS = Matching . pkglib_LTLIBRARIES = HwShower.la -HwShower_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 20:0:0 +HwShower_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 21:0:0 HwShower_la_LIBADD = \ $(top_builddir)/PDF/libHwRemDecayer.la \ $(top_builddir)/PDF/libHwMPIPDF.la HwShower_la_SOURCES = \ UEBase.h UEBase.cc UEBase.fh \ Couplings/ShowerAlphaQCD.h Couplings/ShowerAlphaQCD.cc \ Couplings/ShowerAlphaQED.h Couplings/ShowerAlphaQED.cc\ ShowerHandler.h ShowerHandler.fh ShowerHandler.cc \ SplittingFunctions/HalfHalfOneSplitFn.h SplittingFunctions/HalfHalfOneSplitFn.cc\ SplittingFunctions/HalfHalfOneEWSplitFn.h SplittingFunctions/HalfHalfOneEWSplitFn.cc\ SplittingFunctions/OneOneOneSplitFn.h SplittingFunctions/OneOneOneSplitFn.cc\ SplittingFunctions/ZeroZeroOneSplitFn.h SplittingFunctions/ZeroZeroOneSplitFn.cc\ SplittingFunctions/OneHalfHalfSplitFn.h SplittingFunctions/OneHalfHalfSplitFn.cc\ SplittingFunctions/HalfOneHalfSplitFn.h SplittingFunctions/HalfOneHalfSplitFn.cc\ Default/QTildeSudakov.cc Default/QTildeSudakov.h\ Default/QTildeModel.cc Default/QTildeModel.h\ Default/Decay_QTildeShowerKinematics1to2.cc \ Default/Decay_QTildeShowerKinematics1to2.h \ Default/IS_QTildeShowerKinematics1to2.cc Default/IS_QTildeShowerKinematics1to2.h \ Default/FS_QTildeShowerKinematics1to2.cc Default/FS_QTildeShowerKinematics1to2.h \ Default/QTildeFinder.cc Default/QTildeFinder.h\ Default/QTildeReconstructor.cc Default/QTildeReconstructor.h Default/QTildeReconstructor.tcc \ Base/KinematicsReconstructor.cc \ Base/KinematicsReconstructor.h \ Base/KinematicsReconstructor.fh \ Base/ShowerModel.cc Base/ShowerModel.h Base/ShowerModel.fh \ Base/PartnerFinder.h Base/PartnerFinder.fh Base/PartnerFinder.cc \ Base/Evolver.h Base/Evolver.fh Base/Evolver.cc \ Base/ShowerVeto.h Base/ShowerVeto.fh Base/ShowerVeto.cc noinst_LTLIBRARIES = libHwShower.la libHwShower_la_SOURCES = ShowerConfig.h ShowerConfig.cc \ Base/Branching.h \ Base/ShowerParticle.cc Base/ShowerParticle.fh Base/ShowerParticle.h \ Base/ShowerKinematics.fh Base/ShowerKinematics.h Base/ShowerKinematics.cc \ Base/ShowerBasis.fh Base/ShowerBasis.h Base/ShowerBasis.cc \ Base/ShowerTree.h Base/ShowerTree.fh Base/ShowerTree.cc \ Base/ShowerProgenitor.fh Base/ShowerProgenitor.h \ Base/HardTree.h Base/HardTree.fh Base/HardTree.cc\ Base/SudakovFormFactor.cc Base/SudakovFormFactor.h Base/SudakovFormFactor.fh \ Base/HardBranching.h Base/HardBranching.fh Base/HardBranching.cc\ Couplings/ShowerAlpha.h Couplings/ShowerAlpha.cc Couplings/ShowerAlpha.fh\ SplittingFunctions/SplittingGenerator.cc SplittingFunctions/SplittingGenerator.h\ SplittingFunctions/SplittingGenerator.fh \ SplittingFunctions/SplittingFunction.h SplittingFunctions/SplittingFunction.fh \ SplittingFunctions/SplittingFunction.cc \ Base/ShowerVertex.cc Base/ShowerVertex.fh Base/ShowerVertex.h diff --git a/Shower/ShowerHandler.cc b/Shower/ShowerHandler.cc --- a/Shower/ShowerHandler.cc +++ b/Shower/ShowerHandler.cc @@ -1,817 +1,935 @@ // -*- C++ -*- // // ShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ShowerHandler class. // #include "ShowerHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/Switch.h" +#include "ThePEG/Interface/Command.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/PDF/PartonBinInstance.h" #include "Herwig/PDT/StandardMatchers.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Utilities/Throw.h" +#include "ThePEG/Utilities/StringUtils.h" #include "Herwig/Shower/Base/Evolver.h" #include "Herwig/Shower/Base/ShowerParticle.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Utilities/EnumParticles.h" #include "Herwig/PDF/MPIPDF.h" #include "Herwig/PDF/MinBiasPDF.h" #include "ThePEG/Handlers/EventHandler.h" #include "Herwig/Shower/Base/ShowerTree.h" #include "Herwig/Shower/Base/HardTree.h" #include "Herwig/Shower/Base/KinematicsReconstructor.h" #include "Herwig/Shower/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; DescribeClass describeShowerHandler ("Herwig::ShowerHandler","HwShower.so"); ShowerHandler::~ShowerHandler() {} ShowerHandler * ShowerHandler::currentHandler_ = 0; void ShowerHandler::doinit() { CascadeHandler::doinit(); // copy particles to decay before showering from input vector to the // set used in the simulation if ( particlesDecayInShower_.empty() ) particlesDecayInShower_.insert(inputparticlesDecayInShower_.begin(), inputparticlesDecayInShower_.end()); ShowerTree::_decayInShower = particlesDecayInShower_; ShowerTree::_vmin2 = vMin_; ShowerTree::_spaceTime = includeSpaceTime_; } IBPtr ShowerHandler::clone() const { return new_ptr(*this); } IBPtr ShowerHandler::fullclone() const { return new_ptr(*this); } ShowerHandler::ShowerHandler() : + reweight_(1.0), pdfFreezingScale_(2.5*GeV), maxtry_(10),maxtryMPI_(10),maxtryDP_(10), includeSpaceTime_(false), vMin_(0.1*GeV2), subProcess_(), factorizationScaleFactor_(1.0), renormalizationScaleFactor_(1.0), - hardScaleFactor_(1.0), scaleFactorOption_(0), + hardScaleFactor_(1.0), restrictPhasespace_(true), maxPtIsMuF_(false), splitHardProcess_(true) { inputparticlesDecayInShower_.push_back( 6 ); // top inputparticlesDecayInShower_.push_back( 23 ); // Z0 inputparticlesDecayInShower_.push_back( 24 ); // W+/- inputparticlesDecayInShower_.push_back( 25 ); // h0 } void ShowerHandler::doinitrun(){ CascadeHandler::doinitrun(); //can't use isMPIOn here, because the EventHandler is not set at that stage if(MPIHandler_){ MPIHandler_->initialize(); if(MPIHandler_->softInt()) remDec_->initSoftInteractions(MPIHandler_->Ptmin(), MPIHandler_->beta()); } ShowerTree::_decayInShower = particlesDecayInShower_; ShowerTree::_vmin2 = vMin_; ShowerTree::_spaceTime = includeSpaceTime_; } void ShowerHandler::dofinish(){ CascadeHandler::dofinish(); if(MPIHandler_) MPIHandler_->finalize(); } void ShowerHandler::persistentOutput(PersistentOStream & os) const { os << evolver_ << remDec_ << ounit(pdfFreezingScale_,GeV) << maxtry_ << maxtryMPI_ << maxtryDP_ << inputparticlesDecayInShower_ << particlesDecayInShower_ << MPIHandler_ << PDFA_ << PDFB_ << PDFARemnant_ << PDFBRemnant_ << includeSpaceTime_ << ounit(vMin_,GeV2) << factorizationScaleFactor_ << renormalizationScaleFactor_ - << hardScaleFactor_ << scaleFactorOption_ + << hardScaleFactor_ << restrictPhasespace_ << maxPtIsMuF_ << hardScaleProfile_ - << splitHardProcess_; + << splitHardProcess_ << showerVariations_; } void ShowerHandler::persistentInput(PersistentIStream & is, int) { is >> evolver_ >> remDec_ >> iunit(pdfFreezingScale_,GeV) >> maxtry_ >> maxtryMPI_ >> maxtryDP_ >> inputparticlesDecayInShower_ >> particlesDecayInShower_ >> MPIHandler_ >> PDFA_ >> PDFB_ >> PDFARemnant_ >> PDFBRemnant_ >> includeSpaceTime_ >> iunit(vMin_,GeV2) >> factorizationScaleFactor_ >> renormalizationScaleFactor_ - >> hardScaleFactor_ >> scaleFactorOption_ + >> hardScaleFactor_ >> restrictPhasespace_ >> maxPtIsMuF_ >> hardScaleProfile_ - >> splitHardProcess_; + >> splitHardProcess_ >> showerVariations_; } void ShowerHandler::Init() { static ClassDocumentation documentation ("Main driver class for the showering.", "The Shower evolution was performed using an algorithm described in " "\\cite{Marchesini:1983bm,Marchesini:1987cf,Gieseke:2003rz,Bahr:2008pv}.", "%\\cite{Marchesini:1983bm}\n" "\\bibitem{Marchesini:1983bm}\n" " G.~Marchesini and B.~R.~Webber,\n" " ``Simulation Of QCD Jets Including Soft Gluon Interference,''\n" " Nucl.\\ Phys.\\ B {\\bf 238}, 1 (1984).\n" " %%CITATION = NUPHA,B238,1;%%\n" "%\\cite{Marchesini:1987cf}\n" "\\bibitem{Marchesini:1987cf}\n" " G.~Marchesini and B.~R.~Webber,\n" " ``Monte Carlo Simulation of General Hard Processes with Coherent QCD\n" " Radiation,''\n" " Nucl.\\ Phys.\\ B {\\bf 310}, 461 (1988).\n" " %%CITATION = NUPHA,B310,461;%%\n" "%\\cite{Gieseke:2003rz}\n" "\\bibitem{Gieseke:2003rz}\n" " S.~Gieseke, P.~Stephens and B.~Webber,\n" " ``New formalism for QCD parton showers,''\n" " JHEP {\\bf 0312}, 045 (2003)\n" " [arXiv:hep-ph/0310083].\n" " %%CITATION = JHEPA,0312,045;%%\n" ); static Reference interfaceEvolver("Evolver", "A reference to the Evolver object", &Herwig::ShowerHandler::evolver_, false, false, true, false); static Reference interfaceRemDecayer("RemDecayer", "A reference to the Remnant Decayer object", &Herwig::ShowerHandler::remDec_, false, false, true, false); static Parameter interfacePDFFreezingScale ("PDFFreezingScale", "The PDF freezing scale", &ShowerHandler::pdfFreezingScale_, GeV, 2.5*GeV, 2.0*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceMaxTry ("MaxTry", "The maximum number of attempts for the main showering loop", &ShowerHandler::maxtry_, 10, 1, 100, false, false, Interface::limited); static Parameter interfaceMaxTryMPI ("MaxTryMPI", "The maximum number of regeneration attempts for an additional scattering", &ShowerHandler::maxtryMPI_, 10, 0, 100, false, false, Interface::limited); static Parameter interfaceMaxTryDP ("MaxTryDP", "The maximum number of regeneration attempts for an additional hard scattering", &ShowerHandler::maxtryDP_, 10, 0, 100, false, false, Interface::limited); static ParVector interfaceDecayInShower ("DecayInShower", "PDG codes of the particles to be decayed in the shower", &ShowerHandler::inputparticlesDecayInShower_, -1, 0l, -10000000l, 10000000l, false, false, Interface::limited); static Reference interfaceMPIHandler ("MPIHandler", "The object that administers all additional scatterings.", &ShowerHandler::MPIHandler_, false, false, true, true); static Reference interfacePDFA ("PDFA", "The PDF for beam particle A. Overrides the particle's own PDF setting." "By default used for both the shower and forced splitting in the remnant", &ShowerHandler::PDFA_, false, false, true, true, false); static Reference interfacePDFB ("PDFB", "The PDF for beam particle B. Overrides the particle's own PDF setting." "By default used for both the shower and forced splitting in the remnant", &ShowerHandler::PDFB_, false, false, true, true, false); static Reference interfacePDFARemnant ("PDFARemnant", "The PDF for beam particle A used to generate forced splittings of the remnant." " This overrides both the particle's own PDF setting and the value set by PDFA if used.", &ShowerHandler::PDFARemnant_, false, false, true, true, false); static Reference interfacePDFBRemnant ("PDFBRemnant", "The PDF for beam particle B used to generate forced splittings of the remnant." " This overrides both the particle's own PDF setting and the value set by PDFB if used.", &ShowerHandler::PDFBRemnant_, false, false, true, true, false); static Switch interfaceIncludeSpaceTime ("IncludeSpaceTime", "Whether to include the model for the calculation of space-time distances", &ShowerHandler::includeSpaceTime_, false, false, false); static SwitchOption interfaceIncludeSpaceTimeYes (interfaceIncludeSpaceTime, "Yes", "Include the model", true); static SwitchOption interfaceIncludeSpaceTimeNo (interfaceIncludeSpaceTime, "No", "Only include the displacement from the particle-s lifetime for decaying particles", false); static Parameter interfaceMinimumVirtuality ("MinimumVirtuality", "The minimum virtuality for the space-time model", &ShowerHandler::vMin_, GeV2, 0.1*GeV2, 0.0*GeV2, 1000.0*GeV2, false, false, Interface::limited); static Parameter interfaceFactorizationScaleFactor ("FactorizationScaleFactor", "The factorization scale factor.", &ShowerHandler::factorizationScaleFactor_, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceRenormalizationScaleFactor ("RenormalizationScaleFactor", "The renormalization scale factor.", &ShowerHandler::renormalizationScaleFactor_, 1.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceHardScaleFactor ("HardScaleFactor", "The hard scale factor.", &ShowerHandler::hardScaleFactor_, 1.0, 0.0, 0, false, false, Interface::lowerlim); - static Switch interfaceScaleFactorOption - ("ScaleFactorOption", - "Where to apply scale factors.", - &ShowerHandler::scaleFactorOption_, 0, false, false); - static SwitchOption interfaceScaleFactorOptionAll - (interfaceScaleFactorOption, - "All", - "Apply in first and secondary scatterings.", - 0); - static SwitchOption interfaceScaleFactorOptionHard - (interfaceScaleFactorOption, - "Hard", - "Only apply for the hard process.", - 1); - static SwitchOption interfaceScaleFactorOptionSecondary - (interfaceScaleFactorOption, - "Secondary", - "Only apply to secondary scatterings.", - 2); - static Reference interfaceHardScaleProfile ("HardScaleProfile", "The hard scale profile to use.", &ShowerHandler::hardScaleProfile_, false, false, true, true, false); static Switch interfaceMaxPtIsMuF ("MaxPtIsMuF", "", &ShowerHandler::maxPtIsMuF_, false, false, false); static SwitchOption interfaceMaxPtIsMuFYes (interfaceMaxPtIsMuF, "Yes", "", true); static SwitchOption interfaceMaxPtIsMuFNo (interfaceMaxPtIsMuF, "No", "", false); static Switch interfaceRestrictPhasespace ("RestrictPhasespace", "Switch on or off phasespace restrictions", &ShowerHandler::restrictPhasespace_, true, false, false); static SwitchOption interfaceRestrictPhasespaceOn (interfaceRestrictPhasespace, "On", "Perform phasespace restrictions", true); static SwitchOption interfaceRestrictPhasespaceOff (interfaceRestrictPhasespace, "Off", "Do not perform phasespace restrictions", false); static Switch interfaceSplitHardProcess ("SplitHardProcess", "Whether or not to try and split the hard process into production and decay processes", &ShowerHandler::splitHardProcess_, true, false, false); static SwitchOption interfaceSplitHardProcessYes (interfaceSplitHardProcess, "Yes", "Split the hard process", true); static SwitchOption interfaceSplitHardProcessNo (interfaceSplitHardProcess, "No", "Don't split the hard process", false); + + static Command interfaceAddVariation + ("AddVariation", + "Add a shower variation.", + &ShowerHandler::doAddVariation, false); } Energy ShowerHandler::hardScale() const { return evolver_->hardScale(); } void ShowerHandler::cascade() { + // Initialise the weights in the event object + // so that any variations are output regardless of + // whether showering occurs for the given event + initializeWeights(); + tcPDFPtr first = firstPDF().pdf(); tcPDFPtr second = secondPDF().pdf(); if ( PDFA_ ) first = PDFA_; if ( PDFB_ ) second = PDFB_; resetPDFs(make_pair(first,second)); if( ! rempdfs_.first) rempdfs_.first = PDFARemnant_ ? PDFPtr(PDFARemnant_) : const_ptr_cast(first); if( ! rempdfs_.second) rempdfs_.second = PDFBRemnant_ ? PDFPtr(PDFBRemnant_) : const_ptr_cast(second); // get the incoming partons tPPair incomingPartons = eventHandler()->currentCollision()->primarySubProcess()->incoming(); // and the parton bins PBIPair incomingBins = make_pair(lastExtractor()->partonBinInstance(incomingPartons.first), lastExtractor()->partonBinInstance(incomingPartons.second)); // and the incoming hadrons tPPair incomingHadrons = eventHandler()->currentCollision()->incoming(); remDec_->setHadronContent(incomingHadrons); // check if incoming hadron == incoming parton // and get the incoming hadron if exists or parton otherwise incoming_ = make_pair(incomingBins.first ? incomingBins.first ->particle() : incomingPartons.first, incomingBins.second ? incomingBins.second->particle() : incomingPartons.second); // check the collision is of the beam particles // and if not boost collision to the right frame // i.e. the hadron-hadron CMF of the collision bool btotal(false); LorentzRotation rtotal; if(incoming_.first != incomingHadrons.first || incoming_.second != incomingHadrons.second ) { btotal = true; boostCollision(false); } // set the current ShowerHandler currentHandler_ = this; // first shower the hard process useMe(); try { SubProPtr sub = eventHandler()->currentCollision()->primarySubProcess(); incomingPartons = cascade(sub,lastXCombPtr()); } catch(ShowerTriesVeto &veto){ throw Exception() << "Failed to generate the shower after " << veto.tries << " attempts in ShowerHandler::cascade()" << Exception::eventerror; } if(showerHardProcessVeto()) throw Veto(); // if a non-hadron collision return (both incoming non-hadronic) if( ( !incomingBins.first|| !isResolvedHadron(incomingBins.first ->particle()))&& ( !incomingBins.second|| !isResolvedHadron(incomingBins.second->particle()))) { // boost back to lab if needed if(btotal) boostCollision(true); + // perform the reweighting for the hard process shower + combineWeights(); // unset the current ShowerHandler currentHandler_ = 0; return; } // get the remnants for hadronic collision pair remnants(getRemnants(incomingBins)); // set the starting scale of the forced splitting to the PDF freezing scale remDec_->initialize(remnants, incoming_, *currentStep(), pdfFreezingScale()); // do the first forcedSplitting try { remDec_->doSplit(incomingPartons, make_pair(rempdfs_.first,rempdfs_.second), true); } catch (ExtraScatterVeto) { throw Exception() << "Remnant extraction failed in " << "ShowerHandler::cascade() from primary interaction" << Exception::eventerror; } + // perform the reweighting for the hard process shower + combineWeights(); // if no MPI return if( !isMPIOn() ) { remDec_->finalize(); // boost back to lab if needed if(btotal) boostCollision(true); // unset the current ShowerHandler currentHandler_ = 0; return; } // generate the multiple scatters use modified pdf's now: setMPIPDFs(); // additional "hard" processes unsigned int tries(0); // This is the loop over additional hard scatters (most of the time // only one, but who knows...) for(unsigned int i=1; i <= getMPIHandler()->additionalHardProcs(); i++){ //counter for regeneration unsigned int multSecond = 0; // generate the additional scatters while( multSecond < getMPIHandler()->multiplicity(i) ) { // generate the hard scatter tStdXCombPtr lastXC = getMPIHandler()->generate(i); SubProPtr sub = lastXC->construct(); // add to the Step newStep()->addSubProcess(sub); // increment the counters tries++; multSecond++; if(tries == maxtryDP_) throw Exception() << "Failed to establish the requested number " << "of additional hard processes. If this error " << "occurs often, your selection of additional " << "scatter is probably unphysical" << Exception::eventerror; // Generate the shower. If not possible veto the event try { incomingPartons = cascade(sub,lastXC); } catch(ShowerTriesVeto &veto){ throw Exception() << "Failed to generate the shower of " << "a secondary hard process after " << veto.tries << " attempts in Evolver::showerHardProcess()" << Exception::eventerror; } try { // do the forcedSplitting remDec_->doSplit(incomingPartons, make_pair(remmpipdfs_.first,remmpipdfs_.second), false); } catch(ExtraScatterVeto){ //remove all particles associated with the subprocess newStep()->removeParticle(incomingPartons.first); newStep()->removeParticle(incomingPartons.second); //remove the subprocess from the list newStep()->removeSubProcess(sub); //regenerate the scattering multSecond--; continue; } // connect with the remnants but don't set Remnant colour, // because that causes problems due to the multiple colour lines. if ( !remnants.first ->extract(incomingPartons.first , false) || !remnants.second->extract(incomingPartons.second, false) ) throw Exception() << "Remnant extraction failed in " << "ShowerHandler::cascade() for additional scatter" << Exception::runerror; } + // perform the reweighting for the additional hard scatter shower + combineWeights(); } // the underlying event processes unsigned int ptveto(1), veto(0); unsigned int max(getMPIHandler()->multiplicity()); for(unsigned int i=0; i maxtryMPI_) break; //generate PSpoint tStdXCombPtr lastXC = getMPIHandler()->generate(); SubProPtr sub = lastXC->construct(); //If Algorithm=1 additional scatters of the signal type // with pt > ptmin have to be vetoed //with probability 1/(m+1), where m is the number of occurances in this event if( getMPIHandler()->Algorithm() == 1 ){ //get the pT Energy pt = sub->outgoing().front()->momentum().perp(); if(pt > getMPIHandler()->PtForVeto() && UseRandom::rnd() < 1./(ptveto+1) ){ ptveto++; i--; continue; } } // add to the SubProcess to the step newStep()->addSubProcess(sub); // Run the Shower. If not possible veto the scattering try { incomingPartons = cascade(sub,lastXC); } // discard this extra scattering, but try the next one catch(ShowerTriesVeto) { newStep()->removeSubProcess(sub); //regenerate the scattering veto++; i--; continue; } try{ //do the forcedSplitting remDec_->doSplit(incomingPartons, make_pair(remmpipdfs_.first,remmpipdfs_.second), false); } catch (ExtraScatterVeto) { //remove all particles associated with the subprocess newStep()->removeParticle(incomingPartons.first); newStep()->removeParticle(incomingPartons.second); //remove the subprocess from the list newStep()->removeSubProcess(sub); //regenerate the scattering veto++; i--; continue; } //connect with the remnants but don't set Remnant colour, //because that causes problems due to the multiple colour lines. if ( !remnants.first ->extract(incomingPartons.first , false) || !remnants.second->extract(incomingPartons.second, false) ) throw Exception() << "Remnant extraction failed in " << "ShowerHandler::cascade() for MPI hard scattering" << Exception::runerror; //reset veto counter veto = 0; + // perform the reweighting for the MPI process shower + combineWeights(); } // finalize the remnants remDec_->finalize(getMPIHandler()->colourDisrupt(), getMPIHandler()->softMultiplicity()); // boost back to lab if needed if(btotal) boostCollision(true); // unset the current ShowerHandler currentHandler_ = 0; getMPIHandler()->clean(); } void ShowerHandler::fillEventRecord() { // create a new step StepPtr pstep = newStep(); assert(!done_.empty()); assert(done_[0]->isHard()); // insert the steps for(unsigned int ix=0;ixfillEventRecord(pstep, evolver_->isISRadiationON(), evolver_->isFSRadiationON()); } } void ShowerHandler::prepareCascade(tSubProPtr sub) { current_ = currentStep(); subProcess_ = sub; } +void ShowerHandler::initializeWeights() { + if ( !showerVariations().empty() ) { + + tEventPtr event = eventHandler()->currentEvent(); + + for ( map::const_iterator var = + showerVariations().begin(); + var != showerVariations().end(); ++var ) { + + // Check that this is behaving as intended + //map::iterator wi = event->optionalWeights().find(var->first); + //assert(wi == event->optionalWeights().end() ); + + event->optionalWeights()[var->first] = 1.0; + currentWeights_[var->first] = 1.0; + } + } + reweight_ = 1.0; +} + +void ShowerHandler::resetWeights() { + for ( map::iterator w = currentWeights_.begin(); + w != currentWeights_.end(); ++w ) { + w->second = 1.0; + } + reweight_ = 1.0; +} + +void ShowerHandler::combineWeights() { + tEventPtr event = eventHandler()->currentEvent(); + for ( map::const_iterator w = + currentWeights_.begin(); w != currentWeights_.end(); ++w ) { + map::iterator ew = event->optionalWeights().find(w->first); + if ( ew != event->optionalWeights().end() ) + ew->second *= w->second; + else { + assert(false && "Weight name unknown."); + //event->optionalWeights()[w->first] = w->second; + } + } + if ( reweight_ != 1.0 ) { + Ptr::tptr eh = + dynamic_ptr_cast::tptr>(eventHandler()); + if ( !eh ) { + throw Exception() << "ShowerHandler::combineWeights() : Cross section reweighting " + << "through the shower is currently only available with standard " + << "event generators" << Exception::runerror; + } + eh->reweight(reweight_); + } +} + +string ShowerHandler::ShowerVariation::fromInFile(const string& in) { + // pretty simple for the moment, just to try + // TODO make this better + istringstream read(in); + string where; + read >> renormalizationScaleFactor >> factorizationScaleFactor >> where; + if ( !read ) + return "something went wrong with: " + in; + if ( where != "Hard" && where != "All" && where!= "Secondary" ) + return "The specified process for reweighting does not exist.\nOptions are: Hard, Secondary, All."; + if ( where == "Hard" || where == "All" ) + firstInteraction = true; + else + firstInteraction = false; + if ( where == "Secondary" || where == "All" ) + secondaryInteractions = true; + else + secondaryInteractions = false; + return ""; +} + +void ShowerHandler::ShowerVariation::put(PersistentOStream& os) const { + os << renormalizationScaleFactor << factorizationScaleFactor + << firstInteraction << secondaryInteractions; +} + +void ShowerHandler::ShowerVariation::get(PersistentIStream& is) { + is >> renormalizationScaleFactor >> factorizationScaleFactor + >> firstInteraction >> secondaryInteractions; +} + +string ShowerHandler::doAddVariation(string in) { + if ( in.empty() ) + return "expecting a name and a variation specification"; + string name = StringUtils::car(in); + ShowerVariation var; + string res = var.fromInFile(StringUtils::cdr(in)); + if ( res.empty() ) { + if ( !var.firstInteraction && !var.secondaryInteractions ) { + // TODO what about decay showers? + return "variation does not apply to any shower"; + } + if ( var.renormalizationScaleFactor == 1.0 && + var.factorizationScaleFactor == 1.0 ) { + return "variation does not vary anything"; + } + /* + Repository::clog() << "adding a variation with tag '" << name << "' using\nxir = " + << var.renormalizationScaleFactor + << " xif = " + << var.factorizationScaleFactor + << "\napplying to:\n" + << "first interaction = " << var.firstInteraction << " " + << "secondary interactions = " << var.secondaryInteractions << "\n" + << flush; + */ + showerVariations()[name] = var; + } + return res; +} + tPPair ShowerHandler::cascade(tSubProPtr sub, XCPtr xcomb) { prepareCascade(sub); + resetWeights(); // set the scale variation factors; needs to go after prepareCascade // to trigger possible different variations for hard and secondary // scatters evolver()->renormalizationScaleFactor(renormalizationScaleFactor()); evolver()->factorizationScaleFactor(factorizationScaleFactor()); evolver()->restrictPhasespace(restrictPhasespace()); evolver()->hardScaleIsMuF(hardScaleIsMuF()); // start of the try block for the whole showering process unsigned int countFailures=0; while (countFailuresoutgoing().begin(), currentSubProcess()->outgoing().end()), splitHardProcess_); // if no hard process if(!hard_) throw Exception() << "Shower starting with a decay" << "is not implemented" << Exception::runerror; // perform the shower for the hard process evolver_->showerHardProcess(hard_,xcomb); done_.push_back(hard_); hard_->updateAfterShower(decay_); // if no decaying particles to shower break out of the loop if(decay_.empty()) break; // shower the decay products while(!decay_.empty()) { // find particle whose production process has been showered ShowerDecayMap::iterator dit = decay_.begin(); while(!dit->second->parent()->hasShowered() && dit!=decay_.end()) ++dit; assert(dit!=decay_.end()); // get the particle ShowerTreePtr decayingTree = dit->second; // remove it from the multimap decay_.erase(dit); // make sure the particle has been decayed decayingTree->decay(decay_); // now shower the decay evolver_->showerDecay(decayingTree); done_.push_back(decayingTree); decayingTree->updateAfterShower(decay_); } // suceeded break out of the loop break; } catch (KinematicsReconstructionVeto) { + resetWeights(); ++countFailures; } } // if loop exited because of too many tries, throw event away if (countFailures >= maxtry_) { + resetWeights(); hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); throw Exception() << "Too many tries for main while loop " << "in ShowerHandler::cascade()." << Exception::eventerror; } //enter the particles in the event record fillEventRecord(); // clear storage hard_=ShowerTreePtr(); decay_.clear(); done_.clear(); // non hadronic case return if (!isResolvedHadron(incoming_.first ) && !isResolvedHadron(incoming_.second) ) return incoming_; // remake the remnants (needs to be after the colours are sorted // out in the insertion into the event record) if ( firstInteraction() ) return remakeRemnant(sub->incoming()); //Return the new pair of incoming partons. remakeRemnant is not //necessary here, because the secondary interactions are not yet //connected to the remnants. return make_pair(findFirstParton(sub->incoming().first ), findFirstParton(sub->incoming().second)); } ShowerHandler::RemPair ShowerHandler::getRemnants(PBIPair incomingBins) { RemPair remnants; // first beam particle if(incomingBins.first&&!incomingBins.first->remnants().empty()) { remnants.first = dynamic_ptr_cast(incomingBins.first->remnants()[0] ); if(remnants.first) { ParticleVector children=remnants.first->children(); for(unsigned int ix=0;ixdataPtr()==remnants.first->dataPtr()) remnants.first = dynamic_ptr_cast(children[ix]); } //remove existing colour lines from the remnants if(remnants.first->colourLine()) remnants.first->colourLine()->removeColoured(remnants.first); if(remnants.first->antiColourLine()) remnants.first->antiColourLine()->removeAntiColoured(remnants.first); } } // seconnd beam particle if(incomingBins.second&&!incomingBins. second->remnants().empty()) { remnants.second = dynamic_ptr_cast(incomingBins.second->remnants()[0] ); if(remnants.second) { ParticleVector children=remnants.second->children(); for(unsigned int ix=0;ixdataPtr()==remnants.second->dataPtr()) remnants.second = dynamic_ptr_cast(children[ix]); } //remove existing colour lines from the remnants if(remnants.second->colourLine()) remnants.second->colourLine()->removeColoured(remnants.second); if(remnants.second->antiColourLine()) remnants.second->antiColourLine()->removeAntiColoured(remnants.second); } } assert(remnants.first || remnants.second); return remnants; } tPPair ShowerHandler::remakeRemnant(tPPair oldp){ // get the parton extractor PartonExtractor & pex = *lastExtractor(); // get the new partons tPPair newp = make_pair(findFirstParton(oldp.first ), findFirstParton(oldp.second)); // if the same do nothing if(newp == oldp) return oldp; // Creates the new remnants and returns the new PartonBinInstances // ATTENTION Broken here for very strange configuration PBIPair newbins = pex.newRemnants(oldp, newp, newStep()); newStep()->addIntermediate(newp.first); newStep()->addIntermediate(newp.second); // return the new partons return newp; } PPtr ShowerHandler::findFirstParton(tPPtr seed) const{ if(seed->parents().empty()) return seed; tPPtr parent = seed->parents()[0]; //if no parent there this is a loose end which will //be connected to the remnant soon. if(!parent || parent == incoming_.first || parent == incoming_.second ) return seed; else return findFirstParton(parent); } namespace { void addChildren(tPPtr in,set & particles) { particles.insert(in); for(unsigned int ix=0;ixchildren().size();++ix) addChildren(in->children()[ix],particles); } } void ShowerHandler::boostCollision(bool boost) { // calculate boost from lab to rest if(!boost) { Lorentz5Momentum ptotal=incoming_.first ->momentum()+incoming_.second->momentum(); boost_ = LorentzRotation(-ptotal.boostVector()); Axis axis((boost_*incoming_.first ->momentum()).vect().unit()); if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); boost_.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } } // first call performs the boost and second inverse // get the particles to be boosted set particles; addChildren(incoming_.first,particles); addChildren(incoming_.second,particles); // apply the boost for(set::const_iterator cit=particles.begin(); cit!=particles.end();++cit) { (*cit)->transform(boost_); } if(!boost) boost_.invert(); } void ShowerHandler::setMPIPDFs() { if ( !mpipdfs_.first ) { // first have to check for MinBiasPDF tcMinBiasPDFPtr first = dynamic_ptr_cast(firstPDF().pdf()); if(first) mpipdfs_.first = new_ptr(MPIPDF(first->originalPDF())); else mpipdfs_.first = new_ptr(MPIPDF(firstPDF().pdf())); } if ( !mpipdfs_.second ) { tcMinBiasPDFPtr second = dynamic_ptr_cast(secondPDF().pdf()); if(second) mpipdfs_.second = new_ptr(MPIPDF(second->originalPDF())); else mpipdfs_.second = new_ptr(MPIPDF(secondPDF().pdf())); } if( !remmpipdfs_.first ) { tcMinBiasPDFPtr first = dynamic_ptr_cast(rempdfs_.first); if(first) remmpipdfs_.first = new_ptr(MPIPDF(first->originalPDF())); else remmpipdfs_.first = new_ptr(MPIPDF(rempdfs_.first)); } if( !remmpipdfs_.second ) { tcMinBiasPDFPtr second = dynamic_ptr_cast(rempdfs_.second); if(second) remmpipdfs_.second = new_ptr(MPIPDF(second->originalPDF())); else remmpipdfs_.second = new_ptr(MPIPDF(rempdfs_.second)); } // reset the PDFs stored in the base class resetPDFs(mpipdfs_); } bool ShowerHandler::isResolvedHadron(tPPtr particle) { if(!HadronMatcher::Check(particle->data())) return false; for(unsigned int ix=0;ixchildren().size();++ix) { if(particle->children()[ix]->id()==ParticleID::Remnant) return true; } return false; } HardTreePtr ShowerHandler::generateCKKW(ShowerTreePtr ) const { return HardTreePtr(); } + diff --git a/Shower/ShowerHandler.h b/Shower/ShowerHandler.h --- a/Shower/ShowerHandler.h +++ b/Shower/ShowerHandler.h @@ -1,581 +1,691 @@ // -*- C++ -*- // // ShowerHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_ShowerHandler_H #define HERWIG_ShowerHandler_H // // This is the declaration of the ShowerHandler class. // #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "Herwig/Shower/UEBase.h" #include "Herwig/Shower/Base/Evolver.fh" #include "Herwig/Shower/Base/ShowerParticle.fh" #include "Herwig/Shower/Base/ShowerTree.fh" #include "Herwig/Shower/Base/HardTree.fh" #include "Herwig/PDF/HwRemDecayer.fh" #include "ThePEG/EventRecord/RemnantParticle.fh" #include "ShowerHandler.fh" #include "Herwig/MatrixElement/Matchbox/Matching/HardScaleProfile.h" namespace Herwig { /** * Typedef for the ShowerTree for the decays */ typedef multimap > ShowerDecayMap; using namespace ThePEG; /** \ingroup Shower * * This class is the main driver of the shower: it is responsible for * the proper handling of all other specific collaborating classes * and for the storing of the produced particles in the event record. * * @see \ref ShowerHandlerInterfaces "The interfaces" * * @see ThePEG::CascadeHandler * @see MPIHandler * @see HwRemDecayer */ class ShowerHandler: public CascadeHandler { public: /** Typedef for a pair of ThePEG::RemnantParticle pointers. */ typedef pair RemPair; /** * The default constructor. */ ShowerHandler(); /** * Destructor */ virtual ~ShowerHandler(); public: /** * The main method which manages the multiple interactions and starts * the shower by calling cascade(sub, lastXC). */ virtual void cascade(); /** * Hook to allow vetoing of event after showering hard sub-process * as in e.g. MLM merging. */ - virtual bool showerHardProcessVeto() { return false; }; + virtual bool showerHardProcessVeto() const { return false; } /** * Return true, if this cascade handler will perform reshuffling from hard * process masses. */ virtual bool isReshuffling() const { return true; } public: /**@name Methods related to PDF freezing */ //@{ /** * Get the PDF freezing scale */ - Energy pdfFreezingScale() const {return pdfFreezingScale_;} + Energy pdfFreezingScale() const { return pdfFreezingScale_; } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); public: /** @name Functions to access information. */ //@{ /** * Return true if currently the primary subprocess is showered. */ bool firstInteraction() const { return ( subProcess_ == eventHandler()->currentCollision()->primarySubProcess() ); } /** * Return the currently used SubProcess. */ tSubProPtr currentSubProcess() const { assert(subProcess_); return subProcess_; } /** * Return true if multiple parton interactions are switched on * and can be used for this beam setup. */ bool isMPIOn() const { return MPIHandler_ && MPIHandler_->beamOK(); } /** * Return the remnant decayer. */ tHwRemDecPtr remnantDecayer() const { return remDec_; } //@} /** * Access to the Evolver */ tEvolverPtr evolver() const {return evolver_;} /** * Generate hard emissions for CKKW etc */ virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const; /** * Return true, if the shower handler can generate a truncated * shower for POWHEG style events generated using Matchbox */ virtual bool canHandleMatchboxTrunc() const { return false; } /** * The factorization scale factor. */ double factorizationScaleFactor() const { - if ( scaleFactorOption_ == 0 || !subProcess_ ) return factorizationScaleFactor_; - if ( scaleFactorOption_ == 1 ) - return firstInteraction() ? factorizationScaleFactor_ : 1.0; - if ( scaleFactorOption_ == 2 ) - return !firstInteraction() ? factorizationScaleFactor_ : 1.0; - return 1.0; } /** * The renormalization scale factor. */ - double renormalizationScaleFactor() const { - if ( scaleFactorOption_ == 0 || !subProcess_ ) - return renormalizationScaleFactor_; - if ( scaleFactorOption_ == 1 ) - return firstInteraction() ? renormalizationScaleFactor_ : 1.0; - if ( scaleFactorOption_ == 2 ) - return !firstInteraction() ? renormalizationScaleFactor_ : 1.0; - return 1.0; + double renormalizationScaleFactor() const { + return renormalizationScaleFactor_ ; } /** * The scale factor for the hard scale */ - double hardScaleFactor() const { - if ( scaleFactorOption_ == 0 || !subProcess_ ) - return hardScaleFactor_; - if ( scaleFactorOption_ == 1 ) - return firstInteraction() ? hardScaleFactor_ : 1.0; - if ( scaleFactorOption_ == 2 ) - return !firstInteraction() ? hardScaleFactor_ : 1.0; - return 1.0; + double hardScaleFactor() const { + return hardScaleFactor_; } /** - * The option on when to apply the scale factors - */ - int scaleFactorOption() const { return scaleFactorOption_; } - - /** * Return true, if the phase space restrictions of the dipole shower should * be applied. */ bool restrictPhasespace() const { return restrictPhasespace_; } /** * Return profile scales */ Ptr::tptr profileScales() const { return hardScaleProfile_; } /** * Return the relevant hard scale to be used in the profile scales */ virtual Energy hardScale() const; /** * Return true if maximum pt should be deduced from the factorization scale */ bool hardScaleIsMuF() const { return maxPtIsMuF_; } + /** + * A struct identifying a shower variation + */ + struct ShowerVariation { + + /** + * Vary the renormalization scale by the given factor. + */ + double renormalizationScaleFactor; + + /** + * Vary the factorization scale by the given factor. + */ + double factorizationScaleFactor; + + /** + * Apply the variation to the first interaction + */ + bool firstInteraction; + + /** + * Apply the variation to the secondary interactions + */ + bool secondaryInteractions; + + /** + * Default constructor + */ + ShowerVariation() + : renormalizationScaleFactor(1.0), + factorizationScaleFactor(1.0), + firstInteraction(true), + secondaryInteractions(false) {} + + /** + * Parse from in file command + */ + string fromInFile(const string&); + + /** + * Put to persistent stream + */ + void put(PersistentOStream& os) const; + + /** + * Get from persistent stream + */ + void get(PersistentIStream& is); + + }; + + /** + * Access the shower variations + */ + map& showerVariations() { + return showerVariations_; + } + + /** + * Return the shower variations + */ + const map& showerVariations() const { + return showerVariations_; + } + + /** + * Access the current Weights + */ + map& currentWeights() { + return currentWeights_; + } + + /** + * Return the current Weights + */ + const map& currentWeights() const { + return currentWeights_; + } + + /** + * Change the current reweighting factor + */ + void reweight(double w) { + reweight_ = w; + } + + /** + * Return the current reweighting factor + */ + double reweight() const { + return reweight_; + } + +protected: + + /** + * A reweighting factor applied by the showering + */ + double reweight_; + + /** + * The shower variation weights + */ + map currentWeights_; + + /** + * Combine the variation weights which have been encountered + */ + void combineWeights(); + + /** + * Initialise the weights in currentEvent() + */ + void initializeWeights(); + + /** + * Reset the current weights + */ + void resetWeights(); + 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: /** * Prepare to shower the given subprocess */ void prepareCascade(tSubProPtr sub); /** * The main method which manages the showering of a subprocess. */ virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb); /** * Return the maximum number of attempts for showering * a given subprocess. */ unsigned int maxtry() const { return maxtry_; } /** * At the end of the Showering, transform ShowerParticle objects * into ThePEG particles and fill the event record with them. * Notice that the parent/child relationships and the * transformation from ShowerColourLine objects into ThePEG * ColourLine ones must be properly handled. */ void fillEventRecord(); /** * Find the parton extracted from the incoming particle after ISR */ PPtr findFirstParton(tPPtr seed) const; /** * Fix Remnant connections after ISR */ tPPair remakeRemnant(tPPair oldp); /** * Get the remnants from the ThePEG::PartonBinInstance es and * do some checks. */ RemPair getRemnants(PBIPair incbins); /** * Make the remnant after the shower */ void makeRemnants(); /** * Reset the PDF's after the hard collision has been showered */ void setMPIPDFs(); /** * Boost all the particles in the collision so that the collision always occurs * in the rest frame with the incoming particles along the z axis */ void boostCollision(bool boost); /** * Is a beam particle where hadronic structure is resolved */ bool isResolvedHadron(tPPtr); 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(); /** * Called at the end of the run phase. */ virtual void dofinish(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerHandler & operator=(const ShowerHandler &); private: /** * Access function for the MPIHandler, it should only be called after * checking with isMPIOn. */ tUEBasePtr getMPIHandler() const { assert(MPIHandler_); return MPIHandler_; } private: /** * a MPIHandler to administer the creation of several (semihard) * partonic interactions. */ UEBasePtr MPIHandler_; /** * Pointer to the evolver */ EvolverPtr evolver_; /** * Pointer to the HwRemDecayer */ HwRemDecPtr remDec_; /** * The PDF for beam particle A. Overrides the particle's own PDF setting. */ PDFPtr PDFA_; /** * The PDF for beam particle B. Overrides the particle's own PDF setting. */ PDFPtr PDFB_; /** * The PDF for beam particle A for remnant splitting. Overrides the particle's own PDF setting. */ PDFPtr PDFARemnant_; /** * The PDF for beam particle B for remnant splitting. Overrides the particle's own PDF setting. */ PDFPtr PDFBRemnant_; /** * The PDF freezing scale */ Energy pdfFreezingScale_; /** * Maximum number of attempts for the * main showering loop */ unsigned int maxtry_; /** * Maximum number of attempts for the regeneration of an additional * scattering, before the number of scatters is reduced. */ unsigned int maxtryMPI_; /** * Maximum number of attempts for the regeneration of an additional * hard scattering, before this event is vetoed. */ unsigned int maxtryDP_; /** * PDG codes of the particles which decay during showering * this is fast storage for use during running */ set particlesDecayInShower_; /** * PDG codes of the particles which decay during showering * this is a vector that is interfaced so they can be changed */ vector inputparticlesDecayInShower_; /** * Whether or not to include spa-cetime distances in the shower */ bool includeSpaceTime_; /** * The minimum virtuality for the space-time model */ Energy2 vMin_; /** * The ShowerTree for the hard process */ ShowerTreePtr hard_; /** * The incoming beam particles for the current collision */ tPPair incoming_; /** * The ShowerTree for the decays */ ShowerDecayMap decay_; /** * The ShowerTrees for which the initial shower */ vector done_; /** * Const pointer to the current step */ tcStepPtr current_; /** * Const pointer to the currently handeled ThePEG::SubProcess */ tSubProPtr subProcess_; /** * pointer to "this", the current ShowerHandler. */ static ShowerHandler * currentHandler_; /** * Boost to get back to the lab */ LorentzRotation boost_; /** * The MPI PDF's to be used for secondary scatters. */ pair mpipdfs_; /** * The MPI PDF's to be used for secondary scatters. */ pair rempdfs_; /** * The MPI PDF's to be used for secondary scatters. */ pair remmpipdfs_; /** * The factorization scale factor. */ double factorizationScaleFactor_; /** * The renormalization scale factor. */ double renormalizationScaleFactor_; /** * The scale factor for the hard scale */ double hardScaleFactor_; /** - * The option on when to apply the scale factors - */ - int scaleFactorOption_; - - /** * True, if the phase space restrictions of the dipole shower should * be applied. */ bool restrictPhasespace_; /** * True if maximum pt should be deduced from the factorization scale */ bool maxPtIsMuF_; /** * The profile scales */ Ptr::ptr hardScaleProfile_; /** * Whether or not to split into hard and decay trees */ bool splitHardProcess_; + /** + * The shower variations + */ + map showerVariations_; + + /** + * Command to add a shower variation + */ + string doAddVariation(string); + public: /** * struct that is used to catch exceptions which are thrown * due to energy conservation issues of additional scatters */ struct ExtraScatterVeto {}; /** * struct that is used to catch exceptions which are thrown * due to fact that the Shower has been invoked more than * a defined threshold on a certain configuration */ struct ShowerTriesVeto { /** variable to store the number of attempts */ const int tries; /** constructor */ ShowerTriesVeto(int t) : tries(t) {} }; /** * pointer to "this", the current ShowerHandler. */ - static const ShowerHandler * currentHandler() { + static ShowerHandler * currentHandler() { assert(currentHandler_); return currentHandler_; } protected: /** * Set the current handler */ void setCurrentHandler() { currentHandler_ = this; } }; +inline PersistentOStream& operator<<(PersistentOStream& os, const ShowerHandler::ShowerVariation& var) { + var.put(os); return os; +} + +inline PersistentIStream& operator>>(PersistentIStream& is, ShowerHandler::ShowerVariation& var) { + var.get(is); return is; +} + } #endif /* HERWIG_ShowerHandler_H */ diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -1,264 +1,244 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.63]) AC_INIT([Herwig],[trunk],[herwig@projects.hepforge.org],[Herwig]) AC_CONFIG_SRCDIR([Utilities/HerwigStrategy.cc]) AC_CONFIG_AUX_DIR([Config]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([Config/config.h]) dnl AC_PRESERVE_HELP_ORDER AC_CANONICAL_HOST dnl === disable debug symbols by default ===== if test "x$CXXFLAGS" = "x"; then CXXFLAGS=-O3 fi if test "x$CFLAGS" = "x"; then CFLAGS=-O3 fi AC_LANG([C++]) AM_INIT_AUTOMAKE([1.11 subdir-objects gnu dist-bzip2 no-dist-gzip -Wall]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) dnl Checks for C++ compiler. Handle C++11 flags. -AC_PROG_CXX([g++]) - -dnl this block can go once we decide to have C++11 always on -AC_MSG_CHECKING([whether to include C++11 flag for testing]) -AC_ARG_ENABLE(stdcxx11, - AC_HELP_STRING([--enable-stdcxx11], - [turn on C++11 flag (only for testing, do not use in production!)]), - [], - [enable_stdcxx11=no] - ) - - -if test "x$enable_stdcxx11" = "xyes"; then -AC_MSG_RESULT([yes]) -dnl remove the wrapper if block and "optional" once we decide to have C++11 always on -AX_CXX_COMPILE_STDCXX_11([noext],[optional]) -if test "x$HAVE_CXX11" != "x1"; then -AC_MSG_ERROR([compiler does not recognize requested c++11 option]) -fi -else -AC_MSG_RESULT([no]) -fi +AC_PROG_CXX +AX_CXX_COMPILE_STDCXX([11],[noext],[mandatory]) dnl check for POSIX AC_CHECK_HEADER([unistd.h],[], [AC_MSG_ERROR([Herwig needs "unistd.h". Non-POSIX systems are not supported.])]) dnl Checks for programs. AC_PROG_INSTALL AC_PROG_MAKE_SET AC_PROG_LN_S dnl modified search order AC_PROG_FC([gfortran g95 g77]) dnl xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn xlf90 f90 pgf90 pghpf epcf90 xlf f77 frt pgf77 cf77 fort77 fl32 af77]) AC_LANG_PUSH([Fortran]) AC_MSG_CHECKING([if the Fortran compiler ($FC) works]) AC_COMPILE_IFELSE( AC_LANG_PROGRAM([],[ print *[,]"Hello"]), [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([A Fortran compiler is required to build Herwig.]) ] ) AC_LANG_POP([Fortran]) LT_PREREQ([2.2.6]) LT_INIT([disable-static dlopen pic-only]) dnl #################################### dnl #################################### dnl for Doc/fixinterfaces.pl AC_PATH_PROG(PERL, perl) dnl for Models/Feynrules AM_PATH_PYTHON([2.6],, [:]) AM_CONDITIONAL([HAVE_PYTHON], [test "x$PYTHON" != "x:"]) HERWIG_CHECK_GSL HERWIG_CHECK_THEPEG BOOST_REQUIRE([1.41]) BOOST_FIND_HEADER([boost/array.hpp]) BOOST_FIND_HEADER([boost/numeric/ublas/io.hpp]) BOOST_FIND_HEADER([boost/numeric/ublas/matrix.hpp]) BOOST_FIND_HEADER([boost/numeric/ublas/matrix_proxy.hpp]) BOOST_FIND_HEADER([boost/numeric/ublas/matrix_sparse.hpp]) BOOST_FIND_HEADER([boost/numeric/ublas/symmetric.hpp]) BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp]) BOOST_FIND_HEADER([boost/operators.hpp]) BOOST_FIND_HEADER([boost/progress.hpp]) BOOST_FIND_HEADER([boost/scoped_array.hpp]) BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) BOOST_FIND_HEADER([boost/utility.hpp]) BOOST_FILESYSTEM([mt]) BOOST_TEST() HERWIG_CHECK_VBFNLO HERWIG_CHECK_NJET HERWIG_CHECK_GOSAM HERWIG_CHECK_GOSAM_CONTRIB HERWIG_CHECK_OPENLOOPS HERWIG_CHECK_MADGRAPH HERWIG_CHECK_EVTGEN HERWIG_CHECK_PYTHIA HERWIG_COMPILERFLAGS HERWIG_LOOPTOOLS HERWIG_PDF_PATH FASTJET_CHECK_FASTJET HERWIG_CHECK_ABS_BUG HERWIG_ENABLE_MODELS SHARED_FLAG=-shared AM_CONDITIONAL(NEED_APPLE_FIXES, [test "xx${host/darwin/foundit}xx" != "xx${host}xx"]) if test "xx${host/darwin/foundit}xx" != "xx${host}xx"; then APPLE_DSO_FLAGS=-Wl,-undefined,dynamic_lookup SHARED_FLAG=-bundle fi AC_SUBST([APPLE_DSO_FLAGS]) AC_SUBST([SHARED_FLAG]) AC_CONFIG_FILES([UnderlyingEvent/Makefile Models/Makefile Models/StandardModel/Makefile Models/RSModel/Makefile Models/General/Makefile Models/Susy/Makefile Models/Susy/NMSSM/Makefile Models/Susy/RPV/Makefile Models/UED/Makefile Models/LH/Makefile Models/LHTP/Makefile Models/Transplanckian/Makefile Models/Leptoquarks/Makefile Models/Zprime/Makefile Models/TTbAsymm/Makefile Models/Feynrules/Makefile Models/Feynrules/python/Makefile-FR Models/ADD/Makefile Models/Sextet/Makefile Decay/Makefile Decay/FormFactors/Makefile Decay/Tau/Makefile Decay/Baryon/Makefile Decay/VectorMeson/Makefile Decay/Perturbative/Makefile Decay/ScalarMeson/Makefile Decay/TensorMeson/Makefile Decay/WeakCurrents/Makefile Decay/Partonic/Makefile Decay/General/Makefile Decay/Radiation/Makefile Decay/EvtGen/Makefile Doc/refman.conf Doc/refman.h PDT/Makefile PDF/Makefile MatrixElement/Makefile MatrixElement/General/Makefile MatrixElement/Lepton/Makefile MatrixElement/Hadron/Makefile MatrixElement/DIS/Makefile MatrixElement/Powheg/Makefile MatrixElement/Gamma/Makefile MatrixElement/Reweighters/Makefile MatrixElement/Matchbox/Makefile MatrixElement/Matchbox/Base/Makefile MatrixElement/Matchbox/Utility/Makefile MatrixElement/Matchbox/Phasespace/Makefile MatrixElement/Matchbox/Dipoles/Makefile MatrixElement/Matchbox/InsertionOperators/Makefile MatrixElement/Matchbox/Matching/Makefile MatrixElement/Matchbox/Cuts/Makefile MatrixElement/Matchbox/Scales/Makefile MatrixElement/Matchbox/Scales/MatchboxScale.cc MatrixElement/Matchbox/ColorFull/Makefile MatrixElement/Matchbox/CVolver/Makefile MatrixElement/Matchbox/Builtin/Makefile MatrixElement/Matchbox/Builtin/Amplitudes/Makefile MatrixElement/Matchbox/Tests/Makefile MatrixElement/Matchbox/External/Makefile MatrixElement/Matchbox/External/BLHAGeneric/Makefile MatrixElement/Matchbox/External/VBFNLO/Makefile MatrixElement/Matchbox/External/NJet/Makefile MatrixElement/Matchbox/External/GoSam/Makefile MatrixElement/Matchbox/External/OpenLoops/Makefile MatrixElement/Matchbox/External/MadGraph/Makefile MatrixElement/Matchbox/External/MadGraph/mg2herwig.py Sampling/Makefile Sampling/CellGrids/Makefile Shower/Makefile Shower/Matching/Makefile DipoleShower/Makefile DipoleShower/Base/Makefile DipoleShower/Kernels/Makefile DipoleShower/Kinematics/Makefile DipoleShower/Utility/Makefile DipoleShower/AlphaS/Makefile Utilities/Makefile Utilities/XML/Makefile Utilities/Statistics/Makefile Hadronization/Makefile lib/Makefile include/Makefile src/Makefile src/defaults/Makefile src/snippets/Makefile src/Matchbox/Makefile src/herwig-config Doc/Makefile Doc/HerwigDefaults.in Looptools/Makefile Analysis/Makefile src/Makefile-UserModules src/defaults/Analysis.in src/defaults/MatchboxDefaults.in src/defaults/Decays.in src/defaults/decayers.in src/defaults/setup.gosam.in src/Matchbox/LO-DefaultShower.in src/Matchbox/LO-DipoleShower.in src/Matchbox/MCatLO-DefaultShower.in src/Matchbox/MCatLO-DipoleShower.in src/Matchbox/LO-NoShower.in src/Matchbox/MCatNLO-DefaultShower.in src/Matchbox/MCatNLO-DipoleShower.in src/Matchbox/NLO-NoShower.in src/Matchbox/Powheg-DefaultShower.in src/Matchbox/Powheg-DipoleShower.in Contrib/Makefile Contrib/make_makefiles.sh Tests/Makefile Makefile]) AC_CONFIG_LINKS([Doc/BSMlibs.in:Doc/BSMlibs.in]) AC_CONFIG_FILES([Doc/fixinterfaces.pl],[chmod +x Doc/fixinterfaces.pl]) HERWIG_OVERVIEW AC_CONFIG_COMMANDS([summary],[cat config.herwig]) AC_OUTPUT diff --git a/lib/Makefile.am b/lib/Makefile.am --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,49 +1,49 @@ pkglib_LTLIBRARIES = Herwig.la Herwig_la_SOURCES = Herwig_la_LIBTOOLFLAGS = --tag=CXX -Herwig_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 17:0:0 +Herwig_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 18:0:0 Herwig_la_LDFLAGS += $(THEPEGLDFLAGS) $(BOOST_SYSTEM_LDFLAGS) $(BOOST_FILESYSTEM_LDFLAGS) $(FCLIBS) Herwig_la_LIBADD = \ $(top_builddir)/Hadronization/libHwHadronization.la \ $(top_builddir)/Models/StandardModel/libHwStandardModel.la \ $(top_builddir)/Decay/libHwDecay.la \ $(top_builddir)/Decay/FormFactors/libHwFormFactor.la \ $(top_builddir)/Decay/Radiation/libHwDecRad.la \ $(top_builddir)/Utilities/libHwUtils.la \ $(top_builddir)/Models/General/libHwModelGenerator.la \ $(top_builddir)/Decay/General/libHwGeneralDecay.la \ $(top_builddir)/MatrixElement/General/libHwGeneralME.la \ $(top_builddir)/MatrixElement/libHwME.la \ $(top_builddir)/MatrixElement/Reweighters/libHwReweighters.la \ $(top_builddir)/MatrixElement/Matchbox/libHwMatchbox.la \ $(top_builddir)/Decay/WeakCurrents/libHwWeakCurrent.la \ $(top_builddir)/Looptools/libHwLooptools.la \ $(top_builddir)/Shower/libHwShower.la \ $(THEPEGLIB) $(BOOST_SYSTEM_LIBS) $(BOOST_FILESYSTEM_LIBS) -ldl dist_noinst_SCRIPTS = fix-osx-path POSTPROCESSING = done-all-links if NEED_APPLE_FIXES POSTPROCESSING += apple-fixes endif all-local: $(POSTPROCESSING) done-all-links: Herwig.la find $(top_builddir) \( -name '*.so.*' -or -name '*.so' \) \ -not -name 'lib*' -not -path '$(top_builddir)/lib/*' \ -not -path '$(top_builddir)/.hg/*' -exec $(LN_S) -f \{\} \; $(LN_S) -f .libs/Herwig*so* . echo "stamp" > $@ apple-fixes: fix-osx-path done-all-links ./$< echo "stamp" > $@ clean-local: rm -f *.so *.so.* done-all-links apple-fixes diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx.m4 rename from m4/ax_cxx_compile_stdcxx_11.m4 rename to m4/ax_cxx_compile_stdcxx.m4 --- a/m4/ax_cxx_compile_stdcxx_11.m4 +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -1,133 +1,562 @@ -# ============================================================================ -# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html -# ============================================================================ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== # # SYNOPSIS # -# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # -# Check for baseline language coverage in the compiler for the C++11 -# standard; if necessary, add switches to CXXFLAGS to enable support. +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). # -# The first argument, if specified, indicates whether you insist on an +# The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for an extended mode. # -# The second argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline C++11 support is required and that the macro -# should error out if no mode with that support is found. If specified -# 'optional', then configuration proceeds regardless, after defining -# HAVE_CXX11 if and only if a supporting mode is found. +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any +# and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 3 +#serial 4 -m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [ - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); - - auto d = a; -]) - -AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl - m4_if([$1], [], [], - [$1], [ext], [], - [$1], [noext], [], - [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl - m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], - [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], - [$2], [optional], [ax_cxx_compile_cxx11_required=false], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [], + [$1], [14], [], + [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no - AC_CACHE_CHECK(whether $CXX supports C++11 features by default, - ax_cv_cxx_compile_cxx11, - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [ax_cv_cxx_compile_cxx11=yes], - [ax_cv_cxx_compile_cxx11=no])]) - if test x$ax_cv_cxx_compile_cxx11 = xyes; then + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then ac_success=yes fi - m4_if([$1], [noext], [], [dnl + m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then - for switch in -std=gnu++11 -std=gnu++0x; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + for switch in -std=gnu++$1 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) + CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi ac_success=yes break fi done fi]) - m4_if([$1], [ext], [], [dnl + m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then - for switch in -std=c++11 -std=c++0x; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) + CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi ac_success=yes break fi done fi]) AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) else - if test x$ac_success = xno; then - HAVE_CXX11=0 - AC_MSG_NOTICE([No compiler with C++11 support was found]) - else - HAVE_CXX11=1 - AC_DEFINE(HAVE_CXX11,1, - [define if the compiler supports basic C++11 syntax]) - fi + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) - AC_SUBST(HAVE_CXX11) - fi -]) + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_seperators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) diff --git a/m4/boost.m4 b/m4/boost.m4 --- a/m4/boost.m4 +++ b/m4/boost.m4 @@ -1,1455 +1,1562 @@ # boost.m4: Locate Boost headers and libraries for autoconf-based projects. # Copyright (C) 2007-2011, 2014 Benoit Sigoure # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Additional permission under section 7 of the GNU General Public # License, version 3 ("GPLv3"): # # If you convey this file as part of a work that contains a # configuration script generated by Autoconf, you may do so under # terms of your choice. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . m4_define([_BOOST_SERIAL], [m4_translit([ # serial 25 ], [# ], [])]) # Original sources can be found at http://github.com/tsuna/boost.m4 # You can fetch the latest version of the script by doing: # wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4 # ------ # # README # # ------ # # This file provides several macros to use the various Boost libraries. # The first macro is BOOST_REQUIRE. It will simply check if it's possible to # find the Boost headers of a given (optional) minimum version and it will # define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to # your configure so that users can specify non standard locations. # If the user's environment contains BOOST_ROOT and --with-boost was not # specified, --with-boost=$BOOST_ROOT is implicitly used. # For more README and documentation, go to http://github.com/tsuna/boost.m4 # Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, # simply read the README, it will show you what to do step by step. m4_pattern_forbid([^_?(BOOST|Boost)_]) # _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # -------------------------------------------------------- # Same as AC_EGREP_CPP, but leave the result in conftest.i. # # SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded # in double-quotes, so escape your double quotes. # # It could be useful to turn this into a macro which extracts the # value of any macro. m4_define([_BOOST_SED_CPP], [AC_LANG_PUSH([C++])dnl AC_LANG_PREPROC_REQUIRE()dnl AC_REQUIRE([AC_PROG_SED])dnl AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) AS_IF([dnl eval is necessary to expand ac_cpp. dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. dnl Beware of Windows end-of-lines, for instance if we are running dnl some Windows programs under Wine. In that case, boost/version.hpp dnl is certainly using "\r\n", but the regular Unix shell will only dnl strip `\n' with backquotes, not the `\r'. This results in dnl boost_cv_lib_version='1_37\r' for instance, which breaks dnl everything else. dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK dnl dnl Beware that GCC 5, when expanding macros, may embed # line directives dnl a within single line: dnl dnl # 1 "conftest.cc" dnl # 1 "" dnl # 1 "" dnl # 1 "conftest.cc" dnl # 1 "/opt/local/include/boost/version.hpp" 1 3 dnl # 2 "conftest.cc" 2 dnl boost-lib-version = dnl # 2 "conftest.cc" 3 dnl "1_56" dnl dnl So get rid of the # lines, and glue the remaining ones together. (eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | grep -v '#' | tr -d '\r' | tr -s '\n' ' ' | $SED -n -e "$1" >conftest.i 2>&1], [$3], [$4]) rm -rf conftest* AC_LANG_POP([C++])dnl ])# _BOOST_SED_CPP # BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND]) # ----------------------------------------------- # Look for Boost. If version is given, it must either be a literal of the form # "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a # variable "$var". # Defines the value BOOST_CPPFLAGS. This macro only checks for headers with # the required version, it does not check for any of the Boost libraries. # On # success, defines HAVE_BOOST. On failure, calls the optional # ACTION-IF-NOT-FOUND action if one was supplied. # Otherwise aborts with an error message. AC_DEFUN_ONCE([BOOST_REQUIRE], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_PROG_GREP])dnl echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD boost_save_IFS=$IFS boost_version_req=$1 IFS=. set x $boost_version_req 0 0 0 IFS=$boost_save_IFS shift boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` boost_version_req_string=$[1].$[2].$[3] AC_ARG_WITH([boost], [AS_HELP_STRING([--with-boost=DIR], [prefix of Boost $1 @<:@guess@:>@])])dnl AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl # If BOOST_ROOT is set and the user has not provided a value to # --with-boost, then treat BOOST_ROOT as if it the user supplied it. if test x"$BOOST_ROOT" != x; then if test x"$with_boost" = x; then AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) with_boost=$BOOST_ROOT else AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) fi fi dnl AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], -dnl ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl +dnl ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl boost_save_CPPFLAGS=$CPPFLAGS AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string], [boost_cv_inc_path], [boost_cv_inc_path=no AC_LANG_PUSH([C++])dnl m4_pattern_allow([^BOOST_VERSION$])dnl AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include #if !defined BOOST_VERSION # error BOOST_VERSION is not defined #elif BOOST_VERSION < $boost_version_req # error Boost headers version < $boost_version_req #endif ]])]) # If the user provided a value to --with-boost, use it and only it. case $with_boost in #( ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ /usr/include C:/Boost/include;; #( *) set x "$with_boost/include" "$with_boost";; esac shift for boost_dir do # Without --layout=system, Boost (or at least some versions) installs # itself in /include/boost-. This inner loop helps to # find headers in such directories. # # Any ${boost_dir}/boost-x_xx directories are searched in reverse version # order followed by ${boost_dir}. The final '.' is a sentinel for # searching $boost_dir" itself. Entries are whitespace separated. # # I didn't indent this loop on purpose (to avoid over-indented code) boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ && echo .` for boost_inc in $boost_layout_system_search_list do if test x"$boost_inc" != x.; then boost_inc="$boost_dir/$boost_inc" else boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list fi if test x"$boost_inc" != x; then # We are going to check whether the version of Boost installed # in $boost_inc is usable by running a compilation that # #includes it. But if we pass a -I/some/path in which Boost # is not installed, the compiler will just skip this -I and # use other locations (either from CPPFLAGS, or from its list # of system include directories). As a result we would use # header installed on the machine instead of the /some/path # specified by the user. So in that precise case (trying # $boost_inc), make sure the version.hpp exists. # # Use test -e as there can be symlinks. test -e "$boost_inc/boost/version.hpp" || continue CPPFLAGS="$CPPFLAGS -I$boost_inc" fi AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) if test x"$boost_cv_inc_path" = xyes; then if test x"$boost_inc" != x; then boost_cv_inc_path=$boost_inc fi break 2 fi done done AC_LANG_POP([C++])dnl ]) case $boost_cv_inc_path in #( no) boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])], [AC_MSG_NOTICE([$boost_errmsg])]) $2 ;;#( yes) BOOST_CPPFLAGS= ;;#( *) AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl ;; esac if test x"$boost_cv_inc_path" != xno; then AC_DEFINE([HAVE_BOOST], [1], [Defined if the requested minimum BOOST version is satisfied]) AC_CACHE_CHECK([for Boost's header version], [boost_cv_lib_version], [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]], [#include boost-lib-version = BOOST_LIB_VERSION], [boost_cv_lib_version=`cat conftest.i`])]) # e.g. "134" for 1_34_1 or "135" for 1_35 boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` case $boost_major_version in #( '' | *[[!0-9]]*) AC_MSG_ERROR([invalid value: boost_major_version='$boost_major_version']) ;; esac fi CPPFLAGS=$boost_save_CPPFLAGS ])# BOOST_REQUIRE # BOOST_STATIC() # -------------- # Add the "--enable-static-boost" configure argument. If this argument is given # on the command line, static versions of the libraries will be looked up. AC_DEFUN([BOOST_STATIC], [AC_ARG_ENABLE([static-boost], [AS_HELP_STRING([--enable-static-boost], [Prefer the static boost libraries over the shared ones [no]])], [enable_static_boost=yes], [enable_static_boost=no])])# BOOST_STATIC # BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) # -------------------------------------------------------------------------- # Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for # some parts of the Boost library which are only made of headers and don't # require linking (such as Boost.Foreach). # # Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be # found in the first place, in which case by default a notice is issued to the # user. Presumably if we haven't died already it's because it's OK to not have # Boost, which is why only a notice is issued instead of a hard error. # # Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in # case of success # (where HEADER-NAME is written LIKE_THIS, e.g., # HAVE_BOOST_FOREACH_HPP). AC_DEFUN([BOOST_FIND_HEADER], [AC_REQUIRE([BOOST_REQUIRE])dnl if test x"$boost_cv_inc_path" = xno; then m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])]) else AC_LANG_PUSH([C++])dnl boost_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_CHECK_HEADER([$1], [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], [Define to 1 if you have <$1>])])], [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) CPPFLAGS=$boost_save_CPPFLAGS AC_LANG_POP([C++])dnl fi ])# BOOST_FIND_HEADER # BOOST_FIND_LIBS([COMPONENT-NAME], [CANDIDATE-LIB-NAMES], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Look for the Boost library COMPONENT-NAME (e.g., `thread', for # libboost_thread) under the possible CANDIDATE-LIB-NAMES (e.g., # "thread_win32 thread"). Check that HEADER-NAME works and check that # libboost_LIB-NAME can link with the code CXX-TEST. The optional # argument CXX-PROLOGUE can be used to include some C++ code before # the `main' function. # # Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). # # Boost libraries typically come compiled with several flavors (with different # runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one # or more of the following letters: sgdpn (in that order). s = static # runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, # n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' # must always be used along with `p'). Additionally, PREFERRED-RT-OPT can # start with `mt-' to indicate that there is a preference for multi-thread # builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp # ... If you want to make sure you have a specific version of Boost # (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. AC_DEFUN([BOOST_FIND_LIBS], [AC_REQUIRE([BOOST_REQUIRE])dnl AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl AC_REQUIRE([BOOST_STATIC])dnl AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl if test x"$boost_cv_inc_path" = xno; then AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library]) else dnl The else branch is huge and wasn't intended on purpose. AC_LANG_PUSH([C++])dnl AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl BOOST_FIND_HEADER([$4]) boost_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], [_BOOST_FIND_LIBS($@)]) case $Boost_lib in #( (no) _AC_MSG_LOG_CONFTEST AC_MSG_ERROR([cannot find the flags to link with Boost $1]) ;; esac AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl CPPFLAGS=$boost_save_CPPFLAGS AS_VAR_POPDEF([Boost_lib])dnl AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl AS_VAR_POPDEF([Boost_lib_LDPATH])dnl AS_VAR_POPDEF([Boost_lib_LIBS])dnl AC_LANG_POP([C++])dnl fi ]) # BOOST_FIND_LIB([LIB-NAME], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Backward compatibility wrapper for BOOST_FIND_LIBS. AC_DEFUN([BOOST_FIND_LIB], [BOOST_FIND_LIBS([$1], $@)]) # _BOOST_FIND_LIBS([LIB-NAME], [CANDIDATE-LIB-NAMES], # [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], # [CXX-PROLOGUE]) # -------------------------------------------------------------- # Real implementation of BOOST_FIND_LIBS: rely on these local macros: # Boost_lib, Boost_lib_LDFLAGS, Boost_lib_LDPATH, Boost_lib_LIBS # # The algorithm is as follows: first look for a given library name # according to the user's PREFERRED-RT-OPT. For each library name, we # prefer to use the ones that carry the tag (toolset name). Each # library is searched through the various standard paths were Boost is # usually installed. If we can't find the standard variants, we try # to enforce -mt (for instance on MacOSX, libboost_thread.dylib # doesn't exist but there's -obviously- libboost_thread-mt.dylib). AC_DEFUN([_BOOST_FIND_LIBS], [Boost_lib=no case "$3" in #( (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$3" : 'Xmt-*\(.*\)'`;; #( (*) boost_mt=; boost_rtopt=$3;; esac if test $enable_static_boost = yes; then boost_rtopt="s$boost_rtopt" fi # Find the proper debug variant depending on what we've been asked to find. case $boost_rtopt in #( (*d*) boost_rt_d=$boost_rtopt;; #( (*[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( (*) boost_rt_d='-d';; esac # If the PREFERRED-RT-OPT are not empty, prepend a `-'. test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" $boost_guess_use_mt && boost_mt=-mt # Look for the abs path the static archive. # $libext is computed by Libtool but let's make sure it's non empty. test -z "$libext" && AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) boost_save_ac_objext=$ac_objext # Generate the test file. AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$4> $6], [$5])]) dnl Optimization hacks: compiling C++ is slow, especially with Boost. What dnl we're trying to do here is guess the right combination of link flags dnl (LIBS / LDFLAGS) to use a given library. This can take several dnl iterations before it succeeds and is thus *very* slow. So what we do dnl instead is that we compile the code first (and thus get an object file, dnl typically conftest.o). Then we try various combinations of link flags dnl until we succeed to link conftest.o in an executable. The problem is dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always dnl remove all the temporary files including conftest.o. So the trick here dnl is to temporarily change the value of ac_objext so that conftest.o is dnl preserved accross tests. This is obviously fragile and I will burn in dnl hell for not respecting Autoconf's documented interfaces, but in the dnl mean time, it optimizes the macro by a factor of 5 to 30. dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left dnl empty because the test file is generated only once above (before we dnl start the for loops). AC_COMPILE_IFELSE([], [ac_objext=do_not_rm_me_plz], [AC_MSG_ERROR([cannot compile a test that uses Boost $1])]) ac_objext=$boost_save_ac_objext boost_failed_libs= # Don't bother to ident the following nested for loops, only the 2 # innermost ones matter. for boost_lib_ in $2; do for boost_tag_ in -$boost_cv_lib_tag ''; do for boost_ver_ in -$boost_cv_lib_version ''; do for boost_mt_ in $boost_mt -mt ''; do for boost_rtopt_ in $boost_rtopt '' -d; do for boost_lib in \ boost_$boost_lib_$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_rtopt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_mt_$boost_ver_ \ boost_$boost_lib_$boost_tag_$boost_ver_ do # Avoid testing twice the same lib case $boost_failed_libs in #( (*@$boost_lib@*) continue;; esac # If with_boost is empty, we'll search in /lib first, which is not quite # right so instead we'll try to a location based on where the headers are. boost_tmp_lib=$with_boost test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} for boost_ldpath in "$boost_tmp_lib/lib" '' \ /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ "$with_boost" C:/Boost/lib /lib* do # Don't waste time with directories that don't exist. if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then continue fi boost_save_LDFLAGS=$LDFLAGS # Are we looking for a static library? case $boost_ldpath:$boost_rtopt_ in #( (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" test -e "$Boost_lib_LIBS" || continue;; #( (*) # No: use -lboost_foo to find the shared library. Boost_lib_LIBS="-l$boost_lib";; esac boost_save_LIBS=$LIBS LIBS="$Boost_lib_LIBS $LIBS" test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" dnl First argument of AC_LINK_IFELSE left empty because the test file is dnl generated only once above (before we start the for loops). _BOOST_AC_LINK_IFELSE([], [Boost_lib=yes], [Boost_lib=no]) ac_objext=$boost_save_ac_objext LDFLAGS=$boost_save_LDFLAGS LIBS=$boost_save_LIBS if test x"$Boost_lib" = xyes; then # Check or used cached result of whether or not using -R or # -rpath makes sense. Some implementations of ld, such as for # Mac OSX, require -rpath but -R is the flag known to work on # other systems. https://github.com/tsuna/boost.m4/issues/19 AC_CACHE_VAL([boost_cv_rpath_link_ldflag], [case $boost_ldpath in '') # Nothing to do. boost_cv_rpath_link_ldflag= boost_rpath_link_ldflag_found=yes;; *) for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" LIBS="$boost_save_LIBS $Boost_lib_LIBS" _BOOST_AC_LINK_IFELSE([], [boost_rpath_link_ldflag_found=yes break], [boost_rpath_link_ldflag_found=no]) done ;; esac AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"], [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])]) LDFLAGS=$boost_save_LDFLAGS LIBS=$boost_save_LIBS ]) test x"$boost_ldpath" != x && Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" Boost_lib_LDPATH="$boost_ldpath" break 7 else boost_failed_libs="$boost_failed_libs@$boost_lib@" fi done done done done done done done # boost_lib_ rm -f conftest.$ac_objext ]) # --------------------------------------- # # Checks for the various Boost libraries. # # --------------------------------------- # # List of boost libraries: http://www.boost.org/libs/libraries.htm # The page http://beta.boost.org/doc/libs is useful: it gives the first release # version of each library (among other things). # BOOST_DEFUN(LIBRARY, CODE) # -------------------------- # Define BOOST_ as a macro that runs CODE. # # Use indir to avoid the warning on underquoted macro name given to AC_DEFUN. m4_define([BOOST_DEFUN], [m4_indir([AC_DEFUN], m4_toupper([BOOST_$1]), [m4_pushdef([BOOST_Library], [$1])dnl $2 m4_popdef([BOOST_Library])dnl ]) ]) # BOOST_ARRAY() # ------------- # Look for Boost.Array BOOST_DEFUN([Array], [BOOST_FIND_HEADER([boost/array.hpp])]) # BOOST_ASIO() # ------------ # Look for Boost.Asio (new in Boost 1.35). BOOST_DEFUN([Asio], [AC_REQUIRE([BOOST_SYSTEM])dnl BOOST_FIND_HEADER([boost/asio.hpp])]) # BOOST_BIND() # ------------ # Look for Boost.Bind. BOOST_DEFUN([Bind], [BOOST_FIND_HEADER([boost/bind.hpp])]) # BOOST_CHRONO() # -------------- # Look for Boost.Chrono. BOOST_DEFUN([Chrono], [# Do we have to check for Boost.System? This link-time dependency was # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. boost_filesystem_save_LIBS=$LIBS boost_filesystem_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([chrono], [$1], [boost/chrono.hpp], [boost::chrono::thread_clock d;]) if test $enable_static_boost = yes && test $boost_major_version -ge 135; then BOOST_CHRONO_LIBS="$BOOST_CHRONO_LIBS $BOOST_SYSTEM_LIBS" fi LIBS=$boost_filesystem_save_LIBS LDFLAGS=$boost_filesystem_save_LDFLAGS ])# BOOST_CHRONO # BOOST_CONTEXT([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Context. For the documentation of PREFERRED-RT-OPT, see the -# documentation of BOOST_FIND_LIB above. This library was introduced in Boost -# 1.51.0 +# documentation of BOOST_FIND_LIB above. +# +# * This library was introduced in Boost 1.51.0 +# * The signatures of make_fcontext() and jump_fcontext were changed in 1.56.0 +# * A dependency on boost_thread appears in 1.57.0 BOOST_DEFUN([Context], -[BOOST_FIND_LIB([context], [$1], +[boost_context_save_LIBS=$LIBS + boost_context_save_LDFLAGS=$LDFLAGS +if test $boost_major_version -ge 157; then + BOOST_THREAD([$1]) + m4_pattern_allow([^BOOST_THREAD_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_THREAD_LIBS" + LDFLAGS="$LDFLAGS $BOOST_THREAD_LDFLAGS" +fi +BOOST_FIND_LIB([context], [$1], [boost/context/all.hpp],[[ + // creates a stack void * stack_pointer = new void*[4096]; std::size_t const size = sizeof(void*[4096]); -// context fc uses f() as context function -// fcontext_t is placed on top of context stack -// a pointer to fcontext_t is returned +#if BOOST_VERSION <= 105100 +ctx::make_fcontext(&fc, f); +return ctx::jump_fcontext(&fcm, &fc, 3) == 6; + +#else + fc = ctx::make_fcontext(stack_pointer, size, f); -return ctx::jump_fcontext(&fcm, fc, 3) == 6;]],[dnl +return ctx::jump_fcontext(&fcm, fc, 3) == 6; + +#endif + + +]],[dnl + +#include +#if BOOST_VERSION <= 105100 + +namespace ctx = boost::ctx; + +static ctx::fcontext_t fcm, fc; + +static void f(intptr_t i) { + ctx::jump_fcontext(&fc, &fcm, i * 2); +} + +#elif BOOST_VERSION <= 105500 + namespace ctx = boost::context; + // context static ctx::fcontext_t fcm, *fc; + // context-function static void f(intptr_t i) { ctx::jump_fcontext(fc, &fcm, i * 2); -}]) +} + +#else + +namespace ctx = boost::context; + +// context +static ctx::fcontext_t fcm, fc; + +// context-function +static void f(intptr_t i) { + ctx::jump_fcontext(&fc, fcm, i * 2); +} +#endif +]) +LIBS=$boost_context_save_LIBS +LDFLAGS=$boost_context_save_LDFLAGS ])# BOOST_CONTEXT # BOOST_CONVERSION() # ------------------ # Look for Boost.Conversion (cast / lexical_cast) BOOST_DEFUN([Conversion], [BOOST_FIND_HEADER([boost/cast.hpp]) BOOST_FIND_HEADER([boost/lexical_cast.hpp]) ])# BOOST_CONVERSION # BOOST_COROUTINE([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Coroutine. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.53.0 BOOST_DEFUN([Coroutine], [ boost_coroutine_save_LIBS=$LIBS boost_coroutine_save_LDFLAGS=$LDFLAGS # Link-time dependency from coroutine to context BOOST_CONTEXT([$1]) # Starting from Boost 1.55 a dependency on Boost.System is added if test $boost_major_version -ge 155; then BOOST_SYSTEM([$1]) fi m4_pattern_allow([^BOOST_(CONTEXT|SYSTEM)_(LIBS|LDFLAGS)]) LIBS="$LIBS $BOOST_CONTEXT_LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_CONTEXT_LDFLAGS" -BOOST_FIND_LIB([coroutine], [$1], - [boost/coroutine/coroutine.hpp], - [boost::coroutines::coroutine< int(int) > coro; coro.empty();]) - +# in 1.53 coroutine was a header only library +if test $boost_major_version -eq 153; then + BOOST_FIND_HEADER([boost/coroutine/coroutine.hpp]) +else + BOOST_FIND_LIB([coroutine], [$1], + [boost/coroutine/coroutine.hpp], + [ + #include + #if BOOST_VERSION <= 105500 + boost::coroutines::coroutine coro; coro.get(); + #else + boost::coroutines::asymmetric_coroutine::pull_type coro; coro.get(); + #endif + ]) +fi # Link-time dependency from coroutine to context, existed only in 1.53, in 1.54 # coroutine doesn't use context from its headers but from its library. if test $boost_major_version -eq 153 || test $enable_static_boost = yes && test $boost_major_version -ge 154; then BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_CONTEXT_LIBS" BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_CONTEXT_LDFLAGS" fi if test $enable_static_boost = yes && test $boost_major_version -ge 155; then BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_SYSTEM_LIBS" BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_SYSTEM_LDFLAGS" fi LIBS=$boost_coroutine_save_LIBS LDFLAGS=$boost_coroutine_save_LDFLAGS ])# BOOST_COROUTINE # BOOST_CRC() # ----------- # Look for Boost.CRC BOOST_DEFUN([CRC], [BOOST_FIND_HEADER([boost/crc.hpp]) ])# BOOST_CRC # BOOST_DATE_TIME([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Date_Time], [BOOST_FIND_LIB([date_time], [$1], [boost/date_time/posix_time/posix_time.hpp], [boost::posix_time::ptime t;]) ])# BOOST_DATE_TIME # BOOST_FILESYSTEM([PREFERRED-RT-OPT]) # ------------------------------------ # Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see # the documentation of BOOST_FIND_LIB above. # Do not check for boost/filesystem.hpp because this file was introduced in # 1.34. BOOST_DEFUN([Filesystem], [# Do we have to check for Boost.System? This link-time dependency was # added as of 1.35.0. If we have a version <1.35, we must not attempt to # find Boost.System as it didn't exist by then. if test $boost_major_version -ge 135; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. boost_filesystem_save_LIBS=$LIBS boost_filesystem_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" BOOST_FIND_LIB([filesystem], [$1], [boost/filesystem/path.hpp], [boost::filesystem::path p;]) if test $enable_static_boost = yes && test $boost_major_version -ge 135; then BOOST_FILESYSTEM_LIBS="$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" fi LIBS=$boost_filesystem_save_LIBS LDFLAGS=$boost_filesystem_save_LDFLAGS ])# BOOST_FILESYSTEM # BOOST_FLYWEIGHT() # ----------------- # Look for Boost.Flyweight. BOOST_DEFUN([Flyweight], [dnl There's a hidden dependency on pthreads. AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl BOOST_FIND_HEADER([boost/flyweight.hpp]) AC_SUBST([BOOST_FLYWEIGHT_LIBS], [$boost_cv_pthread_flag]) ]) # BOOST_FOREACH() # --------------- # Look for Boost.Foreach. BOOST_DEFUN([Foreach], [BOOST_FIND_HEADER([boost/foreach.hpp])]) # BOOST_FORMAT() # -------------- # Look for Boost.Format. # Note: we can't check for boost/format/format_fwd.hpp because the header isn't # standalone. It can't be compiled because it triggers the following error: # boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' # does not name a type BOOST_DEFUN([Format], [BOOST_FIND_HEADER([boost/format.hpp])]) # BOOST_FUNCTION() # ---------------- # Look for Boost.Function BOOST_DEFUN([Function], [BOOST_FIND_HEADER([boost/function.hpp])]) # BOOST_GEOMETRY() # ---------------- # Look for Boost.Geometry (new since 1.47.0). BOOST_DEFUN([Geometry], [BOOST_FIND_HEADER([boost/geometry.hpp]) ])# BOOST_GEOMETRY # BOOST_GRAPH([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Graph], -[BOOST_FIND_LIB([graph], [$1], +[boost_graph_save_LIBS=$LIBS +boost_graph_save_LDFLAGS=$LDFLAGS +# Link-time dependency from graph to regex was added as of 1.40.0. +if test $boost_major_version -ge 140; then + BOOST_REGEX([$1]) + m4_pattern_allow([^BOOST_REGEX_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_REGEX_LIBS" + LDFLAGS="$LDFLAGS $BOOST_REGEX_LDFLAGS" +fi +BOOST_FIND_LIB([graph], [$1], [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;]) +LIBS=$boost_graph_save_LIBS +LDFLAGS=$boost_graph_save_LDFLAGS ])# BOOST_GRAPH # BOOST_IOSTREAMS([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([IOStreams], [BOOST_FIND_LIB([iostreams], [$1], [boost/iostreams/device/file_descriptor.hpp], [boost::iostreams::file_descriptor fd; fd.close();]) ])# BOOST_IOSTREAMS # BOOST_HASH() # ------------ # Look for Boost.Functional/Hash BOOST_DEFUN([Hash], [BOOST_FIND_HEADER([boost/functional/hash.hpp])]) # BOOST_LAMBDA() # -------------- # Look for Boost.Lambda BOOST_DEFUN([Lambda], [BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) # BOOST_LOCALE() # -------------- # Look for Boost.Locale BOOST_DEFUN([Locale], -[BOOST_FIND_LIB([locale], [$1], +[ +boost_locale_save_LIBS=$LIBS +boost_locale_save_LDFLAGS=$LDFLAGS +# require SYSTEM for boost-1.50.0 and up +if test $boost_major_version -ge 150; then + BOOST_SYSTEM([$1]) + m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_SYSTEM_LIBS" + LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +fi # end of the Boost.System check. +BOOST_FIND_LIB([locale], [$1], [boost/locale.hpp], [[boost::locale::generator gen; std::locale::global(gen(""));]]) +LIBS=$boost_locale_save_LIBS +LDFLAGS=$boost_locale_save_LDFLAGS ])# BOOST_LOCALE # BOOST_LOG([PREFERRED-RT-OPT]) # ----------------------------- # Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Log], -[BOOST_FIND_LIB([log], [$1], +[boost_log_save_LIBS=$LIBS +boost_log_save_LDFLAGS=$LDFLAGS +BOOST_SYSTEM([$1]) +BOOST_FILESYSTEM([$1]) +BOOST_DATE_TIME([$1]) +m4_pattern_allow([^BOOST_(SYSTEM|FILESYSTEM|DATE_TIME)_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_DATE_TIME_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_DATE_TIME_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([log], [$1], [boost/log/core/core.hpp], [boost::log::attribute a; a.get_value();]) +LIBS=$boost_log_save_LIBS +LDFLAGS=$boost_log_save_LDFLAGS ])# BOOST_LOG # BOOST_LOG_SETUP([PREFERRED-RT-OPT]) # ----------------------------------- # Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Log_Setup], -[AC_REQUIRE([BOOST_LOG])dnl +[boost_log_setup_save_LIBS=$LIBS +boost_log_setup_save_LDFLAGS=$LDFLAGS +BOOST_LOG([$1]) +m4_pattern_allow([^BOOST_LOG_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_LOG_LIBS" +LDFLAGS="$LDFLAGS $BOOST_LOG_LDFLAGS" BOOST_FIND_LIB([log_setup], [$1], [boost/log/utility/setup/from_settings.hpp], [boost::log::basic_settings bs; bs.empty();]) +LIBS=$boost_log_setup_save_LIBS +LDFLAGS=$boost_log_setup_save_LDFLAGS ])# BOOST_LOG_SETUP # BOOST_MATH() # ------------ # Look for Boost.Math # TODO: This library isn't header-only but it comes in multiple different # flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99, # libboost_math_c99f, libboost_math_c99l, libboost_math_tr1, # libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the # right thing anyway. BOOST_DEFUN([Math], [BOOST_FIND_HEADER([boost/math/special_functions.hpp])]) # BOOST_MPI([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost MPI. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. Uses MPICXX variable if it is # set, otherwise tries CXX # BOOST_DEFUN([MPI], [boost_save_CXX=${CXX} boost_save_CXXCPP=${CXXCPP} if test x"${MPICXX}" != x; then CXX=${MPICXX} CXXCPP="${MPICXX} -E" fi BOOST_FIND_LIB([mpi], [$1], [boost/mpi.hpp], [int argc = 0; char **argv = 0; boost::mpi::environment env(argc,argv);]) CXX=${boost_save_CXX} CXXCPP=${boost_save_CXXCPP} ])# BOOST_MPI # BOOST_MULTIARRAY() # ------------------ # Look for Boost.MultiArray BOOST_DEFUN([MultiArray], [BOOST_FIND_HEADER([boost/multi_array.hpp])]) # BOOST_NUMERIC_UBLAS() # -------------------------- # Look for Boost.NumericUblas (Basic Linear Algebra) BOOST_DEFUN([Numeric_Ublas], [BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp]) ])# BOOST_NUMERIC_UBLAS # BOOST_NUMERIC_CONVERSION() # -------------------------- # Look for Boost.NumericConversion (policy-based numeric conversion) BOOST_DEFUN([Numeric_Conversion], [BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp]) ])# BOOST_NUMERIC_CONVERSION # BOOST_OPTIONAL() # ---------------- # Look for Boost.Optional BOOST_DEFUN([Optional], [BOOST_FIND_HEADER([boost/optional.hpp])]) # BOOST_PREPROCESSOR() # -------------------- # Look for Boost.Preprocessor BOOST_DEFUN([Preprocessor], [BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) # BOOST_RANGE() # -------------------- # Look for Boost.Range BOOST_DEFUN([Range], [BOOST_FIND_HEADER([boost/range/adaptors.hpp])]) # BOOST_UNORDERED() # ----------------- # Look for Boost.Unordered BOOST_DEFUN([Unordered], [BOOST_FIND_HEADER([boost/unordered_map.hpp])]) # BOOST_UUID() # ------------ # Look for Boost.Uuid BOOST_DEFUN([Uuid], [BOOST_FIND_HEADER([boost/uuid/uuid.hpp])]) # BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT]) # ----------------------------------------- # Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Program_Options], [BOOST_FIND_LIB([program_options], [$1], [boost/program_options.hpp], [boost::program_options::options_description d("test");]) ])# BOOST_PROGRAM_OPTIONS # _BOOST_PYTHON_CONFIG(VARIABLE, FLAG) # ------------------------------------ # Save VARIABLE, and define it via `python-config --FLAG`. # Substitute BOOST_PYTHON_VARIABLE. m4_define([_BOOST_PYTHON_CONFIG], [AC_SUBST([BOOST_PYTHON_$1], [`python-config --$2 2>/dev/null`])dnl boost_python_save_$1=$$1 $1="$$1 $BOOST_PYTHON_$1"]) # BOOST_PYTHON([PREFERRED-RT-OPT]) # -------------------------------- # Look for Boost.Python. For the documentation of PREFERRED-RT-OPT, # see the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Python], [_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes]) _BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags]) _BOOST_PYTHON_CONFIG([LIBS], [libs]) m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl BOOST_FIND_LIBS([python], [python python3], [$1], [boost/python.hpp], [], [BOOST_PYTHON_MODULE(empty) {}]) CPPFLAGS=$boost_python_save_CPPFLAGS LDFLAGS=$boost_python_save_LDFLAGS LIBS=$boost_python_save_LIBS ])# BOOST_PYTHON # BOOST_REF() # ----------- # Look for Boost.Ref BOOST_DEFUN([Ref], [BOOST_FIND_HEADER([boost/ref.hpp])]) # BOOST_REGEX([PREFERRED-RT-OPT]) # ------------------------------- # Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Regex], [BOOST_FIND_LIB([regex], [$1], [boost/regex.hpp], [boost::regex exp("*"); boost::regex_match("foo", exp);]) ])# BOOST_REGEX # BOOST_SERIALIZATION([PREFERRED-RT-OPT]) # --------------------------------------- # Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see # the documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Serialization], [BOOST_FIND_LIB([serialization], [$1], [boost/archive/text_oarchive.hpp], [std::ostream* o = 0; // Cheap way to get an ostream... boost::archive::text_oarchive t(*o);]) ])# BOOST_SERIALIZATION # BOOST_SIGNALS([PREFERRED-RT-OPT]) # --------------------------------- # Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Signals], [BOOST_FIND_LIB([signals], [$1], [boost/signal.hpp], [boost::signal s;]) ])# BOOST_SIGNALS # BOOST_SIGNALS2() # ---------------- # Look for Boost.Signals2 (new since 1.39.0). BOOST_DEFUN([Signals2], [BOOST_FIND_HEADER([boost/signals2.hpp]) ])# BOOST_SIGNALS2 # BOOST_SMART_PTR() # ----------------- # Look for Boost.SmartPtr BOOST_DEFUN([Smart_Ptr], [BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) BOOST_FIND_HEADER([boost/shared_ptr.hpp]) ]) # BOOST_STATICASSERT() # -------------------- # Look for Boost.StaticAssert BOOST_DEFUN([StaticAssert], [BOOST_FIND_HEADER([boost/static_assert.hpp])]) # BOOST_STRING_ALGO() # ------------------- # Look for Boost.StringAlgo BOOST_DEFUN([String_Algo], [BOOST_FIND_HEADER([boost/algorithm/string.hpp]) ]) # BOOST_SYSTEM([PREFERRED-RT-OPT]) # -------------------------------- # Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. This library was introduced in Boost # 1.35.0. BOOST_DEFUN([System], [BOOST_FIND_LIB([system], [$1], [boost/system/error_code.hpp], [boost::system::error_code e; e.clear();]) ])# BOOST_SYSTEM # BOOST_TEST([PREFERRED-RT-OPT]) # ------------------------------ # Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Test], [m4_pattern_allow([^BOOST_CHECK$])dnl BOOST_FIND_LIB([unit_test_framework], [$1], [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], [using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int argc, char ** argv) { return NULL; }]) ])# BOOST_TEST # BOOST_THREAD([PREFERRED-RT-OPT]) # --------------------------------- # Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Thread], [dnl Having the pthread flag is required at least on GCC3 where dnl boost/thread.hpp would complain if we try to compile without dnl -pthread on GNU/Linux. AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl boost_thread_save_LIBS=$LIBS boost_thread_save_LDFLAGS=$LDFLAGS boost_thread_save_CPPFLAGS=$CPPFLAGS # Link-time dependency from thread to system was added as of 1.49.0. if test $boost_major_version -ge 149; then BOOST_SYSTEM([$1]) fi # end of the Boost.System check. m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" # When compiling for the Windows platform, the threads library is named # differently. This suffix doesn't exist in new versions of Boost, or # possibly new versions of GCC on mingw I am assuming it's Boost's change for # now and I am setting version to 1.48, for lack of knowledge as to when this # change occurred. if test $boost_major_version -lt 148; then case $host_os in (*mingw*) boost_thread_lib_ext=_win32;; esac fi BOOST_FIND_LIBS([thread], [thread$boost_thread_lib_ext], [$1], [boost/thread.hpp], [boost::thread t; boost::mutex m;]) case $host_os in (*mingw*) boost_thread_w32_socket_link=-lws2_32;; esac BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag $boost_thread_w32_socket_link" BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS" BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" LIBS=$boost_thread_save_LIBS LDFLAGS=$boost_thread_save_LDFLAGS CPPFLAGS=$boost_thread_save_CPPFLAGS ])# BOOST_THREAD AU_ALIAS([BOOST_THREADS], [BOOST_THREAD]) # BOOST_TOKENIZER() # ----------------- # Look for Boost.Tokenizer BOOST_DEFUN([Tokenizer], [BOOST_FIND_HEADER([boost/tokenizer.hpp])]) # BOOST_TRIBOOL() # --------------- # Look for Boost.Tribool BOOST_DEFUN([Tribool], [BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) BOOST_FIND_HEADER([boost/logic/tribool.hpp]) ]) # BOOST_TUPLE() # ------------- # Look for Boost.Tuple BOOST_DEFUN([Tuple], [BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) # BOOST_TYPETRAITS() # -------------------- # Look for Boost.TypeTraits BOOST_DEFUN([TypeTraits], [BOOST_FIND_HEADER([boost/type_traits.hpp])]) # BOOST_UTILITY() # --------------- # Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, # etc.) BOOST_DEFUN([Utility], [BOOST_FIND_HEADER([boost/utility.hpp])]) # BOOST_VARIANT() # --------------- # Look for Boost.Variant. BOOST_DEFUN([Variant], [BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) BOOST_FIND_HEADER([boost/variant.hpp])]) # BOOST_POINTER_CONTAINER() # ------------------------ # Look for Boost.PointerContainer BOOST_DEFUN([Pointer_Container], [BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp]) BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp]) ])# BOOST_POINTER_CONTAINER # BOOST_WAVE([PREFERRED-RT-OPT]) # ------------------------------ # NOTE: If you intend to use Wave/Spirit with thread support, make sure you # call BOOST_THREAD first. # Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. BOOST_DEFUN([Wave], [AC_REQUIRE([BOOST_FILESYSTEM])dnl AC_REQUIRE([BOOST_DATE_TIME])dnl boost_wave_save_LIBS=$LIBS boost_wave_save_LDFLAGS=$LDFLAGS m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \ $BOOST_THREAD_LIBS" LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \ $BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" BOOST_FIND_LIB([wave], [$1], [boost/wave.hpp], [boost::wave::token_id id; get_token_name(id);]) LIBS=$boost_wave_save_LIBS LDFLAGS=$boost_wave_save_LDFLAGS ])# BOOST_WAVE # BOOST_XPRESSIVE() # ----------------- # Look for Boost.Xpressive (new since 1.36.0). BOOST_DEFUN([Xpressive], [BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) # ----------------- # # Internal helpers. # # ----------------- # # _BOOST_PTHREAD_FLAG() # --------------------- # Internal helper for BOOST_THREAD. Computes boost_cv_pthread_flag # which must be used in CPPFLAGS and LIBS. # # Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, # boost/thread.hpp will trigger a #error if -pthread isn't used: # boost/config/requires_threads.hpp:47:5: #error "Compiler threading support # is not turned on. Please set the correct command line options for # threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" # # Based on ACX_PTHREAD: http://autoconf-archive.cryp.to/acx_pthread.html AC_DEFUN([_BOOST_PTHREAD_FLAG], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_LANG_PUSH([C++])dnl AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], [ boost_cv_pthread_flag= # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # (none): in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -lpthreads: AIX (must check this before -lpthread) # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) # -pthreads: Solaris/GCC # -mthreads: MinGW32/GCC, Lynx/GCC # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # -lpthread: GNU Linux, etc. # --thread-safe: KAI C++ case $host_os in #( *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( *) boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ -pthreads -mthreads -lpthread --thread-safe -mt";; esac # Generate the test file. AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) for boost_pthread_flag in '' $boost_pthread_flags; do boost_pthread_ok=false dnl Re-use the test file already generated. boost_pthreads__save_LIBS=$LIBS LIBS="$LIBS $boost_pthread_flag" AC_LINK_IFELSE([], [if grep ".*$boost_pthread_flag" conftest.err; then echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD else boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag fi]) LIBS=$boost_pthreads__save_LIBS $boost_pthread_ok && break done ]) AC_LANG_POP([C++])dnl ])# _BOOST_PTHREAD_FLAG # _BOOST_gcc_test(MAJOR, MINOR) # ----------------------------- # Internal helper for _BOOST_FIND_COMPILER_TAG. m4_define([_BOOST_gcc_test], ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl # _BOOST_mingw_test(MAJOR, MINOR) # ----------------------------- # Internal helper for _BOOST_FIND_COMPILER_TAG. m4_define([_BOOST_mingw_test], ["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC && \ (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw$1$2"])dnl # _BOOST_FIND_COMPILER_TAG() # -------------------------- # Internal. When Boost is installed without --layout=system, each library # filename will hold a suffix that encodes the compiler used during the # build. The Boost build system seems to call this a `tag'. AC_DEFUN([_BOOST_FIND_COMPILER_TAG], [AC_REQUIRE([AC_PROG_CXX])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag], [boost_cv_lib_tag=unknown if test x$boost_cv_inc_path != xno; then AC_LANG_PUSH([C++])dnl # The following tests are mostly inspired by boost/config/auto_link.hpp # The list is sorted to most recent/common to oldest compiler (in order # to increase the likelihood of finding the right compiler with the # least number of compilation attempt). # Beware that some tests are sensible to the order (for instance, we must # look for MinGW before looking for GCC3). # I used one compilation test per compiler with a #error to recognize # each compiler so that it works even when cross-compiling (let me know # if you know a better approach). # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): # como, edg, kcc, bck, mp, sw, tru, xlc # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines # the same defines as GCC's). for i in \ + _BOOST_mingw_test(6, 1) \ + _BOOST_gcc_test(6, 1) \ + _BOOST_mingw_test(5, 3) \ + _BOOST_gcc_test(5, 3) \ _BOOST_mingw_test(5, 2) \ _BOOST_gcc_test(5, 2) \ _BOOST_mingw_test(5, 1) \ _BOOST_gcc_test(5, 1) \ _BOOST_mingw_test(5, 0) \ _BOOST_gcc_test(5, 0) \ _BOOST_mingw_test(4, 10) \ _BOOST_gcc_test(4, 10) \ _BOOST_mingw_test(4, 9) \ _BOOST_gcc_test(4, 9) \ _BOOST_mingw_test(4, 8) \ _BOOST_gcc_test(4, 8) \ _BOOST_mingw_test(4, 7) \ _BOOST_gcc_test(4, 7) \ _BOOST_mingw_test(4, 6) \ _BOOST_gcc_test(4, 6) \ _BOOST_mingw_test(4, 5) \ _BOOST_gcc_test(4, 5) \ _BOOST_mingw_test(4, 4) \ _BOOST_gcc_test(4, 4) \ _BOOST_mingw_test(4, 3) \ _BOOST_gcc_test(4, 3) \ _BOOST_mingw_test(4, 2) \ _BOOST_gcc_test(4, 2) \ _BOOST_mingw_test(4, 1) \ _BOOST_gcc_test(4, 1) \ _BOOST_mingw_test(4, 0) \ _BOOST_gcc_test(4, 0) \ "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ _BOOST_gcc_test(3, 4) \ _BOOST_gcc_test(3, 3) \ "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ _BOOST_gcc_test(3, 2) \ "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ _BOOST_gcc_test(3, 1) \ _BOOST_gcc_test(3, 0) \ "defined __BORLANDC__ @ bcb" \ "defined __ICC && (defined __unix || defined __unix__) @ il" \ "defined __ICL @ iw" \ "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ _BOOST_gcc_test(2, 95) \ "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" do boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if $boost_tag_test /* OK */ #else # error $boost_tag_test #endif ]])], [boost_cv_lib_tag=$boost_tag; break], []) done AC_LANG_POP([C++])dnl case $boost_cv_lib_tag in #( # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed # to "gcc41" for instance. *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. gcc*) boost_tag_x= case $host_os in #( darwin*) if test $boost_major_version -ge 136; then # The `x' added in r46793 of Boost. boost_tag_x=x fi;; esac # We can specify multiple tags in this variable because it's used by # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" ;; #( unknown) AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) boost_cv_lib_tag= ;; esac fi])dnl end of AC_CACHE_CHECK ])# _BOOST_FIND_COMPILER_TAG # _BOOST_GUESS_WHETHER_TO_USE_MT() # -------------------------------- # Compile a small test to try to guess whether we should favor MT (Multi # Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], [# Check whether we do better use `mt' even though we weren't ask to. AC_LANG_PUSH([C++])dnl AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if defined _REENTRANT || defined _MT || defined __MT__ /* use -mt */ #else # error MT not needed #endif ]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) AC_LANG_POP([C++])dnl ]) # _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # ------------------------------------------------------------------- # Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, # will break when Autoconf changes its internals. Requires that you manually # rm -f conftest.$ac_objext in between to really different tests, otherwise # you will try to link a conftest.o left behind by a previous test. # Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this # macro). # # Don't use "break" in the actions, as it would short-circuit some code # this macro runs after the actions. m4_define([_BOOST_AC_LINK_IFELSE], [m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl rm -f conftest$ac_exeext boost_save_ac_ext=$ac_ext boost_use_source=: # If we already have a .o, re-use it. We change $ac_ext so that $ac_link # tries to link the existing object file instead of compiling from source. test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) AS_IF([_AC_DO_STDERR($ac_link) && { test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_executable_p conftest$ac_exeext dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. }], [$2], [if $boost_use_source; then _AC_MSG_LOG_CONFTEST fi $3]) ac_objext=$boost_save_ac_objext ac_ext=$boost_save_ac_ext dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), dnl as it would interfere with the next link command. rm -f core conftest.err conftest_ipa8_conftest.oo \ conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl ])# _BOOST_AC_LINK_IFELSE # Local Variables: # mode: autoconf # End: diff --git a/m4/herwig.m4 b/m4/herwig.m4 --- a/m4/herwig.m4 +++ b/m4/herwig.m4 @@ -1,954 +1,954 @@ # check for gcc bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34130 AC_DEFUN([HERWIG_CHECK_ABS_BUG], [ AC_REQUIRE([HERWIG_COMPILERFLAGS]) if test "$GCC" = "yes"; then AC_MSG_CHECKING([for gcc abs bug]) AC_RUN_IFELSE([ AC_LANG_PROGRAM( [[ int foo (int i) { return -2 * __builtin_abs(i - 2); } ]], [[ if ( foo(1) != -2 || foo(3) != -2 ) return 1; ]] )], [ AC_MSG_RESULT([not found. Compiler is ok.]) ], [ AC_MSG_RESULT([found. Builtin abs() is buggy.]) AC_MSG_CHECKING([if -fno-builtin-abs works]) oldcxxflags=$CXXFLAGS CXXFLAGS="$CXXFLAGS -fno-builtin-abs" AC_RUN_IFELSE([ AC_LANG_PROGRAM( [[ #include int foo (int i) { return -2 * std::abs(i - 2); } ]], [[ if (foo(1) != -2 || foo(3) != -2) return 1; ]] )], [ AC_MSG_RESULT([yes. Setting -fno-builtin-abs.]) AM_CXXFLAGS="$AM_CXXFLAGS -fno-builtin-abs" AM_CFLAGS="$AM_CFLAGS -fno-builtin-abs" ], [ AC_MSG_RESULT([no. Setting -fno-builtin.]) AC_MSG_WARN([ ***************************************************************************** For this version of gcc, -fno-builtin-abs alone did not work to avoid the gcc abs() bug. Instead, all gcc builtin functions are now disabled. Update gcc if possible. *****************************************************************************]) AM_CXXFLAGS="$AM_CXXFLAGS -fno-builtin" AM_CFLAGS="$AM_CFLAGS -fno-builtin" ] ) CXXFLAGS=$oldcxxflags ] ) fi ]) dnl ##### THEPEG ##### AC_DEFUN([HERWIG_CHECK_THEPEG], [ defaultlocation="${prefix}" test "x$defaultlocation" = xNONE && defaultlocation="${ac_default_prefix}" AC_MSG_CHECKING([for libThePEG in]) AC_ARG_WITH(thepeg, AC_HELP_STRING([--with-thepeg=DIR],[location of ThePEG installation]), [], [with_thepeg="${defaultlocation}"]) AC_MSG_RESULT([$with_thepeg]) if test "x$with_thepeg" = "xno"; then AC_MSG_ERROR([Cannot build Herwig++ without ThePEG. Please set --with-thepeg.]) fi THEPEGLDFLAGS="-L${with_thepeg}/lib/ThePEG" THEPEGHASLHAPDF="no" if test -e ${with_thepeg}/lib/ThePEG/ThePEGLHAPDF.so ; then THEPEGHASLHAPDF="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/ThePEGLHAPDF.so ; then THEPEGHASLHAPDF="yes" fi fi if test "x$THEPEGHASLHAPDF" == "xno" ; then AC_MSG_ERROR([Herwig++ requires ThePEG to be build with lhapdf.]) fi THEPEGHASFASTJET="no" if test -e ${with_thepeg}/lib/ThePEG/FastJetFinder.so ; then THEPEGHASFASTJET="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/FastJetFinder.so ; then THEPEGHASFASTJET="yes" fi fi if test "x$THEPEGHASFASTJET" == "xno" ; then AC_MSG_ERROR([Herwig++ requires ThePEG to be build with FastJet.]) fi THEPEGPATH="${with_thepeg}" oldldflags="$LDFLAGS" oldlibs="$LIBS" LDFLAGS="$LDFLAGS $THEPEGLDFLAGS" AC_CHECK_LIB([ThePEG],[debugThePEG],[], [AC_MSG_ERROR([No ThePEG libraries in $THEPEGLDFLAGS. Please set --with-thepeg.])]) AC_SUBST([THEPEGLIB],[-lThePEG]) AC_SUBST(THEPEGLDFLAGS) AC_SUBST(THEPEGPATH) AC_SUBST(THEPEGHASLHAPDF) AC_SUBST(THEPEGHASFASTJET) LIBS="$oldlibs" LDFLAGS="$oldldflags" AC_MSG_CHECKING([for ThePEG headers in]) AC_ARG_WITH([thepeg-headers], AC_HELP_STRING([--with-thepeg-headers=DIR],[location of ThePEG include directory]), [], [with_thepeg_headers="${with_thepeg}/include"]) AC_MSG_RESULT([$with_thepeg_headers]) if test "x$with_thepeg_headers" = "xno"; then AC_MSG_ERROR([Cannot build Herwig++ without ThePEG headers. Please set --with-thepeg-headers.]) fi THEPEGINCLUDE="-I$with_thepeg_headers" oldcppflags="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $THEPEGINCLUDE" AC_CHECK_HEADER([ThePEG/Config/ThePEG.h],[], [AC_MSG_ERROR([No ThePEG headers in $with_thepeg_headers. Please set --with-thepeg-headers.])]) CPPFLAGS="$oldcppflags" AC_SUBST(THEPEGINCLUDE) AC_MSG_CHECKING([for HepMCAnalysis.so in ThePEG]) THEPEGHASHEPMC="no" if test -e ${with_thepeg}/lib/ThePEG/HepMCAnalysis.so ; then THEPEGHASHEPMC="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/HepMCAnalysis.so ; then THEPEGHASHEPMC="yes" fi fi if test "x$THEPEGHASHEPMC" == "xno" ; then CREATE_HEPMC="# create" AC_MSG_RESULT([not found]) else CREATE_HEPMC="create" AC_MSG_RESULT([found]) fi AC_SUBST([CREATE_HEPMC]) AC_MSG_CHECKING([for RivetAnalysis.so in ThePEG]) THEPEGHASRIVET="no" if test -e ${with_thepeg}/lib/ThePEG/RivetAnalysis.so ; then THEPEGHASRIVET="yes" fi if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG" if test -e ${with_thepeg}/lib64/ThePEG/RivetAnalysis.so ; then THEPEGHASRIVET="yes" fi fi if test "x$THEPEGHASRIVET" == "xno" ; then CREATE_RIVET="# create" AC_MSG_RESULT([not found]) else CREATE_RIVET="create" AC_MSG_RESULT([found]) fi AC_SUBST([CREATE_RIVET]) ]) dnl ##### LOOPTOOLS ##### AC_DEFUN([HERWIG_LOOPTOOLS], [ AC_REQUIRE([AC_PROG_FC]) AC_REQUIRE([AC_FC_LIBRARY_LDFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([HERWIG_COMPILERFLAGS]) AC_MSG_CHECKING([if Looptools build works]) enable_looptools=yes if test "x$GCC" = "xyes"; then case "${host}" in x86_64-*|*-darwin1*) AM_FCFLAGS="$AM_FCFLAGS -fdefault-integer-8" ;; esac AC_LANG_PUSH([Fortran]) oldFCFLAGS="$FCFLAGS" FCFLAGS="$AM_FCFLAGS" AC_COMPILE_IFELSE( AC_LANG_PROGRAM([],[ print *[,]"Hello"]), [], [AC_MSG_RESULT([no]) AC_MSG_ERROR([needs gfortran on 64bit machines])] ) FCFLAGS="$oldFCFLAGS" AC_LANG_POP([Fortran]) fi AC_MSG_RESULT([$enable_looptools]) AC_SUBST([F77],[$FC]) AC_SUBST([FFLAGS],[$FCFLAGS]) AC_SUBST([AM_FFLAGS],[$AM_FCFLAGS]) AC_SUBST([FLIBS],[$FCLIBS]) ]) dnl ##### VBFNLO ##### AC_DEFUN([HERWIG_CHECK_VBFNLO], [ AC_MSG_CHECKING([for VBFNLO]) AC_ARG_WITH([vbfnlo], AS_HELP_STRING([--with-vbfnlo=DIR], [Installation path of VBFNLO]), [], [with_vbfnlo=no] ) AC_MSG_RESULT([$with_vbfnlo]) AS_IF([test "x$with_vbfnlo" != "xno"], [AC_CHECK_FILES( ${with_vbfnlo}/lib/VBFNLO/libVBFNLO.so, [have_vbfnlo=lib], [have_vbfnlo=no])], [have_vbfnlo=no]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib64/VBFNLO/libVBFNLO.so, [have_vbfnlo=lib64], [have_vbfnlo=no])]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib/VBFNLO/libVBFNLO.dylib, [have_vbfnlo=lib], [have_vbfnlo=no])]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ], [AC_CHECK_FILES( ${with_vbfnlo}/lib64/VBFNLO/libVBFNLO.dylib, [have_vbfnlo=lib64], [have_vbfnlo=no])]) AS_IF([test "x$have_vbfnlo" = "xlib"], [VBFNLOLIBS=${with_vbfnlo}/lib/VBFNLO AC_SUBST(VBFNLOLIBS) ]) AS_IF([test "x$have_vbfnlo" = "xlib64"], [VBFNLOLIBS=${with_vbfnlo}/lib64/VBFNLO AC_SUBST(VBFNLOLIBS) ]) AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno"], [AC_MSG_ERROR([vbfnlo requested but not found])]) AM_CONDITIONAL(HAVE_VBFNLO,[test "x$have_vbfnlo" = "xlib" -o "x$have_vbfnlo" = "xlib64"]) if test "x$have_vbfnlo" = "xlib" -o "x$have_vbfnlo" = "xlib64" ; then VBFNLOINCLUDE=${with_vbfnlo}/include AC_SUBST(VBFNLOINCLUDE) VBFNLOLIB=${with_vbfnlo}/${have_vbfnlo}/VBFNLO AC_SUBST(VBFNLOLIB) LOAD_VBFNLO="library" CREATE_VBFNLO="create" INSERT_VBFNLO="insert" SET_VBFNLO="set" DO_VBFNLO="do" MKDIR_VBFNLO="mkdir" else LOAD_VBFNLO="# library" CREATE_VBFNLO="# create" INSERT_VBFNLO="# insert" SET_VBFNLO="# set" DO_VBFNLO="# do" MKDIR_VBFNLO="# mkdir" fi AC_SUBST([LOAD_VBFNLO]) AC_SUBST([CREATE_VBFNLO]) AC_SUBST([INSERT_VBFNLO]) AC_SUBST([SET_VBFNLO]) AC_SUBST([DO_VBFNLO]) AC_SUBST([MKDIR_VBFNLO]) ]) dnl ##### njet ##### AC_DEFUN([HERWIG_CHECK_NJET], [ AC_MSG_CHECKING([for njet]) AC_ARG_WITH([njet], AS_HELP_STRING([--with-njet=DIR], [Installation path of njet]), [], [with_njet=no] ) AC_MSG_RESULT([$with_njet]) AS_IF([test "x$with_njet" != "xno"], [AC_CHECK_FILES( ${with_njet}/lib/libnjet2.so, [have_njet=lib], [have_njet=no])], [have_njet=no]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], [AC_CHECK_FILES( ${with_njet}/lib64/libnjet2.so, [have_njet=lib64], [have_njet=no])]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ], [AC_CHECK_FILES( ${with_njet}/lib/libnjet2.dylib, [have_njet=lib], [have_njet=no])]) AS_IF([test "x$have_njet" = "xlib"], [NJETLIBPATH=${with_njet}/lib AC_SUBST(NJETLIBPATH) NJETINCLUDEPATH=${with_njet}/include AC_SUBST(NJETINCLUDEPATH) NJETPREFIX=${with_njet} AC_SUBST(NJETPREFIX) ]) AS_IF([test "x$have_njet" = "xlib64"], [NJETLIBPATH=${with_njet}/lib64 AC_SUBST(NJETLIBPATH) NJETINCLUDEPATH=${with_njet}/include AC_SUBST(NJETINCLUDEPATH) NJETPREFIX=${with_njet} AC_SUBST(NJETPREFIX) ]) AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno"], [AC_MSG_ERROR([njet requested but not found])]) AM_CONDITIONAL(HAVE_NJET,[test "x$have_njet" = "xlib" -o "x$have_njet" = "xlib64"]) if test "x$have_njet" = "xlib" -o "x$have_njet" = "xlib64" ; then LOAD_NJET="library" CREATE_NJET="create" INSERT_NJET="insert" DO_NJET="do" else LOAD_NJET="# library" CREATE_NJET="# create" INSERT_NJET="# insert" DO_NJET="# do" fi AC_SUBST([LOAD_NJET]) AC_SUBST([CREATE_NJET]) AC_SUBST([INSERT_NJET]) AC_SUBST([DO_NJET]) ]) dnl ##### gosam ##### AC_DEFUN([HERWIG_CHECK_GOSAM], [ AC_MSG_CHECKING([for gosam]) AC_ARG_WITH([gosam], AS_HELP_STRING([--with-gosam=DIR], [Installation path of gosam]), [], [with_gosam=no] ) AC_MSG_RESULT([$with_gosam]) AS_IF([test "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/bin/gosam.py, [have_gosam=lib], [have_gosam=no])], [have_gosam=no]) AS_IF([test "x$have_gosam" = "xlib"], [GOSAMPREFIX=${with_gosam} AC_SUBST(GOSAMPREFIX) ]) AS_IF([test "x$with_gosam" != "xno" -a "x$have_gosam" = "xno"], [AC_MSG_ERROR([GoSam requested but not found])]) AM_CONDITIONAL(HAVE_GOSAM,[test "x$have_gosam" = "xlib" ]) if test "x$have_gosam" = "xlib" ; then LOAD_GOSAM="library" CREATE_GOSAM="create" INSERT_GOSAM="insert" DO_GOSAM="do" else LOAD_GOSAM="# library" CREATE_GOSAM="# create" INSERT_GOSAM="# insert" DO_GOSAM="# do" fi AC_SUBST([LOAD_GOSAM]) AC_SUBST([CREATE_GOSAM]) AC_SUBST([INSERT_GOSAM]) AC_SUBST([DO_GOSAM]) ]) dnl ##### gosam-contrib ##### AC_DEFUN([HERWIG_CHECK_GOSAM_CONTRIB], [ AC_MSG_CHECKING([for gosam-contrib]) AC_ARG_WITH([gosam-contrib], AS_HELP_STRING([--with-gosam-contrib=DIR], [Installation path of gosam-contrib]), [], [with_gosam_contrib=no] ) AC_MSG_RESULT([$with_gosam_contrib]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib/libsamurai.so, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib64/libsamurai.so, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib/libsamurai.dylib, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_CHECK_FILES( ${with_gosam}/lib64/libsamurai.dylib, [with_gosam_contrib=${with_gosam}], []) ]) AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"], [AC_MSG_ERROR([GoSam requested without requesting GoSam-Contrib])]) AS_IF([test "x$with_gosam_contrib" != "xno"], [AC_CHECK_FILES( ${with_gosam_contrib}/lib/libsamurai.so, [have_gosam_contrib=lib], [have_gosam_contrib=no])], [have_gosam_contrib=no]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib64/libsamurai.so, [have_gosam_contrib=lib64], [have_gosam_contrib=no])]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib/libsamurai.dylib, [have_gosam_contrib=lib], [have_gosam_contrib=no])]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ], [AC_CHECK_FILES( ${with_gosam_contrib}/lib64/libsamurai.dylib, [have_gosam_contrib=lib64], [have_gosam_contrib=no])]) AS_IF([test "x$have_gosam_contrib" != "xno"], [GOSAMCONTRIBPREFIX=${with_gosam_contrib} AC_SUBST(GOSAMCONTRIBPREFIX) ]) AS_IF([test "x$have_gosam_contrib" = "xlib"], [GOSAMCONTRIBLIBS=${with_gosam_contrib}/lib AC_SUBST(GOSAMCONTRIBLIBS) ]) AS_IF([test "x$have_gosam_contrib" = "xlib64"], [GOSAMCONTRIBLIBS=${with_gosam_contrib}/lib64 AC_SUBST(GOSAMCONTRIBLIBS) ]) AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno"], [AC_MSG_ERROR([GoSam-Contrib requested but not found])]) AM_CONDITIONAL(HAVE_GOSAM_CONTRIB,[test "x$have_gosam_contrib" = "xlib" -o "x$have_gosam_contrib" = "xlib64"]) if test "x$have_gosam_contrib" = "xlib" -o "x$have_gosam_contrib" = "xlib64" ; then LOAD_GOSAM_CONTRIB="library" CREATE_GOSAM_CONTRIB="create" INSERT_GOSAM_CONTRIB="insert" else LOAD_GOSAM_CONTRIB="# library" CREATE_GOSAM_CONTRIB="# create" INSERT_GOSAM_CONTRIB="# insert" fi AC_SUBST([LOAD_GOSAM_CONTRIB]) AC_SUBST([CREATE_GOSAM_CONTRIB]) AC_SUBST([INSERT_GOSAM_CONTRIB]) ]) dnl ##### OpenLoops ##### AC_DEFUN([HERWIG_CHECK_OPENLOOPS], [ AC_MSG_CHECKING([for OpenLoops]) AC_ARG_WITH([openloops], AS_HELP_STRING([--with-openloops=DIR], [Installation path of OpenLoops]), [], [with_openloops=no] ) AC_MSG_RESULT([$with_openloops]) AS_IF([test "x$with_openloops" != "xno"], [AC_CHECK_FILES( ${with_openloops}/lib/libopenloops.so, [have_openloops=lib], [have_openloops=no])], [have_openloops=no]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib/libopenloops.dylib, [have_openloops=lib], [have_openloops=no])]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib64/libopenloops.so, [have_openloops=lib64], [have_openloops=no])]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ], [AC_CHECK_FILES( ${with_openloops}/lib64/libopenloops.dylib, [have_openloops=lib64], [have_openloops=no])]) AS_IF([test "x$have_openloops" = "xlib"], [OPENLOOPSLIBS=${with_openloops}/lib AC_SUBST(OPENLOOPSLIBS) ]) AS_IF([test "x$have_openloops" = "xlib64"], [OPENLOOPSLIBS=${with_openloops}/lib64 AC_SUBST(OPENLOOPSLIBS) ]) AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno"], [AC_MSG_ERROR([OpenLoops requested but not found])]) AM_CONDITIONAL(HAVE_OPENLOOPS,[test "x$have_openloops" = "xlib" -o "x$have_openloops" = "xlib64"]) if test "x$have_openloops" = "xlib" -o "x$have_openloops" = "xlib64" ; then OPENLOOPSPREFIX=${with_openloops} LOAD_OPENLOOPS="library" CREATE_OPENLOOPS="create" INSERT_OPENLOOPS="insert" SET_OPENLOOPS="set" DO_OPENLOOPS="do" MKDIR_OPENLOOPS="mkdir" else LOAD_OPENLOOPS="# library" CREATE_OPENLOOPS="# create" INSERT_OPENLOOPS="# insert" SET_OPENLOOPS="# set" DO_OPENLOOPS="# do" MKDIR_OPENLOOPS="# mkdir" fi AC_SUBST([OPENLOOPSPREFIX]) AC_SUBST([LOAD_OPENLOOPS]) AC_SUBST([CREATE_OPENLOOPS]) AC_SUBST([INSERT_OPENLOOPS]) AC_SUBST([SET_OPENLOOPS]) AC_SUBST([DO_OPENLOOPS]) AC_SUBST([MKDIR_OPENLOOPS]) ]) ######################################### dnl ##### madgraph ##### AC_DEFUN([HERWIG_CHECK_MADGRAPH], [ AC_MSG_CHECKING([for MadGraph]) AC_ARG_WITH([madgraph], AS_HELP_STRING([--with-madgraph=DIR], [Installation path of MadGraph]), [], [with_madgraph=no] ) AC_MSG_RESULT([$with_madgraph]) AS_IF([test "x$with_madgraph" != "xno"], [AC_CHECK_FILES( ${with_madgraph}/bin/mg5_aMC, [have_madgraph=yes], [have_madgraph=no])], [have_madgraph=no]) AS_IF([test "x$have_madgraph" = "xyes"], [MADGRAPHPREFIX=${with_madgraph} AC_SUBST(MADGRAPHPREFIX) ]) AS_IF([test "x$with_madgraph" != "xno" -a "x$have_madgraph" = "xno"], [AC_MSG_ERROR([MadGraph requested but not found])]) AM_CONDITIONAL(HAVE_MADGRAPH,[test "x$have_madgraph" = "xyes" ]) if test "x$have_madgraph" = "xyes" ; then LOAD_MADGRAPH="library" CREATE_MADGRAPH="create" INSERT_MADGRAPH="insert" SET_MADGRAPH="set" DO_MADGRAPH="do" else LOAD_MADGRAPH="# library" CREATE_MADGRAPH="# create" INSERT_MADGRAPH="# insert" SET_MADGRAPH="# set" DO_MADGRAPH="# do" fi AC_SUBST([LOAD_MADGRAPH]) AC_SUBST([CREATE_MADGRAPH]) AC_SUBST([INSERT_MADGRAPH]) AC_SUBST([SET_MADGRAPH]) AC_SUBST([DO_MADGRAPH]) ]) dnl ##### EvtGen ##### AC_DEFUN([HERWIG_CHECK_EVTGEN], [ AC_MSG_CHECKING([for evtgen]) AC_ARG_WITH([evtgen], AS_HELP_STRING([--with-evtgen=DIR], [Installation path of EvtGen]), [], [with_evtgen=no] ) AC_MSG_RESULT([$with_evtgen]) AS_IF([test "x$with_evtgen" != "xno"], [AC_CHECK_FILES( ${with_evtgen}/lib/libEvtGenExternal.so, [have_evtgen=lib], [have_evtgen=no])], [have_evtgen=no]) AS_IF([test "x$have_evtgen" = "xlib"], [EVTGENPREFIX=${with_evtgen} AC_SUBST(EVTGENPREFIX) ]) AS_IF([test "x$with_evtgen" != "xno" -a "x$have_evtgen" = "xno"], [AC_MSG_ERROR([EvtGen requested but not found])]) AM_CONDITIONAL(HAVE_EVTGEN,[test "x$have_evtgen" = "xlib" ]) if test "x$have_evtgen" = "xlib" ; then LOAD_EVTGEN_DECAYS="read EvtGenBDecays.in" LOAD_EVTGEN_DECAYER="read EvtGenDecayer.in" EVTGENLIBS="-L$with_evtgen/lib -lEvtGen -lEvtGenExternal" else LOAD_EVTGEN_DECAYS="read HerwigBDecays.in" LOAD_EVTGEN_DECAYER="#read EvtGenDecayer.in" EVTGENLIBS="" fi AC_SUBST([LOAD_EVTGEN_DECAYS]) AC_SUBST([LOAD_EVTGEN_DECAYER]) AC_SUBST([EVTGENLIBS]) ]) AC_DEFUN([HERWIG_CHECK_PYTHIA], [ dnl check if a directory is specified for Pythia AC_ARG_WITH(pythia, [AC_HELP_STRING([--with-pythia=dir], [Assume the given directory for Pythia])]) dnl search for the pythia-config script if test "$with_pythia" = ""; then AC_PATH_PROG(pythiaconfig, pythia8-config, no) else AC_PATH_PROG(pythiaconfig, pythia8-config, no, ${with_pythia}/bin) fi if test "${pythiaconfig}" = "no"; then AC_MSG_CHECKING(Pythia) AC_MSG_RESULT(no); # $2 else PYTHIA8DATA=`${pythiaconfig} --datadir`/xmldoc fi AC_SUBST(PYTHIA8DATA) ]) dnl CHECK PYTHIA END dnl ##### PDF PATH ##### AC_DEFUN([HERWIG_PDF_PATH], [ AC_MSG_CHECKING([which Herwig++ PDF data to use]) AC_ARG_WITH(pdf, AC_HELP_STRING([--with-pdf=DIR],[installation path of Herwig++PDF data tarball]), [], [with_pdf=${prefix}] ) HERWIG_PDF_PREFIX=${with_pdf}/share/Herwig++PDF if test -f "${HERWIG_PDF_PREFIX}/mrst/2008/mrstMCal.dat"; then AC_MSG_RESULT([$with_pdf]) localPDFneeded=false else AC_MSG_RESULT([Using built-in PDF data set. For other data sets, set --with-pdf.]) HERWIG_PDF_PREFIX=PDF localPDFneeded=true fi HERWIG_PDF_DEFAULT=${HERWIG_PDF_PREFIX}/mrst/2008/mrstMCal.dat HERWIG_PDF_NLO=${HERWIG_PDF_PREFIX}/mrst/2002/mrst2002nlo.dat HERWIG_PDF_POMERON=${HERWIG_PDF_PREFIX}/diffraction/ AM_CONDITIONAL(WANT_LOCAL_PDF,[test "x$localPDFneeded" = "xtrue"]) AC_SUBST(HERWIG_PDF_DEFAULT) AC_SUBST(HERWIG_PDF_NLO) AC_SUBST(HERWIG_PDF_POMERON) ]) dnl ###### GSL ###### AC_DEFUN([HERWIG_CHECK_GSL], [ AC_MSG_CHECKING([for gsl location]) GSLINCLUDE="" GSLLIBS="" AC_ARG_WITH(gsl, AC_HELP_STRING([--with-gsl=DIR],[location of gsl installation @<:@default=system libs@:>@]), [], [with_gsl=system]) if test "x$with_gsl" = "xno"; then AC_MSG_ERROR([libgsl is required. Please install the GNU scientific library and header files.]) fi if test "x$with_gsl" = "xsystem"; then AC_MSG_RESULT([in system libraries]) oldlibs="$LIBS" AC_CHECK_LIB(m,main) AC_CHECK_LIB(gslcblas,main) AC_CHECK_LIB(gsl,main,[], [ AC_MSG_ERROR([Cannot find libgsl. Please install the GNU scientific library and header files or use --with-gsl=.]) ] ) GSLLIBS="$LIBS" GSLPATH="$with_gsl" LIBS=$oldlibs else if test "`uname -m`" = "x86_64" -a -e "$with_gsl/lib64/libgsl.a" -a -d "$with_gsl/include/gsl"; then AC_MSG_RESULT([found in $with_gsl]) GSLLIBS="-L$with_gsl/lib64 -R$with_gsl/lib64 -lgslcblas -lgsl" GSLINCLUDE="-I$with_gsl/include" GSLPATH="$with_gsl" elif test -e "$with_gsl/lib/libgsl.a" -a -d "$with_gsl/include/gsl"; then AC_MSG_RESULT([found in $with_gsl]) GSLLIBS="-L$with_gsl/lib -R$with_gsl/lib -lgslcblas -lgsl" GSLINCLUDE="-I$with_gsl/include" GSLPATH="$with_gsl" else AC_MSG_RESULT([not found]) AC_MSG_ERROR([Can't find $with_gsl/lib/libgsl.a or the headers in $with_gsl/include]) fi fi AC_SUBST(GSLINCLUDE) AC_SUBST(GSLLIBS) AC_SUBST(GSLPATH) ]) dnl ##### COMPILERFLAGS ##### AC_DEFUN([HERWIG_COMPILERFLAGS], [ AC_REQUIRE([HERWIG_CHECK_GSL]) AC_REQUIRE([HERWIG_CHECK_THEPEG]) AC_REQUIRE([BOOST_REQUIRE]) AC_REQUIRE([AX_COMPILER_VENDOR]) AM_CPPFLAGS="-I\$(top_builddir)/include $THEPEGINCLUDE \$(GSLINCLUDE) \$(BOOST_CPPFLAGS)" AC_MSG_CHECKING([for debugging mode]) AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[debug mode, use --enable-debug=slow for additional options that slow down the run.]), [], [enable_debug=no] ) AC_MSG_RESULT([$enable_debug]) if test "x$enable_debug" = "xno"; then debugflags="" else debugflags="-g" fi dnl -Wfloat-equal -fvisibility-inlines-hidden -Wctor-dtor-privacy -Weffc++ if test -n "$GCC"; then - warnflags="-ansi -pedantic -Wall -Wextra -Wno-overloaded-virtual" + warnflags="-pedantic -Wall -Wextra -Wno-overloaded-virtual" if test "x$enable_debug" = "xslow"; then debugflags="$debugflags -fno-inline" AM_CPPFLAGS="$AM_CPPFLAGS -D_GLIBCXX_DEBUG" fi fi dnl do an actual capability check on ld instead of this workaround case "${host}" in *-darwin*) ;; *) AM_LDFLAGS="-Wl,--enable-new-dtags" ;; esac case "${ax_cv_cxx_compiler_vendor}" in gnu) - AM_CXXFLAGS="-ansi -pedantic -Wall -W" + AM_CXXFLAGS="-pedantic -Wall -W" ;; clang) - AM_CXXFLAGS="-ansi -pedantic -Wall -Wno-overloaded-virtual -Wno-unused-function" + AM_CXXFLAGS="-pedantic -Wall -Wno-overloaded-virtual -Wno-unused-function" dnl -Wno-unneeded-internal-declaration ;; intel) AM_CXXFLAGS="-strict-ansi -Wall -wd13000,1418,981,444,383,1599,1572,2259,980" ;; esac AC_SUBST(AM_CPPFLAGS) AC_SUBST(AM_CFLAGS, ["$warnflags $debugflags"]) AC_SUBST(AM_CXXFLAGS,["$AM_CXXFLAGS $warnflags $debugflags"]) AC_SUBST(AM_FCFLAGS, ["$debugflags"]) AC_SUBST(AM_LDFLAGS) ]) AC_DEFUN([HERWIG_ENABLE_MODELS], [ AC_MSG_CHECKING([if BSM models should be built]) AC_ARG_ENABLE(models, AC_HELP_STRING([--disable-models],[Turn off compilation of BSM models.]), [], [enable_models=yes] ) AC_MSG_RESULT([$enable_models]) LOAD_BSM="" if test "$enable_models" = "yes"; then LOAD_BSM="read BSMlibs.in" fi AC_SUBST(LOAD_BSM) AM_CONDITIONAL(WANT_BSM,[test "$enable_models" = "yes"]) ]) AC_DEFUN([HERWIG_OVERVIEW], [ FCSTRING=`$FC --version | head -1` CXXSTRING=`$CXX --version | head -1` CCSTRING=`$CC --version | head -1` if test "x$PYTHON" != "x:" then python_was_found="yes, using Python $PYTHON_VERSION" else python_was_found="no, requires Python >= 2.6" fi cat << _HW_EOF_ > config.herwig ***************************************************** *** $PACKAGE_STRING configuration summary *** Please include this information in bug reports! ***-------------------------------------------------- *** Prefix: $prefix *** *** BSM models: $enable_models *** UFO converter: ${python_was_found} *** *** Herwig debug mode: $enable_debug *** *** ThePEG: $with_thepeg *** ThePEG headers: $with_thepeg_headers *** *** GoSam: $with_gosam *** GoSam-Contrib: $with_gosam_contrib *** MadGraph: $with_madgraph *** njet: $with_njet *** OpenLoops: $with_openloops *** VBFNLO: $with_vbfnlo *** *** EvtGen: $with_evtgen *** GSL: $with_gsl *** boost: ${BOOST_CPPFLAGS:-system} *** Fastjet: ${fjconfig} *** *** Host: $host *** CC: $CCSTRING *** CXX: $CXXSTRING *** FC: $FCSTRING *** *** CXXFLAGS: $CXXFLAGS ***************************************************** _HW_EOF_ ]) diff --git a/src/defaults/MatchboxLoopInduced.in b/src/defaults/MatchboxLoopInduced.in --- a/src/defaults/MatchboxLoopInduced.in +++ b/src/defaults/MatchboxLoopInduced.in @@ -1,139 +1,139 @@ # -*- ThePEG-repository -*- ##### Set up effective vertices for loop induced processes ######################## ##### To be included from LHC-Matchbox.in, if loop induced ######################## ##### processes are under consideration. ######################## ##### Loop Particles ##### cd /Herwig/Particles/ # neutral loop particle # effect of a loop transmitting no color and no charge create ThePEG::ParticleData neutralLoopParticle setup neutralLoopParticle 200002 nLP 0. 0. 0. 0 0 0 1 1 # charged and colored loop particles # effects of loops transmitting color and charge create ThePEG::ParticleData ccLP- setup ccLP- -200004 ccLP- 0. 0. 0. 0 -3 8 1 1 create ThePEG::ParticleData ccLP+ setup ccLP+ 200004 ccLP+ 0. 0. 0. 0 3 8 1 1 makeanti ccLP- ccLP+ # colored loop particle # effect of a loop transmitting color but no charge create ThePEG::ParticleData cLP setup cLP 200001 cLP 0. 0. 0. 0 0 8 1 1 ##### Vertices ##### cd /Herwig/Vertices/ # self interactions of loop particles # (nLP,nLP,nLP), (cLP,cLP,cLP), (cLP,cLP,nLP) #create Herwig::GenericSVVVertex genericSVVVertex4 #create Herwig::GenericSVVVertex genericSVVVertex5 #create Herwig::GenericSVVVertex genericSVVVertex6 #do genericSVVVertex4:pids 200002 200002 200002 #do genericSVVVertex5:pids 200001 200001 200001 #do genericSVVVertex6:pids 200001 200001 200002 #set genericSVVVertex4:OrderInAlphaS 0 #set genericSVVVertex4:OrderInAlphaEW 0 #set genericSVVVertex5:OrderInAlphaS 0 #set genericSVVVertex5:OrderInAlphaEW 0 #set genericSVVVertex6:OrderInAlphaS 0 #set genericSVVVertex6:OrderInAlphaEW 0 -#insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex4 -#insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex5 -#insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex6 +#insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex4 +#insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex5 +#insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex6 # splits of loop particles to (g,g), (gamma,gamma) or (gamma,g) # (g,g,nLP), (gamma,gamma,nLP), (gamma,g,cLP) create Herwig::GenericSVVVertex genericSVVVertex1 create Herwig::GenericSVVVertex genericSVVVertex2 create Herwig::GenericSVVVertex genericSVVVertex3 do genericSVVVertex1:pids 21 21 200002 do genericSVVVertex2:pids 22 22 200002 do genericSVVVertex3:pids 22 21 200001 set genericSVVVertex1:OrderInAlphaS 2 set genericSVVVertex1:OrderInAlphaEW 0 set genericSVVVertex2:OrderInAlphaS 0 set genericSVVVertex2:OrderInAlphaEW 2 set genericSVVVertex3:OrderInAlphaS 1 set genericSVVVertex3:OrderInAlphaEW 1 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex1 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex2 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex3 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex1 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex2 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex3 # single radiation of gamma or g off loop particles # (nLP,nLP,gamma), (cLP,cLP,g), (cLP,cLP,gamma), (cLP,nLP,g) create Herwig::GenericSVVVertex genericSVVVertex7 create Herwig::GenericSVVVertex genericSVVVertex8 create Herwig::GenericSVVVertex genericSVVVertex9 create Herwig::GenericSVVVertex genericSVVVertex10 do genericSVVVertex7:pids 200002 200002 22 do genericSVVVertex8:pids 200001 200001 21 do genericSVVVertex9:pids 200001 200001 22 do genericSVVVertex10:pids 200001 200002 21 set genericSVVVertex7:OrderInAlphaS 0 set genericSVVVertex7:OrderInAlphaEW 1 set genericSVVVertex8:OrderInAlphaS 1 set genericSVVVertex8:OrderInAlphaEW 0 set genericSVVVertex9:OrderInAlphaS 0 set genericSVVVertex9:OrderInAlphaEW 1 set genericSVVVertex10:OrderInAlphaS 1 set genericSVVVertex10:OrderInAlphaEW 0 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex7 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex8 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex9 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex10 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex7 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex8 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex9 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex10 # splits of loop particles to two vector bosons, # with at least one charged vector boson # (nLP,W+,W-), (ccLP-,g,W+), (ccLP+,g,W-) create Herwig::GenericSVVVertex genericSVVVertex11 create Herwig::GenericSVVVertex genericSVVVertex21 create Herwig::GenericSVVVertex genericSVVVertex31 do genericSVVVertex11:pids 200002 24 -24 do genericSVVVertex21:pids -200004 21 24 do genericSVVVertex31:pids 200004 21 -24 set genericSVVVertex11:OrderInAlphaS 0 set genericSVVVertex11:OrderInAlphaEW 2 set genericSVVVertex21:OrderInAlphaS 1 set genericSVVVertex21:OrderInAlphaEW 1 set genericSVVVertex31:OrderInAlphaS 1 set genericSVVVertex31:OrderInAlphaEW 1 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex11 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex21 -insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex31 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex11 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex21 +insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex31 # single radiation of W+ off loop particles # (cLP,ccLP-,W+) #create Herwig::GenericSVVVertex genericSVVVertex41 #do genericSVVVertex41:pids 200001 -200004 24 #set genericSVVVertex41:OrderInAlphaS 0 #set genericSVVVertex41:OrderInAlphaEW 0 -#insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericSVVVertex41 +#insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericSVVVertex41 ########## ## simple effective (g,g,gamma) and (g,g,Z) vertices ## this needs a VVV vertex #create Herwig::GenericVVVVertex genericVVVVertex51 #create Herwig::GenericVVVVertex genericVVVVertex61 #do genericVVVVertex51:pids 21 21 22 #do genericVVVVertex61:pids 21 21 23 #set genericVVVVertex51:OrderInAlphaS 2 #set genericVVVVertex51:OrderInAlphaEW 1 #set genericVVVVertex61:OrderInAlphaS 2 #set genericVVVVertex61:OrderInAlphaEW 1 -#insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericVVVVertex51 -#insert /Herwig/MatrixElements/Matchbox/PPFactory:DiagramGenerator:Vertices 0 genericVVVVertex61 +#insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericVVVVertex51 +#insert /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator:Vertices 0 genericVVVVertex61