diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -1,102 +1,103 @@ 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$ +^Contrib/.*/.*\.(log|out|tex|run)$ ^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,21 +1,22 @@ 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 +f5c4aa956880f2def763ebd57de7b5bfa55cb1db herwig-7-0-3 diff --git a/AUTHORS b/AUTHORS --- a/AUTHORS +++ b/AUTHORS @@ -1,56 +1,56 @@ ================================================================================ -Herwig 7.0.2 +Herwig 7.0.3 ================================================================================ 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/Analysis/EventShapes.cc b/Analysis/EventShapes.cc --- a/Analysis/EventShapes.cc +++ b/Analysis/EventShapes.cc @@ -1,397 +1,397 @@ // -*- C++ -*- // // EventShapes.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 EventShapes class. // #include "EventShapes.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; NoPIOClassDescription EventShapes::initEventShapes; // Definition of the static class description member. void EventShapes::Init() { static ClassDocumentation documentation ("There is no documentation for the EventShapes class"); } void EventShapes::calcHemisphereMasses() { Lorentz5Momentum pos, neg; Energy pden(ZERO),epos(ZERO),eneg(ZERO); for(unsigned int ix=0;ix<_pv.size();++ix) { if(_pv[ix].vect() * thrustAxis() > ZERO) { pos += _pv[ix]; // can be replaced with, once perp() is giving non-nan results // for nearly parallel vectors. // epos += _pv[ix].perp(thrustAxis()); epos += _pv[ix].vect().cross(thrustAxis()).mag(); } else { neg += _pv[ix]; // see above // eneg += _pv[ix].perp(thrustAxis()); eneg += _pv[ix].vect().cross(thrustAxis()).mag(); } pden += _pv[ix].vect().mag(); } // denominator and masses Energy2 den(sqr(pos.e()+neg.e())); _mPlus = pos.m2()/den; _mMinus = neg.m2()/den; if (_mPlus < _mMinus) swap(_mPlus, _mMinus); // jet broadening _bPlus = 0.5*epos/pden; _bMinus = 0.5*eneg/pden; if (_bPlus < _bMinus) swap(_bPlus, _bMinus); } vector EventShapes::eigenvalues(const double T[3][3]) { // b, c, d are the coefficients of the characteristic polynomial, // a lambda^3 + b lambda^2 + c lambda + d // where a is chosen to be +1. double t11, t12, t13, t22, t23, t33; t11 = T[0][0]; t12 = T[0][1]; t13 = T[0][2]; t22 = T[1][1]; t23 = T[1][2]; t33 = T[2][2]; double b = -(t11 + t22 + t33); double c = t11*t22 + t11*t33 + t22*t33 - sqr(t12) - sqr(t13) - sqr(t23); double d = - t11*t22*t33 - 2.*t12*t23*t13 + t11*sqr(t23) + t22*sqr(t13) + t33*sqr(t12); // use Cardano's formula to compute the zeros double p = (3.*c - sqr(b))/3.; double q = (2.*sqr(b)*b - 9.*b*c + 27.*d)/27.; // check diskriminant to double precision vector lambda; if (4.*p*sqr(p) + 27.*sqr(q) > 2.0e-16) { for (unsigned int i=0; i<3; ++i) { lambda.push_back(-1.); } cerr << "EventShapes::eigenvalues: found D = " << 4.*p*sqr(p) + 27.*sqr(q) << " > 0! No real Eigenvalues!\n"; } else { // get solutions double alpha = acos(-q/2.*sqrt(-27./(p*p*p)))/3.; double w = sqrt(-4.*p/3.); lambda.push_back(w*cos(alpha) - b/3.); lambda.push_back(-w*cos(alpha+M_PI/3.) - b/3.); lambda.push_back(-w*cos(alpha-M_PI/3.) - b/3.); } // sort according to size of eigenvalues // such that lambda[0] > lambda[1] > lambda[2] if (lambda[0] < lambda[1]) { swap(lambda[0], lambda[1]); } if (lambda[0] < lambda[2]) { swap(lambda[0], lambda[2]); } if (lambda[1] < lambda[2]) { swap(lambda[1], lambda[2]); } return lambda; } -Axis EventShapes::eigenvector(const double T[3][3], const double &lam) { +Axis EventShapes::eigenvector(const double T[3][3], double lam) { // set up matrix of system to be solved double a11, a12, a13, a23, a33; a11 = T[0][0] - lam; a12 = T[0][1]; a13 = T[0][2]; a23 = T[1][2]; a33 = T[2][2] - lam; // intermediate steps from gauss type algorithm double b1, b2, b4; b1 = a11*a33 - sqr(a13); b2 = a12*a33 - a13*a23; b4 = a11*a23 - a12*a13; // eigenvector Axis u(b2, -b1, b4); return u.unit(); } vector EventShapes:: eigenvectors(const double T[3][3], const vector &lam) { vector n; for (unsigned int i=0; i<3; ++i) { n.push_back(eigenvector(T, lam[i])); } return n; } void EventShapes::diagonalizeTensors(bool linear, bool cmboost) { // initialize double Theta[3][3]; for(int i=0; i<3; ++i) { for(int j=0; j<3; ++j) { Theta[i][j] = 0.0; } } double sum = 0.; Momentum3 sumvec; vector lam; vector n; // get cm-frame Lorentz5Momentum pcm = Lorentz5Momentum(); Boost beta; if (cmboost) { for(unsigned int ix=0;ix<_pv.size();++ix) { pcm += _pv[ix]; } beta = pcm.findBoostToCM(); } // get Theta_ij for(unsigned int ix=0;ix<_pv.size();++ix) { Lorentz5Momentum dum(_pv[ix]); if (cmboost) { dum.boost( beta ); } Momentum3 pvec = dum.vect(); double pvec_MeV[3] = {pvec.x()/MeV, pvec.y()/MeV, pvec.z()/MeV}; if (pvec.mag() > ZERO) { sumvec += pvec; if (linear) { sum += pvec.mag()*UnitRemoval::InvE; } else { sum += pvec.mag2()*UnitRemoval::InvE2; } for(int i=0; i<3; ++i) { for(int j=i; j<3; ++j) { if (linear) { Theta[i][j] += (pvec_MeV[i])*(pvec_MeV[j])*MeV/(pvec.mag()); } else { Theta[i][j] += (pvec_MeV[i])*(pvec_MeV[j]); } } } } } for(int i=0; i<3; ++i) { for(int j=0; j<3; ++j) { Theta[i][j] /= sum; } } // diagonalize it lam = eigenvalues(Theta); n = eigenvectors(Theta, lam); if (linear) { _linTen = lam; _linTenAxis = n; } else { _spher = lam; _spherAxis = n; } } void EventShapes::calculateThrust() { // explicitly calculate in units of MeV // algorithm based on Brandt/Dahmen Z Phys C1 (1978) // and 'tasso' code from HERWIG // assumes all momenta in cm system, no explicit boost performed here! // unlike for C and D _thrust.clear(); _thrustAxis.clear(); if (_pv.size() < 2) { for (int i=0; i<3; ++i) { _thrust.push_back(-1); _thrustAxis.push_back(Axis()); } return; } // thrust vector p; Energy psum = ZERO; for(unsigned int l=0; l<_pv.size(); ++l) { p.push_back(_pv[l].vect()); psum += p.back().mag(); } Axis axis; if (p.size() == 2) { _thrust.push_back(1.0); _thrust.push_back(0.0); _thrust.push_back(0.0); axis = p[0].unit(); if (axis.z() < 0) axis = -axis; _thrustAxis.push_back(axis); _thrustAxis.push_back(axis.orthogonal()); axis = _thrustAxis[0].cross(_thrustAxis[1]); return; } if (p.size() == 3) { if (p[0].mag2() < p[1].mag2()) swap(p[0], p[1]); if (p[0].mag2() < p[2].mag2()) swap(p[0], p[2]); if (p[1].mag2() < p[2].mag2()) swap(p[1], p[2]); // thrust axis = p[0].unit(); if (axis.z() < 0) axis = -axis; _thrust.push_back(2.*p[0].mag()/psum); _thrustAxis.push_back(axis); // major axis = (p[1] - (axis*p[1])*axis).unit(); if (axis.x() < 0) axis = -axis; _thrust.push_back((abs(p[1]*axis) + abs(p[2]*axis))/psum); _thrustAxis.push_back(axis); // minor _thrust.push_back(0.0); axis = _thrustAxis[0].cross(_thrustAxis[1]); _thrustAxis.push_back(axis); return; } // ACHTUNG special case with >= 4 coplanar particles will still fail. // probably not too important... Energy2 val; calcT(p, val, axis); _thrust.push_back(sqrt(val)/psum); if (axis.z() < 0) axis = -axis; _thrustAxis.push_back(axis.unit()); //major Momentum3 par; for (unsigned int l=0; l<_pv.size(); ++l) { par = (p[l]*axis.unit())*axis.unit(); p[l] = p[l] - par; } calcM(p, val, axis); _thrust.push_back(sqrt(val)/psum); if (axis.x() < 0) axis = -axis; _thrustAxis.push_back(axis.unit()); // minor if (_thrustAxis[0]*_thrustAxis[1] < 1e-10) { Energy eval = ZERO; axis = _thrustAxis[0].cross(_thrustAxis[1]); _thrustAxis.push_back(axis); for (unsigned int l=0; l<_pv.size(); ++l) eval += abs(axis*_pv[l].vect()); _thrust.push_back(eval/psum); } else { _thrust.push_back(-1.0); _thrustAxis.push_back(Axis()); } } void EventShapes::calcT(const vector &p, Energy2 &t, Axis &taxis) { Energy2 tval; t = ZERO; ThreeVector tv; Momentum3 ptot; vector cpm; for (unsigned int k=1; k < p.size(); ++k) { for (unsigned int j=0; j ZERO) { ptot += p[l]; } else { ptot -= p[l]; } } } cpm.clear(); cpm.push_back(ptot-p[j]-p[k]); cpm.push_back(ptot-p[j]+p[k]); cpm.push_back(ptot+p[j]-p[k]); cpm.push_back(ptot+p[j]+p[k]); for (vector::iterator it = cpm.begin(); it != cpm.end(); ++it) { tval = it->mag2(); if (tval > t) { t = tval; taxis = it->unit(); } } } } } void EventShapes::calcM(const vector &p, Energy2 &m, Axis &maxis) { Energy2 mval; m = ZERO; Momentum3 tv, ptot; vector cpm; for (unsigned int j=0; j < p.size(); ++j) { tv = p[j]; ptot = Momentum3(); for (unsigned int l=0; l ZERO) { ptot += p[l]; } else { ptot -= p[l]; } } } cpm.clear(); cpm.push_back(ptot-p[j]); cpm.push_back(ptot+p[j]); for (vector::iterator it = cpm.begin(); it != cpm.end(); ++it) { mval = it->mag2(); if (mval > m) { m = mval; maxis = it->unit(); } } } } void EventShapes::bookEEC(vector & hi) { // hi is the histogram. It is understood that hi.front() contains // the bin [-1 < cos(chi) < -1+delta] and hi.back() the bin [1-delta // < cos(chi) < 1]. Here, delta = 2/hi.size(). Energy Evis(ZERO); for (unsigned int bin = 0; bin < hi.size(); ++bin) { double delta = 2./hi.size(); double coschi = -1+bin*delta; if (_pv.size() > 1) { for (unsigned int i = 0; i < _pv.size()-1; ++i) { Evis += _pv[i].e(); for (unsigned int j = i+1; j < _pv.size(); ++j) { double diff = abs(coschi-cos( _pv[i].vect().angle(_pv[j].vect()) )); if (delta > diff) hi[bin] += _pv[i].e()*_pv[j].e() / MeV2; } } } hi[bin] /= (Evis*Evis) / MeV2; } } diff --git a/Analysis/EventShapes.h b/Analysis/EventShapes.h --- a/Analysis/EventShapes.h +++ b/Analysis/EventShapes.h @@ -1,703 +1,703 @@ // -*- C++ -*- // // EventShapes.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_EventShapes_H #define HERWIG_EventShapes_H // // This is the declaration of the EventShapes class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Handlers/AnalysisHandler.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Vectors/ThreeVector.h" #include "ThePEG/EventRecord/Particle.h" #include "EventShapes.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Analysis * * The EventShapes class is designed so that certain event shapes, such * as the thrust are only calculated once per event given the speed of * the calculation. * * @see \ref EventShapesInterfaces "The interfaces" defined for * EventShapes. */ class EventShapes: public Interfaced { public: /** * The default constructor. */ EventShapes() : _thrustDone(false), _spherDone(false), _linTenDone(false), _hemDone(false), _useCmBoost(false), _mPlus(), _mMinus(), _bPlus(), _bMinus() {} /** * Member to reset the particles to be considered */ void reset(const tPVector &part) { _pv.resize(part.size()); for(unsigned int ix=0;ixmomentum(); _thrustDone = false; _spherDone = false; _linTenDone = false; _hemDone = false; _useCmBoost = false; } public: /** * Member functions to return thrust related shapes */ //@{ /** * The thrust */ double thrust() { checkThrust(); return _thrust[0]; } /** * The major */ double thrustMajor() { checkThrust(); return _thrust[1]; } /** * The minor */ double thrustMinor() { checkThrust(); return _thrust[2]; } /** * The oblateness */ double oblateness() { checkThrust(); return _thrust[1]-_thrust[2]; } /** * The thrust axis */ Axis thrustAxis() { checkThrust(); return _thrustAxis[0]; } /** * The major axis */ Axis majorAxis() { checkThrust(); return _thrustAxis[1]; } /** * The minor axis */ Axis minorAxis() { checkThrust(); return _thrustAxis[2]; } //@} /** * Linear momentum tensor related event shapes */ //@{ /** * The C parameter */ double CParameter() { checkLinTen(); return 3.*(_linTen[0]*_linTen[1]+_linTen[1]*_linTen[2] +_linTen[2]*_linTen[0]); } /** * The D parameter */ double DParameter() { checkLinTen(); return 27.*(_linTen[0]*_linTen[1]*_linTen[2]); } /** * The eigenvalues in descending order */ vector linTenEigenValues() { checkLinTen(); return _linTen; } /** * The eigenvectors in order of descending eigenvalue */ vector linTenEigenVectors() { checkLinTen(); return _linTenAxis; } //@} /** * Quadratic momentum tensor related variables */ //@{ /** * The sphericity */ double sphericity() { checkSphericity(); return 3./2.*(_spher[1]+_spher[2]); } /** * The aplanarity */ double aplanarity() { checkSphericity(); return 3./2.*_spher[2]; } /** * The planarity */ double planarity() { checkSphericity(); return _spher[1]-_spher[2]; } /** * The sphericity axis */ Axis sphericityAxis() { checkSphericity(); return _spherAxis[0]; } /** * The sphericity eigenvalues */ vector sphericityEigenValues() { checkSphericity(); return _spher; } /** * The sphericity eigenvectors */ vector sphericityEigenVectors() { checkSphericity(); return _spherAxis; } //@} /** * Jet mass related event shapes */ //@{ /** * The high hemishpere mass squared divided by the visible energy * squared */ double Mhigh2() { checkHemispheres(); return _mPlus; } /** * The low hemishpere mass squared divided by the visible energy * squared */ double Mlow2() { checkHemispheres(); return _mMinus; } /** * The difference between the * hemishpere masses squared divided by the visible energy squared */ double Mdiff2() { checkHemispheres(); return _mPlus-_mMinus; } //@} /** * Jet broadening related event shapes */ //@{ /** * The wide jet broadening */ double Bmax() { checkHemispheres(); return _bPlus; } /** * The narrow jet broadening */ double Bmin() { checkHemispheres(); return _bMinus; } /** * The sum of the jet broadenings */ double Bsum() { checkHemispheres(); return _bPlus+_bMinus; } /** * The difference of the jet broadenings */ double Bdiff() { checkHemispheres(); return _bPlus-_bMinus; } //@} /** * Single particle variables which do not depend on event shapes axes */ //@{ /** * The scaled momentum \f$\xi=-\log\left( p/E_{\rm beam}\right)\f$. */ double getXi(const Lorentz5Momentum & p, const Energy & Ebeam) { return((Ebeam > 0*MeV && p.vect().mag() > 0*MeV) ? log(Ebeam/p.vect().mag()) : -1.); } /** * Transverse momentum with respect to the beam */ Energy getPt(const Lorentz5Momentum & p) { return p.perp(); } /** * Rapidity with respect to the beam direction */ double getRapidity(const Lorentz5Momentum & p) { return (p.t() > p.z() ? p.rapidity() : 1e99); } //@} /** * Single particle variables related to one of the shape axis. */ //@{ /** * Transverse momentum with respect to the thrust axis in the event plane */ Energy ptInT(const Lorentz5Momentum & p) { checkThrust(); return p.vect()*_thrustAxis[1]; } /** * Transverse momentum with respect to the thrust axis out of the * event plane */ Energy ptOutT(const Lorentz5Momentum & p) { checkThrust(); return p.vect()*_thrustAxis[2]; } /** * Rapidity with respect to the thrust axis */ double yT(const Lorentz5Momentum & p) { checkThrust(); return (p.t() > p.vect()*_thrustAxis[0] ? p.rapidity(_thrustAxis[0]) : 1e99); } /** * Transverse momentum with respect to the sphericity axis in the * event plane */ Energy ptInS(const Lorentz5Momentum & p) { checkSphericity(); return p.vect()*_spherAxis[1]; } /** * Transverse momentum with respect to the sphericity axis out of the * event plane */ Energy ptOutS(const Lorentz5Momentum & p) { checkSphericity(); return p.vect()*_spherAxis[2]; } /** * Rapidity with respect to the sphericity axis */ double yS(const Lorentz5Momentum & p) { checkSphericity(); return (p.t() > p.vect()*_spherAxis[0] ? p.rapidity(_spherAxis[0]) : 1e99); } //@} /** * Energy-energy correlation (EEC) @param hi is the histogram and has * to be provided externally It is understood that the range of the * histogam is -1 < cos(chi) < 1. hi.front() contains the bin [-1 < * cos(chi) < -1+delta] and hi.back() the bin [1-delta < cos(chi) < * 1]. delta = 2/hi.size(). We use classical indices to access the * vector. */ void bookEEC(vector & hi); /** * Before writing the histogram it has to be normalized according to * the number of events. */ void normalizeEEC(vector & hi, long evts) { for (unsigned int bin = 0; bin < hi.size(); bin++) bin /= (hi.size()*evts); } /** * The asymmetry of EEC is calculated from a given \f$\cos\chi\f$ and * EEC histogram, which is a vector as described above. */ double AEEC(vector & hi, double& coschi) { if (coschi > 0. && coschi <= 1.) { int i = static_cast( floor((-coschi+1.)/2.*hi.size()) ); int j = static_cast( floor(( coschi+1.)/2.*hi.size()) ); return hi[i]-hi[j]; } else { return 1e99; } } public: /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or when this class is dynamically * loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. @return a pointer to the new * object. */ virtual IBPtr clone() const {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: /** * Check whether the initialization of a certain class of event shapes * has been calculated and if not do so */ //@{ /** * Check if thrust related variables have been calculated and if not * do so */ void checkThrust() { if (!_thrustDone) { _thrustDone = true; calculateThrust(); } } /** * Check if the linear tensor related variables have been calculated * and if not do so */ void checkLinTen() { if (!_linTenDone) { _linTenDone = true; diagonalizeTensors(true, _useCmBoost); } } /** * Check if the quadratic tensor related variables have been * calculated and if not do so */ void checkSphericity() { if (!_spherDone) { _spherDone = true; diagonalizeTensors(false, _useCmBoost); } } /** * Check if the hemisphere mass variables and jet broadenings have * been calculated and if not do so */ void checkHemispheres() { if (!_hemDone) { _hemDone = true; calcHemisphereMasses(); } } //@} /** * Methods that actually calculate the event shapes */ //@{ /** * Calculate the hemisphere masses and jet broadenings */ void calcHemisphereMasses(); /** * Calculate the thrust and related axes */ void calculateThrust(); /** * Diagonalize the tensors @param linear switch between * diagonalization of linear/quadratic tensor. @param cmboost tells * whether to boost into cm frame of all momenta first, or not * (default off, and no interface to this). */ void diagonalizeTensors(bool linear, bool cmboost); /** * Quite general diagonalization of a symmetric Matrix T, given as an * array of doubles. The symmetry is not checked explicitly as this * is clear in the context. It uses an explicit generic solution of * the eigenvalue problem and no numerical approximation, based on * Cardano's formula. @param T Matrix to be diagonalised */ vector eigenvalues(const double T[3][3]); /** * The eigenvector of @param T to a given eigenvalue @param lam */ - Axis eigenvector(const double T[3][3], const double &lam); + Axis eigenvector(const double T[3][3], double lam); /** * The eigenvectors of @param T corresponding to the eigenvectors * @param lam . The ordering of the vectors corresponds to the * ordering of the eigenvalues. */ vector eigenvectors(const double T[3][3], const vector &lam); /** * Member to calculate the thrust * @param p The three vectors * @param t The thrust-squared (up to an Energy scale factor) * @param taxis The thrust axis */ void calcT(const vector &p, Energy2 &t, Axis &taxis); /** * Member to calculate the major * @param p The three vectors * @param m The major-squared (up to an Energy scale factor) * @param maxis The major axis */ void calcM(const vector &p, Energy2 &m, Axis &maxis); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static NoPIOClassDescription initEventShapes; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ EventShapes & operator=(const EventShapes &); private: /** * Vector of particle momenta to be analysed */ vector _pv; /** * Various event shape axes */ //@{ /** * The thrust related axes */ vector _thrustAxis; /** * The sphericity related axes */ vector _spherAxis; /** * The linearised tensor axes */ vector _linTenAxis; //@} /** * Values of axis related event shapes */ //@{ /** * Values of thrust related variables */ vector _thrust; /** * Values of sphericity related variables */ vector _spher; /** * Values of linearized tensor related variables */ vector _linTen; //@} /** * Whether or not certain event axes have been calculated */ //@{ /** * Whether or not the thrust is calculated */ bool _thrustDone; /** * Whether or not the sphericity is calculated */ bool _spherDone; /** * Whether or not the linearizes tensor is calculated */ bool _linTenDone; /** * Whether or not the hemisphere masses have been calculated */ bool _hemDone; //@} /** * Whether ot not to boost to the CMS frame for the tensor diagonalizations */ bool _useCmBoost; /** * Hemisphere masses */ //@{ /** * The high hemisphere mass */ double _mPlus; /** * The low hemisphere mass */ double _mMinus; //@} /** * The jet broadenings */ //@{ /** * The wide jet broadening */ double _bPlus; /** * The narrow jet broadening */ double _bMinus; //@} }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of EventShapes. */ template <> struct BaseClassTrait { /** Typedef of the first base class of EventShapes. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the EventShapes 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::EventShapes"; } /** Return the name(s) of the shared library (or libraries) be loaded to get * access to the EventShapes class and any other class on which it depends * (except the base class). */ static string library() { return "HwAnalysis.so"; } }; /** @endcond */ } #endif /* HERWIG_EventShapes_H */ diff --git a/Analysis/Makefile.am b/Analysis/Makefile.am --- a/Analysis/Makefile.am +++ b/Analysis/Makefile.am @@ -1,59 +1,59 @@ pkglib_LTLIBRARIES = HwAnalysis.la HwAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 10:0:0 HwAnalysis_la_SOURCES = \ EventShapes.cc EventShapes.fh EventShapes.h \ EventShapesMasterAnalysis.cc EventShapesMasterAnalysis.h \ BasicConsistency.cc BasicConsistency.h \ LEPMultiplicityCount.cc LEPMultiplicityCount.h \ MultiplicityInfo.h \ LEPBMultiplicity.cc\ LEPBMultiplicity.h \ SimpleLHCAnalysis.h SimpleLHCAnalysis.cc\ TTbarAnalysis.h TTbarAnalysis.cc\ LPairAnalysis.h LPairAnalysis.cc\ GammaGammaAnalysis.h GammaGammaAnalysis.cc\ GammaJetAnalysis.h GammaJetAnalysis.cc\ HiggsJetAnalysis.h HiggsJetAnalysis.cc \ ParallelRunAnalysis.h ParallelRunAnalysis.cc \ DrellYanPT.h DrellYanPT.cc pkglib_LTLIBRARIES += HwJetsAnalysis.la -HwJetsAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0 +HwJetsAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0 HwJetsAnalysis_la_SOURCES = \ LeptonsJetsAnalysis.h LeptonsJetsAnalysis.cc \ JetsPlusAnalysis.h JetsPlusAnalysis.cc \ HJetsAnalysis.h HJetsAnalysis.cc \ ZJetsAnalysis.h ZJetsAnalysis.cc \ TTJetsAnalysis.h TTJetsAnalysis.cc \ CrossSectionAnalysis.h CrossSectionAnalysis.cc pkglib_LTLIBRARIES += HwLEPAnalysis.la HwLEPAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 7:0:0 HwLEPAnalysis_la_SOURCES = \ BFragmentationAnalysisHandler.cc BFragmentationAnalysisHandler.h\ SingleParticleAnalysis.cc SingleParticleAnalysis.h\ LEPEventShapes.cc LEPEventShapes.h\ IdentifiedParticleAnalysis.cc IdentifiedParticleAnalysis.h\ BELLECharmAnalysis.h BELLECharmAnalysis.cc\ CLEOCharmAnalysis.h CLEOCharmAnalysis.cc # analysis code which depends on fastjet if WANT_LIBFASTJET pkglib_LTLIBRARIES += HwLEPJetAnalysis.la HwLEPJetAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:1:0 HwLEPJetAnalysis_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \ -I$(FASTJETPATH) HwLEPJetAnalysis_la_LIBADD = $(FASTJETLIBS) HwLEPJetAnalysis_la_SOURCES = \ LEPJetAnalysis.cc LEPJetAnalysis.h\ LEPFourJetsAnalysis.cc LEPFourJetsAnalysis.h endif pkglib_LTLIBRARIES += HwTevatronAnalysis.la HwTevatronAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0 HwTevatronAnalysis_la_CPPFLAGS = $(AM_CPPFLAGS) HwTevatronAnalysis_la_SOURCES = \ ZpTRun2.cc ZpTRun2.h \ ZpTRun1.cc ZpTRun1.h \ Wpt.cc Wpt.h \ Zrapidity.cc Zrapidity.h diff --git a/Config/ltmain.sh b/Config/ltmain.sh --- a/Config/ltmain.sh +++ b/Config/ltmain.sh @@ -1,11147 +1,11149 @@ #! /bin/sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2014-01-03.01 # libtool (GNU libtool) 2.4.6 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 . PROGRAM=libtool PACKAGE=libtool VERSION=2.4.6 package_revision=2.4.6 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2015-01-20.17; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # Copyright (C) 2004-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # 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. # As a special exception to the GNU General Public License, if you distribute # this file as part of a program or library that is built using GNU Libtool, # you may include this file under the same distribution terms that you use # for the rest of that program. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNES 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 . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1+=\\ \$func_quote_for_eval_result" }' else func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1=\$$1\\ \$func_quote_for_eval_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_for_eval ARG... # -------------------------- # Aesthetically quote ARGs to be evaled later. # This function returns two values: # i) func_quote_for_eval_result # double-quoted, suitable for a subsequent eval # ii) func_quote_for_eval_unquoted_result # has all characters that are still active within double # quotes backslashified. func_quote_for_eval () { $debug_cmd func_quote_for_eval_unquoted_result= func_quote_for_eval_result= while test 0 -lt $#; do case $1 in *[\\\`\"\$]*) _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; *) _G_unquoted_arg=$1 ;; esac if test -n "$func_quote_for_eval_unquoted_result"; then func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" else func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" fi case $_G_unquoted_arg in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_quoted_arg=\"$_G_unquoted_arg\" ;; *) _G_quoted_arg=$_G_unquoted_arg ;; esac if test -n "$func_quote_for_eval_result"; then func_append func_quote_for_eval_result " $_G_quoted_arg" else func_append func_quote_for_eval_result "$_G_quoted_arg" fi shift done } # func_quote_for_expand ARG # ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { $debug_cmd case $1 in *[\\\`\"]*) _G_arg=`$ECHO "$1" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) _G_arg=$1 ;; esac case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_arg=\"$_G_arg\" ;; esac func_quote_for_expand_result=$_G_arg } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_for_expand "$_G_cmd" eval "func_notquiet $func_quote_for_expand_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_for_expand "$_G_cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # Set a version string for this script. scriptversion=2014-01-07.03; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # Copyright (C) 2010-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # 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. # 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 . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# warranty; '. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # to the main code. A hook is just a named list of of function, that can # be run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of functions called by FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It is assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do eval $_G_hook '"$@"' # store returned options list back into positional # parameters for next 'cmd' execution. eval _G_hook_result=\$${_G_hook}_result eval set dummy "$_G_hook_result"; shift done func_quote_for_eval ${1+"$@"} func_run_hooks_result=$func_quote_for_eval_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, remove any # options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # func_quote_for_eval ${1+"$@"} # my_options_prep_result=$func_quote_for_eval_result # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # # Note that for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # ;; # *) set dummy "$_G_opt" "$*"; shift; break ;; # esac # done # # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # # func_quote_for_eval ${1+"$@"} # my_option_validation_result=$func_quote_for_eval_result # } # func_add_hook func_validate_options my_option_validation # # You'll alse need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd func_options_prep ${1+"$@"} eval func_parse_options \ ${func_options_prep_result+"$func_options_prep_result"} eval func_validate_options \ ${func_parse_options_result+"$func_parse_options_result"} eval func_run_hooks func_options \ ${func_validate_options_result+"$func_validate_options_result"} # save modified positional parameters for caller func_options_result=$func_run_hooks_result } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propogate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before # returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} # Adjust func_parse_options positional parameters to match eval set dummy "$func_run_hooks_result"; shift # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) test $# = 0 && func_missing_arg $_G_opt && break case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables after # splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} test "x$func_split_equals_lhs" = "x$1" \ && func_split_equals_rhs= }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /(C)/!b go :more /\./!{ N s|\n# | | b more } :go /^# Written by /,/# warranty; / { s|^# || s|^# *$|| s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| p } /^# Written by / { s|^# || p } /^warranty; /q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.6' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname (GNU libtool) 2.4.6 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func__fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote_for_eval ${1+"$@"} libtool_validate_options_result=$func_quote_for_eval_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang memory and address sanitizer -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -fsanitize=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_for_eval "$arg" arg=$func_quote_for_eval_result fi ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: diff --git a/Contrib/AlpGen/AlpGenHandler.cc b/Contrib/AlpGen/AlpGenHandler.cc --- a/Contrib/AlpGen/AlpGenHandler.cc +++ b/Contrib/AlpGen/AlpGenHandler.cc @@ -1,1394 +1,1394 @@ #include "AlpGenHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include #include "ThePEG/Utilities/Throw.h" -#include "Herwig/Shower/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequence.hh" #include "gsl/gsl_rng.h" #include "gsl/gsl_randist.h" using namespace Herwig; bool recordEntry(PPtr i,PPtr j) { return (i->number()number()); } bool pTsortFunction(PPtr i,PPtr j) { return (i->momentum().perp2()>j->momentum().perp2()); } bool ETsortFunction(pair i,pair j) { return (i.first>j.first); } bool isMomLessThanEpsilon(Lorentz5Momentum p,Energy epsilon) { return (abs(p.x())> alphaS_ >> ncy_ >> ncphi_ >> ihvy_ >> nph_ >> nh_ >> iunit(etclusmean_,GeV) >> rclus_ >> etaclmax_ >> rclusfactor_ >> ihrd_ >> njets_ >> drjmin_ >> highestMultiplicity_ >> ycmax_ >> ycmin_ >> jetAlgorithm_ >> vetoIsTurnedOff_ >> inputIsNLO_ >> highestNLOMultiplicity_ >> etclusfixed_ >> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV); } ClassDescription AlpGenHandler::initAlpGenHandler; // Definition of the static class description member. void AlpGenHandler::Init() { static ClassDocumentation documentation ("The AlpGenHandler class performs MEPS merging " "using the MLM procedure."); static Reference interfaceShowerAlpha ("ShowerAlpha", "The object calculating the strong coupling constant", &AlpGenHandler::alphaS_, false, false, true, false, false); static Parameter interfaceNoCellsInRapidity ("NoCellsInRapidity", "The number of cells spanning the rapidity interval of " "the calorimeter", &AlpGenHandler::ncy_, 100, 1, 10000, false, false, Interface::limited); static Parameter interfaceNoCellsInPhi ("NoCellsInPhi", "The number of cells spanning the phi interval of " "the calorimeter", &AlpGenHandler::ncphi_, 60, 1, 10000, false, false, Interface::limited); static Parameter interfaceihvy ("ihvy", "heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t)", &AlpGenHandler::ihvy_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenph ("nph", "Number of photons in the AlpGen process", &AlpGenHandler::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenh ("nh", "Number of higgses in the AlpGen process", &AlpGenHandler::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfaceETClus ("ETClus", "The ET threshold defining a jet in the merging procedure", &AlpGenHandler::etclusmean_, GeV, 20*GeV, 0*GeV, 14000*GeV, false, false, Interface::limited); static Parameter interfaceRClus ("RClus", "The cone size used to define a jet in the merging procedure", &AlpGenHandler::rclus_, 0.4, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceEtaClusMax ("EtaClusMax", "The maximum |eta| used to define a jet in the merging procedure", &AlpGenHandler::etaclmax_, 5.0, 0.0, 15.0, false, false, Interface::limited); static Parameter interfaceRClusFactor ("RClusFactor", "The prefactor for RClus used to define the jet-parton matching " "distance", &AlpGenHandler::rclusfactor_, 1.5, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceihrd ("ihrd", "The AlpGen hard process code", &AlpGenHandler::ihrd_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacenjets ("njets", "The number of light jets in the AlpGen process (i.e. the " "extra ones)", &AlpGenHandler::njets_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacedrjmin ("drjmin", "Mimimum parton-parton R-sep used for generation.", &AlpGenHandler::drjmin_, 0.7, 0.0, 4.0, false, false, Interface::limited); static Parameter interfacehighestMultiplicity ("highestMultiplicity", "If true it indicates that this is the highest multiplicity input " "ME-level configuration to be processed.", &AlpGenHandler::highestMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfacehighestNLOMultiplicity ("highestNLOMultiplicity", "If true it indicates that this is the highest NLO multiplicity input " "ME-level configuration to be processed.", &AlpGenHandler::highestNLOMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfaceETClusFixed ("ETClusFixed", "If false, indicates that the jet merging scale, etclus_ is allowed to vary" "according to epsetclus_", &AlpGenHandler::etclusfixed_, 1, 0, 1, false, false, Interface::limited); static Parameter interfaceEpsilonETClus ("EpsilonETClus", "The ET threshold defining a jet in the merging procedure", &AlpGenHandler::epsetclus_, GeV, 2.5*GeV, 0*GeV, 100.0*GeV, false, false, Interface::limited); static Switch interfaceJetAlgorithm ("JetAlgorithm", "Determines the jet algorithm for finding jets in parton-jet " "matching in the MLM procedure.", &AlpGenHandler::jetAlgorithm_, 2, false, false); static SwitchOption AntiKt (interfaceJetAlgorithm, "AntiKt", "The anti-kt jet algorithm.", -1); static SwitchOption CambridgeAachen (interfaceJetAlgorithm, "CambridgeAachen", "The Cambridge-Aachen jet algorithm.", 0); static SwitchOption Kt (interfaceJetAlgorithm, "Kt", "The Kt jet algorithm.", 1); static SwitchOption GetJet (interfaceJetAlgorithm, "GetJet", "Calorimeter-based GetJet algorithm (default).", 2); static Switch interfaceVetoIsTurnedOff ("VetoIsTurnedOff", "Allows the vetoing mechanism to be switched off.", &AlpGenHandler::vetoIsTurnedOff_, false, false, false); static SwitchOption VetoingIsOn (interfaceVetoIsTurnedOff, "VetoingIsOn", "The MLM merging veto mechanism is switched ON.", false); static SwitchOption VetoingIsOff (interfaceVetoIsTurnedOff, "VetoingIsOff", "The MLM merging veto mechanism is switched OFF.", true); static Switch interfaceInputIsNLO ("InputIsNLO", "Signals whether the input LH file is tree-level accurate " "or contains NLO (Powheg) events.", &AlpGenHandler::inputIsNLO_, false, false, false); static SwitchOption InputIsNotNLO (interfaceInputIsNLO, "InputIsNotNLO", "The input LH events have tree-level accuracy.", false); static SwitchOption InputIsNLO (interfaceInputIsNLO, "InputIsNLO", "The input LH events have NLO accuracy.", true); } void AlpGenHandler::dofinish() { ShowerHandler::dofinish(); } void AlpGenHandler::doinit() { //print error if HardProcID is not set in input file if(ihrd_ == -999) { cout << "Error: AlpGenHandler:ihrd not set!" << endl; exit(1); } ShowerHandler::doinit(); // Compute calorimeter edges in rapidity for GetJet algorithm. ycmax_=etaclmax_+rclus_; ycmin_=-ycmax_; // Initialise calorimeter. calini_m(); } // Throws a veto according to MLM strategy ... when we finish writing it. bool AlpGenHandler::showerHardProcessVeto() { if(vetoIsTurnedOff_) return false; // Skip veto for processes in which merging is not implemented: if(ihrd_==7||ihrd_==8||ihrd_==13) { ostringstream wstring; wstring << "AlpGenHandler::showerHardProcessVeto() - warning." << "MLM merging not implemented for AlpGen " << "processes 4Q (ihrd=7), QQh (ihrd=8), " << "(single) top (ihrd=13) \n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); return false; } // Fill preshowerISPs_ pair and preshowerFSPs_ particle pointer vector. getPreshowerParticles(); // Fill showeredISHs_, showeredISPs and showeredRems pairs, as well as // showeredFSPs_ particle pointer vector. getShoweredParticles(); // Turn on some screen output debugging: 0 = none ---> 5 = very verbose. doSanityChecks(0); // Dimensions of each calorimter cell in y and phi. dely_ = (ycmax_-ycmin_)/double(ncy_); delphi_ = 2*M_PI/double(ncphi_); // Fill partonsToMatch_ with only those pre-shower partons intended to // used in jet-parton matching and fill particlesToCluster_ using only // those final state particles (post-shower) which are supposed to go // in the jet clustering used to do merging. partonsToMatch_ = preshowerFSPs_; particlesToCluster_ = showeredFSPs_ ; // <--- TO DO: add remnants in here ??? // Filter out all but the 'extra' light-parton progenitors and their // associated final state particles. caldel_m(); double prob(1); //if etclusfixed_ then set the etclus_ to the fixed chosen value if(etclusfixed_) { etclus_ = etclusmean_; } else { //else, if we wish to vary etclus_, we use the probability distribution //choose a probability between 0 and 1 prob = rnd(); etclus_ = etclusran_(prob); } if(jetAlgorithm_==2) { // If using GetJet fill the calorimeter cells now from particlesToCluster_ calsim_m(); // Make jets from the calorimeter blobs. getjet_m(rclus_,etclus_,etaclmax_); } else { // Cluster particlesToCluster_ into jets with FastJet. getFastJets(rclus_,etclus_,etaclmax_); } // If there are less jets than partons then parton-jet matching is // bound to fail: reject the event already. Also, if the input is // an NLO event file it will 99.5% of the time contain a number of // light partons in the F.S. equal to that in the real emission // process in the NLO calculation, moreover, it has already // effectively merged njets_-1 and njets jet events. So in that // case we do not reject events on the grounds they have jet // multiplicity less than partonsToMatch_.size() but rather less // jets than partonsToMatch.size()-1; such events are better // described by the lower-by-one-unit (partonsToMatch_.size()-1) // of multiplicity NLO event file, or the lower-by-two-units // (partonsToMatch_.size()-2) of multiplicity LO event file. // If it is not jet production apply rejection criterion as above. if(ihrd_!=9) { if(!inputIsNLO_) { if(pjet_.size() < partonsToMatch_.size()) return true; } else { if(pjet_.size() < partonsToMatch_.size()-1) return true; } // Otherwise, in the case of jet production allow the lowest // contributing multiplicity process (just at NLO), namely, // dijet production, to give rise to 1-jet and even 0-jet // events, since these can contribute to, for example, the // inclusive jet cross section i.e. in this case the rejection // is only applied in the case of the next-to-lowest multiplicity // processes (>2 parton events at LO and >3 parton events at NLO). } else { if(!inputIsNLO_) { // KH - March 5th // Removed the following line giving special treatment // also to the LO events, to maintain consistency with // the fortran algorithm, at least for now. So now jet // production at LO is being treated the same as all // other processes. // if(partonsToMatch_.size()==2 && pjet_.size()<2) return false; if(pjet_.size() < partonsToMatch_.size()) return true; } else { if(partonsToMatch_.size()<=3 && pjet_.size()<2) return false; if(pjet_.size() < partonsToMatch_.size()-1) return true; } } // Sort partonsToMatch_ from high to low pT. sort(partonsToMatch_.begin(),partonsToMatch_.end(),pTsortFunction); // Match light progenitors to jets. vector jetToPartonMap(pjet_.size(),-999); Energy etmin(777e100*GeV); // If the input is NLO events then don't do any jet-parton matching! if(!inputIsNLO_) { // For each parton, starting with the hardest one ... for(unsigned int ixx=0; ixx=0) { jetToPartonMap[jetIndexForDRmin]=ixx; if(ixx==0||etjet_[jetIndexForDRmin]partonsToMatch_.size() && !inputIsNLO_) return true; if(inputIsNLO_) { if(!highestNLOMultiplicity_) { if(pjet_.size()>partonsToMatch_.size()-1) return true; } else { if(!highestMultiplicity_&&pjet_.size()>partonsToMatch_.size()) return true; } } // Veto events where matched jets are softer than non-matched ones, // in the inclusive (highestMultiplicity_ = true) mode, unless we // are dealing with NLO input events. if(highestMultiplicity_ && !inputIsNLO_ ) { for(unsigned int ixx=0; ixxid())==4||abs(partonsToMatch_[jxx]->id())==5)) continue; if(partonJetDeltaR(partonsToMatch_[jxx],pjet_[ixx])etmin) return true; } } } // Otherwise we accept the event ... return false; } /* Function that returns the R distance between a particle and a jet. */ double AlpGenHandler::partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom) { LorentzMomentum partonmom(partonptr->momentum()); // Calculate DY, DPhi and then DR double DY(partonmom.eta()-jetmom.eta()); double DPhi(partonmom.phi()-jetmom.phi()); if(DPhi>M_PI) DPhi=2*M_PI-DPhi; double DR(sqrt(sqr(DY)+sqr(DPhi))); return DR; } // Initialize calorimeter for calsim_m and getjet_m. Note that // because initialization is separte calsim_m can be called more // than once to simulate pileup of several events. void AlpGenHandler::calini_m() { // Making sure arrays are clear before filling; cphcal_.clear(); sphcal_.clear(); cthcal_.clear(); sthcal_.clear(); // Fill array holding phi values of calorimeter cell centres. double deltaPhi(2*M_PI/ncphi_); for(unsigned int iphi=1; iphi<=ncphi_; iphi++) { double phi(deltaPhi*(iphi-0.5)); // Goes phi~=0 to phi~=2*pi (iphi=0--->ncphi). cphcal_.push_back(cos(phi)); // ==> goes from +1 ---> +1 (iphi=0--->ncphi). sphcal_.push_back(sin(phi)); // ==> goes 0 -> 1 -> 0 -> -1 -> 0 (iphi=0--->ncphi). } // Fill array holding theta values of calorimeter cell centres in Y. double deltaY((ycmax_-ycmin_)/double(ncy_)); for(unsigned int iy=1; iy<=ncy_; iy++) { double Y(deltaY*(iy-0.5)+ycmin_); double th(2*atan(exp(-Y))); // Goes bwds th~=pi to fwds th~=0 (iy=0--->ncy). cthcal_.push_back(cos(th)); // ==> goes from -1 ---> +1 (iy=0--->ncy). sthcal_.push_back(sin(th)); // ==> goes from 0 ---> +1 ---> 0 (iy=0--->ncy). } return; } // Get FastJets void AlpGenHandler::getFastJets(double rjet, Energy ejcut, double etajcut) { vector particlesToCluster; for(unsigned int ipar=0; iparmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it may go in the jet finder. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { // input particles into fastjet pseudojet fastjet::PseudoJet p(particlesToCluster_[ipar]->momentum().x()/GeV, particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().z()/GeV, particlesToCluster_[ipar]->momentum().e()/GeV); p.set_user_index(ipar); particlesToCluster.push_back(p); } } } fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme; fastjet::Strategy strategy = fastjet::Best; double R(rjet); fastjet::JetDefinition theJetDefinition; switch (jetAlgorithm_) { case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm, R, recombinationScheme, strategy); break; case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm, R, recombinationScheme, strategy); break; default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; } fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition); vector inclusiveJets = fastjetEvent.inclusive_jets(); inclusiveJets = fastjet::sorted_by_pt(inclusiveJets); // Fill the array of jet momenta for the rest of the veto procedure. pjet_.clear(); pjet_.resize(inclusiveJets.size()); etjet_.clear(); etjet_.resize(inclusiveJets.size()); for(unsigned int ffj=0; ffjetajcut) { pjet_.erase(pjet_.begin()+fj); etjet_.erase(etjet_.begin()+fj); fj--; } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it goes in the calorimeter. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { double phi(atan2(particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().x()/GeV)); if(phi<0) phi+=2*M_PI; unsigned int iy(int((y-ycmin_)/dely_)); unsigned int iphi(int(phi/delphi_)); et_[iy][iphi]+=particlesToCluster_[ipar]->momentum().e()*sthcal_[iy]; } } } return; } // Find highest remaining cell > etstop and sum surrounding cells // with -- delta(y)^2+delta(phi)^2 < Rjet^2 , ET>eccut. Keep sets // with ET>ejcut and abs(eta)=etstop) { // Find the cell with the highest ET from // those not already assigned to a jet. etmax=0*GeV; int iymx(0), iphimx(0); for(unsigned int iphi=0; iphietmax&&jetIdx_[iy][iphi]<0) { etmax = et_[iy][iphi]; iymx = iy; iphimx = iphi; } // If the remaining cell with the highest ET has ET < etstop, stop. if(etmax(ncy_*ncphi_)) { cout << "AlpGenHandler::getjet_m() - Fatal error." << endl; cout << "We found " << ipass << " calo cells with the highest ET so" << "far\nbut the calorimeter only has " << ncy_*ncphi_ << " " << "cells in it!" << endl; exit(10); } // Add a jet vector (may get deleted if jet fails ET / eta cuts). etjet_.push_back(0*GeV); pjet_.push_back(Lorentz5Momentum(0.*GeV,0.*GeV,0.*GeV,0.*GeV,0.*GeV)); // Loop over all calo cells in range iphimx +/- nphi1 (inclusive) // wrapping round in azimuth if required. for(unsigned int iphi1=0; iphi1<=2*nphi1; iphi1++) { int iphix(iphimx-nphi1+iphi1); if(iphix<0) iphix += ncphi_; if(iphix>=int(ncphi_)) iphix -= ncphi_; // Loop over all calo cells in range iymx +/- ny1 (inclusive). for(unsigned int iy1=0; iy1<=2*ny1; iy1++) { int iyx(iymx-ny1+iy1); // If the cell is outside the calorimeter OR if it was already // associated to a jet then skip to the next loop. if(iyx>=0&&iyx=eccut) { Energy ECell(et_[iyx][iphix]/sthcal_[iyx]); pjet_.back()+=LorentzMomentum(ECell*sthcal_[iyx]*cphcal_[iphix], // px ECell*sthcal_[iyx]*sphcal_[iphix], // py ECell*cthcal_[iyx],ECell); // pz, E. // N.B. This is the same reln as in ThePEG between phi and x,y. etjet_.back()+=et_[iyx][iphix]; jetIdx_[iyx][iphix] = pjet_.size()-1; // Identify cell with this jet. } } } } // Compute the current jet's mass. pjet_.back().rescaleMass(); // Throw the jet away if it's ET is less than ejcut. if(etjet_.back()etajcut) { pjet_.pop_back(); etjet_.pop_back(); } } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxchildren()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else getDescendents(theChildren[ixx]); return; } void AlpGenHandler::caldel_m() { preshowerFSPsToDelete_.clear(); showeredFSPsToDelete_.clear(); for(unsigned int ixx=0; ixxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24|| abs(preshowerFSPs_[ixx]->id())==22|| abs(preshowerFSPs_[ixx]->id())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); } if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==6) { getDescendents(preshowerFSPs_[ixx]->parents()[0]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==4&&ixx<1)|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+1)))|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+2)))|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2)) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparticlesToCluster_.size()) { throw Exception() << "AlpGenHandler::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of showered particles to build jets from = " << particlesToCluster_.size() << "\n" << "There should be at least as many partons to\n" << "cluster as there are partons to match to.\n" << Exception::eventerror; } // Acid test. unsigned int tmpUnsignedInt(njets_); if(!inputIsNLO_&&partonsToMatch_.size()!=tmpUnsignedInt) { for(unsigned int ixx=0; ixxid())>=6&& abs(partonsToMatch_[ixx]->id())!=21) throw Exception() << "AlpGenHandler::caldel_m() - ERROR!\n" << "Found a parton to match to which is not a quark or gluon!" << *partonsToMatch_[ixx] << "\n" << Exception::eventerror; } throw Exception() << "AlpGenHandler::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of light jets (njets) in AlpGen process = " << njets_ << "\n" << "These should be equal." << "\n" << Exception::eventerror; } return; } // This looks for all descendents of a top up to but not including // the W and b children. void AlpGenHandler::getTopRadiation(PPtr theParticle) { ParticleVector theChildren(theParticle->children()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else if(abs(theChildren[ixx]->id())==5||abs(theChildren[ixx]->id())==24) return; else getTopRadiation(theChildren[ixx]); return; } void AlpGenHandler::caldel_hvq() { // Fill partonsToMatch_ with only those pre-shower partons intended to // be used in heavy-quark-jet matching and fill particlesToCluster_ using // only those final state particles (post-shower) which are supposed // in the heavy-quark-jet clustering used to do merging. To begin with // these are made from the corresponding sets of particles that were // omitted from the initial jet-parton matching run. partonsToMatch_ = preshowerFSPsToDelete_; particlesToCluster_.resize(showeredFSPsToDelete_.size()); for(unsigned int ixx=0; ixxid())<4||abs(partonsToMatch_[ixx]->id())>6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxid())==5&& partonsToMatch_[ixx]->parents().size()>0&& abs(partonsToMatch_[ixx]->parents()[0]->id())==6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxparents().size()>0&& (abs(partonsToMatch_[ixx]->parents()[0]->id())==23|| abs(partonsToMatch_[ixx]->parents()[0]->id())==24|| abs(partonsToMatch_[ixx]->parents()[0]->id())==25)) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxsubProcess()->intermediates()); for(unsigned int ixx=0; ixxid())==6) { partonsToMatch_.push_back(intermediates[ixx]); tmpList_.clear(); getTopRadiation(partonsToMatch_.back()); for(unsigned int jxx=0; jxxid())>=4&&abs(partonsToMatch_[ixx]->id())<=6) { theProgenitor = partonsToMatch_[ixx]; // Follow the heavy quark line down to where it stops branching. while(theProgenitor->children().size()>0) { theLastProgenitor = theProgenitor; for(unsigned int jxx=0; jxxchildren().size(); jxx++) { if(theProgenitor->children()[jxx]->id()==theProgenitor->id()) theProgenitor=theProgenitor->children()[jxx]; } // If the progenitor had children but none of them had // the same particle id as it, then it must have undergone // a decay rather than a branching, i.e. it is the end of // the evolution line, so, if(theProgenitor==theLastProgenitor) break; } evolvedHeavyQuarks.push_back(theProgenitor); } } // Now delete the evolved heavy quark from the particlesToCluster. for(unsigned int ixx=0; ixxsubProcess()->incoming(); // LH file final-state partICLEs: preshowerFSPs_ = lastXCombPtr()->subProcess()->outgoing(); return; } void AlpGenHandler::getShoweredParticles() { // Post-shower initial-state hadrons: showeredISHs_ = eventHandler()->currentEvent()->incoming(); // Post-shower initial-state partons: for(unsigned int ixx=0; ixx<(showeredISHs_.first)->children().size(); ixx++) if(((showeredISHs_.first)->children()[ixx]->id())<6|| ((showeredISHs_.first)->children()[ixx]->id())==21) showeredISPs_.first=(showeredISHs_.first)->children()[ixx]; for(unsigned int ixx=0; ixx<(showeredISHs_.second)->children().size(); ixx++) if(((showeredISHs_.second)->children()[ixx]->id())<6|| ((showeredISHs_.second)->children()[ixx]->id())==21) showeredISPs_.second=(showeredISHs_.second)->children()[ixx]; // Post-shower final-state partICLEs plus remnants (to be removed later): showeredFSPs_ = eventHandler()->currentEvent()->getFinalState(); // Post-shower final-state remnants: for(unsigned int ixx=0; ixxPDGName()=="Rem:p+"|| showeredFSPs_[ixx]->PDGName()=="Rem:pbar-") { if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.first) showeredRems_.first=showeredFSPs_[ixx]; else if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.second) showeredRems_.second=showeredFSPs_[ixx]; } } // Now delete found remnants from the showeredFSPs vector for consistency. for(unsigned int ixx=0; ixxPDGName()=="Rem:p+") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); for(unsigned int ixx=0; ixxPDGName()=="Rem:pbar-") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); sort(showeredFSPs_.begin(),showeredFSPs_.end(),recordEntry); return; } void AlpGenHandler::doSanityChecks(int debugLevel) { // When checking momentum conservation in the form // p_in - p_out, any momentum component bigger / less // than + / - epsilon will result in the p_in - p_out // vector being flagged as "non-null", triggering a // warning that momentum conservation is violated. Energy epsilon(0.5*GeV); if(debugLevel>=5) epsilon=1e-9*GeV; // Print out what was found for the incoming and outgoing // partons in the lastXCombPtr regardless. if(debugLevel>=5) { cout << "\n\n\n\n"; cout << "****************************************************" << endl; cout << " The following are the hard subprocess momenta from " << "\n" << " lastXCombPtr and should be basically identical to " << "\n" << " the input LH file momenta." << "\n\n"; cout << " Incoming particles:" << "\n" << *(preshowerISPs_.first) << "\n" << *(preshowerISPs_.second) << endl; cout << " Outgoing particles:" << endl; for(unsigned int ixx=0; ixx=5) { cout << "\n\n"; cout << "****************************************************" << endl; cout << " The following are the particles left at the end of" << "\n" << " the showering step." << "\n\n"; cout << " Incoming hadrons:" << "\n" << *(showeredISHs_.first) << "\n" << *(showeredISHs_.second) << endl; cout << " Incoming partons:" << "\n" << *(showeredISPs_.first) << "\n" << *(showeredISPs_.second) << endl; cout << " Outgoing partons:" << endl; for(unsigned int ixx=0; ixx=4) { Lorentz5Momentum tmpMom; tmpMom += showeredISPs_.first->momentum(); tmpMom += showeredISPs_.second->momentum(); for(unsigned int ixx=0; ixxmomentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Total parton mom.in - total parton mom.out = " << tmpMom/GeV << endl; tmpMom = showeredISHs_.first->momentum() - showeredRems_.first->momentum() -showeredISPs_.first->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "First p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; tmpMom = showeredISHs_.second->momentum() - showeredRems_.second->momentum()-showeredISPs_.second->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Second p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; } // Check if what we found to be the remnant is consistent with // what we identified as the parent incoming hadron i.e. p+ // goes with Rem:p+ and pbar- goes with Rem:pbar-. if(debugLevel>=0) { string tmpString; tmpString=showeredRems_.first->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.first->PDGName()!=tmpString) { cout << "AlpGenHandler::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.first) << "\n" << "Parent hadron = " << *(showeredISHs_.first) << endl; cout << showeredISHs_.first->PDGName() << endl; cout << tmpString << endl; } tmpString=showeredRems_.second->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.second->PDGName()!=tmpString) { cout << "AlpGenHandler::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.second) << "\n" << "Parent hadron = " << *(showeredISHs_.second) << endl; cout << showeredISHs_.second->PDGName() << endl; cout << tmpString << endl; } } return; } void AlpGenHandler::printMomVec(vector momVec) { cout << "\n\n"; // Label columns. printf("%5s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n", "jet #", "px","py","pz","E", "eta","phi","pt","et","mass"); // Print out the details for each jet for (unsigned int ixx=0; ixx ETSTOP and sum surrounding cells with -- * DELTA(Y)**2+DELTA(PHI)**2 < RJET**2 , ET>ECCUT. * Keep sets with ET>EJCUT and ABS(ETA)currentEvent()->... * filling the particle pairs showeredISHs_, showeredISPs_, * showeredRems_ and the particle pointer vector showeredFSPs_. */ void getShoweredParticles(); /** * Allows printing of debug output and sanity checks like * total momentum consrvation to be carried out. * debugLevel = -1, 0, ...5 * = no debugging, minimal debugging, ... verbose. */ void doSanityChecks(int debugLevel); /** * Given a pointer to a particle this finds all its final state * descendents. */ void getDescendents(PPtr theParticle); /** * Accumulates all descendents of tops down to the b and W * but not including them. */ void getTopRadiation(PPtr theParticle); /** * Sorts a given vector of particles by descending pT or ETJET */ ParticleVector pTsort(ParticleVector unsortedVec); pair< vector, vector > ETsort(vector unsortedetjet, vector unsortedVec); /* * A function that prints a vector of Lorentz5Momenta in a fancy way */ void printMomVec(vector momVec); /* * A probability function for varying etclus_ about the mean value */ Energy etclusran_(double petc); private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initAlpGenHandler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ AlpGenHandler & operator=(const AlpGenHandler &); private: /** * Initial-state incoming partons prior to showering * (i.e. from lastXCombPtr). */ PPair preshowerISPs_; /** * Final-state outgoing partICLEs prior to showering * (i.e. from lastXCombPtr). */ ParticleVector preshowerFSPs_; /** * Final-state outgoing partICLEs prior to showering _to_be_removed_ * from preShowerFSPs_ prior to the light-parton-light-jet matching * step. This same list is the starting point for determining * partonsToMatch_ for the case of merging in heavy quark production. */ ParticleVector preshowerFSPsToDelete_; /** * Initial-state incoming hadrons after shower of hard process * (eventHandler()->currentEvent()->incoming()). */ PPair showeredISHs_; /** * Initial-state incoming partons after shower of hard process * (look for partonic children of showeredISHs_). */ PPair showeredISPs_; /** * Final-state outgoing partICLEs after shower of hard process * (eventHandler()->currentEvent()->getFinalState()). */ tPVector showeredFSPs_; /** * Final-state outgoing partICLEs after shower of hard process * _to_be_removed_ from showeredFSPs_ prior to the * light-parton-light-jet matching step. This same list is the * starting point for determining particlesToCluster_ for the * case of merging in heavy quark production. */ ParticleVector showeredFSPsToDelete_; /** * ONLY the final-state partons from preshowerFSPs_ that are * supposed to enter the jet-parton matching. */ ParticleVector partonsToMatch_; /* * The shower progenitors */ PPtr theProgenitor; PPtr theLastProgenitor; /** * ONLY the final-state particles from showeredFSPs_ (and maybe * also showeredRems_) that are supposed to go for jet clustering. */ tPVector particlesToCluster_; /** * Final-state remnants after shower of hard process * (look for remnants initially in showeredFSPs_). */ PPair showeredRems_; /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alphaS_; /** * Information extracted from the XComb object */ //@{ /** * The fixed factorization scale used in the MEs. */ Energy pdfScale_; /** * Centre of mass energy */ Energy2 sHat_; /** * Constant alphaS used to generate LH events - if not already * using CKKW scale (ickkw = 1 in AlpGen for example). */ double alphaSME_; //@} /* * Number of rapidity segments of the calorimeter. */ unsigned int ncy_; /* * Number of phi segments of the calorimeter. */ unsigned int ncphi_; /* * Heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t). */ int ihvy_; /* * Number of photons in the AlpGen process. */ int nph_; /* * Number of higgses in the AlpGen process. */ int nh_; /* * Jet ET cut to apply in jet clustering (in merging). */ Energy etclus_; /* * Mean Jet ET cut to apply in jet clustering (in merging). */ Energy etclusmean_; /* * maximum deviation from mean Jet ET cut to apply in jet clustering (in merging). */ Energy epsetclus_; /* * Cone size used in jet clustering (in merging). */ double rclus_; /* * Max |eta| for jets in clustering (in merging). */ double etaclmax_; /* * Default 1.5 factor used to decide if a jet matches a parton * in merging: if DR(parton,jet) ncphi). * ==> Cosine goes from +1 ---> +1 (index = 0 ---> ncphi). */ vector cphcal_; /* * Sine of phi values of calorimeter cell centres. * Goes phi~=0 to phi~=2*pi (index = 0 ---> ncphi). * ==> Sine goes 0 -> 1 -> 0 -> -1 -> 0 (index = 0 ---> ncphi). */ vector sphcal_; /* * Cosine of theta values of calorimeter cell centres in Y. * Goes bwds th~=pi to fwds th~=0 (index = 0 ---> ncy). * ==> Cosine goes from -1 ---> +1 (index = 0 ---> ncy). */ vector cthcal_; /* * Sine of theta values of calorimeter cell centres in Y. * Goes bwds th~=pi to fwds th~=0 (index = 0 ---> ncy). * ==> Sine goes from 0 ---> +1 ---> 0 (index = 0 ---> ncy). */ vector sthcal_; /* * Transverse energy deposit in a given calorimeter cell. * First array index corresponds to rapidity index of cell, * second array index corresponds to phi cell index. */ vector > et_; /* * For a given calorimeter cell this holds the index of the jet * that the cell was clustered into. */ vector > jetIdx_; /* * Vector holding the Lorentz 5 momenta of each jet. */ vector pjet_; /* * Vector holding the list of FS particles resulting from * the particle input to getDescendents. */ ParticleVector tmpList_; /* * Variables for the C++ translation of the calini_m(), calsim_m(), * getjet_m(...) and caldel_m() functions */ vector etjet_; double dely_, delphi_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of AlpGenHandler. */ template <> struct BaseClassTrait { /** Typedef of the first base class of AlpGenHandler. */ typedef Herwig::ShowerHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the AlpGenHandler 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::AlpGenHandler"; } /** * The name of a file containing the dynamic library where the class * AlpGenHandler is implemented. It may also include several, space-separated, * libraries if the class AlpGenHandler 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 "AlpGenHandler.so"; } }; /** @endcond */ } #endif /* HERWIG_AlpGenHandler_H */ diff --git a/Contrib/Analysis2/Analysis2/EventShapes2.cc b/Contrib/Analysis2/Analysis2/EventShapes2.cc --- a/Contrib/Analysis2/Analysis2/EventShapes2.cc +++ b/Contrib/Analysis2/Analysis2/EventShapes2.cc @@ -1,562 +1,562 @@ // -*- C++ -*- // (C) 2007-2009 Simon Plaetzer -- sp@particle.uni-karlsruhe.de // Copyright (C) 2002-2007 The Herwig Collaboration #include "EventShapes2.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "EventShapes2.tcc" #endif #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Analysis2; EventShapes2::~EventShapes2() {} void EventShapes2::persistentOutput(PersistentOStream & os) const { // *** ATTENTION *** os << ; // Add all member variable which should be written persistently here. os << _omthr << _maj << _min << _obl << _sph << _apl << _pla << _c << _d << _mhi << _mlo << _mdiff << _bmax << _bmin << _bsum << _bdiff; } void EventShapes2::persistentInput(PersistentIStream & is, int) { // *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here. is >> _omthr >> _maj >> _min >> _obl >> _sph >> _apl >> _pla >> _c >> _d >> _mhi >> _mlo >> _mdiff >> _bmax >> _bmin >> _bsum >> _bdiff; } ClassDescription EventShapes2::initEventShapes2; // Definition of the static class description member. void EventShapes2::Init() { static ClassDocumentation documentation ("Analyse event shapes"); static Parameter interfaceOneMinusThrust ("OneMinusThrust", "Options for 1-T", &EventShapes2::_omthr, "", false, false); static Parameter interfaceThrustMajor ("ThrustMajor", "Options for thrust major", &EventShapes2::_maj, "", false, false); static Parameter interfaceThrustMinor ("ThrustMinor", "Options for thrust minor", &EventShapes2::_min, "", false, false); static Parameter interfaceOblateness ("Oblateness", "Options for Oblateness", &EventShapes2::_obl, "", false, false); static Parameter interfaceSphericity ("Sphericity", "Options for Sphericity", &EventShapes2::_sph, "", false, false); static Parameter interfaceAplanarity ("Aplanarity", "Options for Aplanarity", &EventShapes2::_apl, "", false, false); static Parameter interfacePlanarity ("Planarity", "Options for Planarity", &EventShapes2::_pla, "", false, false); static Parameter interfaceCParameter ("CParameter", "Options for C parameter", &EventShapes2::_c, "", false, false); static Parameter interfaceDParameter ("DParameter", "Options for D parameter", &EventShapes2::_d, "", false, false); static Parameter interfaceMHigh ("MHigh", "Options for high hemisphere mass", &EventShapes2::_mhi, "", false, false); static Parameter interfaceMLow ("MLow", "Options for low hemisphere mass", &EventShapes2::_mlo, "", false, false); static Parameter interfaceMDiff ("MDiff", "Options for difference in hemisphere masses", &EventShapes2::_mdiff, "", false, false); static Parameter interfaceBMax ("BMax", "Options for wide jet broadening", &EventShapes2::_bmax, "", false, false); static Parameter interfaceBMin ("BMin", "Options for narrow jet broadening", &EventShapes2::_bmin, "", false, false); static Parameter interfaceBSum ("BSum", "Options for sum of jet broadening measures", &EventShapes2::_bsum, "", false, false); static Parameter interfaceBDiff ("BDiff", "Options for difference of jet broadening measures", &EventShapes2::_bdiff, "", false, false); } inline void EventShapes2::dofinish() { finish("OneMinusThrust"); finish("ThrustMajor"); finish("ThrustMinor"); finish("Oblateness"); finish("Sphericity"); finish("Aplanarity"); finish("Planarity"); finish("CParameter"); finish("DParameter"); finish("MHigh"); finish("MLow"); finish("MDiff"); finish("BMax"); finish("BMin"); finish("BSum"); finish("BDiff"); Analysis2Base::dofinish(); } inline void EventShapes2::doinit() throw(InitException) { Analysis2Base::doinit(); int plotFlags = HistogramOutput::Ylog | HistogramOutput::Frame | HistogramOutput::Errorbars; Histogram2Options options (plotFlags); insert("OneMinusThrust", _omthr,options); insert("ThrustMajor", _maj,options); insert("ThrustMinor", _min,options); insert("Oblateness", _obl,options); insert("Sphericity", _sph,options); insert("Aplanarity", _apl,options); insert("Planarity", _pla,options); insert("CParameter", _c,options); insert("DParameter", _d,options); insert("MHigh", _mhi,options); insert("MLow", _mlo,options); insert("MDiff", _mdiff,options); insert("BMax", _bmax,options); insert("BMin", _bmin,options); insert("BSum", _bsum,options); insert("BDiff", _bdiff,options); } void EventShapes2::analyze(const tPVector &) { pair,double> ev; while (*eventExtractor() >> ev) { reset(ev.first); book(1.-thrust(), "OneMinusThrust", ev.second); book(thrustMajor(), "ThrustMajor", ev.second); book(thrustMinor(), "ThrustMinor", ev.second); book(oblateness(), "Oblateness", ev.second); book(CParameter(), "CParameter", ev.second); book(DParameter(), "DParameter", ev.second); book(sphericity(), "Sphericity", ev.second); book(aplanarity(), "Aplanarity", ev.second); book(planarity(), "Planarity", ev.second); book(Mhigh2(), "MHigh", ev.second); book(Mlow2(), "MLow", ev.second); book(Mdiff2(), "MDiff", ev.second); book(Bmax(), "BMax", ev.second); book(Bmin(), "BMin", ev.second); book(Bsum(), "BSum", ev.second); book(Bdiff(), "BDiff", ev.second); } } vector EventShapes2::eigenvalues(const double T[3][3]) { vector lambda; if (_pv.size() > 2) { // b, c, d are the coefficients of the characteristic polynomial, // a lambda^3 + b lambda^2 + c lambda + d // where a is chosen to be +1. double t11, t12, t13, t22, t23, t33; t11 = T[0][0]; t12 = T[0][1]; t13 = T[0][2]; t22 = T[1][1]; t23 = T[1][2]; t33 = T[2][2]; double b = -(t11 + t22 + t33); double c = t11*t22 + t11*t33 + t22*t33 - sqr(t12) - sqr(t13) - sqr(t23); double d = - t11*t22*t33 - 2.*t12*t23*t13 + t11*sqr(t23) + t22*sqr(t13) + t33*sqr(t12); // use Cardano's formula to compute the zeros double p = (3.*c - sqr(b))/3.; double q = (2.*sqr(b)*b - 9.*b*c + 27.*d)/27.; // check diskriminant if (4.*p*sqr(p) + 27.*sqr(q) > 0) { for (unsigned int i=0; i<3; i++) { lambda.push_back(-1.); } cout << flush << "EventShapes2::eigenvalues: found D > 0! \n" << "Matrix doesn't have real Eigenvalues in this case\n" << "(event with " << _pv.size() << " final state particles)\n"; cout << flush << "| " << T[0][0] << " " << T[0][1] << " " << T[0][2] << " |\n" << "| " << T[1][0] << " " << T[1][1] << " " << T[1][2] << " |\n" << "| " << T[2][0] << " " << T[2][1] << " " << T[2][2] << " |\n" << flush; } else { // get solutions double alpha = acos(-q/2.*sqrt(-27./(p*p*p)))/3.; double w = sqrt(-4.*p/3.); lambda.push_back(w*cos(alpha) - b/3.); lambda.push_back(-w*cos(alpha+M_PI/3.) - b/3.); lambda.push_back(-w*cos(alpha-M_PI/3.) - b/3.); } } else { // linear and sphericity coincide for ideal back-to-back // as q_i q_j/(2 q^2) where q = p_1 = -p_2 // eigenvalues trivial to get double mag2 = _pv[0].vect().mag2() / MeV2; double q1 = _pv[0].vect().x() / MeV; double q2 = _pv[0].vect().y() / MeV; double q3 = _pv[0].vect().z() / MeV; lambda.resize(3); lambda[0] = sqr(q1)/(2.*mag2); lambda[1] = sqr(q2)/(2.*mag2); lambda[2] = sqr(q3)/(2.*mag2); } // sort according to size of eigenvalues // such that lambda[0] > lambda[1] > lambda[2] if (lambda[0] < lambda[1]) { swap(lambda[0], lambda[1]); } if (lambda[0] < lambda[2]) { swap(lambda[0], lambda[2]); } if (lambda[1] < lambda[2]) { swap(lambda[1], lambda[2]); } return lambda; } -Axis EventShapes2::eigenvector(const double T[3][3], const double &lam) { +Axis EventShapes2::eigenvector(const double T[3][3], double lam) { // set up matrix of system to be solved double a11, a12, a13, a23, a33; a11 = T[0][0] - lam; a12 = T[0][1]; a13 = T[0][2]; a23 = T[1][2]; a33 = T[2][2] - lam; // intermediate steps from gauss type algorithm double b1, b2, b4; b1 = a11*a33 - sqr(a13); b2 = a12*a33 - a13*a23; b4 = a11*a23 - a12*a13; // eigenvector Axis u(b2, -b1, b4); return u.unit(); } vector EventShapes2:: eigenvectors(const double T[3][3], const vector &lam) { vector n; for (unsigned int i=0; i<3; i++) { n.push_back(eigenvector(T, lam[i])); } return n; } void EventShapes2::diagonalizeTensors(bool linear, bool cmboost) { // initialize double Theta[3][3]; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { Theta[i][j] = 0.0; } } double sum = 0.; Momentum3 sumvec; vector lam; vector n; // get cm-frame Lorentz5Momentum pcm = Lorentz5Momentum(); Boost beta; if (cmboost) { for(unsigned int ix=0;ix<_pv.size();++ix) { pcm += _pv[ix]; } beta = pcm.findBoostToCM(); } // get Theta_ij for(unsigned int ix=0;ix<_pv.size();++ix) { Lorentz5Momentum dum(_pv[ix]); if (cmboost) { dum.boost( beta ); } Momentum3 pvec = dum.vect(); double pvec_MeV[3] = {pvec.x()/MeV, pvec.y()/MeV, pvec.z()/MeV}; if (pvec.mag() > 0*MeV) { sumvec += pvec; if (linear) { sum += pvec.mag()*UnitRemoval::InvE; } else { sum += pvec.mag2()*UnitRemoval::InvE2; } for(int i=0; i<3; i++) { for(int j=i; j<3; j++) { if (linear) { Theta[i][j] += (pvec_MeV[i])*(pvec_MeV[j])*MeV/(pvec.mag()); } else { Theta[i][j] += (pvec_MeV[i])*(pvec_MeV[j]); } } } } } for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { Theta[i][j] /= sum; } } // diagonalize it lam = eigenvalues(Theta); n = eigenvectors(Theta, lam); if (linear) { _linTen = lam; _linTenAxis = n; } else { _spher = lam; _spherAxis = n; } } void EventShapes2::calculateThrust() { // explicitly calculate in units of MeV // algorithm based on Brandt/Dahmen Z Phys C1 (1978) // and 'tasso' code from HERWIG // assumes all momenta in cm system, no explicit boost performed here! // unlike for C and D _thrust.clear(); _thrustAxis.clear(); if (_pv.size() < 2) { for (int i=0; i<3; i++) { _thrust.push_back(-1); _thrustAxis.push_back(Axis()); } return; } // thrust vector p; Energy psum = 0.0*MeV; for(unsigned int l=0; l<_pv.size(); l++) { p.push_back(_pv[l].vect()); psum += p.back().mag(); } Axis axis; if (p.size() == 2) { _thrust.push_back(1.0); _thrust.push_back(0.0); _thrust.push_back(0.0); axis = p[0].unit(); if (axis.z() < 0) axis = -axis; _thrustAxis.push_back(axis); _thrustAxis.push_back(axis.orthogonal()); axis = _thrustAxis[0].cross(_thrustAxis[1]); return; } if (p.size() == 3) { if (p[0].mag2() < p[1].mag2()) swap(p[0], p[1]); if (p[0].mag2() < p[2].mag2()) swap(p[0], p[2]); if (p[1].mag2() < p[2].mag2()) swap(p[1], p[2]); // thrust axis = p[0].unit(); if (axis.z() < 0) axis = -axis; _thrust.push_back(2.*p[0].mag()/psum); _thrustAxis.push_back(axis); // major axis = (p[1] - (axis*p[1])*axis).unit(); if (axis.x() < 0) axis = -axis; _thrust.push_back((abs(p[1]*axis) + abs(p[2]*axis))/psum); _thrustAxis.push_back(axis); // minor _thrust.push_back(0.0); axis = _thrustAxis[0].cross(_thrustAxis[1]); _thrustAxis.push_back(axis); return; } // ACHTUNG special case with >= 4 coplanar particles will still fail. // probably not too important... Energy2 val; calcT(p, val, axis); _thrust.push_back(sqrt(val)/psum); if (axis.z() < 0) axis = -axis; _thrustAxis.push_back(axis.unit()); //major Momentum3 par; for (unsigned int l=0; l<_pv.size(); l++) { par = (p[l]*axis.unit())*axis.unit(); p[l] = p[l] - par; } calcM(p, val, axis); _thrust.push_back(sqrt(val)/psum); if (axis.x() < 0) axis = -axis; _thrustAxis.push_back(axis.unit()); // minor if (_thrustAxis[0]*_thrustAxis[1] < 1e-10) { Energy eval = 0.*MeV; axis = _thrustAxis[0].cross(_thrustAxis[1]); _thrustAxis.push_back(axis); for (unsigned int l=0; l<_pv.size(); l++) eval += abs(axis*_pv[l].vect()); _thrust.push_back(eval/psum); } else { _thrust.push_back(-1.0); _thrustAxis.push_back(Axis()); } } void EventShapes2::calcT(const vector &p, Energy2 &t, Axis &taxis) { Energy2 tval; t = 0.0*MeV2; ThreeVector tv; Momentum3 ptot; vector cpm; for (unsigned int k=1; k < p.size(); k++) { for (unsigned int j=0; j 0.0*MeV*MeV2) { ptot += p[l]; } else { ptot -= p[l]; } } } cpm.clear(); cpm.push_back(ptot-p[j]-p[k]); cpm.push_back(ptot-p[j]+p[k]); cpm.push_back(ptot+p[j]-p[k]); cpm.push_back(ptot+p[j]+p[k]); for (vector::iterator it = cpm.begin(); it != cpm.end(); it++) { tval = it->mag2(); if (tval > t) { t = tval; taxis = it->unit(); } } } } } void EventShapes2::calcM(const vector &p, Energy2 &m, Axis &maxis) { Energy2 mval; m = 0.0 * MeV2; Momentum3 tv, ptot; vector cpm; for (unsigned int j=0; j < p.size(); j++) { tv = p[j]; ptot = Momentum3(); for (unsigned int l=0; l 0.0*MeV2) { ptot += p[l]; } else { ptot -= p[l]; } } } cpm.clear(); cpm.push_back(ptot-p[j]); cpm.push_back(ptot+p[j]); for (vector::iterator it = cpm.begin(); it != cpm.end(); it++) { mval = it->mag2(); if (mval > m) { m = mval; maxis = it->unit(); } } } } diff --git a/Contrib/Analysis2/Analysis2/EventShapes2.h b/Contrib/Analysis2/Analysis2/EventShapes2.h --- a/Contrib/Analysis2/Analysis2/EventShapes2.h +++ b/Contrib/Analysis2/Analysis2/EventShapes2.h @@ -1,669 +1,669 @@ // -*- C++ -*- // (C) 2007-2009 Simon Plaetzer -- sp@particle.uni-karlsruhe.de // Copyright (C) 2002-2007 The Herwig Collaboration #ifndef Analysis2_EventShapes2_H #define Analysis2_EventShapes2_H // // This is the declaration of the EventShapes2 class. // #include "Analysis2Base.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Vectors/ThreeVector.h" #include "ThePEG/EventRecord/Particle.h" #include "EventShapes2.fh" namespace Analysis2 { using namespace ThePEG; /**\ingroup Analysis2 * * Class to analyse event shapes * * @see \ref EventShapes2Interfaces "The interfaces" * defined for EventShapes2. */ class EventShapes2: public Analysis2Base { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ inline EventShapes2(); /** * The destructor. */ virtual ~EventShapes2(); //@} public: /** * Analyze the given vector of particles. The default version calls * analyze(tPPtr) for each of the particles. * @param particles the vector of pointers to particles to be analyzed */ virtual void analyze(const tPVector & particles); 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; /** 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; //@} protected: /** * Member to reset the particles to be considered */ inline void reset(const vector &part); /** * Member functions to return thrust related shapes */ //@{ /** * The thrust */ inline double thrust(); /** * The major */ inline double thrustMajor(); /** * The minor */ inline double thrustMinor(); /** * The oblateness */ inline double oblateness(); /** * The thrust axis */ inline Axis thrustAxis(); /** * The major axis */ inline Axis majorAxis(); /** * The minor axis */ inline Axis minorAxis(); //@} /** * Linear momentum tensor related event shapes */ //@{ /** * The C parameter */ inline double CParameter(); /** * The D parameter */ inline double DParameter(); /** * The eigenvalues in descending order */ inline vector linTenEigenValues(); /** * The eigenvectors in order of descending eigenvalue */ inline vector linTenEigenVectors(); //@} /** * Quadratic momentum tensor related variables */ //@{ /** * The sphericity */ inline double sphericity(); /** * The aplanarity */ inline double aplanarity(); /** * The planarity */ inline double planarity(); /** * The sphericity axis */ inline Axis sphericityAxis(); /** * The sphericity eigenvalues */ inline vector sphericityEigenValues(); /** * The sphericity eigenvectors */ inline vector sphericityEigenVectors(); //@} /** * Jet mass related event shapes */ //@{ /** * The high hemishpere mass squared divided by the visible energy squared */ inline double Mhigh2(); /** * The low hemishpere mass squared divided by the visible energy squared */ inline double Mlow2(); /** * The difference between the * hemishpere masses squared divided by the visible energy squared */ inline double Mdiff2(); //@} /** * Jet broadening related event shapes */ //@{ /** * The wide jet broadening */ inline double Bmax(); /** * The narrow jet broadening */ inline double Bmin(); /** * The sum of the jet broadenings */ inline double Bsum(); /** * The difference of the jet broadenings */ inline double Bdiff(); //@} /** * Single particle variables which do not depend on event shapes axes */ //@{ /** * Ratio of momentum to beam momentum */ inline double getX(const Lorentz5Momentum & p, const Energy & Ebeam); /** * The scaled momentum \f$\xi=-\log\left( p/E_{\rm beam}\right)\f$. */ inline double getXi(const Lorentz5Momentum & p, const Energy & Ebeam); /** * Transverse momentum with respect to the beam */ inline Energy getPt(const Lorentz5Momentum & p); /** * Rapidity with respect to the beam direction */ inline double getRapidity(const Lorentz5Momentum & p); //@} /** * Single particle variables related to one of the shape axis. */ //@{ /** * Transverse momentum with respect to the thrust axis in the event plane */ inline Energy ptInT(const Lorentz5Momentum & p); /** * Transverse momentum with respect to the thrust axis out of the event plane */ inline Energy ptOutT(const Lorentz5Momentum & p); /** * Rapidity with respect to the thrust axis */ inline double yT(const Lorentz5Momentum & p); /** * Transverse momentum with respect to the sphericity axis in the event plane */ inline Energy ptInS(const Lorentz5Momentum & p); /** * Transverse momentum with respect to the sphericity axis out of the event plane */ inline Energy ptOutS(const Lorentz5Momentum & p); /** * Rapidity with respect to the sphericity axis */ inline double yS(const Lorentz5Momentum & p); //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit() throw(InitException); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); private: /** * Check whether the initialization of a certain class of event shapes * has been calculated and if not do so */ //@{ /** * Check if thrust related variables have been calculated and if not do so */ inline void checkThrust(); /** * Check if the linear tensor related variables have been calculated and if not do so */ inline void checkLinTen(); /** * Check if the quadratic tensor related variables have been calculated and if not do so */ inline void checkSphericity(); /** * Check if the hemisphere mass variables and jet broadenings * have been calculated and if not do so */ inline void checkHemispheres(); //@} /** * Methods that actually calculate the event shapes */ //@{ /** * Calculate the hemisphere masses and jet broadenings */ inline void calcHemisphereMasses(); /** * Calculate the thrust and related axes */ void calculateThrust(); /** * Diagonalize the tensors * @param linear switch between diagonalization of linear/quadratic tensor. * @param cmboost tells whether to boost into cm frame of all * momenta first, or not (default off, and no interface to this). */ void diagonalizeTensors(bool linear, bool cmboost); /** * Quite general diagonalization of a symmetric Matrix T, given as * an array of doubles. The symmetry is not checked explicitly as * this is clear in the context. It uses an explicit generic * solution of the eigenvalue problem and no numerical * approximation, based on Cardano's formula. * @param T Matrix to be diagonalised */ vector eigenvalues(const double T[3][3]); /** * The eigenvector of @param T to a given eigenvalue @param lam */ - Axis eigenvector(const double T[3][3], const double &lam); + Axis eigenvector(const double T[3][3], double lam); /** * The eigenvectors of @param T corresponding to the eigenvectors * @param lam . The ordering of the vectors corresponds to the * ordering of the eigenvalues. */ vector eigenvectors(const double T[3][3], const vector &lam); /** * Member to calculate the thrust * @param p The three vectors * @param t The thrust-squared (up to an Energy scale factor) * @param taxis The thrust axis */ void calcT(const vector &p, Energy2 &t, Axis &taxis); /** * Member to calculate the major * @param p The three vectors * @param m The major-squared (up to an Energy scale factor) * @param maxis The major axis */ void calcM(const vector &p, Energy2 &m, Axis &maxis); //@} private: /** * Vector of particle momenta to be analysed */ vector _pv; /** * Various event shape axes */ //@{ /** * The thrust related axes */ vector _thrustAxis; /** * The sphericity related axes */ vector _spherAxis; /** * The linearised tensor axes */ vector _linTenAxis; //@} /** * Values of axis related event shapes */ //@{ /** * Values of thrust related variables */ vector _thrust; /** * Values of sphericity related variables */ vector _spher; /** * Values of linearized tensor related variables */ vector _linTen; //@} /** * Whether or not certain event axes have been calculated */ //@{ /** * Whether or not the thrust is calculated */ bool _thrustDone; /** * Whether or not the sphericity is calculated */ bool _spherDone; /** * Whether or not the linearizes tensor is calculated */ bool _linTenDone; /** * Whether or not the hemisphere masses have been calculated */ bool _hemDone; //@} /** * Whether ot not to boost to the CMS frame for the tensor diagonalizations */ bool _useCmBoost; /** * Hemisphere masses */ //@{ /** * The high hemisphere mass */ double _mPlus; /** * The low hemisphere mass */ double _mMinus; //@} /** * The jet broadenings */ //@{ /** * The wide jet broadening */ double _bPlus; /** * The narrow jet broadening */ double _bMinus; //@} private: /** * Output option strings for \f$1-T\f$ distribution. */ string _omthr; /** * Output option strings for the major distribution */ string _maj; /** * Output option strings for the minor distribution */ string _min; /** *Output option strings for the oblateness distribution */ string _obl; /** * Output option strings for the sphericity distribution */ string _sph; /** * Output option strings for the aplanarity distribution */ string _apl; /** * Output option strings for the planarity distribution */ string _pla; /** * Output option strings for the C distribution */ string _c; /** * Output option strings for the D distribution */ string _d; /** * Output option strings for the \f$M_{\rm high}\f$ distribution */ string _mhi; /** * Output option strings for the \f$M_{\rm low}\f$ distribution */ string _mlo; /** * Output option strings for the \f$M_{\rm high}-M_{\rm low}\f$ distribution */ string _mdiff; /** * Output option strings for the \f$B_{\rm max}\f$ distribution */ string _bmax; /** * Output option strings for the \f$B_{\rm min}\f$ distribution */ string _bmin; /** * Output option strings for the \f$B_{\rm max}+B_{\rm min}\f$ distribution */ string _bsum; /** * Output option strings for the \f$B_{\rm max}-B_{\rm min}\f$ distribution */ string _bdiff; /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initEventShapes2; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ EventShapes2 & operator=(const EventShapes2 &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of EventShapes2. */ template <> struct BaseClassTrait { /** Typedef of the first base class of EventShapes2. */ typedef Analysis2::Analysis2Base NthBase; }; /** This template specialization informs ThePEG about the name of * the EventShapes2 class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Analysis2::EventShapes2"; } /** * The name of a file containing the dynamic library where the class * EventShapes2 is implemented. It may also include several, space-separated, * libraries if the class EventShapes2 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 "Analysis2.so"; } }; /** @endcond */ } #include "EventShapes2.icc" #ifndef ThePEG_TEMPLATES_IN_CC_FILE // #include "EventShapes2.tcc" #endif #endif /* Analysis2_EventShapes2_H */ diff --git a/Contrib/FxFx/FxFxHandler.cc b/Contrib/FxFx/FxFxHandler.cc --- a/Contrib/FxFx/FxFxHandler.cc +++ b/Contrib/FxFx/FxFxHandler.cc @@ -1,1435 +1,1435 @@ #include "FxFxHandler.h" #include "FxFxReader.h" #include "FxFxReader.fh" #include "FxFxEventHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include #include "ThePEG/Utilities/Throw.h" -#include "Herwig/Shower/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequence.hh" #include "gsl/gsl_rng.h" #include "gsl/gsl_randist.h" #include using namespace Herwig; using namespace ThePEG; bool recordEntry(PPtr i,PPtr j) { return (i->number()number()); } bool pTsortFunction(PPtr i,PPtr j) { return (i->momentum().perp2()>j->momentum().perp2()); } bool ETsortFunction(pair i,pair j) { return (i.first>j.first); } bool isMomLessThanEpsilon(Lorentz5Momentum p,Energy epsilon) { return (abs(p.x())> alphaS_ >> ncy_ >> ncphi_ >> ihvy_ >> nph_ >> nh_ >> iunit(etclusmean_,GeV) >> rclus_ >> etaclmax_ >> rclusfactor_ >> ihrd_ >> njets_ >> drjmin_ >> highestMultiplicity_ >> ycmax_ >> ycmin_ >> jetAlgorithm_ >> vetoIsTurnedOff_ >> vetoSoftThanMatched_ >> etclusfixed_ >> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV); } ClassDescription FxFxHandler::initFxFxHandler; // Definition of the static class description member. void FxFxHandler::Init() { static ClassDocumentation documentation ("The FxFxHandler class performs MEPS merging " "using the MLM procedure."); static Reference interfaceShowerAlpha ("ShowerAlpha", "The object calculating the strong coupling constant", &FxFxHandler::alphaS_, false, false, true, false, false); static Parameter interfaceihvy ("ihvy", "heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t)", &FxFxHandler::ihvy_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenph ("nph", "Number of photons in the AlpGen process", &FxFxHandler::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenh ("nh", "Number of higgses in the AlpGen process", &FxFxHandler::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfaceETClus ("ETClus", "The ET threshold defining a jet in the merging procedure", &FxFxHandler::etclusmean_, GeV, 20*GeV, 0*GeV, 14000*GeV, false, false, Interface::limited); static Parameter interfaceRClus ("RClus", "The cone size used to define a jet in the merging procedure", &FxFxHandler::rclus_, 0.4, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceEtaClusMax ("EtaClusMax", "The maximum |eta| used to define a jet in the merging procedure", &FxFxHandler::etaclmax_, 5.0, 0.0, 15.0, false, false, Interface::limited); static Parameter interfaceRClusFactor ("RClusFactor", "The prefactor for RClus used to define the jet-parton matching " "distance", &FxFxHandler::rclusfactor_, 1.5, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceihrd ("ihrd", "The AlpGen hard process code", &FxFxHandler::ihrd_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacenjetsmax ("njetsmax", "The number of light jets in the maximum-multiplicity process", &FxFxHandler::njets_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacedrjmin ("drjmin", "Mimimum parton-parton R-sep used for generation.", &FxFxHandler::drjmin_, 0.7, 0.0, 4.0, false, false, Interface::limited); static Parameter interfacehighestMultiplicity ("highestMultiplicity", "If true it indicates that this is the highest multiplicity input " "ME-level configuration to be processed.", &FxFxHandler::highestMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfaceETClusFixed ("ETClusFixed", "If false, indicates that the jet merging scale, etclus_ is allowed to vary" "according to epsetclus_", &FxFxHandler::etclusfixed_, 1, 0, 1, false, false, Interface::limited); static Parameter interfaceEpsilonETClus ("EpsilonETClus", "The ET threshold defining a jet in the merging procedure", &FxFxHandler::epsetclus_, GeV, 2.5*GeV, 0*GeV, 100.0*GeV, false, false, Interface::limited); static Switch interfaceJetAlgorithm ("JetAlgorithm", "Determines the jet algorithm for finding jets in parton-jet " "matching in the MLM procedure.", &FxFxHandler::jetAlgorithm_, 1, false, false); static SwitchOption AntiKt (interfaceJetAlgorithm, "AntiKt", "The anti-kt jet algorithm.", -1); static SwitchOption CambridgeAachen (interfaceJetAlgorithm, "CambridgeAachen", "The Cambridge-Aachen jet algorithm.", 0); static SwitchOption Kt (interfaceJetAlgorithm, "Kt", "The Kt jet algorithm.", 1); static Switch interfaceVetoIsTurnedOff ("VetoIsTurnedOff", "Allows the vetoing mechanism to be switched off.", &FxFxHandler::vetoIsTurnedOff_, false, false, false); static SwitchOption VetoingIsOn (interfaceVetoIsTurnedOff, "VetoingIsOn", "The MLM merging veto mechanism is switched ON.", false); static SwitchOption VetoingIsOff (interfaceVetoIsTurnedOff, "VetoingIsOff", "The MLM merging veto mechanism is switched OFF.", true); static Switch interfaceVetoSoftThanMatched ("VetoSoftThanMatched", "Allows the vetoing mechanism to be switched off.", &FxFxHandler::vetoSoftThanMatched_, false, false, false); static SwitchOption VetoSoftIsOn (interfaceVetoSoftThanMatched, "VetoSoftIsOn", "The vetoing of highest-mult. events with jets softer than matched ones is ON", true); static SwitchOption VetoSoftIsOff (interfaceVetoSoftThanMatched, "VetoSoftIsOff", "The vetoing of highest-mult. events with jets softer than matched ones is OFF.", false); } void FxFxHandler::dofinish() { ShowerHandler::dofinish(); } void FxFxHandler::doinit() { //print error if HardProcID is not set in input file if(ihrd_ == -999) { cout << "Error: FxFxHandler:ihrd not set!" << endl; exit(1); } ShowerHandler::doinit(); // Compute calorimeter edges in rapidity for GetJet algorithm. ycmax_=etaclmax_+rclus_; ycmin_=-ycmax_; // Initialise calorimeter. calini_m(); } // Throws a veto according to MLM strategy ... when we finish writing it. bool FxFxHandler::showerHardProcessVeto() { if(vetoIsTurnedOff_) return false; // Skip veto for processes in which merging is not implemented: if(ihrd_==7||ihrd_==8||ihrd_==13) { ostringstream wstring; wstring << "FxFxHandler::showerHardProcessVeto() - warning." << "MLM merging not implemented " << "processes 4Q (ihrd=7), QQh (ihrd=8), " << "(single) top (ihrd=13) \n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); return false; } // Fill preshowerISPs_ pair and preshowerFSPs_ particle pointer vector. getPreshowerParticles(); // Fill showeredISHs_, showeredISPs and showeredRems pairs, as well as // showeredFSPs_ particle pointer vector. getShoweredParticles(); // Get npLO_ and npNLO_ for FxFx matching getnpFxFx(); // print the npXLO_ values obtained // cout << "HANDLER:\t\t\t\t" << npLO_ << "\t\t" << npNLO_ << endl; // Turn on some screen output debugging: 0 = none ---> 5 = very verbose. int debug_mode = 0; doSanityChecks(debug_mode); // Dimensions of each calorimter cell in y and phi. dely_ = (ycmax_-ycmin_)/double(ncy_); delphi_ = 2*M_PI/double(ncphi_); // Fill partonsToMatch_ with only those pre-shower partons intended to // used in jet-parton matching and fill particlesToCluster_ using only // those final state particles (post-shower) which are supposed to go // in the jet clustering used to do merging. partonsToMatch_ = preshowerFSPs_; particlesToCluster_ = showeredFSPs_ ; // Filter out all but the 'extra' light-parton progenitors and their // associated final state particles. caldel_m(); double prob(1); //if etclusfixed_ then set the etclus_ to the fixed chosen value if(etclusfixed_) { etclus_ = etclusmean_; } else { //else, if we wish to vary etclus_, we use the probability distribution //choose a probability between 0 and 1 prob = rnd(); etclus_ = etclusran_(prob); } // Cluster particlesToCluster_ into jets with FastJet. getFastJets(rclus_,etclus_,etaclmax_); //FxFx modifications start here. // Sort partonsToMatch_ from high to low pT. sort(partonsToMatch_.begin(),partonsToMatch_.end(),pTsortFunction); // Count the number of jets. int njets_found(pjet_.size()); // If the number of jets found is not equal to the number of partons in the Born // (i.e., the number of partons in the S-event, or one less than the number of partons in an H-event), // the jets cannot be matched and the event has to be rejected. The number of partons in the Born is written in the event file with a name “npNLO” // if there are no jets to match and no jets have been found, do not veto. if(njets_found == 0 && npNLO_ == 0) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", accepting" << endl;*/ return false; } //if the number of jets is smaller than npNLO -> reject the event. if(njets_found < npNLO_) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", rejecting" << endl;*/ return true; } // For the maximum-multiplicity sample, the number of jets obtained does not have to be exactly equal to npNLO, it may also be larger; if(njets_found > npNLO_ && npNLO_ != njets_) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", rejecting" << endl;*/ return true; } // Create the matrix-element jets. // Cluster also the partons at the hard-matrix element level into jets with the same algorithm as above, // but without the requirement of a minimal pT on the jets (or set it very small). // By construction, for S-events you should find exactly npNLO jets, while for the H-events it is either npNLO or npNLO+1. // Cluster partonsToMatch_ into jets with FastJet. getFastJetsToMatch(rclus_,0*GeV,etaclmax_); int me_njets_found(pjetME_.size()); // cout << "number of ME jets found = " << me_njets_found << "partons to match: " << partonsToMatch_.size() << endl; // Match light progenitors to jets. vector jetToPartonMap(pjetME_.size(),-999); Energy etmin(777e100*GeV); // Match the jets. // Try to match the “npNLO” hardest jets created post-shower with any of the jets pre-shower. Two jets are matched if the distance between them is smaller than 1.5*DeltaR. // If not all the npNLO hardest shower jets are matched the event has to be rejected. // Note that if the current event does not belong to the maximum multiplicity sample, this means that all the shower jets need to be matched, because the requirement above already rejects // events that do not have npNLO shower jets. // For those events, at the level of the matrix elements there can either be npNLO or npNLO+1 matrix-element jets, depending on S- or H-events and the kinematics of those partons. // Still only the shower jets need to be matched, so an event should not be rejected if a matrix-element jet cannot be matched. // For each parton, starting with the hardest one ... for(unsigned int ixx=0; ixx=0) { jetToPartonMap[jetIndexForDRmin]=ixx; if(ixx==0||etjet_[jetIndexForDRmin]id())==4||abs(partonsToMatch_[jxx]->id())==5)) continue; if(partonJetDeltaR(partonsToMatch_[jxx],pjet_[ixx])etmin) return true; } */ } // Otherwise we accept the event ... return false; } /* Function that returns the R distance between a particle and a jet. */ double FxFxHandler::partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom) { LorentzMomentum partonmom(partonptr->momentum()); // Calculate DY, DPhi and then DR double DY(partonmom.eta()-jetmom.eta()); double DPhi(partonmom.phi()-jetmom.phi()); if(DPhi>M_PI) DPhi=2*M_PI-DPhi; double DR(sqrt(sqr(DY)+sqr(DPhi))); return DR; } double FxFxHandler::partonJetDeltaR(LorentzMomentum jetmom1, LorentzMomentum jetmom2) { // Calculate DY, DPhi and then DR double DY(jetmom1.eta()-jetmom2.eta()); double DPhi(jetmom1.phi()-jetmom2.phi()); if(DPhi>M_PI) DPhi=2*M_PI-DPhi; double DR(sqrt(sqr(DY)+sqr(DPhi))); return DR; } // Initialize calorimeter for calsim_m and getjet_m. Note that // because initialization is separte calsim_m can be called more // than once to simulate pileup of several events. void FxFxHandler::calini_m() { // Making sure arrays are clear before filling; cphcal_.clear(); sphcal_.clear(); cthcal_.clear(); sthcal_.clear(); // Fill array holding phi values of calorimeter cell centres. double deltaPhi(2*M_PI/ncphi_); for(unsigned int iphi=1; iphi<=ncphi_; iphi++) { double phi(deltaPhi*(iphi-0.5)); // Goes phi~=0 to phi~=2*pi (iphi=0--->ncphi). cphcal_.push_back(cos(phi)); // ==> goes from +1 ---> +1 (iphi=0--->ncphi). sphcal_.push_back(sin(phi)); // ==> goes 0 -> 1 -> 0 -> -1 -> 0 (iphi=0--->ncphi). } // Fill array holding theta values of calorimeter cell centres in Y. double deltaY((ycmax_-ycmin_)/double(ncy_)); for(unsigned int iy=1; iy<=ncy_; iy++) { double Y(deltaY*(iy-0.5)+ycmin_); double th(2*atan(exp(-Y))); // Goes bwds th~=pi to fwds th~=0 (iy=0--->ncy). cthcal_.push_back(cos(th)); // ==> goes from -1 ---> +1 (iy=0--->ncy). sthcal_.push_back(sin(th)); // ==> goes from 0 ---> +1 ---> 0 (iy=0--->ncy). } return; } // Get FastJets void FxFxHandler::getFastJets(double rjet, Energy ejcut, double etajcut) { vector particlesToCluster; for(unsigned int ipar=0; iparmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it may go in the jet finder. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { // input particles into fastjet pseudojet fastjet::PseudoJet p(particlesToCluster_[ipar]->momentum().x()/GeV, particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().z()/GeV, particlesToCluster_[ipar]->momentum().e()/GeV); p.set_user_index(ipar); particlesToCluster.push_back(p); } } } fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme; fastjet::Strategy strategy = fastjet::Best; double R(rjet); fastjet::JetDefinition theJetDefinition; switch (jetAlgorithm_) { case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm, R, recombinationScheme, strategy); break; case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm, R, recombinationScheme, strategy); break; default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; } fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition); vector inclusiveJets = fastjetEvent.inclusive_jets(); inclusiveJets = fastjet::sorted_by_pt(inclusiveJets); // Fill the array of jet momenta for the rest of the veto procedure. pjet_.clear(); pjet_.resize(inclusiveJets.size()); etjet_.clear(); etjet_.resize(inclusiveJets.size()); for(unsigned int ffj=0; ffjetajcut) { pjet_.erase(pjet_.begin()+fj); etjet_.erase(etjet_.begin()+fj); fj--; } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixx particlesToCluster; for(unsigned int ipar=0; iparmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(partonsToMatch_[ipar]->id())); // If it's not a lepton / top / photon it may go in the jet finder. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { // input particles into fastjet pseudojet fastjet::PseudoJet p(partonsToMatch_[ipar]->momentum().x()/GeV, partonsToMatch_[ipar]->momentum().y()/GeV, partonsToMatch_[ipar]->momentum().z()/GeV, partonsToMatch_[ipar]->momentum().e()/GeV); p.set_user_index(ipar); particlesToCluster.push_back(p); } } } fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme; fastjet::Strategy strategy = fastjet::Best; double R(rjet); fastjet::JetDefinition theJetDefinition; switch (jetAlgorithm_) { case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm, R, recombinationScheme, strategy); break; case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm, R, recombinationScheme, strategy); break; default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; } fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition); vector inclusiveJets = fastjetEvent.inclusive_jets(); inclusiveJets = fastjet::sorted_by_pt(inclusiveJets); // Fill the array of jet momenta for the rest of the veto procedure. pjetME_.clear(); pjetME_.resize(inclusiveJets.size()); for(unsigned int ffj=0; ffjmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it goes in the calorimeter. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { double phi(atan2(particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().x()/GeV)); if(phi<0) phi+=2*M_PI; unsigned int iy(int((y-ycmin_)/dely_)); unsigned int iphi(int(phi/delphi_)); et_[iy][iphi]+=particlesToCluster_[ipar]->momentum().e()*sthcal_[iy]; } } } return; } // Find highest remaining cell > etstop and sum surrounding cells // with -- delta(y)^2+delta(phi)^2 < Rjet^2 , ET>eccut. Keep sets // with ET>ejcut and abs(eta)=etstop) { // Find the cell with the highest ET from // those not already assigned to a jet. etmax=0*GeV; int iymx(0), iphimx(0); for(unsigned int iphi=0; iphietmax&&jetIdx_[iy][iphi]<0) { etmax = et_[iy][iphi]; iymx = iy; iphimx = iphi; } // If the remaining cell with the highest ET has ET < etstop, stop. if(etmax(ncy_*ncphi_)) { cout << "FxFxHandler::getjet_m() - Fatal error." << endl; cout << "We found " << ipass << " calo cells with the highest ET so" << "far\nbut the calorimeter only has " << ncy_*ncphi_ << " " << "cells in it!" << endl; exit(10); } // Add a jet vector (may get deleted if jet fails ET / eta cuts). etjet_.push_back(0*GeV); pjet_.push_back(Lorentz5Momentum(0.*GeV,0.*GeV,0.*GeV,0.*GeV,0.*GeV)); // Loop over all calo cells in range iphimx +/- nphi1 (inclusive) // wrapping round in azimuth if required. for(unsigned int iphi1=0; iphi1<=2*nphi1; iphi1++) { int iphix(iphimx-nphi1+iphi1); if(iphix<0) iphix += ncphi_; if(iphix>=int(ncphi_)) iphix -= ncphi_; // Loop over all calo cells in range iymx +/- ny1 (inclusive). for(unsigned int iy1=0; iy1<=2*ny1; iy1++) { int iyx(iymx-ny1+iy1); // If the cell is outside the calorimeter OR if it was already // associated to a jet then skip to the next loop. if(iyx>=0&&iyx=eccut) { Energy ECell(et_[iyx][iphix]/sthcal_[iyx]); pjet_.back()+=LorentzMomentum(ECell*sthcal_[iyx]*cphcal_[iphix], // px ECell*sthcal_[iyx]*sphcal_[iphix], // py ECell*cthcal_[iyx],ECell); // pz, E. // N.B. This is the same reln as in ThePEG between phi and x,y. etjet_.back()+=et_[iyx][iphix]; jetIdx_[iyx][iphix] = pjet_.size()-1; // Identify cell with this jet. } } } } // Compute the current jet's mass. pjet_.back().rescaleMass(); // Throw the jet away if it's ET is less than ejcut. if(etjet_.back()etajcut) { pjet_.pop_back(); etjet_.pop_back(); } } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxchildren()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else getDescendents(theChildren[ixx]); return; } void FxFxHandler::caldel_m() { preshowerFSPsToDelete_.clear(); showeredFSPsToDelete_.clear(); for(unsigned int ixx=0; ixxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24|| abs(preshowerFSPs_[ixx]->id())==22|| abs(preshowerFSPs_[ixx]->id())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); } if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==6) { getDescendents(preshowerFSPs_[ixx]->parents()[0]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==4&&ixx<1)|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+1)))|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+2)))|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2)) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxsubProcess()->incoming(); // LH file final-state partICLEs: preshowerFSPs_ = lastXCombPtr()->subProcess()->outgoing(); return; } void FxFxHandler::getShoweredParticles() { // Post-shower initial-state hadrons: showeredISHs_ = eventHandler()->currentEvent()->incoming(); // Post-shower initial-state partons: for(unsigned int ixx=0; ixx<(showeredISHs_.first)->children().size(); ixx++) if(((showeredISHs_.first)->children()[ixx]->id())<6|| ((showeredISHs_.first)->children()[ixx]->id())==21) showeredISPs_.first=(showeredISHs_.first)->children()[ixx]; for(unsigned int ixx=0; ixx<(showeredISHs_.second)->children().size(); ixx++) if(((showeredISHs_.second)->children()[ixx]->id())<6|| ((showeredISHs_.second)->children()[ixx]->id())==21) showeredISPs_.second=(showeredISHs_.second)->children()[ixx]; // Post-shower final-state partICLEs plus remnants (to be removed later): showeredFSPs_ = eventHandler()->currentEvent()->getFinalState(); // Post-shower final-state remnants: for(unsigned int ixx=0; ixxPDGName()=="Rem:p+"|| showeredFSPs_[ixx]->PDGName()=="Rem:pbar-") { if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.first) showeredRems_.first=showeredFSPs_[ixx]; else if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.second) showeredRems_.second=showeredFSPs_[ixx]; } } // Now delete found remnants from the showeredFSPs vector for consistency. for(unsigned int ixx=0; ixxPDGName()=="Rem:p+") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); for(unsigned int ixx=0; ixxPDGName()=="Rem:pbar-") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); sort(showeredFSPs_.begin(),showeredFSPs_.end(),recordEntry); return; } void FxFxHandler::doSanityChecks(int debugLevel) { // When checking momentum conservation in the form // p_in - p_out, any momentum component bigger / less // than + / - epsilon will result in the p_in - p_out // vector being flagged as "non-null", triggering a // warning that momentum conservation is violated. Energy epsilon(0.5*GeV); if(debugLevel>=5) epsilon=1e-9*GeV; // Print out what was found for the incoming and outgoing // partons in the lastXCombPtr regardless. if(debugLevel>=5) { cout << "\n\n\n\n"; cout << "****************************************************" << endl; cout << " The following are the hard subprocess momenta from " << "\n" << " lastXCombPtr and should be basically identical to " << "\n" << " the input LH file momenta." << "\n\n"; cout << " Incoming particles:" << "\n" << *(preshowerISPs_.first) << "\n" << *(preshowerISPs_.second) << endl; cout << " Outgoing particles:" << endl; for(unsigned int ixx=0; ixx=5) { cout << "\n\n"; cout << "****************************************************" << endl; cout << " The following are the particles left at the end of" << "\n" << " the showering step." << "\n\n"; cout << " Incoming hadrons:" << "\n" << *(showeredISHs_.first) << "\n" << *(showeredISHs_.second) << endl; cout << " Incoming partons:" << "\n" << *(showeredISPs_.first) << "\n" << *(showeredISPs_.second) << endl; cout << " Outgoing partons:" << endl; for(unsigned int ixx=0; ixx=4) { Lorentz5Momentum tmpMom; tmpMom += showeredISPs_.first->momentum(); tmpMom += showeredISPs_.second->momentum(); for(unsigned int ixx=0; ixxmomentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Total parton mom.in - total parton mom.out = " << tmpMom/GeV << endl; tmpMom = showeredISHs_.first->momentum() - showeredRems_.first->momentum() -showeredISPs_.first->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "First p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; tmpMom = showeredISHs_.second->momentum() - showeredRems_.second->momentum()-showeredISPs_.second->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Second p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; } // Check if what we found to be the remnant is consistent with // what we identified as the parent incoming hadron i.e. p+ // goes with Rem:p+ and pbar- goes with Rem:pbar-. if(debugLevel>=0) { string tmpString; tmpString=showeredRems_.first->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.first->PDGName()!=tmpString) { cout << "FxFxHandler::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.first) << "\n" << "Parent hadron = " << *(showeredISHs_.first) << endl; cout << showeredISHs_.first->PDGName() << endl; cout << tmpString << endl; } tmpString=showeredRems_.second->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.second->PDGName()!=tmpString) { cout << "FxFxHandler::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.second) << "\n" << "Parent hadron = " << *(showeredISHs_.second) << endl; cout << showeredISHs_.second->PDGName() << endl; cout << tmpString << endl; } } return; } void FxFxHandler::printMomVec(vector momVec) { cout << "\n\n"; // Label columns. printf("%5s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n", "jet #", "px","py","pz","E", "eta","phi","pt","et","mass"); // Print out the details for each jet for (unsigned int ixx=0; ixx split_vector_type; /** * Here is the documentation of the FxFxHandler class. * * @see \ref FxFxHandlerInterfaces "The interfaces" * defined for FxFxHandler. */ class FxFxHandler: public ShowerHandler { /** * FxFxHandler should have access to our private parts. */ friend class FxFxEventHandler; friend class FxFxReader; public: /** * The default constructor. */ FxFxHandler(); 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. */ //@{ /** * Finalize the object */ virtual void dofinish(); /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} public: /** * Hook to allow vetoing of event after showering hard sub-process * as in e.g. MLM merging. */ virtual bool showerHardProcessVeto(); /** * information for FxFx merging */ int npLO_; int npNLO_; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /* * Run MLM jet-parton matching on the 'extra' jets. */ bool lightJetPartonVeto(); /* * Function that calculates deltaR between a parton and a jet */ double partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom); double partonJetDeltaR(LorentzMomentum jetmom1, LorentzMomentum jetmom2); /** * c++ translation of subroutine of same name from alpsho.f. * Initialize calorimeter for calsim_m and getjet_m. Note that * because initialization is separte calsim_m can be called more * than once to simulate pileup of several events. */ void calini_m(); /** * c++ translation of subroutine of same name from alpsho.f. * Simple calorimeter simulation - assume uniform Y and phi bins. */ void calsim_m(); /** * Find jets using the FastJet package on particlesToCluster_. */ void getFastJets(double rjet, Energy ejcut, double etajcut); /** * Find jets using the FastJet package on particlesToCluster_. */ void getFastJetsToMatch(double rjet, Energy ejcut, double etajcut); /** * c++ translation of subroutine of same name from alpsho.f. * Simple jet-finding algorithm (similar to UA1). Find highest * remaining cell > ETSTOP and sum surrounding cells with -- * DELTA(Y)**2+DELTA(PHI)**2 < RJET**2 , ET>ECCUT. * Keep sets with ET>EJCUT and ABS(ETA)currentEvent()->... * filling the particle pairs showeredISHs_, showeredISPs_, * showeredRems_ and the particle pointer vector showeredFSPs_. */ void getShoweredParticles(); /** * Allows printing of debug output and sanity checks like * total momentum consrvation to be carried out. * debugLevel = -1, 0, ...5 * = no debugging, minimal debugging, ... verbose. */ void doSanityChecks(int debugLevel); /** * Given a pointer to a particle this finds all its final state * descendents. */ void getDescendents(PPtr theParticle); /** * Accumulates all descendents of tops down to the b and W * but not including them. */ void getTopRadiation(PPtr theParticle); /** * Sorts a given vector of particles by descending pT or ETJET */ ParticleVector pTsort(ParticleVector unsortedVec); pair< vector, vector > ETsort(vector unsortedetjet, vector unsortedVec); /* * A function that prints a vector of Lorentz5Momenta in a fancy way */ void printMomVec(vector momVec); /* * A probability function for varying etclus_ about the mean value */ Energy etclusran_(double petc); private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFxFxHandler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FxFxHandler & operator=(const FxFxHandler &); private: /** * Initial-state incoming partons prior to showering * (i.e. from lastXCombPtr). */ PPair preshowerISPs_; /** * Final-state outgoing partICLEs prior to showering * (i.e. from lastXCombPtr). */ ParticleVector preshowerFSPs_; /** * Final-state outgoing partICLEs prior to showering _to_be_removed_ * from preShowerFSPs_ prior to the light-parton-light-jet matching * step. This same list is the starting point for determining * partonsToMatch_ for the case of merging in heavy quark production. */ ParticleVector preshowerFSPsToDelete_; /** * Initial-state incoming hadrons after shower of hard process * (eventHandler()->currentEvent()->incoming()). */ PPair showeredISHs_; /** * Initial-state incoming partons after shower of hard process * (look for partonic children of showeredISHs_). */ PPair showeredISPs_; /** * Final-state outgoing partICLEs after shower of hard process * (eventHandler()->currentEvent()->getFinalState()). */ tPVector showeredFSPs_; /** * Final-state outgoing partICLEs after shower of hard process * _to_be_removed_ from showeredFSPs_ prior to the * light-parton-light-jet matching step. This same list is the * starting point for determining particlesToCluster_ for the * case of merging in heavy quark production. */ ParticleVector showeredFSPsToDelete_; /** * ONLY the final-state partons from preshowerFSPs_ that are * supposed to enter the jet-parton matching. */ ParticleVector partonsToMatch_; /* * The shower progenitors */ PPtr theProgenitor; PPtr theLastProgenitor; /** * ONLY the final-state particles from showeredFSPs_ (and maybe * also showeredRems_) that are supposed to go for jet clustering. */ tPVector particlesToCluster_; /** * Final-state remnants after shower of hard process * (look for remnants initially in showeredFSPs_). */ PPair showeredRems_; /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alphaS_; /** * Information extracted from the XComb object */ //@{ /** * The fixed factorization scale used in the MEs. */ Energy pdfScale_; /** * Centre of mass energy */ Energy2 sHat_; /** * Constant alphaS used to generate LH events - if not already * using CKKW scale (ickkw = 1 in AlpGen for example). */ double alphaSME_; //@} /* * Number of rapidity segments of the calorimeter. */ unsigned int ncy_; /* * Number of phi segments of the calorimeter. */ unsigned int ncphi_; /* * Heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t). */ int ihvy_; /* * Number of photons in the AlpGen process. */ int nph_; /* * Number of higgses in the AlpGen process. */ int nh_; /* * Jet ET cut to apply in jet clustering (in merging). */ Energy etclus_; /* * Mean Jet ET cut to apply in jet clustering (in merging). */ Energy etclusmean_; /* * maximum deviation from mean Jet ET cut to apply in jet clustering (in merging). */ Energy epsetclus_; /* * Cone size used in jet clustering (in merging). */ double rclus_; /* * Max |eta| for jets in clustering (in merging). */ double etaclmax_; /* * Default 1.5 factor used to decide if a jet matches a parton * in merging: if DR(parton,jet) ncphi). * ==> Cosine goes from +1 ---> +1 (index = 0 ---> ncphi). */ vector cphcal_; /* * Sine of phi values of calorimeter cell centres. * Goes phi~=0 to phi~=2*pi (index = 0 ---> ncphi). * ==> Sine goes 0 -> 1 -> 0 -> -1 -> 0 (index = 0 ---> ncphi). */ vector sphcal_; /* * Cosine of theta values of calorimeter cell centres in Y. * Goes bwds th~=pi to fwds th~=0 (index = 0 ---> ncy). * ==> Cosine goes from -1 ---> +1 (index = 0 ---> ncy). */ vector cthcal_; /* * Sine of theta values of calorimeter cell centres in Y. * Goes bwds th~=pi to fwds th~=0 (index = 0 ---> ncy). * ==> Sine goes from 0 ---> +1 ---> 0 (index = 0 ---> ncy). */ vector sthcal_; /* * Transverse energy deposit in a given calorimeter cell. * First array index corresponds to rapidity index of cell, * second array index corresponds to phi cell index. */ vector > et_; /* * For a given calorimeter cell this holds the index of the jet * that the cell was clustered into. */ vector > jetIdx_; /* * Vector holding the Lorentz 5 momenta of each jet. */ vector pjet_; /* * Vector holding the Lorentz 5 momenta of each jet from ME partons */ vector pjetME_; /* * Vector holding the list of FS particles resulting from * the particle input to getDescendents. */ ParticleVector tmpList_; /* * Variables for the C++ translation of the calini_m(), calsim_m(), * getjet_m(...) and caldel_m() functions */ vector etjet_; vector etjetME_; double dely_, delphi_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FxFxHandler. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FxFxHandler. */ typedef Herwig::ShowerHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the FxFxHandler 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::FxFxHandler"; } /** * The name of a file containing the dynamic library where the class * FxFxHandler is implemented. It may also include several, space-separated, * libraries if the class FxFxHandler 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 "FxFxHandler.so"; } }; /** @endcond */ } #endif /* HERWIG_FxFxHandler_H */ diff --git a/Contrib/HiggsPairOL/AlpGenHandlerOL.cc b/Contrib/HiggsPairOL/AlpGenHandlerOL.cc --- a/Contrib/HiggsPairOL/AlpGenHandlerOL.cc +++ b/Contrib/HiggsPairOL/AlpGenHandlerOL.cc @@ -1,1472 +1,1472 @@ #include "AlpGenHandlerOL.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" #include #include "ThePEG/Utilities/Throw.h" -#include "Herwig/Shower/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" #include "fastjet/PseudoJet.hh" #include "fastjet/ClusterSequence.hh" #include "gsl/gsl_rng.h" #include "gsl/gsl_randist.h" using namespace Herwig; bool recordEntry(PPtr i,PPtr j) { return (i->number()number()); } bool pTsortFunction(PPtr i,PPtr j) { return (i->momentum().perp2()>j->momentum().perp2()); } bool ETsortFunction(pair i,pair j) { return (i.first>j.first); } bool isMomLessThanEpsilon(Lorentz5Momentum p,Energy epsilon) { return (abs(p.x())> alphaS_ >> ncy_ >> ncphi_ >> ihvy_ >> nph_ >> nh_ >> iunit(etclusmean_,GeV) >> rclus_ >> etaclmax_ >> rclusfactor_ >> ihrd_ >> njets_ >> drjmin_ >> highestMultiplicity_ >> highestNjets_ >> ycmax_ >> ycmin_ >> jetAlgorithm_ >> vetoIsTurnedOff_ >> vetoType_ >> inputIsNLO_ >> highestNLOMultiplicity_ >> etclusfixed_ >> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV) >> smoothingtype_; } ClassDescription AlpGenHandlerOL::initAlpGenHandlerOL; // Definition of the static class description member. void AlpGenHandlerOL::Init() { static ClassDocumentation documentation ("The AlpGenHandlerOL class performs MEPS merging " "using the MLM procedure."); static Reference interfaceShowerAlpha ("ShowerAlpha", "The object calculating the strong coupling constant", &AlpGenHandlerOL::alphaS_, false, false, true, false, false); static Parameter interfaceNoCellsInRapidity ("NoCellsInRapidity", "The number of cells spanning the rapidity interval of " "the calorimeter", &AlpGenHandlerOL::ncy_, 100, 1, 10000, false, false, Interface::limited); static Parameter interfaceNoCellsInPhi ("NoCellsInPhi", "The number of cells spanning the phi interval of " "the calorimeter", &AlpGenHandlerOL::ncphi_, 60, 1, 10000, false, false, Interface::limited); static Parameter interfaceihvy ("ihvy", "heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t)", &AlpGenHandlerOL::ihvy_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenph ("nph", "Number of photons in the AlpGen process", &AlpGenHandlerOL::nph_, -999, -999, 7, false, false, Interface::limited); static Parameter interfacenh ("nh", "Number of higgses in the AlpGen process", &AlpGenHandlerOL::nh_, -999, -999, 7, false, false, Interface::limited); static Parameter interfaceETClus ("ETClus", "The ET threshold defining a jet in the merging procedure", &AlpGenHandlerOL::etclusmean_, GeV, 20*GeV, 0*GeV, 14000*GeV, false, false, Interface::limited); static Parameter interfaceRClus ("RClus", "The cone size used to define a jet in the merging procedure", &AlpGenHandlerOL::rclus_, 0.4, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceEtaClusMax ("EtaClusMax", "The maximum |eta| used to define a jet in the merging procedure", &AlpGenHandlerOL::etaclmax_, 5.0, 0.0, 15.0, false, false, Interface::limited); static Parameter interfaceRClusFactor ("RClusFactor", "The prefactor for RClus used to define the jet-parton matching " "distance", &AlpGenHandlerOL::rclusfactor_, 1.5, 0.0, 4.0, false, false, Interface::limited); static Parameter interfaceihrd ("ihrd", "The AlpGen hard process code", &AlpGenHandlerOL::ihrd_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacenjets ("njets", "The number of light jets in the AlpGen process (i.e. the " "extra ones)", &AlpGenHandlerOL::njets_, -999, 0, 10000, false, false, Interface::limited); static Parameter interfacedrjmin ("drjmin", "Mimimum parton-parton R-sep used for generation.", &AlpGenHandlerOL::drjmin_, 0.7, 0.0, 4.0, false, false, Interface::limited); static Parameter interfacehighestMultiplicity ("highestMultiplicity", "If true it indicates that this is the highest multiplicity input " "ME-level configuration to be processed.", &AlpGenHandlerOL::highestMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfacehighestNjets ("highestNjets", "If true it indicates that this is the highest multiplicity input " "ME-level configuration to be processed.", &AlpGenHandlerOL::highestNjets_, 1, 0, 100, false, false, Interface::limited); static Parameter interfacehighestNLOMultiplicity ("highestNLOMultiplicity", "If true it indicates that this is the highest NLO multiplicity input " "ME-level configuration to be processed.", &AlpGenHandlerOL::highestNLOMultiplicity_, 0, 0, 1, false, false, Interface::limited); static Parameter interfaceETClusFixed ("ETClusFixed", "If false, indicates that the jet merging scale, etclus_ is allowed to vary" "according to epsetclus_", &AlpGenHandlerOL::etclusfixed_, 1, 0, 1, false, false, Interface::limited); static Parameter interfaceEpsilonETClus ("EpsilonETClus", "The ET threshold defining a jet in the merging procedure", &AlpGenHandlerOL::epsetclus_, GeV, 2.5*GeV, 0*GeV, 100.0*GeV, false, false, Interface::limited); static Switch interfaceSmoothingType ("SmoothingType", "Determines the kind of smoothing to use ", &AlpGenHandlerOL::smoothingtype_, 0, false, false); static SwitchOption Sine (interfaceSmoothingType, "Sine", "Sinusoidal smoothing.", 0); static SwitchOption Unifnorm (interfaceSmoothingType, "Uniform", "Uniform smoothing.", 1); static Switch interfaceJetAlgorithm ("JetAlgorithm", "Determines the jet algorithm for finding jets in parton-jet " "matching in the MLM procedure.", &AlpGenHandlerOL::jetAlgorithm_, 2, false, false); static SwitchOption AntiKt (interfaceJetAlgorithm, "AntiKt", "The anti-kt jet algorithm.", -1); static SwitchOption CambridgeAachen (interfaceJetAlgorithm, "CambridgeAachen", "The Cambridge-Aachen jet algorithm.", 0); static SwitchOption Kt (interfaceJetAlgorithm, "Kt", "The Kt jet algorithm.", 1); static SwitchOption GetJet (interfaceJetAlgorithm, "GetJet", "Calorimeter-based GetJet algorithm (default).", 2); static Switch interfaceVetoIsTurnedOff ("VetoIsTurnedOff", "Allows the vetoing mechanism to be switched off.", &AlpGenHandlerOL::vetoIsTurnedOff_, false, false, false); static SwitchOption VetoingIsOn (interfaceVetoIsTurnedOff, "VetoingIsOn", "The MLM merging veto mechanism is switched ON.", false); static SwitchOption VetoingIsOff (interfaceVetoIsTurnedOff, "VetoingIsOff", "The MLM merging veto mechanism is switched OFF.", true); static Switch interfaceVetoType ("VetoType", "Allows choosing betwewen the original vetoing mechanism and the one used for OL.", &AlpGenHandlerOL::vetoType_, 1, false, false); static SwitchOption Original (interfaceVetoType, "Original", "The MLM merging veto mechanism in the original form.", 0); static SwitchOption OpenLoops (interfaceVetoType, "OpenLoops", "The MLM merging veto meechanism in the OpenLoops implementation.", 1); static Switch interfaceInputIsNLO ("InputIsNLO", "Signals whether the input LH file is tree-level accurate " "or contains NLO (Powheg) events.", &AlpGenHandlerOL::inputIsNLO_, false, false, false); static SwitchOption InputIsNotNLO (interfaceInputIsNLO, "InputIsNotNLO", "The input LH events have tree-level accuracy.", false); static SwitchOption InputIsNLO (interfaceInputIsNLO, "InputIsNLO", "The input LH events have NLO accuracy.", true); } void AlpGenHandlerOL::dofinish() { ShowerHandler::dofinish(); } void AlpGenHandlerOL::doinit() { //print error if HardProcID is not set in input file if(ihrd_ == -999) { cout << "Error: AlpGenHandlerOL:ihrd not set!" << endl; exit(1); } ShowerHandler::doinit(); // Compute calorimeter edges in rapidity for GetJet algorithm. ycmax_=etaclmax_+rclus_; ycmin_=-ycmax_; // Initialise calorimeter. calini_m(); } // Throws a veto according to MLM strategy ... when we finish writing it. bool AlpGenHandlerOL::showerHardProcessVeto() { if(vetoIsTurnedOff_) return false; // Skip veto for processes in which merging is not implemented: if(ihrd_==7||ihrd_==8||ihrd_==13) { ostringstream wstring; wstring << "AlpGenHandlerOL::showerHardProcessVeto() - warning." << "MLM merging not implemented for AlpGen " << "processes 4Q (ihrd=7), QQh (ihrd=8), " << "(single) top (ihrd=13) \n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); return false; } // Fill preshowerISPs_ pair and preshowerFSPs_ particle pointer vector. getPreshowerParticles(); // Fill showeredISHs_, showeredISPs and showeredRems pairs, as well as // showeredFSPs_ particle pointer vector. getShoweredParticles(); // Turn on some screen output debugging: 0 = none ---> 5 = very verbose. doSanityChecks(0); // Dimensions of each calorimter cell in y and phi. dely_ = (ycmax_-ycmin_)/double(ncy_); delphi_ = 2*M_PI/double(ncphi_); // Fill partonsToMatch_ with only those pre-shower partons intended to // used in jet-parton matching and fill particlesToCluster_ using only // those final state particles (post-shower) which are supposed to go // in the jet clustering used to do merging. partonsToMatch_ = preshowerFSPs_; particlesToCluster_ = showeredFSPs_ ; // <--- TO DO: add remnants in here ??? // Filter out all but the 'extra' light-parton progenitors and their // associated final state particles. caldel_m(); double prob(1); //if etclusfixed_ then set the etclus_ to the fixed chosen value if(etclusfixed_) { etclus_ = etclusmean_; } else { //else, if we wish to vary etclus_, we use the probability distribution //choose a probability between 0 and 1 prob = rnd(); etclus_ = etclusran_(prob); } if(jetAlgorithm_==2) { // If using GetJet fill the calorimeter cells now from particlesToCluster_ calsim_m(); // Make jets from the calorimeter blobs. getjet_m(rclus_,etclus_,etaclmax_); } else { // Cluster particlesToCluster_ into jets with FastJet. getFastJets(rclus_,etclus_,etaclmax_); } // If there are less jets than partons then parton-jet matching is // bound to fail: reject the event already. Also, if the input is // an NLO event file it will 99.5% of the time contain a number of // light partons in the F.S. equal to that in the real emission // process in the NLO calculation, moreover, it has already // effectively merged njets_-1 and njets jet events. So in that // case we do not reject events on the grounds they have jet // multiplicity less than partonsToMatch_.size() but rather less // jets than partonsToMatch.size()-1; such events are better // described by the lower-by-one-unit (partonsToMatch_.size()-1) // of multiplicity NLO event file, or the lower-by-two-units // (partonsToMatch_.size()-2) of multiplicity LO event file. // If it is not jet production apply rejection criterion as above. if(ihrd_!=9) { if(!inputIsNLO_) { if(pjet_.size() < partonsToMatch_.size()) { // cout << "multiplicity: " << partonsToMatch_.size() << " jets: " << pjet_.size() << endl; return true; } } else { if(pjet_.size() < partonsToMatch_.size()-1) return true; } // Otherwise, in the case of jet production allow the lowest // contributing multiplicity process (just at NLO), namely, // dijet production, to give rise to 1-jet and even 0-jet // events, since these can contribute to, for example, the // inclusive jet cross section i.e. in this case the rejection // is only applied in the case of the next-to-lowest multiplicity // processes (>2 parton events at LO and >3 parton events at NLO). } else { if(!inputIsNLO_) { // KH - March 5th // Removed the following line giving special treatment // also to the LO events, to maintain consistency with // the fortran algorithm, at least for now. So now jet // production at LO is being treated the same as all // other processes. // if(partonsToMatch_.size()==2 && pjet_.size()<2) return false; if(pjet_.size() < partonsToMatch_.size()) return true; } else { if(partonsToMatch_.size()<=3 && pjet_.size()<2) return false; if(pjet_.size() < partonsToMatch_.size()-1) return true; } } // Sort partonsToMatch_ from high to low pT. sort(partonsToMatch_.begin(),partonsToMatch_.end(),pTsortFunction); // Match light progenitors to jets. vector jetToPartonMap(pjet_.size(),-999); Energy etmin(777e100*GeV); // If the input is NLO events then don't do any jet-parton matching! if(!inputIsNLO_) { // For each parton, starting with the hardest one ... for(unsigned int ixx=0; ixx=0) { jetToPartonMap[jetIndexForDRmin]=ixx; if(ixx==0||etjet_[jetIndexForDRmin]partonsToMatch_.size() && !inputIsNLO_) { // cout << "multiplicity: " << partonsToMatch_.size() << " jets: " << pjet_.size() << endl; return true; } if(inputIsNLO_) { if(!highestNLOMultiplicity_) { if(pjet_.size()>partonsToMatch_.size()-1) return true; } else { if(!highestMultiplicity_&&pjet_.size()>partonsToMatch_.size()) return true; } } // Veto events where matched jets are softer than non-matched ones, // in the inclusive (highestMultiplicity_ = true) mode, unless we // are dealing with NLO input events. if(highestMultiplicity_ && !inputIsNLO_ ) { for(unsigned int ixx=0; ixxpartonsToMatch_.size() if(partonsToMatch_.size()partonsToMatch_.size() && !inputIsNLO_) { // cout << "multiplicity: " << partonsToMatch_.size() << " jets: " << pjet_.size() << endl; return true; } if(inputIsNLO_) { if(!highestNLOMultiplicity_) { if(pjet_.size()>partonsToMatch_.size()-1) return true; } else { if(partonsToMatch_.size()partonsToMatch_.size()) return true; } } // Veto events where matched jets are softer than non-matched ones, // in the inclusive (highestMultiplicity_ = true) mode, unless we // are dealing with NLO input events. if(partonsToMatch_.size()==highestNjets_ && !inputIsNLO_ ) { // cout << "multiplicity: " << partonsToMatch_.size() << " jets: " << pjet_.size() << endl; for(unsigned int ixx=0; ixxid())==4||abs(partonsToMatch_[jxx]->id())==5)) continue; if(partonJetDeltaR(partonsToMatch_[jxx],pjet_[ixx])etmin) return true; } } } // Otherwise we accept the event ... return false; } /* Function that returns the R distance between a particle and a jet. */ double AlpGenHandlerOL::partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom) { LorentzMomentum partonmom(partonptr->momentum()); // Calculate DY, DPhi and then DR double DY(partonmom.eta()-jetmom.eta()); double DPhi(partonmom.phi()-jetmom.phi()); if(DPhi>M_PI) DPhi=2*M_PI-DPhi; double DR(sqrt(sqr(DY)+sqr(DPhi))); return DR; } // Initialize calorimeter for calsim_m and getjet_m. Note that // because initialization is separte calsim_m can be called more // than once to simulate pileup of several events. void AlpGenHandlerOL::calini_m() { // Making sure arrays are clear before filling; cphcal_.clear(); sphcal_.clear(); cthcal_.clear(); sthcal_.clear(); // Fill array holding phi values of calorimeter cell centres. double deltaPhi(2*M_PI/ncphi_); for(unsigned int iphi=1; iphi<=ncphi_; iphi++) { double phi(deltaPhi*(iphi-0.5)); // Goes phi~=0 to phi~=2*pi (iphi=0--->ncphi). cphcal_.push_back(cos(phi)); // ==> goes from +1 ---> +1 (iphi=0--->ncphi). sphcal_.push_back(sin(phi)); // ==> goes 0 -> 1 -> 0 -> -1 -> 0 (iphi=0--->ncphi). } // Fill array holding theta values of calorimeter cell centres in Y. double deltaY((ycmax_-ycmin_)/double(ncy_)); for(unsigned int iy=1; iy<=ncy_; iy++) { double Y(deltaY*(iy-0.5)+ycmin_); double th(2*atan(exp(-Y))); // Goes bwds th~=pi to fwds th~=0 (iy=0--->ncy). cthcal_.push_back(cos(th)); // ==> goes from -1 ---> +1 (iy=0--->ncy). sthcal_.push_back(sin(th)); // ==> goes from 0 ---> +1 ---> 0 (iy=0--->ncy). } return; } // Get FastJets void AlpGenHandlerOL::getFastJets(double rjet, Energy ejcut, double etajcut) { vector particlesToCluster; for(unsigned int ipar=0; iparmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it may go in the jet finder. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { // input particles into fastjet pseudojet fastjet::PseudoJet p(particlesToCluster_[ipar]->momentum().x()/GeV, particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().z()/GeV, particlesToCluster_[ipar]->momentum().e()/GeV); p.set_user_index(ipar); particlesToCluster.push_back(p); } } } fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme; fastjet::Strategy strategy = fastjet::Best; double R(rjet); fastjet::JetDefinition theJetDefinition; switch (jetAlgorithm_) { case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm, R, recombinationScheme, strategy); break; case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm, R, recombinationScheme, strategy); break; default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm, R, recombinationScheme, strategy); break; } fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition); vector inclusiveJets = fastjetEvent.inclusive_jets(); inclusiveJets = fastjet::sorted_by_pt(inclusiveJets); // Fill the array of jet momenta for the rest of the veto procedure. pjet_.clear(); pjet_.resize(inclusiveJets.size()); etjet_.clear(); etjet_.resize(inclusiveJets.size()); for(unsigned int ffj=0; ffjetajcut) { pjet_.erase(pjet_.begin()+fj); etjet_.erase(etjet_.begin()+fj); fj--; } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxmomentum().eta()); if(y>=ycmin_&&y<=ycmax_) { int absId(abs(particlesToCluster_[ipar]->id())); // If it's not a lepton / top / photon it goes in the calorimeter. if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) { double phi(atan2(particlesToCluster_[ipar]->momentum().y()/GeV, particlesToCluster_[ipar]->momentum().x()/GeV)); if(phi<0) phi+=2*M_PI; unsigned int iy(int((y-ycmin_)/dely_)); unsigned int iphi(int(phi/delphi_)); et_[iy][iphi]+=particlesToCluster_[ipar]->momentum().e()*sthcal_[iy]; } } } return; } // Find highest remaining cell > etstop and sum surrounding cells // with -- delta(y)^2+delta(phi)^2 < Rjet^2 , ET>eccut. Keep sets // with ET>ejcut and abs(eta)=etstop) { // Find the cell with the highest ET from // those not already assigned to a jet. etmax=0*GeV; int iymx(0), iphimx(0); for(unsigned int iphi=0; iphietmax&&jetIdx_[iy][iphi]<0) { etmax = et_[iy][iphi]; iymx = iy; iphimx = iphi; } // If the remaining cell with the highest ET has ET < etstop, stop. if(etmax(ncy_*ncphi_)) { cout << "AlpGenHandlerOL::getjet_m() - Fatal error." << endl; cout << "We found " << ipass << " calo cells with the highest ET so" << "far\nbut the calorimeter only has " << ncy_*ncphi_ << " " << "cells in it!" << endl; exit(10); } // Add a jet vector (may get deleted if jet fails ET / eta cuts). etjet_.push_back(0*GeV); pjet_.push_back(Lorentz5Momentum(0.*GeV,0.*GeV,0.*GeV,0.*GeV,0.*GeV)); // Loop over all calo cells in range iphimx +/- nphi1 (inclusive) // wrapping round in azimuth if required. for(unsigned int iphi1=0; iphi1<=2*nphi1; iphi1++) { int iphix(iphimx-nphi1+iphi1); if(iphix<0) iphix += ncphi_; if(iphix>=int(ncphi_)) iphix -= ncphi_; // Loop over all calo cells in range iymx +/- ny1 (inclusive). for(unsigned int iy1=0; iy1<=2*ny1; iy1++) { int iyx(iymx-ny1+iy1); // If the cell is outside the calorimeter OR if it was already // associated to a jet then skip to the next loop. if(iyx>=0&&iyx=eccut) { Energy ECell(et_[iyx][iphix]/sthcal_[iyx]); pjet_.back()+=LorentzMomentum(ECell*sthcal_[iyx]*cphcal_[iphix], // px ECell*sthcal_[iyx]*sphcal_[iphix], // py ECell*cthcal_[iyx],ECell); // pz, E. // N.B. This is the same reln as in ThePEG between phi and x,y. etjet_.back()+=et_[iyx][iphix]; jetIdx_[iyx][iphix] = pjet_.size()-1; // Identify cell with this jet. } } } } // Compute the current jet's mass. pjet_.back().rescaleMass(); // Throw the jet away if it's ET is less than ejcut. if(etjet_.back()etajcut) { pjet_.pop_back(); etjet_.pop_back(); } } // Sort jets from high to low ET. vector > etjet_pjet; for(unsigned int ixx=0; ixxchildren()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else getDescendents(theChildren[ixx]); return; } void AlpGenHandlerOL::caldel_m() { preshowerFSPsToDelete_.clear(); showeredFSPsToDelete_.clear(); for(unsigned int ixx=0; ixxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==23|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24|| abs(preshowerFSPs_[ixx]->id())==22|| abs(preshowerFSPs_[ixx]->id())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); } if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==6) { getDescendents(preshowerFSPs_[ixx]->parents()[0]); for(unsigned int jxx=0; jxxid())==ihvy_&&ixx<2) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==4&&ixx<1)|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==25) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+1)))|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+2)))|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==6|| abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxid())==22|| (abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2)) { preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]); getDescendents(preshowerFSPs_[ixx]); for(unsigned int jxx=0; jxxparticlesToCluster_.size()) { throw Exception() << "AlpGenHandlerOL::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of showered particles to build jets from = " << particlesToCluster_.size() << "\n" << "There should be at least as many partons to\n" << "cluster as there are partons to match to.\n" << Exception::eventerror; } // Acid test. unsigned int tmpUnsignedInt(njets_); if(!inputIsNLO_&&partonsToMatch_.size()!=tmpUnsignedInt) { for(unsigned int ixx=0; ixxid())>=6&& abs(partonsToMatch_[ixx]->id())!=21) throw Exception() << "AlpGenHandlerOL::caldel_m() - ERROR!\n" << "Found a parton to match to which is not a quark or gluon!" << *partonsToMatch_[ixx] << "\n" << Exception::eventerror; } if(vetoType_==0) { throw Exception() << "AlpGenHandlerOL::caldel_m() - ERROR!\n" << "No. of ME level partons to be matched to jets = " << partonsToMatch_.size() << "\n" << "No. of light jets (njets) in AlpGen process = " << njets_ << "\n" << "These should be equal." << "\n" << Exception::eventerror; } } return; } // This looks for all descendents of a top up to but not including // the W and b children. void AlpGenHandlerOL::getTopRadiation(PPtr theParticle) { ParticleVector theChildren(theParticle->children()); for (unsigned int ixx=0; ixxchildren().size()==0) tmpList_.push_back(theChildren[ixx]); else if(abs(theChildren[ixx]->id())==5||abs(theChildren[ixx]->id())==24) return; else getTopRadiation(theChildren[ixx]); return; } void AlpGenHandlerOL::caldel_hvq() { // Fill partonsToMatch_ with only those pre-shower partons intended to // be used in heavy-quark-jet matching and fill particlesToCluster_ using // only those final state particles (post-shower) which are supposed // in the heavy-quark-jet clustering used to do merging. To begin with // these are made from the corresponding sets of particles that were // omitted from the initial jet-parton matching run. partonsToMatch_ = preshowerFSPsToDelete_; particlesToCluster_.resize(showeredFSPsToDelete_.size()); for(unsigned int ixx=0; ixxid())<4||abs(partonsToMatch_[ixx]->id())>6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxid())==5&& partonsToMatch_[ixx]->parents().size()>0&& abs(partonsToMatch_[ixx]->parents()[0]->id())==6) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxparents().size()>0&& (abs(partonsToMatch_[ixx]->parents()[0]->id())==23|| abs(partonsToMatch_[ixx]->parents()[0]->id())==24|| abs(partonsToMatch_[ixx]->parents()[0]->id())==25)) { preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]); tmpList_.clear(); getDescendents(partonsToMatch_[ixx]); for(unsigned int jxx=0; jxxsubProcess()->intermediates()); for(unsigned int ixx=0; ixxid())==6) { partonsToMatch_.push_back(intermediates[ixx]); tmpList_.clear(); getTopRadiation(partonsToMatch_.back()); for(unsigned int jxx=0; jxxid())>=4&&abs(partonsToMatch_[ixx]->id())<=6) { theProgenitor = partonsToMatch_[ixx]; // Follow the heavy quark line down to where it stops branching. while(theProgenitor->children().size()>0) { theLastProgenitor = theProgenitor; for(unsigned int jxx=0; jxxchildren().size(); jxx++) { if(theProgenitor->children()[jxx]->id()==theProgenitor->id()) theProgenitor=theProgenitor->children()[jxx]; } // If the progenitor had children but none of them had // the same particle id as it, then it must have undergone // a decay rather than a branching, i.e. it is the end of // the evolution line, so, if(theProgenitor==theLastProgenitor) break; } evolvedHeavyQuarks.push_back(theProgenitor); } } // Now delete the evolved heavy quark from the particlesToCluster. for(unsigned int ixx=0; ixxsubProcess()->incoming(); // LH file final-state partICLEs: preshowerFSPs_ = lastXCombPtr()->subProcess()->outgoing(); return; } void AlpGenHandlerOL::getShoweredParticles() { // Post-shower initial-state hadrons: showeredISHs_ = eventHandler()->currentEvent()->incoming(); // Post-shower initial-state partons: for(unsigned int ixx=0; ixx<(showeredISHs_.first)->children().size(); ixx++) if(((showeredISHs_.first)->children()[ixx]->id())<6|| ((showeredISHs_.first)->children()[ixx]->id())==21) showeredISPs_.first=(showeredISHs_.first)->children()[ixx]; for(unsigned int ixx=0; ixx<(showeredISHs_.second)->children().size(); ixx++) if(((showeredISHs_.second)->children()[ixx]->id())<6|| ((showeredISHs_.second)->children()[ixx]->id())==21) showeredISPs_.second=(showeredISHs_.second)->children()[ixx]; // Post-shower final-state partICLEs plus remnants (to be removed later): showeredFSPs_ = eventHandler()->currentEvent()->getFinalState(); // Post-shower final-state remnants: for(unsigned int ixx=0; ixxPDGName()=="Rem:p+"|| showeredFSPs_[ixx]->PDGName()=="Rem:pbar-") { if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.first) showeredRems_.first=showeredFSPs_[ixx]; else if(showeredFSPs_[ixx]->parents()[0]->parents()[0]== showeredISHs_.second) showeredRems_.second=showeredFSPs_[ixx]; } } // Now delete found remnants from the showeredFSPs vector for consistency. for(unsigned int ixx=0; ixxPDGName()=="Rem:p+") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); for(unsigned int ixx=0; ixxPDGName()=="Rem:pbar-") showeredFSPs_.erase(showeredFSPs_.begin()+ixx); sort(showeredFSPs_.begin(),showeredFSPs_.end(),recordEntry); return; } void AlpGenHandlerOL::doSanityChecks(int debugLevel) { // When checking momentum conservation in the form // p_in - p_out, any momentum component bigger / less // than + / - epsilon will result in the p_in - p_out // vector being flagged as "non-null", triggering a // warning that momentum conservation is violated. Energy epsilon(0.5*GeV); if(debugLevel>=5) epsilon=1e-9*GeV; // Print out what was found for the incoming and outgoing // partons in the lastXCombPtr regardless. if(debugLevel>=5) { cout << "\n\n\n\n"; cout << "****************************************************" << endl; cout << " The following are the hard subprocess momenta from " << "\n" << " lastXCombPtr and should be basically identical to " << "\n" << " the input LH file momenta." << "\n\n"; cout << " Incoming particles:" << "\n" << *(preshowerISPs_.first) << "\n" << *(preshowerISPs_.second) << endl; cout << " Outgoing particles:" << endl; for(unsigned int ixx=0; ixx=5) { cout << "\n\n"; cout << "****************************************************" << endl; cout << " The following are the particles left at the end of" << "\n" << " the showering step." << "\n\n"; cout << " Incoming hadrons:" << "\n" << *(showeredISHs_.first) << "\n" << *(showeredISHs_.second) << endl; cout << " Incoming partons:" << "\n" << *(showeredISPs_.first) << "\n" << *(showeredISPs_.second) << endl; cout << " Outgoing partons:" << endl; for(unsigned int ixx=0; ixx=4) { Lorentz5Momentum tmpMom; tmpMom += showeredISPs_.first->momentum(); tmpMom += showeredISPs_.second->momentum(); for(unsigned int ixx=0; ixxmomentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Total parton mom.in - total parton mom.out = " << tmpMom/GeV << endl; tmpMom = showeredISHs_.first->momentum() - showeredRems_.first->momentum() -showeredISPs_.first->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "First p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; tmpMom = showeredISHs_.second->momentum() - showeredRems_.second->momentum()-showeredISPs_.second->momentum(); if(!isMomLessThanEpsilon(tmpMom,epsilon)) cout << "Second p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl; } // Check if what we found to be the remnant is consistent with // what we identified as the parent incoming hadron i.e. p+ // goes with Rem:p+ and pbar- goes with Rem:pbar-. if(debugLevel>=0) { string tmpString; tmpString=showeredRems_.first->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.first->PDGName()!=tmpString) { cout << "AlpGenHandlerOL::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.first) << "\n" << "Parent hadron = " << *(showeredISHs_.first) << endl; cout << showeredISHs_.first->PDGName() << endl; cout << tmpString << endl; } tmpString=showeredRems_.second->PDGName(); tmpString=tmpString.substr(tmpString.find_first_of(":")+1, string::npos); if(showeredISHs_.second->PDGName()!=tmpString) { cout << "AlpGenHandlerOL::showerHardProcessVeto" << "\n" << "Fatal error in pairing of remnant and parent hadron." << "\n" << "Remnant = " << *(showeredRems_.second) << "\n" << "Parent hadron = " << *(showeredISHs_.second) << endl; cout << showeredISHs_.second->PDGName() << endl; cout << tmpString << endl; } } return; } void AlpGenHandlerOL::printMomVec(vector momVec) { cout << "\n\n"; // Label columns. printf("%5s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n", "jet #", "px","py","pz","E", "eta","phi","pt","et","mass"); // Print out the details for each jet for (unsigned int ixx=0; ixx ETSTOP and sum surrounding cells with -- * DELTA(Y)**2+DELTA(PHI)**2 < RJET**2 , ET>ECCUT. * Keep sets with ET>EJCUT and ABS(ETA)currentEvent()->... * filling the particle pairs showeredISHs_, showeredISPs_, * showeredRems_ and the particle pointer vector showeredFSPs_. */ void getShoweredParticles(); /** * Allows printing of debug output and sanity checks like * total momentum consrvation to be carried out. * debugLevel = -1, 0, ...5 * = no debugging, minimal debugging, ... verbose. */ void doSanityChecks(int debugLevel); /** * Given a pointer to a particle this finds all its final state * descendents. */ void getDescendents(PPtr theParticle); /** * Accumulates all descendents of tops down to the b and W * but not including them. */ void getTopRadiation(PPtr theParticle); /** * Sorts a given vector of particles by descending pT or ETJET */ ParticleVector pTsort(ParticleVector unsortedVec); pair< vector, vector > ETsort(vector unsortedetjet, vector unsortedVec); /* * A function that prints a vector of Lorentz5Momenta in a fancy way */ void printMomVec(vector momVec); /* * A probability function for varying etclus_ about the mean value */ Energy etclusran_(double petc); private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initAlpGenHandlerOL; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ AlpGenHandlerOL & operator=(const AlpGenHandlerOL &); private: /** * Initial-state incoming partons prior to showering * (i.e. from lastXCombPtr). */ PPair preshowerISPs_; /** * Final-state outgoing partICLEs prior to showering * (i.e. from lastXCombPtr). */ ParticleVector preshowerFSPs_; /** * Final-state outgoing partICLEs prior to showering _to_be_removed_ * from preShowerFSPs_ prior to the light-parton-light-jet matching * step. This same list is the starting point for determining * partonsToMatch_ for the case of merging in heavy quark production. */ ParticleVector preshowerFSPsToDelete_; /** * Initial-state incoming hadrons after shower of hard process * (eventHandler()->currentEvent()->incoming()). */ PPair showeredISHs_; /** * Initial-state incoming partons after shower of hard process * (look for partonic children of showeredISHs_). */ PPair showeredISPs_; /** * Final-state outgoing partICLEs after shower of hard process * (eventHandler()->currentEvent()->getFinalState()). */ tPVector showeredFSPs_; /** * Final-state outgoing partICLEs after shower of hard process * _to_be_removed_ from showeredFSPs_ prior to the * light-parton-light-jet matching step. This same list is the * starting point for determining particlesToCluster_ for the * case of merging in heavy quark production. */ ParticleVector showeredFSPsToDelete_; /** * ONLY the final-state partons from preshowerFSPs_ that are * supposed to enter the jet-parton matching. */ ParticleVector partonsToMatch_; /* * The shower progenitors */ PPtr theProgenitor; PPtr theLastProgenitor; /** * ONLY the final-state particles from showeredFSPs_ (and maybe * also showeredRems_) that are supposed to go for jet clustering. */ tPVector particlesToCluster_; /** * Final-state remnants after shower of hard process * (look for remnants initially in showeredFSPs_). */ PPair showeredRems_; /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alphaS_; /** * Information extracted from the XComb object */ //@{ /** * The fixed factorization scale used in the MEs. */ Energy pdfScale_; /** * Centre of mass energy */ Energy2 sHat_; /** * Constant alphaS used to generate LH events - if not already * using CKKW scale (ickkw = 1 in AlpGen for example). */ double alphaSME_; //@} /* * Number of rapidity segments of the calorimeter. */ unsigned int ncy_; /* * Number of phi segments of the calorimeter. */ unsigned int ncphi_; /* * Heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t). */ int ihvy_; /* * Number of photons in the AlpGen process. */ int nph_; /* * Number of higgses in the AlpGen process. */ int nh_; /* * Jet ET cut to apply in jet clustering (in merging). */ Energy etclus_; /* * Mean Jet ET cut to apply in jet clustering (in merging). */ Energy etclusmean_; /* * maximum deviation from mean Jet ET cut to apply in jet clustering (in merging). */ Energy epsetclus_; /* * type of smoothing function to use */ unsigned int smoothingtype_; /* * Cone size used in jet clustering (in merging). */ double rclus_; /* * Max |eta| for jets in clustering (in merging). */ double etaclmax_; /* * Default 1.5 factor used to decide if a jet matches a parton * in merging: if DR(parton,jet) ncphi). * ==> Cosine goes from +1 ---> +1 (index = 0 ---> ncphi). */ vector cphcal_; /* * Sine of phi values of calorimeter cell centres. * Goes phi~=0 to phi~=2*pi (index = 0 ---> ncphi). * ==> Sine goes 0 -> 1 -> 0 -> -1 -> 0 (index = 0 ---> ncphi). */ vector sphcal_; /* * Cosine of theta values of calorimeter cell centres in Y. * Goes bwds th~=pi to fwds th~=0 (index = 0 ---> ncy). * ==> Cosine goes from -1 ---> +1 (index = 0 ---> ncy). */ vector cthcal_; /* * Sine of theta values of calorimeter cell centres in Y. * Goes bwds th~=pi to fwds th~=0 (index = 0 ---> ncy). * ==> Sine goes from 0 ---> +1 ---> 0 (index = 0 ---> ncy). */ vector sthcal_; /* * Transverse energy deposit in a given calorimeter cell. * First array index corresponds to rapidity index of cell, * second array index corresponds to phi cell index. */ vector > et_; /* * For a given calorimeter cell this holds the index of the jet * that the cell was clustered into. */ vector > jetIdx_; /* * Vector holding the Lorentz 5 momenta of each jet. */ vector pjet_; /* * Vector holding the list of FS particles resulting from * the particle input to getDescendents. */ ParticleVector tmpList_; /* * Variables for the C++ translation of the calini_m(), calsim_m(), * getjet_m(...) and caldel_m() functions */ vector etjet_; double dely_, delphi_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of AlpGenHandlerOL. */ template <> struct BaseClassTrait { /** Typedef of the first base class of AlpGenHandlerOL. */ typedef Herwig::ShowerHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the AlpGenHandlerOL 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::AlpGenHandlerOL"; } /** * The name of a file containing the dynamic library where the class * AlpGenHandlerOL is implemented. It may also include several, space-separated, * libraries if the class AlpGenHandlerOL 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 "AlpGenHandlerOL.so"; } }; /** @endcond */ } #endif /* HERWIG_AlpGenHandlerOL_H */ diff --git a/Contrib/LeptonME/MEee2Higgs2SM.cc b/Contrib/LeptonME/MEee2Higgs2SM.cc --- a/Contrib/LeptonME/MEee2Higgs2SM.cc +++ b/Contrib/LeptonME/MEee2Higgs2SM.cc @@ -1,277 +1,349 @@ // -*- C++ -*- // // MEee2Higgs2SM.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 MEee2Higgs2SM class. // #include "MEee2Higgs2SM.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/HardVertex.h" #include "ThePEG/PDT/EnumParticles.h" using namespace Herwig; void MEee2Higgs2SM::doinit() { ME2to2Base::doinit(); - _h0 = getParticleData(ThePEG::ParticleID::h0); + h0_ = getParticleData(ThePEG::ParticleID::h0); tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast(standardModel()); // do the initialisation if(hwsm) { - _theFFHVertex = hwsm->vertexFFH(); + FFHVertex_ = hwsm->vertexFFH(); + HGGVertex_ = hwsm->vertexHGG(); } else { throw InitException() << "Must have Herwig StandardModel object in " << "MEee2Higgs2SM::doinit()" << Exception::runerror; } } Energy2 MEee2Higgs2SM::scale() const { return sHat(); } unsigned int MEee2Higgs2SM::orderInAlphaS() const { return 0; } unsigned int MEee2Higgs2SM::orderInAlphaEW() const { return 2; } void MEee2Higgs2SM::getDiagrams() const { // specific the diagrams tcPDPtr ep = getParticleData(ParticleID::eplus ); tcPDPtr em = getParticleData(ParticleID::eminus); // outgoing quarks for(int i=1;i<=5;++i) { - if(_allowed==0 || _allowed==1 || _allowed==i+2) { + if(allowed_==0 || allowed_==1 || allowed_==i+2) { tcPDPtr lm = getParticleData(i); tcPDPtr lp = lm->CC(); - add(new_ptr((Tree2toNDiagram(2), em, ep, 1, _h0, 3, lm, 3, lp, -1))); + add(new_ptr((Tree2toNDiagram(2), em, ep, 1, h0_, 3, lm, 3, lp, -1))); } } // outgoing leptons for( int i =11;i<=16;i+=2) { - if(_allowed==0 || _allowed==2 || _allowed==(i+7)/2) { + if(allowed_==0 || allowed_==2 || allowed_==(i+7)/2) { tcPDPtr lm = getParticleData(i); tcPDPtr lp = lm->CC(); - add(new_ptr((Tree2toNDiagram(2), em, ep, 1, _h0, 3, lm, 3, lp, -1))); + add(new_ptr((Tree2toNDiagram(2), em, ep, 1, h0_, 3, lm, 3, lp, -1))); } } + if(allowed_==0 || allowed_==12) { + tcPDPtr g = getParticleData(ParticleID::g); + add(new_ptr((Tree2toNDiagram(2), em, ep, 1, h0_, 3, g, 3, g, -1))); + } } double MEee2Higgs2SM::me2() const { double aver=0.; // get the order right int ielectron(0),ipositron(1),ilp(2),ilm(3); if(mePartonData()[0]->id()!=11) swap(ielectron,ipositron); if(mePartonData()[2]->id()>mePartonData()[3]->id()) swap(ilp,ilm); // the arrays for the wavefunction to be passed to the matrix element - vector fin,aout; - vector ain,fout; + vector fin; + vector ain; for(unsigned int ihel=0;ihel<2;++ihel) { fin .push_back(SpinorWaveFunction(meMomenta()[ielectron], mePartonData()[ielectron],ihel,incoming)); ain .push_back(SpinorBarWaveFunction(meMomenta()[ipositron], mePartonData()[ipositron],ihel,incoming)); - fout.push_back(SpinorBarWaveFunction(meMomenta()[ilm], - mePartonData()[ilm],ihel,outgoing)); - aout.push_back(SpinorWaveFunction(meMomenta()[ilp], - mePartonData()[ilp],ihel,outgoing)); } - HelicityME(fin,ain,fout,aout,aver); - if(mePartonData()[ilm]->id()<=6) aver*=3.; + // H -> f fbar + if(mePartonData()[2]->id()!=ParticleID::g) { + vector aout; + vector fout; + for(unsigned int ihel=0;ihel<2;++ihel) { + fout.push_back(SpinorBarWaveFunction(meMomenta()[ilm], + mePartonData()[ilm],ihel,outgoing)); + aout.push_back(SpinorWaveFunction(meMomenta()[ilp], + mePartonData()[ilp],ihel,outgoing)); + } + HelicityME(fin,ain,fout,aout,aver); + if(mePartonData()[ilm]->id()<=6) aver*=3.; + } + else { + vector g1,g2; + for(unsigned int ihel=0;ihel<2;++ihel) { + g1.push_back(VectorWaveFunction(meMomenta()[2],mePartonData()[2], + 2*ihel,outgoing)); + g2.push_back(VectorWaveFunction(meMomenta()[3],mePartonData()[3], + 2*ihel,outgoing)); + } + ggME(fin,ain,g1,g2,aver); + aver *= 8.; + } return aver; } // the helicity amplitude matrix element ProductionMatrixElement MEee2Higgs2SM::HelicityME(vector fin, vector ain, vector fout, vector aout, double & aver) const { // the particles should be in the order // for the incoming // 0 incoming fermion (u spinor) // 1 incoming antifermion (vbar spinor) // for the outgoing // 0 outgoing fermion (ubar spinor) // 1 outgoing antifermion (v spinor) // me to be returned ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); // wavefunctions for the intermediate particles ScalarWaveFunction interh; // temporary storage of the different diagrams Complex diag; aver=0.; // sum over helicities to get the matrix element unsigned int inhel1,inhel2,outhel1,outhel2; for(inhel1=0;inhel1<2;++inhel1) { for(inhel2=0;inhel2<2;++inhel2) { - interh = _theFFHVertex->evaluate(sHat(),1,_h0,fin[inhel1],ain[inhel2]); + interh = FFHVertex_->evaluate(sHat(),1,h0_,fin[inhel1],ain[inhel2]); for(outhel1=0;outhel1<2;++outhel1) { for(outhel2=0;outhel2<2;++outhel2) { - diag = _theFFHVertex->evaluate(sHat(),aout[outhel2], + diag = FFHVertex_->evaluate(sHat(),aout[outhel2], fout[outhel1],interh); output(inhel1,inhel2,outhel1,outhel2)=diag; aver +=real(diag*conj(diag)); } } } } return output; } Selector MEee2Higgs2SM::diagrams(const DiagramVector &) const { Selector sel;sel.insert(1.0, 0); return sel; } Selector MEee2Higgs2SM::colourGeometries(tcDiagPtr diag) const { static ColourLines neutral ( " " ); static ColourLines quarks ( "-5 4"); + static ColourLines gluons ( "-5 4, 5 -4"); Selector sel; int id = abs((diag->partons()[2])->id()); if (id<=6 ) sel.insert(1.0, &quarks); + if (id==21) + sel.insert(1.0, &gluons); else sel.insert(1.0, &neutral); return sel; } void MEee2Higgs2SM::persistentOutput(PersistentOStream & os) const { - os << _theFFHVertex << _h0 << _allowed; + os << FFHVertex_ << HGGVertex_ << h0_ << allowed_; } void MEee2Higgs2SM::persistentInput(PersistentIStream & is, int) { - is >> _theFFHVertex >> _h0 >>_allowed; + is >> FFHVertex_ >> HGGVertex_ >> h0_ >> allowed_; } ClassDescription MEee2Higgs2SM::initMEee2Higgs2SM; // Definition of the static class description member. void MEee2Higgs2SM::Init() { static ClassDocumentation documentation ("The MEee2Higgs2SM class implements the matrix element for e+e- to" " SM particle via Higgs exchnage and is designed to be a process to test" " things involving scalar particles. "); static Switch interfaceallowed ("Allowed", "Allowed outgoing particles", - &MEee2Higgs2SM::_allowed, 0, false, false); + &MEee2Higgs2SM::allowed_, 0, false, false); static SwitchOption interfaceallowedAll (interfaceallowed, "All", "All SM particles allowed", 0); static SwitchOption interfaceallowed1 (interfaceallowed, "Quarks", "Only the quarks allowed", 1); static SwitchOption interfaceallowed2 (interfaceallowed, "Leptons", "Only the leptons allowed", 2); static SwitchOption interfacealloweddown (interfaceallowed, "Down", "Only d dbar allowed", 3); static SwitchOption interfaceallowedup (interfaceallowed, "Up", "Only u ubar allowed", 4); static SwitchOption interfaceallowedstrange (interfaceallowed, "Strange", "Only s sbar allowed", 5); static SwitchOption interfaceallowedcharm (interfaceallowed, "Charm", "Only c cbar allowed", 6); static SwitchOption interfaceallowedbottom (interfaceallowed, "Bottom", "Only b bbar allowed", 7); static SwitchOption interfaceallowedtop (interfaceallowed, "Top", "Only t tbar allowed", 8); static SwitchOption interfaceallowedelectron (interfaceallowed, "Electron", "Only e+e- allowed", 9); static SwitchOption interfaceallowedMuon (interfaceallowed, "Muon", "Only mu+mu- allowed", 10); static SwitchOption interfaceallowedTau (interfaceallowed, "Tau", "Only tau+tau- allowed", 11); + static SwitchOption interfaceallowedGluon + (interfaceallowed, + "Gluon", + "Only gg allowed", + 12); } void MEee2Higgs2SM::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]); if(hard[0]->id()id()) swap(hard[0],hard[1]); if(hard[2]->id()id()) swap(hard[2],hard[3]); - vector fin,aout; - vector ain,fout; + vector fin; + vector ain; SpinorWaveFunction( fin ,hard[0],incoming,false,true); SpinorBarWaveFunction(ain ,hard[1],incoming,false,true); - SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true); - SpinorWaveFunction( aout,hard[3],outgoing,true ,true); - // calculate the matrix element double me; - ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me); + ProductionMatrixElement prodme; + if(hard[2]->id()!=ParticleID::g) { + vector aout; + vector fout; + SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true); + SpinorWaveFunction( aout,hard[3],outgoing,true ,true); + // calculate the matrix element + prodme=HelicityME(fin,ain,fout,aout,me); + } + else { + vector g1,g2; + VectorWaveFunction(g1,hard[2],outgoing,true,true); + VectorWaveFunction(g2,hard[3],outgoing,true,true); + prodme=ggME(fin,ain,g1,g2,me); + } // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(prodme); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) { (hard[ix]->spinInfo())->productionVertex(hardvertex); } } -void MEee2Higgs2SM::rebind(const TranslationMap & trans) - { +void MEee2Higgs2SM::rebind(const TranslationMap & trans) { // dummy = trans.translate(dummy); - _theFFHVertex = trans.translate(_theFFHVertex); - _h0 = trans.translate(_h0); + FFHVertex_ = trans.translate(FFHVertex_); + HGGVertex_ = trans.translate(HGGVertex_); + h0_ = trans.translate(h0_); ME2to2Base::rebind(trans); } IVector MEee2Higgs2SM::getReferences() { IVector ret = ME2to2Base::getReferences(); - ret.push_back(_theFFHVertex); - ret.push_back(_h0); + ret.push_back(FFHVertex_); + ret.push_back(HGGVertex_); + ret.push_back(h0_); return ret; } +// the helicity amplitude matrix element +ProductionMatrixElement MEee2Higgs2SM::ggME(vector fin, + vector ain, + vector g1, + vector g2, + double & aver) const { + ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half, + PDT::Spin1,PDT::Spin1); + // wavefunctions for the intermediate particles + ScalarWaveFunction interh; + // temporary storage of the different diagrams + Complex diag; + aver=0.; + // sum over helicities to get the matrix element + unsigned int inhel1,inhel2,outhel1,outhel2; + for(inhel1=0;inhel1<2;++inhel1) { + for(inhel2=0;inhel2<2;++inhel2) { + interh = FFHVertex_->evaluate(sHat(),1,h0_,fin[inhel1],ain[inhel2]); + for(outhel1=0;outhel1<2;++outhel1) { + for(outhel2=0;outhel2<2;++outhel2) { + diag = HGGVertex_->evaluate(sHat(),g1[outhel2],g2[outhel1],interh); + output(inhel1,inhel2,outhel1,outhel2)=diag; + aver +=real(diag*conj(diag)); + } + } + } + } + return output; +} diff --git a/Contrib/LeptonME/MEee2Higgs2SM.h b/Contrib/LeptonME/MEee2Higgs2SM.h --- a/Contrib/LeptonME/MEee2Higgs2SM.h +++ b/Contrib/LeptonME/MEee2Higgs2SM.h @@ -1,259 +1,277 @@ // -*- C++ -*- // // MEee2Higgs2SM.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_MEee2Higgs2SM_H #define HERWIG_MEee2Higgs2SM_H // // This is the declaration of the MEee2Higgs2SM class. // #include "ThePEG/MatrixElement/ME2to2Base.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" namespace Herwig { using namespace ThePEG; /** * The MEee2Higgs2SM class implements the production of an \f$s\f$-channel * Higgs in \f$e^+e^-\f$ collisions in order to allow easy tests of Higgs * decays. It should not be used for physics studies. * * @see \ref MEee2Higgs2SMInterfaces "The interfaces" * defined for MEee2Higgs2SM. */ class MEee2Higgs2SM: public ME2to2Base { public: /** * The default constructor. */ - inline MEee2Higgs2SM() : _allowed(0) {} + inline MEee2Higgs2SM() : allowed_(0) {} /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EW}\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; /** * set up the spin correlations */ virtual void constructVertex(tSubProPtr sub); //@} 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: /** @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(); /** * Rebind pointer to other Interfaced objects. Called in the setup phase * after all objects used in an EventGenerator has been cloned so that * the pointers will refer to the cloned objects afterwards. * @param trans a TranslationMap relating the original objects to * their respective clones. * @throws RebindException if no cloned object was found for a given * pointer. */ virtual void rebind(const TranslationMap & trans) ; /** * Return a vector of all pointers to Interfaced objects used in this * object. * @return a vector of pointers. */ virtual IVector getReferences(); //@} private: /** * The matrix element * @param fin The incoming spinor wavefunction * @param ain The incoming spinorbar wavefunction * @param fout The outgoing spinor bar wavefunction * @param aout The outgoing spinor wavefunction * @param me The spin averaged matrix element */ ProductionMatrixElement HelicityME(vector fin, vector ain, vector fout, vector aout,double& me) const; + /** + * \f$H\to gg\f$ matrix element + * @param fin The incoming spinor wavefunction + * @param ain The incoming spinorbar wavefunction + * @param g1 Outgoing gluon wavefunction + * @param g2 Outgoing gluon wavefunction + * @param me The spin averaged matrix element + */ + ProductionMatrixElement ggME(vector fin, + vector ain, + vector g1, + vector g2, + double & me) const; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initMEee2Higgs2SM; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEee2Higgs2SM & operator=(const MEee2Higgs2SM &); private: /** - * Pointer to the Higgs vertex + * Pointer to the Higgs fermion-antifermion vertex */ - AbstractFFSVertexPtr _theFFHVertex; + AbstractFFSVertexPtr FFHVertex_; + + /** + * Pointer to Higgs-gluon-gluon vertex + */ + AbstractVVSVertexPtr HGGVertex_; /** * Allowed outgoing particles */ - int _allowed; + int allowed_; /** * Pointer to the Higgs ParticleData object */ - PDPtr _h0; + PDPtr h0_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEee2Higgs2SM. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MEee2Higgs2SM. */ typedef ME2to2Base NthBase; }; /** This template specialization informs ThePEG about the name of * the MEee2Higgs2SM 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::MEee2Higgs2SM"; } /** * The name of a file containing the dynamic library where the class * MEee2Higgs2SM is implemented. It may also include several, space-separated, * libraries if the class MEee2Higgs2SM 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 "LeptonME.so"; } }; /** @endcond */ } #endif /* HERWIG_MEee2Higgs2SM_H */ diff --git a/Contrib/LeptonME/Makefile.in b/Contrib/LeptonME/Makefile.in --- a/Contrib/LeptonME/Makefile.in +++ b/Contrib/LeptonME/Makefile.in @@ -1,36 +1,36 @@ # -*- Makefile -*- (for emacs) # # This Makefile is intended for compiling Herwig++ plugins # You can find plugins here: INSERT URL # # This Makefile received very little testing, # any bug reports are very welcome! # # location of include files THEPEGINCLUDE= HERWIGINCLUDE= GSLINCLUDE= LDFLAGS = SHARED_FLAG = INCLUDE = $(THEPEGINCLUDE) $(HERWIGINCLUDE) $(GSLINCLUDE) # # C++ flags # CXX = CXXFLAGS = ALLCCFILES=$(shell echo *.cc) default : LeptonME.so %.o : %.cc %.h $(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) -c -shared $< -o $@ LeptonME.so: MEee2Higgs2SM.o MEee2Z.o $(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) \ - MEee2Higgs2SM.o MEee2VectorMeson.o MEee2Z.o $(SHARED_FLAG) $(LDFLAGS) -o LeptonME.so + MEee2Higgs2SM.o MEee2Z.o $(SHARED_FLAG) $(LDFLAGS) -o LeptonME.so clean: rm -f $(ALLCCFILES:.cc=.o) LeptonME.so diff --git a/Contrib/MCPWNLO/EPEM/LEPAnalysis/MyEventShapes.cc b/Contrib/MCPWNLO/EPEM/LEPAnalysis/MyEventShapes.cc --- a/Contrib/MCPWNLO/EPEM/LEPAnalysis/MyEventShapes.cc +++ b/Contrib/MCPWNLO/EPEM/LEPAnalysis/MyEventShapes.cc @@ -1,405 +1,405 @@ // -*- C++ -*- // // MyEventShapes.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 MyEventShapes class. // #include "MyEventShapes.h" #include "ThePEG/Interface/ClassDocumentation.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "MyEventShapes.tcc" #endif #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; //MyEventShapes::~MyEventShapes() {} //void MyEventShapes::persistentOutput(PersistentOStream &) const { // *** ATTENTION *** os << ; // Add all member variable which should be written persistently here. //} //void MyEventShapes::persistentInput(PersistentIStream &, int) { // *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here. //} NoPIOClassDescription MyEventShapes::initMyEventShapes; // Definition of the static class description member. void MyEventShapes::Init() { static ClassDocumentation documentation ("There is no documentation for the MyEventShapes class"); } // void MyEventShapes::calcHemisphereMasses() { // Lorentz5Momentum pos, neg; // Energy pden(ZERO),epos(ZERO),eneg(ZERO); // for(unsigned int ix=0;ix<_pv.size();++ix) // { // if(_pv[ix].vect() * thrustAxis() > ZERO) // { // pos += _pv[ix]; // epos += _pv[ix].perp(thrustAxis()); // } // else // { // neg += _pv[ix]; // eneg += _pv[ix].perp(thrustAxis()); // } // pden += _pv[ix].vect().mag(); // } // // denominator and masses // Energy2 den(sqr(pos.e()+neg.e())); // _mPlus = pos.m2()/den; // _mMinus = neg.m2()/den; // if (_mPlus < _mMinus) swap(_mPlus, _mMinus); // // jet broadening // _bPlus = 0.5*epos/pden; // _bMinus = 0.5*eneg/pden; // if (_bPlus < _bMinus) swap(_bPlus, _bMinus); // } vector MyEventShapes::eigenvalues(const double T[3][3]) { // b, c, d are the coefficients of the characteristic polynomial, // a lambda^3 + b lambda^2 + c lambda + d // where a is chosen to be +1. double t11, t12, t13, t22, t23, t33; t11 = T[0][0]; t12 = T[0][1]; t13 = T[0][2]; t22 = T[1][1]; t23 = T[1][2]; t33 = T[2][2]; double b = -(t11 + t22 + t33); double c = t11*t22 + t11*t33 + t22*t33 - sqr(t12) - sqr(t13) - sqr(t23); double d = - t11*t22*t33 - 2.*t12*t23*t13 + t11*sqr(t23) + t22*sqr(t13) + t33*sqr(t12); // use Cardano's formula to compute the zeros double p = (3.*c - sqr(b))/3.; double q = (2.*sqr(b)*b - 9.*b*c + 27.*d)/27.; // check diskriminant vector lambda; if (4.*p*sqr(p) + 27.*sqr(q) > 0) { for (unsigned int i=0; i<3; i++) { lambda.push_back(-1.); } cerr << "MyEventShapes::eigenvalues: found D > 0! \n" << "Matrix doesn't have real Eigenvalues in this case\n"; } else { // get solutions double alpha = acos(-q/2.*sqrt(-27./(p*p*p)))/3.; double w = sqrt(-4.*p/3.); lambda.push_back(w*cos(alpha) - b/3.); lambda.push_back(-w*cos(alpha+M_PI/3.) - b/3.); lambda.push_back(-w*cos(alpha-M_PI/3.) - b/3.); } // sort according to size of eigenvalues // such that lambda[0] > lambda[1] > lambda[2] if (lambda[0] < lambda[1]) { swap(lambda[0], lambda[1]); } if (lambda[0] < lambda[2]) { swap(lambda[0], lambda[2]); } if (lambda[1] < lambda[2]) { swap(lambda[1], lambda[2]); } return lambda; } -Axis MyEventShapes::eigenvector(const double T[3][3], const double &lam) { +Axis MyEventShapes::eigenvector(const double T[3][3], double lam) { // set up matrix of system to be solved double a11, a12, a13, a23, a33; a11 = T[0][0] - lam; a12 = T[0][1]; a13 = T[0][2]; a23 = T[1][2]; a33 = T[2][2] - lam; // intermediate steps from gauss type algorithm double b1, b2, b4; b1 = a11*a33 - sqr(a13); b2 = a12*a33 - a13*a23; b4 = a11*a23 - a12*a13; // eigenvector Axis u(b2, -b1, b4); return u.unit(); } vector MyEventShapes:: eigenvectors(const double T[3][3], const vector &lam) { vector n; for (unsigned int i=0; i<3; i++) { n.push_back(eigenvector(T, lam[i])); } return n; } void MyEventShapes::diagonalizeTensors(bool linear, bool cmboost) { // initialize double Theta[3][3]; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { Theta[i][j] = 0.0; } } double sum = 0.; Momentum3 sumvec; vector lam; vector n; // get cm-frame Lorentz5Momentum pcm = Lorentz5Momentum(); Boost beta; if (cmboost) { for(unsigned int ix=0;ix<_pv.size();++ix) { pcm += _pv[ix]; } beta = pcm.findBoostToCM(); } // get Theta_ij for(unsigned int ix=0;ix<_pv.size();++ix) { Lorentz5Momentum dum(_pv[ix]); if (cmboost) { dum.boost( beta ); } Momentum3 pvec = dum.vect(); double pvec_MeV[3] = {pvec.x()/MeV, pvec.y()/MeV, pvec.z()/MeV}; if (pvec.mag() > ZERO) { sumvec += pvec; if (linear) { sum += pvec.mag()*UnitRemoval::InvE; } else { sum += pvec.mag2()*UnitRemoval::InvE2; } for(int i=0; i<3; i++) { for(int j=i; j<3; j++) { if (linear) { Theta[i][j] += (pvec_MeV[i])*(pvec_MeV[j])*MeV/(pvec.mag()); } else { Theta[i][j] += (pvec_MeV[i])*(pvec_MeV[j]); } } } } } for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { Theta[i][j] /= sum; } } // diagonalize it lam = eigenvalues(Theta); n = eigenvectors(Theta, lam); if (linear) { _linTen = lam; _linTenAxis = n; } else { _spher = lam; _spherAxis = n; } } void MyEventShapes::calculateThrust() { // explicitly calculate in units of MeV // algorithm based on Brandt/Dahmen Z Phys C1 (1978) // and 'tasso' code from HERWIG // assumes all momenta in cm system, no explicit boost performed here! // unlike for C and D _thrust.clear(); _thrustAxis.clear(); if (_pv.size() < 2) { for (int i=0; i<3; i++) { _thrust.push_back(-1); _thrustAxis.push_back(Axis()); } return; } // thrust vector p; Energy psum = ZERO; for(unsigned int l=0; l<_pv.size(); l++) { p.push_back(_pv[l].vect()); psum += p.back().mag(); } Axis axis; if (p.size() == 2) { _thrust.push_back(1.0); _thrust.push_back(0.0); _thrust.push_back(0.0); axis = p[0].unit(); if (axis.z() < 0) axis = -axis; _thrustAxis.push_back(axis); _thrustAxis.push_back(axis.orthogonal()); axis = _thrustAxis[0].cross(_thrustAxis[1]); return; } if (p.size() == 3) { if (p[0].mag2() < p[1].mag2()) swap(p[0], p[1]); if (p[0].mag2() < p[2].mag2()) swap(p[0], p[2]); if (p[1].mag2() < p[2].mag2()) swap(p[1], p[2]); // thrust axis = p[0].unit(); if (axis.z() < 0) axis = -axis; _thrust.push_back(2.*p[0].mag()/psum); _thrustAxis.push_back(axis); // major axis = (p[1] - (axis*p[1])*axis).unit(); if (axis.x() < 0) axis = -axis; _thrust.push_back((abs(p[1]*axis) + abs(p[2]*axis))/psum); _thrustAxis.push_back(axis); // minor _thrust.push_back(0.0); axis = _thrustAxis[0].cross(_thrustAxis[1]); _thrustAxis.push_back(axis); return; } // ACHTUNG special case with >= 4 coplanar particles will still fail. // probably not too important... Energy2 val; calcT(p, val, axis); _thrust.push_back(sqrt(val)/psum); if (axis.z() < 0) axis = -axis; _thrustAxis.push_back(axis.unit()); //major Momentum3 par; for (unsigned int l=0; l<_pv.size(); l++) { par = (p[l]*axis.unit())*axis.unit(); p[l] = p[l] - par; } calcM(p, val, axis); _thrust.push_back(sqrt(val)/psum); if (axis.x() < 0) axis = -axis; _thrustAxis.push_back(axis.unit()); // minor if (_thrustAxis[0]*_thrustAxis[1] < 1e-10) { Energy eval = ZERO; axis = _thrustAxis[0].cross(_thrustAxis[1]); _thrustAxis.push_back(axis); for (unsigned int l=0; l<_pv.size(); l++) eval += abs(axis*_pv[l].vect()); _thrust.push_back(eval/psum); } else { _thrust.push_back(-1.0); _thrustAxis.push_back(Axis()); } } void MyEventShapes::calcT(const vector &p, Energy2 &t, Axis &taxis) { Energy2 tval; t = ZERO; ThreeVector tv; Momentum3 ptot; vector cpm; for (unsigned int k=1; k < p.size(); k++) { for (unsigned int j=0; j ZERO) { ptot += p[l]; } else { ptot -= p[l]; } } } cpm.clear(); cpm.push_back(ptot-p[j]-p[k]); cpm.push_back(ptot-p[j]+p[k]); cpm.push_back(ptot+p[j]-p[k]); cpm.push_back(ptot+p[j]+p[k]); for (vector::iterator it = cpm.begin(); it != cpm.end(); it++) { tval = it->mag2(); if (tval > t) { t = tval; taxis = it->unit(); } } } } } void MyEventShapes::calcM(const vector &p, Energy2 &m, Axis &maxis) { Energy2 mval; m = ZERO; Momentum3 tv, ptot; vector cpm; for (unsigned int j=0; j < p.size(); j++) { tv = p[j]; ptot = Momentum3(); for (unsigned int l=0; l ZERO) { ptot += p[l]; } else { ptot -= p[l]; } } } cpm.clear(); cpm.push_back(ptot-p[j]); cpm.push_back(ptot+p[j]); for (vector::iterator it = cpm.begin(); it != cpm.end(); it++) { mval = it->mag2(); if (mval > m) { m = mval; maxis = it->unit(); } } } } void MyEventShapes::bookEEC(vector & hi) { // hi is the histogram. It is understood that hi.front() contains // the bin [-1 < cos(chi) < -1+delta] and hi.back() the bin [1-delta // < cos(chi) < 1]. Here, delta = 2/hi.size(). Energy Evis(ZERO); for (unsigned int bin = 0; bin < hi.size(); bin++) { double delta = 2./hi.size(); double coschi = -1+bin*delta; if (_pv.size() > 1) { for (unsigned int i = 0; i < _pv.size()-1; i++) { Evis += _pv[i].e(); for (unsigned int j = i+1; j < _pv.size(); j++) { double diff = abs(coschi-cos( _pv[i].vect().angle(_pv[j].vect()) )); if (delta > diff) hi[bin] += _pv[i].e()*_pv[j].e() * UnitRemoval::InvE2; } } } hi[bin] /= (Evis*Evis) * UnitRemoval::InvE2; } } diff --git a/Contrib/MCPWNLO/EPEM/LEPAnalysis/MyEventShapes.h b/Contrib/MCPWNLO/EPEM/LEPAnalysis/MyEventShapes.h --- a/Contrib/MCPWNLO/EPEM/LEPAnalysis/MyEventShapes.h +++ b/Contrib/MCPWNLO/EPEM/LEPAnalysis/MyEventShapes.h @@ -1,582 +1,582 @@ // -*- C++ -*- // // MyEventShapes.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_MyEventShapes_H #define HERWIG_MyEventShapes_H // // This is the declaration of the MyEventShapes class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Handlers/AnalysisHandler.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Vectors/ThreeVector.h" #include "ThePEG/EventRecord/Particle.h" #include "MyEventShapes.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Analysis * * The MyEventShapes class is designed so that certain event shapes, * such as the thrust are only calculated once per event given the * speed of the calculation. * * @see \ref MyEventShapesInterfaces "The interfaces" * defined for MyEventShapes. */ class MyEventShapes: public Interfaced { //public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ // inline MyEventShapes(); /** * The copy constructor. */ // inline MyEventShapes(const MyEventShapes &); /** * The destructor. */ // virtual ~MyEventShapes(); //@} public: /** * Member to reset the particles to be considered */ inline void reset(const tPVector &part); public: /** * Member functions to return thrust related shapes */ //@{ /** * The thrust */ inline double thrust(); /** * The major */ inline double thrustMajor(); /** * The minor */ inline double thrustMinor(); /** * The oblateness */ inline double oblateness(); /** * The thrust axis */ inline Axis thrustAxis(); /** * The major axis */ inline Axis majorAxis(); /** * The minor axis */ inline Axis minorAxis(); //@} /** * Linear momentum tensor related event shapes */ //@{ /** * The C parameter */ inline double CParameter(); /** * The D parameter */ inline double DParameter(); /** * The eigenvalues in descending order */ inline vector linTenEigenValues(); /** * The eigenvectors in order of descending eigenvalue */ inline vector linTenEigenVectors(); //@} /** * Quadratic momentum tensor related variables */ //@{ /** * The sphericity */ inline double sphericity(); /** * The aplanarity */ inline double aplanarity(); /** * The planarity */ inline double planarity(); /** * The sphericity axis */ inline Axis sphericityAxis(); /** * The sphericity eigenvalues */ inline vector sphericityEigenValues(); /** * The sphericity eigenvectors */ inline vector sphericityEigenVectors(); //@} /** * Jet mass related event shapes */ //@{ /** * The high hemishpere mass squared divided by the visible energy squared */ inline double Mhigh2(); /** * The low hemishpere mass squared divided by the visible energy squared */ inline double Mlow2(); /** * The difference between the * hemishpere masses squared divided by the visible energy squared */ inline double Mdiff2(); //@} /** * Jet broadening related event shapes */ //@{ /** * The wide jet broadening */ inline double Bmax(); /** * The narrow jet broadening */ inline double Bmin(); /** * The sum of the jet broadenings */ inline double Bsum(); /** * The difference of the jet broadenings */ inline double Bdiff(); //@} /** * The scaled momentum \f$\xi=-\log\left( p/E_{\rm beam}\right)\f$. */ inline double getXi(const Lorentz5Momentum & p, const Energy & Ebeam); /** * Transverse momentum with respect to the beam */ inline Energy getPt(const Lorentz5Momentum & p); /** * Rapidity with respect to the beam direction */ inline double getRapidity(const Lorentz5Momentum & p); //@} /** * Single particle variables related to one of the shape axis. */ //@{ /** * Transverse momentum with respect to the thrust axis in the event plane */ inline Energy ptInT(const Lorentz5Momentum & p); /** * Transverse momentum with respect to the thrust axis out of the event plane */ inline Energy ptOutT(const Lorentz5Momentum & p); /** * Rapidity with respect to the thrust axis */ inline double yT(const Lorentz5Momentum & p); /** * Transverse momentum with respect to the sphericity axis in the event plane */ inline Energy ptInS(const Lorentz5Momentum & p); /** * Transverse momentum with respect to the sphericity axis out of the event plane */ inline Energy ptOutS(const Lorentz5Momentum & p); /** * Rapidity with respect to the sphericity axis */ inline double yS(const Lorentz5Momentum & p); //@} /** * Energy-energy correlation (EEC) * @param hi is the histogram and has to be provided externally * It is understood that * the range of the histogam is -1 < cos(chi) < 1. * hi.front() contains the bin [-1 < cos(chi) < -1+delta] and * hi.back() the bin [1-delta < cos(chi) < 1]. delta = * 2/hi.size(). We use classical indices to access the vector. */ void bookEEC(vector & hi); /** * Before writing the histogram it has to be normalized according to the * number of events. */ inline void normalizeEEC(vector & hi, long evts); /** * The asymmetry of EEC is calculated from a given \f$\cos\chi\f$ and EEC * histogram, which is a vector as described above. */ inline double AEEC(vector & hi, double& coschi); 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);} //@} private: /** * Check whether the initialization of a certain class of event shapes * has been calculated and if not do so */ //@{ /** * Check if thrust related variables have been calculated and if not do so */ inline void checkThrust(); /** * Check if the linear tensor related variables have been calculated and if not do so */ inline void checkLinTen(); /** * Check if the quadratic tensor related variables have been calculated and if not do so */ inline void checkSphericity(); /** * Check if the hemisphere mass variables and jet broadenings * have been calculated and if not do so */ inline void checkHemispheres(); //@} /** * Methods that actually calculate the event shapes */ //@{ /** * Calculate the hemisphere masses and jet broadenings */ inline void calcHemisphereMasses(); /** * Calculate the thrust and related axes */ void calculateThrust(); /** * Diagonalize the tensors * @param linear switch between diagonalization of linear/quadratic tensor. * @param cmboost tells whether to boost into cm frame of all * momenta first, or not (default off, and no interface to this). */ void diagonalizeTensors(bool linear, bool cmboost); /** * Quite general diagonalization of a symmetric Matrix T, given as * an array of doubles. The symmetry is not checked explicitly as * this is clear in the context. It uses an explicit generic * solution of the eigenvalue problem and no numerical * approximation, based on Cardano's formula. * @param T Matrix to be diagonalised */ vector eigenvalues(const double T[3][3]); /** * The eigenvector of @param T to a given eigenvalue @param lam */ - Axis eigenvector(const double T[3][3], const double &lam); + Axis eigenvector(const double T[3][3], double lam); /** * The eigenvectors of @param T corresponding to the eigenvectors * @param lam . The ordering of the vectors corresponds to the * ordering of the eigenvalues. */ vector eigenvectors(const double T[3][3], const vector &lam); /** * Member to calculate the thrust * @param p The three vectors * @param t The thrust-squared (up to an Energy scale factor) * @param taxis The thrust axis */ void calcT(const vector &p, Energy2 &t, Axis &taxis); /** * Member to calculate the major * @param p The three vectors * @param m The major-squared (up to an Energy scale factor) * @param maxis The major axis */ void calcM(const vector &p, Energy2 &m, Axis &maxis); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static NoPIOClassDescription initMyEventShapes; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MyEventShapes & operator=(const MyEventShapes &); private: /** * Vector of particle momenta to be analysed */ vector _pv; /** * Various event shape axes */ //@{ /** * The thrust related axes */ vector _thrustAxis; /** * The sphericity related axes */ vector _spherAxis; /** * The linearised tensor axes */ vector _linTenAxis; //@} /** * Values of axis related event shapes */ //@{ /** * Values of thrust related variables */ vector _thrust; /** * Values of sphericity related variables */ vector _spher; /** * Values of linearized tensor related variables */ vector _linTen; //@} /** * Whether or not certain event axes have been calculated */ //@{ /** * Whether or not the thrust is calculated */ bool _thrustDone; /** * Whether or not the sphericity is calculated */ bool _spherDone; /** * Whether or not the linearizes tensor is calculated */ bool _linTenDone; /** * Whether or not the hemisphere masses have been calculated */ bool _hemDone; //@} /** * Whether ot not to boost to the CMS frame for the tensor diagonalizations */ bool _useCmBoost; /** * Hemisphere masses */ //@{ /** * The high hemisphere mass */ double _mPlus; /** * The low hemisphere mass */ double _mMinus; //@} /** * The jet broadenings */ //@{ /** * The wide jet broadening */ double _bPlus; /** * The narrow jet broadening */ double _bMinus; //@} }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MyEventShapes. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MyEventShapes. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the MyEventShapes 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::MyEventShapes"; } /** Return the name(s) of the shared library (or libraries) be loaded to get * access to the MyEventShapes class and any other class on which it depends * (except the base class). */ static string library() { return "MyEventShapes.so"; } // static string library() { return "HwAnalysis.so"; } }; /** @endcond */ } #include "MyEventShapes.icc" #ifndef ThePEG_TEMPLATES_IN_CC_FILE // #include "MyEventShapes.tcc" #endif #endif /* HERWIG_MyEventShapes_H */ diff --git a/Contrib/MCPWNLO/PWInstallFiles/Evolver.cc b/Contrib/MCPWNLO/PWInstallFiles/Evolver.cc --- a/Contrib/MCPWNLO/PWInstallFiles/Evolver.cc +++ b/Contrib/MCPWNLO/PWInstallFiles/Evolver.cc @@ -1,845 +1,845 @@ // -*- C++ -*- // // Evolver.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 Evolver class. // #include "Evolver.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ShowerKinematics.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Utilities/Throw.h" #include "ShowerTree.h" #include "ShowerProgenitor.h" #include "KinematicsReconstructor.h" #include "PartnerFinder.h" #include "MECorrectionBase.h" #include "ThePEG/Handlers/XComb.h" using namespace Herwig; IBPtr Evolver::clone() const { return new_ptr(*this); } IBPtr Evolver::fullclone() const { return new_ptr(*this); } void Evolver::persistentOutput(PersistentOStream & os) const { os << _model << _splittingGenerator << _maxtry << _meCorrMode << _hardVetoMode << _hardVetoRead << _PHtopveto << _limitEmissions << ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV) << _vetoes ; } void Evolver::persistentInput(PersistentIStream & is, int) { is >> _model >> _splittingGenerator >> _maxtry >> _meCorrMode >> _hardVetoMode >> _hardVetoRead >> _PHtopveto >> _limitEmissions >> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV) >> _vetoes ; } void Evolver::doinitrun() { Interfaced::doinitrun(); for(unsigned int ix=0;ixmeCorrections().size();++ix) { showerModel()->meCorrections()[ix]->evolver(this); } } ClassDescription Evolver::initEvolver; // Definition of the static class description member. void Evolver::Init() { static ClassDocumentation documentation ("This class is responsible for carrying out the showering,", "including the kinematics reconstruction, in a given scale range."); static Reference interfaceSplitGen("SplittingGenerator", "A reference to the SplittingGenerator object", &Herwig::Evolver::_splittingGenerator, false, false, true, false); static Reference interfaceShowerModel ("ShowerModel", "The pointer to the object which defines the shower evolution model.", &Evolver::_model, false, false, true, false, false); static Parameter interfaceMaxTry ("MaxTry", "The maximum number of attempts to generate the shower from a" " particular ShowerTree", &Evolver::_maxtry, 100, 1, 1000, false, false, Interface::limited); static Switch ifaceMECorrMode ("MECorrMode", "Choice of the ME Correction Mode", &Evolver::_meCorrMode, 1, false, false); static SwitchOption off (ifaceMECorrMode,"No","MECorrections off", 0); static SwitchOption on (ifaceMECorrMode,"Yes","hard+soft on", 1); static SwitchOption hard (ifaceMECorrMode,"Hard","only hard on", 2); static SwitchOption soft (ifaceMECorrMode,"Soft","only soft on", 3); static Switch ifaceHardVetoMode ("HardVetoMode", "Choice of the Hard Veto Mode", &Evolver::_hardVetoMode, 0, false, false); static SwitchOption HVoff (ifaceHardVetoMode,"No","hard vetos off", 0); static SwitchOption HVon (ifaceHardVetoMode,"Yes","hard vetos on", 1); static SwitchOption HVIS (ifaceHardVetoMode,"Initial", "only IS emissions vetoed", 2); static SwitchOption HVFS (ifaceHardVetoMode,"Final","only FS emissions vetoed", 3); static Switch ifacePHtopveto ("POWHEGTOPVeto", "Choice of the PHtopVeto", &Evolver::_PHtopveto, 0, false, false); static SwitchOption PHtopvetoOff (ifacePHtopveto,"No","TopVeto off", 0); static SwitchOption PHtopvetoOn (ifacePHtopveto,"Yes","Both top prod+ decay vetoes on", 1); static SwitchOption prodveto (ifacePHtopveto,"Prod","Only top production veto on", 2); static SwitchOption decayveto (ifacePHtopveto,"Decay","Only top decay veto on", 3); static Switch ifaceHardVetoRead ("HardVetoScaleSource", "If hard veto scale is to be read", &Evolver::_hardVetoRead, 0, false, false); static SwitchOption HVRcalc (ifaceHardVetoRead,"Calculate","Calculate from hard process", 0); static SwitchOption HVRread (ifaceHardVetoRead,"Read","Read from XComb->lastScale", 1); static Parameter ifaceiptrms ("IntrinsicPtGaussian", "RMS of intrinsic pT of Gaussian distribution:\n" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &Evolver::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV, false, false, Interface::limited); static Parameter ifacebeta ("IntrinsicPtBeta", "Proportion of inverse quadratic distribution in generating intrinsic pT.\n" "(1-Beta) is the proportion of Gaussian distribution", &Evolver::_beta, 0, 0, 1, false, false, Interface::limited); static Parameter ifacegamma ("IntrinsicPtGamma", "Parameter for inverse quadratic:\n" "2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))", &Evolver::_gamma,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static Parameter ifaceiptmax ("IntrinsicPtIptmax", "Upper bound on intrinsic pT for inverse quadratic", &Evolver::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static RefVector ifaceVetoes ("Vetoes", "The vetoes to be checked during showering", &Evolver::_vetoes, -1, false,false,true,true,false); static Switch interfaceLimitEmissions ("LimitEmissions", "Limit the number and type of emissions for testing", &Evolver::_limitEmissions, 0, false, false); static SwitchOption interfaceLimitEmissionsNoLimit (interfaceLimitEmissions, "NoLimit", "Allow an arbitrary number of emissions", 0); static SwitchOption interfaceLimitEmissionsOneInitialStateEmission (interfaceLimitEmissions, "OneInitialStateEmission", "Allow one emission in the initial state and none in the final state", 1); static SwitchOption interfaceLimitEmissionsOneFinalStateEmission (interfaceLimitEmissions, "OneFinalStateEmission", "Allow one emission in the final state and none in the initial state", 2); } void Evolver::generateIntrinsicpT(vector particlesToShower) { _intrinsic.clear(); if ( !ipTon() || !isISRadiationON() ) return; // don't do anything for the moment for secondary scatters if( !ShowerHandler::currentHandler()->firstInteraction() ) return; // generate intrinsic pT for(unsigned int ix=0;ixprogenitor()->isFinalState()) continue; if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue; Energy ipt; if(UseRandom::rnd() > _beta) { ipt=_iptrms*sqrt(-log(UseRandom::rnd())); } else { ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.); } pair pt = make_pair(ipt,UseRandom::rnd(Constants::twopi)); _intrinsic[particlesToShower[ix]] = pt; } } void Evolver::setupMaximumScales(ShowerTreePtr hard, vector p) { // find out if hard partonic subprocess. bool isPartonic(false); map::const_iterator cit = _currenttree->incomingLines().begin(); Lorentz5Momentum pcm; for(; cit!=hard->incomingLines().end(); ++cit) { pcm += cit->first->progenitor()->momentum(); isPartonic |= cit->first->progenitor()->coloured(); } // find maximum pt from hard process, the maximum pt from all outgoing // coloured lines (this is simpler and more general than // 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will // be transverse mass. Energy ptmax = -1.0*GeV, pt = ZERO, mass = ZERO, ptest = ZERO; if (!PHtopveto()) { // general case calculate the scale if (!hardVetoXComb()) { // scattering process if(hard->isHard()) { // coloured incoming particles if (isPartonic) { map::const_iterator cjt = hard->outgoingLines().begin(); for(; cjt!=hard->outgoingLines().end(); ++cjt) { if (cjt->first->progenitor()->coloured()) ptmax = max(ptmax,cjt->first->progenitor()->momentum().mt()); } } if (ptmax < ZERO) ptmax = pcm.m(); } // decay, incoming() is the decaying particle. else { ptmax = hard->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } // hepeup.SCALUP is written into the lastXComb by the // LesHouchesReader itself - use this by user's choice. // Can be more general than this. else { ptmax = sqrt( ShowerHandler::currentHandler() ->lastXCombPtr()->lastScale() ); } } // ********************************************************************************* if (PHtopveto()) { map::const_iterator cjt, ctt, cbt, cet; ctt = hard->outgoingLines().begin(); //store t and tbar mmt double tmmt[5],pp; for(; ctt!=hard->outgoingLines().end(); ++ctt) { tmmt[3]+=ctt->first->progenitor()->momentum().z(); tmmt[2]+=ctt->first->progenitor()->momentum().y(); tmmt[1]+=ctt->first->progenitor()->momentum().x(); tmmt[4]+=ctt->first->progenitor()->momentum().e(); } cet = hard->outgoingLines().begin(); double Wmmt[5]; // W boson momenta for(; cet!=hard->outgoingLines().end(); ++cet) { if(fabs(cet->first->progenitor()->id())==11 ||fabs(cet->first->progenitor()->id())==12 ){ Wmmt[3]+=cet->first->progenitor()->momentum().z(); Wmmt[2]+=cet->first->progenitor()->momentum().y(); Wmmt[1]+=cet->first->progenitor()->momentum().x(); Wmmt[4]+=cet->first->progenitor()->momentum().e(); }} Wmmt[0]=sqrt(pow(Wmmt[4],2)-(pow(Wmmt[3],2)+pow(Wmmt[2],2)+pow(Wmmt[1],2))); cjt = hard->outgoingLines().begin(); for(; cjt!=hard->outgoingLines().end(); ++cjt) { if (cjt->first->progenitor()->coloured()) { if (cjt->first->progenitor()->id()==21){ pt = cjt->first->progenitor()->momentum().perp(); mass = cjt->first->progenitor()->momentum().m(); ptest = sqrt(pt*pt); if (prodveto()){ if (ptest > ptmax) { ptmax = ptest; } } }} } cbt = hard->outgoingLines().begin(); for(; cbt!=hard->outgoingLines().end(); ++cbt) { if (cbt->first->progenitor()->coloured()) { if (fabs(cbt->first->progenitor()->id())==5){ //if decay there must be a b quark: use that instead pp= sqrt(pow(tmmt[3],2)+pow(tmmt[2],2)+pow(tmmt[1],2)); tmmt[0] = sqrt(pow(tmmt[4],2)-pow(pp,2)); double v = pp/tmmt[4]; double bmmt[5]; // bottom momenta bmmt[3]=cbt->first->progenitor()->momentum().z(); bmmt[2]=cbt->first->progenitor()->momentum().y(); bmmt[1]=cbt->first->progenitor()->momentum().x(); bmmt[4]=sqrt(pow(bmmt[3],2)+pow(bmmt[2],2)+pow(bmmt[1],2)); //Transform to top rest frame bmmt[3] = (bmmt[3]*tmmt[3]+bmmt[2]*tmmt[2]+bmmt[1]*tmmt[1])/pp; bmmt[4]=1./sqrt(1.-pow(v,2))*(bmmt[4]-v*bmmt[3]); Wmmt[3]=(Wmmt[3]*tmmt[3]+Wmmt[1]*tmmt[1]+Wmmt[2]*tmmt[2])/pp; Wmmt[4]=1./sqrt(1.-pow(v,2))*(Wmmt[4]-v*Wmmt[3]); double x1 = 2.*Wmmt[4]/tmmt[0]; double a =pow(Wmmt[0]/tmmt[0],2); if (x1-a > 1.) {x1=1.+a-0.00001;} double x3 = 2.-x1-2.*bmmt[4]/tmmt[0]; pt =sqrt(pow(tmmt[0],2)*(1.-x1+a)*(x1-a+x3*(2.-x1)-pow(x3,2)-1.)/(pow(x1,2)-4.*a)); if (decayveto()) { ptmax = pt;} }} } } // ********************************************************************************* // set maxHardPt for all progenitors. For partonic processes this // is now the max pt in the FS, for non-partonic processes or // processes with no coloured FS the invariant mass of the IS vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax); } void Evolver::showerHardProcess(ShowerTreePtr hard) { // set the current tree currentTree(hard); // zero number of emissions _nis = _nfs = 0; // extract particles to shower vector particlesToShower=setupShower(true); // setup the maximum scales for the shower, given by the hard process if (hardVetoOn()) setupMaximumScales(_currenttree, particlesToShower); // generate the intrinsic p_T once and for all generateIntrinsicpT(particlesToShower); unsigned int ntry(0); do { // clear results of last attempt if(ntry!=0) { currentTree()->clear(); setColourPartners(true); _nis = 0; _nfs = 0; } // generate the shower // pick random starting point unsigned int istart=UseRandom::irnd(particlesToShower.size()); unsigned int istop = particlesToShower.size(); // loop over particles with random starting point for(unsigned int ix=istart;ix<=istop;++ix) { if(ix==particlesToShower.size()) { if(istart!=0) { istop = istart-1; ix=0; } else break; } // set the progenitor _progenitor=particlesToShower[ix]; // initial-state if(!_progenitor->progenitor()->isFinalState()) { if(!isISRadiationON()) continue; // get the PDF setBeamParticle(_progenitor->beam()); assert(beamParticle()); // perform the shower // set the beam particle tPPtr beamparticle=_progenitor->original(); if(!beamparticle->parents().empty()) beamparticle=beamparticle->parents()[0]; // generate the shower _progenitor->hasEmitted(startSpaceLikeShower(beamparticle)); } // final-state else { if(!isFSRadiationON()) continue; // perform shower _progenitor->hasEmitted(startTimeLikeShower()); } } } while(!_model->kinematicsReconstructor()->reconstructHardJets(hard,_intrinsic)&& _maxtry>++ntry); if(_maxtry==ntry) throw ShowerHandler::ShowerTriesVeto(ntry); // the tree has now showered _currenttree->hasShowered(true); } void Evolver::hardMatrixElementCorrection() { // set me correction to null pointer _currentme=MECorrectionPtr(); // set the initial enhancement factors for the soft correction _initialenhance=1.; _finalenhance =1.; // if hard matrix element switched off return if(!MECOn()) return; // see if there is an appropriate matrix element correction for(unsigned int ix=0;ixmeCorrections().size();++ix) { double initial,final; if(!showerModel()->meCorrections()[ix]->canHandle(_currenttree, initial,final,this)) continue; if(_currentme) { ostringstream output; output << "There is more than one possible matrix" << "element which could be applied for "; map::const_iterator cit; for(cit=_currenttree->incomingLines().begin(); cit!=_currenttree->incomingLines().end();++cit) {output << cit->first->progenitor()->PDGName() << " ";} output << " -> "; map::const_iterator cjt; for(cjt=_currenttree->outgoingLines().begin(); cjt!=_currenttree->outgoingLines().end();++cjt) {output << cjt->first->progenitor()->PDGName() << " ";} output << "in Evolver::hardMatrixElementCorrection()\n"; throw Exception() << output << Exception::runerror; } else { _currentme=showerModel()->meCorrections()[ix]; _initialenhance = initial; _finalenhance = final; } } // now apply the hard correction if(_currentme && hardMEC()) _currentme->applyHardMatrixElementCorrection(_currenttree); } bool Evolver::timeLikeShower(tShowerParticlePtr particle) { // don't do anything if not needed if(_limitEmissions == 1 || ( _limitEmissions == 2 && _nfs != 0) ) return false; // generate the emission Branching fb; while (true) { fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance); // no emission return if(!fb.kinematics) return false; // if emission OK break if(!timeLikeVetoed(fb,particle)) break; // otherwise reset scale and continue particle->setEvolutionScale(fb.kinematics->scale()); } // has emitted // Assign the shower kinematics to the emitting particle. particle->setShowerKinematics(fb.kinematics); // Assign the splitting function to the emitting particle. // For the time being we are considering only 1->2 branching // Create the ShowerParticle objects for the two children of // the emitting particle; set the parent/child relationship // if same as definition create particles, otherwise create cc tcPDPtr pdata[2]; for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]); if(particle->id()!=fb.ids[0]) { for(unsigned int ix=0;ix<2;++ix) { tPDPtr cc(pdata[ix]->CC()); if(cc) pdata[ix]=cc; } } ShowerParticleVector theChildren; theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true))); theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true))); // update the children particle->showerKinematics()->updateChildren(particle, theChildren); // update the history if needed if(particle==_currenttree->getFinalStateShowerProduct(_progenitor)) _currenttree->updateFinalStateShowerProduct(_progenitor, particle,theChildren); _currenttree->addFinalStateBranching(particle,theChildren); // update number of emissions ++_nfs; if(_limitEmissions!=0) return true; // shower the first particle timeLikeShower(theChildren[0]); // shower the second particle timeLikeShower(theChildren[1]); // branching has happened return true; } bool Evolver::spaceLikeShower(tShowerParticlePtr particle, PPtr beam) { // don't do anything if not needed if(_limitEmissions == 2 || ( _limitEmissions == 1 && _nis != 0 ) ) return false; Branching bb; // generate branching while (true) { bb=_splittingGenerator->chooseBackwardBranching(*particle,beam, _initialenhance,_beam); // return if no emission if(!bb.kinematics) return false; // if not vetoed break if(!spaceLikeVetoed(bb,particle)) break; // otherwise reset scale and continue particle->setEvolutionScale(bb.kinematics->scale()); } // assign the splitting function and shower kinematics particle->setShowerKinematics(bb.kinematics); // For the time being we are considering only 1->2 branching // particles as in Sudakov form factor tcPDPtr part[2]={getParticleData(bb.ids[0]), getParticleData(bb.ids[2])}; if(particle->id()!=bb.ids[1]) { if(part[0]->CC()) part[0]=part[0]->CC(); if(part[1]->CC()) part[1]=part[1]->CC(); } // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent=new_ptr(ShowerParticle(part[0],false)); ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true)); ShowerParticleVector theChildren; theChildren.push_back(particle); theChildren.push_back(otherChild); particle->showerKinematics()->updateParent(newParent, theChildren); // update the history if needed _currenttree->updateInitialStateShowerProduct(_progenitor,newParent); _currenttree->addInitialStateBranching(particle,newParent,otherChild); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower ++_nis; bool emitted = _limitEmissions==0 ? spaceLikeShower(newParent,beam) : false; // now reconstruct the momentum if(!emitted) { if(_intrinsic.find(_progenitor)==_intrinsic.end()) { bb.kinematics->updateLast(newParent,ZERO,ZERO); } else { pair kt=_intrinsic[_progenitor]; bb.kinematics->updateLast(newParent, kt.first*cos(kt.second), kt.first*sin(kt.second)); } } particle->showerKinematics()->updateChildren(newParent, theChildren); if(_limitEmissions!=0) return true; // perform the shower of the final-state particle timeLikeShower(otherChild); // return the emitted return true; } void Evolver::showerDecay(ShowerTreePtr decay) { // set the ShowerTree to be showered currentTree(decay); // extract particles to be shower, set scales and perform hard matrix element // correction vector particlesToShower=setupShower(false); setupMaximumScales(_currenttree, particlesToShower); // compute the minimum mass of the final-state Energy minmass(ZERO); for(unsigned int ix=0;ixprogenitor()->isFinalState()) minmass+=particlesToShower[ix]->progenitor()->mass(); } // main showering loop unsigned int ntry(0); do { // clear results of last attempt if(ntry!=0) { _currenttree->clear(); setColourPartners(false); } unsigned int istart=UseRandom::irnd(particlesToShower.size()); unsigned int istop = particlesToShower.size(); // loop over particles with random starting point for(unsigned int ix=istart;ix<=istop;++ix) { if(ix==particlesToShower.size()) { if(istart!=0) { istop = istart-1; ix=0; } else break; } // extract the progenitor _progenitor=particlesToShower[ix]; // final-state radiation if(_progenitor->progenitor()->isFinalState()) { if(!isFSRadiationON()) continue; // perform shower _progenitor->hasEmitted(startTimeLikeShower()); } // initial-state radiation else { if(!isISRadiationON()) continue; // perform shower // set the scales correctly. The current scale is the maximum scale for // emission not the starting scale Energy maxscale=_progenitor->progenitor()->evolutionScale(); Energy startScale=_progenitor->progenitor()->mass(); _progenitor->progenitor()->setEvolutionScale(startScale); // perform the shower _progenitor->hasEmitted(spaceLikeDecayShower(_progenitor->progenitor(), maxscale,minmass)); } } } while(!showerModel()->kinematicsReconstructor()->reconstructDecayJets(decay)&& maximumTries()>++ntry); if(maximumTries()==ntry) throw Exception() << "Failed to generate the shower after " << ntry << " attempts in Evolver::showerDecay()" << Exception::eventerror; // tree has now showered _currenttree->hasShowered(true); } bool Evolver::spaceLikeDecayShower(tShowerParticlePtr particle, Energy maxscale, Energy minmass) { Branching fb; while (true) { fb=_splittingGenerator->chooseDecayBranching(*particle,maxscale,minmass, _initialenhance); // return if no radiation if(!fb.kinematics) return false; // if not vetoed break if(!spaceLikeDecayVetoed(fb,particle)) break; // otherwise reset scale and continue particle->setEvolutionScale(fb.kinematics->scale()); } // has emitted // Assign the shower kinematics to the emitting particle. particle->setShowerKinematics(fb.kinematics); // For the time being we are considering only 1->2 branching // Create the ShowerParticle objects for the two children of // the emitting particle; set the parent/child relationship // if same as definition create particles, otherwise create cc tcPDPtr pdata[2]; for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]); if(particle->id()!=fb.ids[0]) { for(unsigned int ix=0;ix<2;++ix) { tPDPtr cc(pdata[ix]->CC()); if(cc) pdata[ix]=cc; } } ShowerParticleVector theChildren; theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true))); theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true))); // some code moved to updateChildren particle->showerKinematics()->updateChildren(particle, theChildren); // In the case of splittings which involves coloured particles, // set properly the colour flow of the branching. // update the history if needed _currenttree->updateInitialStateShowerProduct(_progenitor,theChildren[0]); _currenttree->addInitialStateBranching(particle,theChildren[0],theChildren[1]); // shower the first particle spaceLikeDecayShower(theChildren[0],maxscale,minmass); // shower the second particle timeLikeShower(theChildren[1]); // branching has happened return true; } vector Evolver::setupShower(bool hard) { // put all the particles into a data structure which has the particles // and the maximum pt for emission from the particle // set the initial colour partners setColourPartners(hard); map::const_iterator cit; map::const_iterator cjt; // generate the hard matrix element correction if needed hardMatrixElementCorrection(); // get the particles to be showered vector particlesToShower; // incoming particles for(cit=_currenttree->incomingLines().begin(); cit!=_currenttree->incomingLines().end();++cit) particlesToShower.push_back((*cit).first); // outgoing particles for(cjt=_currenttree->outgoingLines().begin(); cjt!=_currenttree->outgoingLines().end();++cjt) particlesToShower.push_back(((*cjt).first)); // remake the colour partners if needed if(_currenttree->hardMatrixElementCorrection()) { setColourPartners(hard); _currenttree->resetShowerProducts(); } return particlesToShower; } void Evolver::setColourPartners(bool hard) { vector particles; map::const_iterator cit; map::const_iterator cjt; for(cit=_currenttree->incomingLines().begin(); cit!=_currenttree->incomingLines().end();++cit) particles.push_back(cit->first->progenitor()); assert((particles.size()==1&&!hard)||(particles.size()==2&&hard)); // outgoing particles for(cjt=_currenttree->outgoingLines().begin(); cjt!=_currenttree->outgoingLines().end();++cjt) particles.push_back(cjt->first->progenitor()); // Set the initial evolution scales showerModel()->partnerFinder()->setInitialEvolutionScales(particles,!hard); } bool Evolver::startTimeLikeShower() { return timeLikeShower(_progenitor->progenitor()); } bool Evolver::startSpaceLikeShower(PPtr parent) { return spaceLikeShower(_progenitor->progenitor(),parent); } bool Evolver::timeLikeVetoed(const Branching & fb, ShowerParticlePtr particle) { // check whether emission was harder than largest pt of hard subprocess if (hardVetoFS() && fb.kinematics->pT() > _progenitor->maxHardPt()) return true; // soft matrix elementr correction veto if(_currentme && softMEC() && _currentme->softMatrixElementVeto(_progenitor,particle,fb)) return true; // veto on maximum pt if(fb.kinematics->pT()>_progenitor->maximumpT()) return true; // general vetos if (fb.kinematics && !_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoTimeLike(_progenitor,particle,fb); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if(vetoed) return true; } return false; } bool Evolver::spaceLikeVetoed(const Branching & bb,ShowerParticlePtr particle) { // check whether emission was harder than largest pt of hard subprocess if (hardVetoIS() && bb.kinematics->pT() > _progenitor->maxHardPt()) return true; // apply the soft correction if(_currentme && softMEC() && _currentme->softMatrixElementVeto(_progenitor,particle,bb)) return true; // check vs max pt for the shower if(bb.kinematics->pT()>_progenitor->maximumpT()) return true; // the more general vetos if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,bb); switch ((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if (vetoed) return true; } return false; } bool Evolver::spaceLikeDecayVetoed(const Branching & fb, ShowerParticlePtr particle) { // apply the soft correction if(_currentme && softMEC() && _currentme->softMatrixElementVeto(_progenitor,particle,fb)) return true; // veto on hardest pt in the shower if(fb.kinematics->pT()>_progenitor->maximumpT()) return true; // general vetos if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,fb); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } if (vetoed) return true; } } return false; } diff --git a/Contrib/MCPWNLO/PWInstallFiles/Evolver.h b/Contrib/MCPWNLO/PWInstallFiles/Evolver.h --- a/Contrib/MCPWNLO/PWInstallFiles/Evolver.h +++ b/Contrib/MCPWNLO/PWInstallFiles/Evolver.h @@ -1,595 +1,595 @@ // -*- C++ -*- // // Evolver.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_Evolver_H #define HERWIG_Evolver_H // // This is the declaration of the Evolver class. // #include "ThePEG/Interface/Interfaced.h" -#include "Herwig/Shower/SplittingFunctions/SplittingGenerator.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.h" #include "ShowerModel.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ShowerTree.h" #include "MECorrectionBase.fh" #include "ShowerProgenitor.fh" #include "Herwig/Shower/ShowerHandler.fh" #include "ShowerVeto.h" #include "Evolver.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * Here is the documentation of the Evolver class. * * @see \ref EvolverInterfaces "The interfaces" * defined for Evolver. */ class Evolver: public Interfaced { /** * The ShowerHandler is a friend to set some parameters at initialisation */ friend class ShowerHandler; /** * The MECorrectionBase class is a friend to access some protected * member functions to set the radiation enhancement factors */ friend class MECorrectionBase; public: /** * Default Constructor */ Evolver() : _maxtry(100), _meCorrMode(1), _hardVetoMode(1), _hardVetoRead(0),_PHtopveto(0), _iptrms(ZERO), _beta(0.), _gamma(ZERO), _iptmax(), _limitEmissions(0), _initialenhance(1.), _finalenhance(1.) {} /** * Member to perform the shower */ //@{ /** * Perform the shower of the hard process */ virtual void showerHardProcess(ShowerTreePtr); /** * Perform the shower of a decay */ virtual void showerDecay(ShowerTreePtr); //@} /** * Access to the flags and shower variables */ //@{ /** * Is there any showering switched on */ bool showeringON() const { return isISRadiationON() || isFSRadiationON(); } /** * It returns true/false if the initial-state radiation is on/off. */ bool isISRadiationON() const { return _splittingGenerator->isISRadiationON(); } /** * It returns true/false if the final-state radiation is on/off. */ bool isFSRadiationON() const { return _splittingGenerator->isFSRadiationON(); } /** * Get the ShowerModel */ ShowerModelPtr showerModel() const {return _model;} /** * Get the SplittingGenerator */ tSplittingGeneratorPtr splittingGenerator() const { return _splittingGenerator; } //@} 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: /** * Generate the hard matrix element correction */ virtual void hardMatrixElementCorrection(); /** * Extract the particles to be showered, set the evolution scales * and apply the hard matrix element correction * @param hard Whether this is a hard process or decay * @return The particles to be showered */ virtual vector setupShower(bool hard); /** * set the colour partners */ virtual void setColourPartners(bool hard); /** * Methods to perform the evolution of an individual particle, including * recursive calling on the products */ //@{ /** * It does the forward evolution of the time-like input particle * (and recursively for all its radiation products). * accepting only emissions which conforms to the showerVariables * and soft matrix element correction pointed by meCorrectionPtr. * If at least one emission has occurred then the method returns true. * @param particle The particle to be showered */ virtual bool timeLikeShower(tShowerParticlePtr particle); /** * It does the backward evolution of the space-like input particle * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * If at least one emission has occurred then the method returns true * @param particle The particle to be showered * @param beam The beam particle */ virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam); /** * If does the forward evolution of the input on-shell particle * involved in a decay * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * @param particle The particle to be showered * @param maxscale The maximum scale for the shower. * @param minimumMass The minimum mass of the final-state system */ virtual bool spaceLikeDecayShower(tShowerParticlePtr particle, Energy maxscale, Energy minimumMass); //@} /** * Switches for matrix element corrections */ //@{ /** * Any ME correction? */ bool MECOn() const { return _meCorrMode > 0; } /** * Any hard ME correction? */ bool hardMEC() const { return _meCorrMode == 1 || _meCorrMode == 2; } /** * Any soft ME correction? */ bool softMEC() const { return _meCorrMode == 1 || _meCorrMode > 2; } /* Switch for top veto * * Any POWHEGtopvetoes? */ bool PHtopveto() const { return _PHtopveto > 0;} bool prodveto() const {return _PHtopveto == 1 || _PHtopveto == 2;} bool decayveto() const {return _PHtopveto == 1 || _PHtopveto > 2;} //@} /** * Switch for intrinsic pT */ //@{ /** * Any intrinsic pT? */ bool ipTon() const { return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO ); } //@} /**@name Additional shower vetoes */ //@{ /** * Insert a veto. */ void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); } /** * Remove a veto. */ void removeVeto (ShowerVetoPtr v) { vector::iterator vit = find(_vetoes.begin(),_vetoes.end(),v); if (vit != _vetoes.end()) _vetoes.erase(vit); } //@} /** * Switches for vetoing hard emissions */ //@{ /** * Vetos on? */ bool hardVetoOn() const { return _hardVetoMode > 0; } /** * veto hard emissions in IS shower? */ bool hardVetoIS() const { return _hardVetoMode == 1 || _hardVetoMode == 2; } /** * veto hard emissions in FS shower? */ bool hardVetoFS() const { return _hardVetoMode == 1 || _hardVetoMode > 2; } /** * veto hard emissions according to lastScale from XComb? */ bool hardVetoXComb() const {return (_hardVetoRead == 1);} //@} /** * Enhancement factors for radiation needed to generate the soft matrix * element correction. */ //@{ /** * Access the enhancement factor for initial-state radiation */ double initialStateRadiationEnhancementFactor() const { return _initialenhance; } /** * Access the enhancement factor for final-state radiation */ double finalStateRadiationEnhancementFactor() const { return _finalenhance; } /** * Set the enhancement factor for initial-state radiation */ void initialStateRadiationEnhancementFactor(double in) { _initialenhance=in; } /** * Set the enhancement factor for final-state radiation */ void finalStateRadiationEnhancementFactor(double in) { _finalenhance=in; } //@} /** * Access/set the beam particle for the current initial-state shower */ //@{ /** * Get the beam particle data */ Ptr::const_pointer beamParticle() const { return _beam; } /** * Set the beam particle data */ void setBeamParticle(Ptr::const_pointer in) { _beam=in; } //@} /** * Set/Get the current tree being evolverd for inheriting classes */ //@{ /** * Get the tree */ tShowerTreePtr currentTree() { return _currenttree; } /** * Set the tree */ void currentTree(tShowerTreePtr tree) { _currenttree=tree; } //@} /** * Access the maximum number of attempts to generate the shower */ unsigned int maximumTries() const { return _maxtry; } /** * Set/Get the ShowerProgenitor for the current shower */ //@{ /** * Access the progenitor */ ShowerProgenitorPtr progenitor() { return _progenitor; } /** * Set the progenitor */ void progenitor(ShowerProgenitorPtr in) { _progenitor=in; } //@} /** * Calculate the intrinsic \f$p_T\f$. */ virtual void generateIntrinsicpT(vector); /** * Access to the intrinsic \f$p_T\f$ for inheriting classes */ map > & intrinsicpT() { return _intrinsic; } /** * find the maximally allowed pt acc to the hard process. */ void setupMaximumScales(ShowerTreePtr, vector); protected: /** * Start the shower of a timelike particle */ virtual bool startTimeLikeShower(); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeShower(PPtr); /** * Vetos for the timelike shower */ virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initEvolver; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Evolver & operator=(const Evolver &); private: /** * Pointer to the model for the shower evolution model */ ShowerModelPtr _model; /** * Pointer to the splitting generator */ SplittingGeneratorPtr _splittingGenerator; /** * Maximum number of tries to generate the shower of a particular tree */ unsigned int _maxtry; /** * Matrix element correction switch */ unsigned int _meCorrMode; /** * Hard emission veto switch */ unsigned int _hardVetoMode; /** * Hard veto to be read switch */ unsigned int _hardVetoRead; /** * POWHEGveto switch */ unsigned int _PHtopveto; /** * rms intrinsic pT of Gaussian distribution */ Energy _iptrms; /** * Proportion of inverse quadratic intrinsic pT distribution */ double _beta; /** * Parameter for inverse quadratic: 2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT)) */ Energy _gamma; /** * Upper bound on intrinsic pT for inverse quadratic */ Energy _iptmax; /** * Limit the number of emissions for testing */ unsigned int _limitEmissions; /** * The progenitor of the current shower */ ShowerProgenitorPtr _progenitor; /** * Matrix element correction used for the current shower */ MECorrectionPtr _currentme; /** * The ShowerTree currently being showered */ ShowerTreePtr _currenttree; /** * Radiation enhancement factors for use with the veto algorithm * if needed by the soft matrix element correction */ //@{ /** * Enhancement factor for initial-state radiation */ double _initialenhance; /** * Enhancement factor for final-state radiation */ double _finalenhance; //@} /** * The beam particle data for the current initial-state shower */ Ptr::const_pointer _beam; /** * Storage of the intrinsic \f$p_t\f$ of the particles */ map > _intrinsic; /** * Vetoes */ vector _vetoes; /** * number of IS emissions */ unsigned int _nis; /** * Number of FS emissions */ unsigned int _nfs; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of Evolver. */ template <> struct BaseClassTrait { /** Typedef of the first base class of Evolver. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the Evolver 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::Evolver"; } /** * The name of a file containing the dynamic library where the class * Evolver is implemented. It may also include several, space-separated, * libraries if the class Evolver 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_Evolver_H */ diff --git a/Contrib/Makefile.am b/Contrib/Makefile.am --- a/Contrib/Makefile.am +++ b/Contrib/Makefile.am @@ -1,20 +1,21 @@ EXTRA_DIST = \ AcerDetInterface \ AlpGen \ Analysis2 \ AnomalousHVV \ DecayAnalysis \ FxFx \ HiggsPair \ HiggsPairOL \ LeptonME \ PGSInterface \ RadiativeZPrime \ TauAnalysis \ -MultiWeight +MultiWeight \ +ShowerVeto dist-hook: rm -rf `find $(distdir) -name '.svn' -or -name 'Makefile' -or -name '.hg'` all: bash make_makefiles.sh diff --git a/Contrib/ShowerVeto/LHC.in b/Contrib/ShowerVeto/LHC.in new file mode 100644 --- /dev/null +++ b/Contrib/ShowerVeto/LHC.in @@ -0,0 +1,62 @@ +# -*- ThePEG-repository -*- + +################################################## +# Example generator based on LHC parameters +# usage: Herwig read LHC.in +################################################## + +################################################## +# Technical parameters for this run +################################################## +cd /Herwig/Generators +set LHCGenerator:NumberOfEvents 10000000 +set LHCGenerator:RandomNumberGenerator:Seed 31122001 +set LHCGenerator:PrintEvent 10000 +set LHCGenerator:MaxErrors 10000 + +################################################## +# LHC physics parameters (override defaults here) +################################################## + +# Intrinsic pT tune extrapolated to LHC energy +set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV + +######################## +## sqrt(s) = 13000 GeV ## +######################## +set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 + +################################################## +# Matrix Elements for hadron-hadron collisions +# (by default only gamma/Z switched on) +################################################## +cd /Herwig/MatrixElements/ + +# +# QCD and gamma processes +# +# QCD 2-2 scattering +insert SimpleQCD:MatrixElements[0] MEQCD2to2 +set MEQCD2to2:Process 1 + +cd /Herwig/Shower +# setup to reweight events ensuring b quarks after shower +create Herwig::NonBShowerVeto NonBShowerVeto HwShowerVeto.so +insert Evolver:FullShowerVetoes 0 NonBShowerVeto +set NonBShowerVeto:Type Primary +# reweighting, change for other behaviour +set NonBShowerVeto:Behaviour ShowerReweight +# or to veto events which don't have b quarks after shower +# set NonBShowerVeto:Behaviour Event +set Evolver:MaxTry 1000 + + +cd /Herwig/Generators +################################################## +# Save run for later usage with 'Herwig run' +################################################## +set /Herwig/Analysis/Basics:CheckQuark 0 +set /Herwig/Shower/ShowerHandler:MPIHandler NULL +set LHCGenerator:EventHandler:DecayHandler NULL +set LHCGenerator:EventHandler:HadronizationHandler NULL +saverun LHC LHCGenerator diff --git a/Contrib/ShowerVeto/Makefile.in b/Contrib/ShowerVeto/Makefile.in new file mode 100644 --- /dev/null +++ b/Contrib/ShowerVeto/Makefile.in @@ -0,0 +1,36 @@ +# -*- Makefile -*- (for emacs) + +# +# This Makefile is intended for compiling Herwig++ plugins +# You can find plugins here: INSERT URL +# +# This Makefile received very little testing, +# any bug reports are very welcome! +# + +# location of include files +THEPEGINCLUDE = +GSLINCLUDE = +HERWIGINCLUDE = +INCLUDE = $(THEPEGINCLUDE) $(GSLINCLUDE) $(HERWIGINCLUDE) +# +# C++ flags +# +CXX = +CXXFLAGS = +LDFLAGS = +SHARED_FLAG = + +ALLCCFILES=$(shell echo *.cc) + +default : HwShowerVeto.so + +%.o : %.cc %.h + $(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) -c -shared $< -o $@ + +HwShowerVeto.so: NonBShowerVeto.o + $(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) \ + NonBShowerVeto.o $(SHARED_FLAG) $(LDFLAGS) -o HwShowerVeto.so + +clean: + rm -f $(ALLCCFILES:.cc=.o) HwShowerVeto.so diff --git a/Contrib/ShowerVeto/NonBShowerVeto.cc b/Contrib/ShowerVeto/NonBShowerVeto.cc new file mode 100644 --- /dev/null +++ b/Contrib/ShowerVeto/NonBShowerVeto.cc @@ -0,0 +1,46 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the NonBShowerVeto class. +// + +#include "NonBShowerVeto.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/Utilities/DescribeClass.h" + +using namespace Herwig; + +IBPtr NonBShowerVeto::clone() const { + return new_ptr(*this); +} + +IBPtr NonBShowerVeto::fullclone() const { + return new_ptr(*this); +} + +// The following static variable is needed for the type +// description system in ThePEG. +DescribeNoPIOClass + describeHerwigNonBShowerVeto("Herwig::NonBShowerVeto", "HwShowerVeto.so"); + +void NonBShowerVeto::Init() { + + static ClassDocumentation documentation + ("The NonBShowerVeto class vetos the parton-shower when no b (anti)quarks have been produced"); + +} + +bool NonBShowerVeto::vetoShower() { + // loop over final-state + for(vector::const_iterator it=finalState().begin(); it!=finalState().end();++it) { + // don't veto if find a b (anti)quark + if(abs((**it).id())==5) { + return false; + } + } + // no b (anti)quarks veto shower + return true; +} diff --git a/Contrib/ShowerVeto/NonBShowerVeto.h b/Contrib/ShowerVeto/NonBShowerVeto.h new file mode 100644 --- /dev/null +++ b/Contrib/ShowerVeto/NonBShowerVeto.h @@ -0,0 +1,75 @@ +// -*- C++ -*- +#ifndef Herwig_NonBShowerVeto_H +#define Herwig_NonBShowerVeto_H +// +// This is the declaration of the NonBShowerVeto class. +// + +#include "Herwig/Shower/Base/FullShowerVeto.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * The NonBShowerVeto class vetos parton showers where no b (anti)quarks are produced. + * + * @see \ref NonBShowerVetoInterfaces "The interfaces" + * defined for NonBShowerVeto. + */ +class NonBShowerVeto: public FullShowerVeto { + +public: + /** + * The default constructor. + */ + NonBShowerVeto() {} + +protected: + + /** + * Determine whether to not to veto the shower, to be implemented in inheriting classes + */ + virtual bool vetoShower(); + + +public: + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +protected: + + /** @name Clone Methods. */ + //@{ + /** + * Make a simple clone of this object. + * @return a pointer to the new object. + */ + virtual IBPtr clone() const; + + /** Make a clone of this object, possibly modifying the cloned object + * to make it sane. + * @return a pointer to the new object. + */ + virtual IBPtr fullclone() const; + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + NonBShowerVeto & operator=(const NonBShowerVeto &); + +}; + +} + +#endif /* Herwig_NonBShowerVeto_H */ diff --git a/Decay/FormFactors/Makefile.am b/Decay/FormFactors/Makefile.am --- a/Decay/FormFactors/Makefile.am +++ b/Decay/FormFactors/Makefile.am @@ -1,31 +1,31 @@ noinst_LTLIBRARIES = libHwFormFactor.la pkglib_LTLIBRARIES = HwFormFactors.la libHwFormFactor_la_SOURCES = \ BaryonFormFactor.cc BaryonFormFactor.fh \ BaryonFormFactor.h \ ScalarFormFactor.cc ScalarFormFactor.fh \ ScalarFormFactor.h \ BtoSGammaHadronicMass.h \ BtoSGammaHadronicMass.cc BtoSGammaHadronicMass.fh -HwFormFactors_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0 +HwFormFactors_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:1:0 HwFormFactors_la_SOURCES = \ BallZwickyScalarFormFactor.cc BallZwickyScalarFormFactor.h \ BallZwickyVectorFormFactor.cc BallZwickyVectorFormFactor.h \ BaryonSimpleFormFactor.cc BaryonSimpleFormFactor.h \ BaryonThreeQuarkModelFormFactor.cc BaryonThreeQuarkModelFormFactor.h \ ChengHeavyBaryonFormFactor.cc ChengHeavyBaryonFormFactor.h \ ISGW2FormFactor.cc ISGW2FormFactor.h \ ISGWFormFactor.cc ISGWFormFactor.h \ LambdabExcitedLambdacSumRuleFormFactor.cc \ LambdabExcitedLambdacSumRuleFormFactor.h \ LightBaryonQuarkModelFormFactor.cc LightBaryonQuarkModelFormFactor.h \ SingletonFormFactor.cc SingletonFormFactor.h\ WSBFormFactor.cc WSBFormFactor.h\ KiselevBcFormFactor.cc KiselevBcFormFactor.h\ MelikhovFormFactor.cc MelikhovFormFactor.h \ MelikhovStechFormFactor.cc MelikhovStechFormFactor.h \ BtoSGammaFlatEnergy.h BtoSGammaFlatEnergy.cc \ BtoSGammaKagan.h BtoSGammaKagan.cc\ HQETFormFactor.h HQETFormFactor.cc diff --git a/Decay/General/GeneralTwoBodyDecayer.cc b/Decay/General/GeneralTwoBodyDecayer.cc --- a/Decay/General/GeneralTwoBodyDecayer.cc +++ b/Decay/General/GeneralTwoBodyDecayer.cc @@ -1,1430 +1,1374 @@ // -*- C++ -*- // // GeneralTwoBodyDecayer.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 GeneralTwoBodyDecayer class. // #include "GeneralTwoBodyDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Utilities/Exception.h" -#include "Herwig/Shower/Base/HardTree.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; ParticleVector GeneralTwoBodyDecayer::decay(const Particle & parent, const tPDVector & children) const { // return empty vector if products heavier than parent Energy mout(ZERO); for(tPDVector::const_iterator it=children.begin(); it!=children.end();++it) mout+=(**it).massMin(); if(mout>parent.mass()) return ParticleVector(); // generate the decay bool cc; int imode=modeNumber(cc,parent.dataPtr(),children); // generate the kinematics ParticleVector decay=generate(generateIntermediates(),cc,imode,parent); // make the colour connections colourConnections(parent, decay); // return the answer return decay; } void GeneralTwoBodyDecayer::doinit() { DecayIntegrator::doinit(); assert( vertex_ ); assert( _incoming && _outgoing.size()==2); vertex_->init(); //create phase space mode tPDVector extpart(3); extpart[0] = _incoming; extpart[1] = _outgoing[0]; extpart[2] = _outgoing[1]; addMode(new_ptr(DecayPhaseSpaceMode(extpart, this)), _maxweight, vector()); } int GeneralTwoBodyDecayer::modeNumber(bool & cc, tcPDPtr parent, const tPDVector & children) const { long parentID = parent->id(); long id1 = children[0]->id(); long id2 = children[1]->id(); cc = false; long out1 = _outgoing[0]->id(); long out2 = _outgoing[1]->id(); if( parentID == _incoming->id() && ((id1 == out1 && id2 == out2) || (id1 == out2 && id2 == out1)) ) { return 0; } else if(_incoming->CC() && parentID == _incoming->CC()->id()) { cc = true; if( _outgoing[0]->CC()) out1 = _outgoing[0]->CC()->id(); if( _outgoing[1]->CC()) out2 = _outgoing[1]->CC()->id(); if((id1 == out1 && id2 == out2) || (id1 == out2 && id2 == out1)) return 0; } return -1; } void GeneralTwoBodyDecayer:: colourConnections(const Particle & parent, const ParticleVector & out) const { PDT::Colour incColour(parent.data().iColour()); PDT::Colour outaColour(out[0]->data().iColour()); PDT::Colour outbColour(out[1]->data().iColour()); //incoming colour singlet if(incColour == PDT::Colour0) { // colour triplet-colourantitriplet if((outaColour == PDT::Colour3 && outbColour == PDT::Colour3bar) || (outaColour == PDT::Colour3bar && outbColour == PDT::Colour3)) { bool ac(out[0]->id() < 0); out[0]->colourNeighbour(out[1],!ac); } //colour octet else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour8) { out[0]->colourNeighbour(out[1]); out[0]->antiColourNeighbour(out[1]); } // colour singlets else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour0) { } // unknown else throw Exception() << "Unknown outgoing colours for decaying " << "colour singlet in " << "GeneralTwoBodyDecayer::colourConnections " << outaColour << " " << outbColour << Exception::runerror; } //incoming colour triplet else if(incColour == PDT::Colour3) { // colour triplet + singlet if(outaColour == PDT::Colour3 && outbColour == PDT::Colour0) { out[0]->incomingColour(const_ptr_cast(&parent)); } //opposite order else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour3) { out[1]->incomingColour(const_ptr_cast(&parent)); } // octet + triplet else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour3) { out[0]->incomingColour(const_ptr_cast(&parent)); out[1]->antiColourNeighbour(out[0]); } //opposite order else if(outaColour == PDT::Colour3 && outbColour == PDT::Colour8) { out[1]->incomingColour(const_ptr_cast(&parent)); out[0]->antiColourNeighbour(out[1]); } else if(outaColour == PDT::Colour3bar && outaColour == PDT::Colour3bar) { tColinePtr col[2] = {ColourLine::create(out[0],true), ColourLine::create(out[1],true)}; parent.colourLine()->setSinkNeighbours(col[0],col[1]); } else throw Exception() << "Unknown outgoing colours for decaying " << "colour triplet in " << "GeneralTwoBodyDecayer::colourConnections() " << outaColour << " " << outbColour << Exception::runerror; } // incoming colour anti triplet else if(incColour == PDT::Colour3bar) { // colour antitriplet +singlet if(outaColour == PDT::Colour3bar && outbColour == PDT::Colour0) { out[0]->incomingAntiColour(const_ptr_cast(&parent)); } //opposite order else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour3bar) { out[1]->incomingAntiColour(const_ptr_cast(&parent)); } //octet + antitriplet else if(outaColour == PDT::Colour3bar && outbColour == PDT::Colour8) { out[1]->incomingAntiColour(const_ptr_cast(&parent)); out[0]->colourNeighbour(out[1]); } //opposite order else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour3bar) { out[0]->incomingAntiColour(const_ptr_cast(&parent)); out[1]->colourNeighbour(out[0]); } else if(outaColour == PDT::Colour3 && outbColour == PDT::Colour3) { tColinePtr col[2] = {ColourLine::create(out[0]), ColourLine::create(out[1])}; parent.antiColourLine()->setSourceNeighbours(col[0],col[1]); } else throw Exception() << "Unknown outgoing colours for decaying " << "colour antitriplet " << "in GeneralTwoBodyDecayer::colourConnections() " << outaColour << " " << outbColour << Exception::runerror; } //incoming colour octet else if(incColour == PDT::Colour8) { // triplet-antitriplet if(outaColour == PDT::Colour3&&outbColour == PDT::Colour3bar) { out[0]->incomingColour(const_ptr_cast(&parent)); out[1]->incomingAntiColour(const_ptr_cast(&parent)); } // opposite order else if(outbColour == PDT::Colour3&&outaColour == PDT::Colour3bar) { out[0]->incomingAntiColour(const_ptr_cast(&parent)); out[1]->incomingColour(const_ptr_cast(&parent)); } // neutral octet else if(outaColour == PDT::Colour0&&outbColour == PDT::Colour8) { out[1]->incomingColour(const_ptr_cast(&parent)); out[1]->incomingAntiColour(const_ptr_cast(&parent)); } else if(outbColour == PDT::Colour0&&outaColour == PDT::Colour8) { out[0]->incomingColour(const_ptr_cast(&parent)); out[0]->incomingAntiColour(const_ptr_cast(&parent)); } else throw Exception() << "Unknown outgoing colours for decaying " << "colour octet " << "in GeneralTwoBodyDecayer::colourConnections() " << outaColour << " " << outbColour << Exception::runerror; } else if(incColour == PDT::Colour6) { if(outaColour == PDT::Colour3 && outbColour == PDT::Colour3) { tPPtr tempParent = const_ptr_cast(&parent); Ptr::pointer parentColour = dynamic_ptr_cast::pointer> (tempParent->colourInfo()); tColinePtr line1 = const_ptr_cast(parentColour->colourLines()[0]); line1->addColoured(dynamic_ptr_cast(out[0])); tColinePtr line2 = const_ptr_cast(parentColour->colourLines()[1]); line2->addColoured(dynamic_ptr_cast(out[1])); } else throw Exception() << "Unknown outgoing colours for decaying " << "colour sextet " << "in GeneralTwoBodyDecayer::colourConnections() " << outaColour << " " << outbColour << Exception::runerror; } else if(incColour == PDT::Colour6bar) { if(outaColour == PDT::Colour3bar && outbColour == PDT::Colour3bar) { tPPtr tempParent = const_ptr_cast(&parent); Ptr::pointer parentColour = dynamic_ptr_cast::pointer> (tempParent->colourInfo()); tColinePtr line1 = const_ptr_cast(parentColour->antiColourLines()[0]); line1->addAntiColoured(dynamic_ptr_cast(out[0])); tColinePtr line2 = const_ptr_cast(parentColour->antiColourLines()[1]); line2->addAntiColoured(dynamic_ptr_cast(out[1])); } else throw Exception() << "Unknown outgoing colours for decaying " << "colour anti-sextet " << "in GeneralTwoBodyDecayer::colourConnections() " << outaColour << " " << outbColour << Exception::runerror; } else throw Exception() << "Unknown incoming colour in " << "GeneralTwoBodyDecayer::colourConnections() " << incColour << Exception::runerror; } bool GeneralTwoBodyDecayer::twoBodyMEcode(const DecayMode & dm, int & mecode, double & coupling) const { assert(dm.parent()->id() == _incoming->id()); ParticleMSet::const_iterator pit = dm.products().begin(); long id1 = (*pit)->id(); ++pit; long id2 = (*pit)->id(); long id1t(_outgoing[0]->id()), id2t(_outgoing[1]->id()); mecode = -1; coupling = 1.; if( id1 == id1t && id2 == id2t ) { return true; } else if( id1 == id2t && id2 == id1t ) { return false; } else assert(false); return false; } void GeneralTwoBodyDecayer::persistentOutput(PersistentOStream & os) const { os << vertex_ << _incoming << _outgoing << _maxweight << ounit(pTmin_,GeV) << coupling_ << incomingVertex_ << outgoingVertices_ << fourPointVertex_; } void GeneralTwoBodyDecayer::persistentInput(PersistentIStream & is, int) { is >> vertex_ >> _incoming >> _outgoing >> _maxweight >> iunit(pTmin_,GeV) >> coupling_ >> incomingVertex_ >> outgoingVertices_ >> fourPointVertex_; } AbstractClassDescription GeneralTwoBodyDecayer::initGeneralTwoBodyDecayer; // Definition of the static class description member. void GeneralTwoBodyDecayer::Init() { static ClassDocumentation documentation ("This class is designed to be a base class for all 2 body decays" "in a general model"); static Parameter interfacepTmin ("pTmin", "Minimum transverse momentum from gluon radiation", &GeneralTwoBodyDecayer::pTmin_, GeV, 1.0*GeV, 0.0*GeV, 10.0*GeV, false, false, Interface::limited); static Reference interfaceCoupling ("Coupling", "Object for the coupling in the generation of hard radiation", &GeneralTwoBodyDecayer::coupling_, false, false, true, false, false); } double GeneralTwoBodyDecayer::brat(const DecayMode &, const Particle & p, double oldbrat) const { ParticleVector children = p.children(); if( children.size() != 2 || !p.data().widthGenerator() ) return oldbrat; // partial width for this mode Energy scale = p.mass(); Energy pwidth = partialWidth( make_pair(p.dataPtr(), scale), make_pair(children[0]->dataPtr(), children[0]->mass()), make_pair(children[1]->dataPtr(), children[1]->mass()) ); Energy width = p.data().widthGenerator()->width(p.data(), scale); return pwidth/width; } void GeneralTwoBodyDecayer::doinitrun() { vertex_->initrun(); DecayIntegrator::doinitrun(); for(unsigned int ix=0;ixexternalParticles(0)->iSpin())-1); mode(ix)->setMaxWeight(fact*mode(ix)->maxWeight()); } } double GeneralTwoBodyDecayer::colourFactor(tcPDPtr in, tcPDPtr out1, tcPDPtr out2) const { // identical particle symmetry factor double output = out1->id()==out2->id() ? 0.5 : 1.; // colour neutral incoming particle if(in->iColour()==PDT::Colour0) { // both colour neutral if(out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour0) output *= 1.; // colour triplet/ antitriplet else if((out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3bar) || (out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3 ) ) { output *= 3.; } // colour octet colour octet else if(out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour8 ) { output *= 8.; } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour neutral particle in " << "GeneralTwoBodyDecayer::colourFactor() for " << in->PDGName() << " -> " << out1->PDGName() << " " << out2->PDGName() << Exception::runerror; } // triplet else if(in->iColour()==PDT::Colour3) { // colour triplet + neutral if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour3) || (out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour0) ) { output *= 1.; } // colour triplet + octet else if((out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour3) || (out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour8) ) { output *= 4./3.; } // colour anti triplet anti triplet else if(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3bar) { output *= 2.; } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour triplet particle in " << "GeneralTwoBodyDecayer::colourFactor() for " << in->PDGName() << " -> " << out1->PDGName() << " " << out2->PDGName() << Exception::runerror; } // anti triplet else if(in->iColour()==PDT::Colour3bar) { // colour anti triplet + neutral if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour3bar ) || (out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour0 ) ) { output *= 1.; } // colour anti triplet + octet else if((out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour3bar ) || (out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour8 ) ) { output *= 4./3.; } // colour triplet triplet else if(out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3) { output *= 2.; } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour anti triplet particle in " << "GeneralTwoBodyDecayer::colourFactor() for " << in->PDGName() << " -> " << out1->PDGName() << " " << out2->PDGName() << Exception::runerror; } else if(in->iColour()==PDT::Colour8) { // colour octet + neutral if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour8 ) || (out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour0 ) ) { output *= 1.; } // colour triplet/antitriplet else if((out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3bar) || (out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3 ) ) { output *= 0.5; } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour octet particle in " << "GeneralTwoBodyDecayer::colourFactor() for " << in->PDGName() << " -> " << out1->PDGName() << " " << out2->PDGName() << Exception::runerror; } else if(in->iColour()==PDT::Colour6) { // colour sextet -> triplet triplet if( out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3 ) { output *= 1.; } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour sextet particle in " << "GeneralTwoBodyDecayer::colourFactor() for " << in->PDGName() << " -> " << out1->PDGName() << " " << out2->PDGName() << Exception::runerror; } else if(in->iColour()==PDT::Colour6bar) { // colour sextet -> triplet triplet if( out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3bar ) { output *= 1.; } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour anti-sextet particle in " << "GeneralTwoBodyDecayer::colourFactor() for " << in->PDGName() << " -> " << out1->PDGName() << " " << out2->PDGName() << Exception::runerror; } else throw Exception() << "Unknown colour " << in->iColour() << " for the decaying particle in " << "GeneralTwoBodyDecayer::colourFactor() for " << in->PDGName() << " -> " << out1->PDGName() << " " << out2->PDGName() << Exception::runerror; return output; } Energy GeneralTwoBodyDecayer::partialWidth(PMPair inpart, PMPair outa, PMPair outb) const { // select the number of the mode tPDVector children; children.push_back(const_ptr_cast(outa.first)); children.push_back(const_ptr_cast(outb.first)); bool cc; int nmode=modeNumber(cc,inpart.first,children); tcPDPtr newchild[2] = {mode(nmode)->externalParticles(1), mode(nmode)->externalParticles(2)}; // make the particles Lorentz5Momentum pparent = Lorentz5Momentum(inpart.second); PPtr parent = inpart.first->produceParticle(pparent); Lorentz5Momentum pout[2]; double ctheta,phi; Kinematics::generateAngles(ctheta,phi); Kinematics::twoBodyDecay(pparent, outa.second, outb.second, ctheta, phi,pout[0],pout[1]); if( ( !cc && outa.first!=newchild[0]) || ( cc && !(( outa.first->CC() && outa.first->CC() == newchild[0])|| ( !outa.first->CC() && outa.first == newchild[0]) ))) swap(pout[0],pout[1]); ParticleVector decay; decay.push_back(newchild[0]->produceParticle(pout[0])); decay.push_back(newchild[1]->produceParticle(pout[1])); double me = me2(-1,*parent,decay,Initialize); Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second, outb.second); return me/(8.*Constants::pi)*pcm; } void GeneralTwoBodyDecayer::setDecayInfo(PDPtr incoming,PDPair outgoing, VertexBasePtr vertex, VertexBasePtr inV, const vector & outV, VertexBasePtr fourV) { _incoming=incoming; _outgoing.clear(); _outgoing.push_back(outgoing.first ); _outgoing.push_back(outgoing.second); vertex_ = vertex; incomingVertex_ = inV; outgoingVertices_ = outV; fourPointVertex_ = fourV; } -HardTreePtr GeneralTwoBodyDecayer::generateHardest(ShowerTreePtr tree) { +RealEmissionProcessPtr GeneralTwoBodyDecayer::generateHardest(RealEmissionProcessPtr born) { + // check one incoming + assert(born->bornIncoming().size()==1); + // check exactly two outgoing particles + assert(born->bornOutgoing().size()==2); // ignore effective vertices if (vertex_ && (vertex_->orderInGem()+vertex_->orderInGs())>1) - return HardTreePtr(); + return RealEmissionProcessPtr(); // search for coloured particles - bool colouredParticles=false; - vector Progenitors = tree->extractProgenitors(); - for (unsigned int it=0; itprogenitor()->dataPtr()->coloured()){ - colouredParticles=true; - break; + bool colouredParticles=born->bornIncoming()[0]->dataPtr()->coloured(); + if(!colouredParticles) { + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(born->bornOutgoing()[ix]->dataPtr()->coloured()) { + colouredParticles=true; + break; + } } } // if no coloured particles return - if ( !colouredParticles ) return HardTreePtr(); - // check exactly two outgoing particles - if (tree->outgoingLines().size()!=2) - assert(false); + if ( !colouredParticles ) return RealEmissionProcessPtr(); // for decay b -> a c // set progenitors - ShowerProgenitorPtr - cProgenitor = tree->outgoingLines(). begin()->first, - aProgenitor = tree->outgoingLines().rbegin()->first; + PPtr cProgenitor = born->bornOutgoing()[0]; + PPtr aProgenitor = born->bornOutgoing()[1]; // get the decaying particle - ShowerProgenitorPtr bProgenitor = tree->incomingLines().begin()->first; + PPtr bProgenitor = born->bornIncoming()[0]; // identify which dipoles are required vector dipoles; if(!identifyDipoles(dipoles,aProgenitor,bProgenitor,cProgenitor)) { - return HardTreePtr(); + return RealEmissionProcessPtr(); } Energy trialpT = pTmin_; LorentzRotation eventFrame; vector momenta; vector trialMomenta(4); - ShowerProgenitorPtr finalEmitter, finalSpectator; - ShowerProgenitorPtr trialEmitter, trialSpectator; + PPtr finalEmitter, finalSpectator; + PPtr trialEmitter, trialSpectator; + dipoleType finalType(FFa); for (int i=0; iprogenitor()->momentum() - .findBoostToCM() ); - Lorentz5Momentum pspectator = (trialEventFrame* - trialSpectator->progenitor()->momentum()); + LorentzRotation trialEventFrame(bProgenitor->momentum().findBoostToCM()); + Lorentz5Momentum pspectator = (trialEventFrame*trialSpectator->momentum()); trialEventFrame.rotateZ( -pspectator.phi() ); trialEventFrame.rotateY( -pspectator.theta() - Constants::pi ); // invert it trialEventFrame.invert(); // try to generate an emission pT_ = pTmin_; vector trialMomenta = hardMomenta(bProgenitor, trialEmitter, trialSpectator, dipoles, i); - + // select dipole which gives highest pT emission - if(pT_>trialpT){ + if(pT_>trialpT) { trialpT = pT_; momenta = trialMomenta; eventFrame = trialEventFrame; finalEmitter = trialEmitter; finalSpectator = trialSpectator; + finalType = dipoles[i]; if (dipoles[i]==FFc || dipoles[i]==FFa ) { if((momenta[3]+momenta[1]).m2()-momenta[1].m2()>(momenta[3]+momenta[2]).m2()-momenta[2].m2()) { swap(finalEmitter,finalSpectator); swap(momenta[1],momenta[2]); } } } } pT_ = trialpT; // if no emission return if(momenta.empty()) { - bProgenitor->maximumpT(pTmin_,ShowerInteraction::QCD); - aProgenitor->maximumpT(pTmin_,ShowerInteraction::QCD); - cProgenitor->maximumpT(pTmin_,ShowerInteraction::QCD); - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = pTmin_; + return born; } // rotate momenta back to the lab for(unsigned int ix=0;ixmaximumpT(pT_,ShowerInteraction::QCD); - finalEmitter ->maximumpT(pT_,ShowerInteraction::QCD); - finalSpectator->maximumpT(pT_,ShowerInteraction::QCD); + born->pT()[ShowerInteraction::QCD] = pT_; // get ParticleData objects - tcPDPtr b = bProgenitor ->progenitor()->dataPtr(); - tcPDPtr e = finalEmitter ->progenitor()->dataPtr(); - tcPDPtr s = finalSpectator->progenitor()->dataPtr(); + tcPDPtr b = bProgenitor ->dataPtr(); + tcPDPtr e = finalEmitter ->dataPtr(); + tcPDPtr s = finalSpectator->dataPtr(); tcPDPtr gluon = getParticleData(ParticleID::g); // create new ShowerParticles - ShowerParticlePtr emitter (new_ptr(ShowerParticle(e, true ))); - ShowerParticlePtr spectator(new_ptr(ShowerParticle(s, true ))); - ShowerParticlePtr gauge (new_ptr(ShowerParticle(gluon, true ))); - ShowerParticlePtr incoming (new_ptr(ShowerParticle(b, false))); - ShowerParticlePtr parent (new_ptr(ShowerParticle(e, true ))); + PPtr emitter = e ->produceParticle(momenta[1]); + PPtr spectator = s ->produceParticle(momenta[2]); + PPtr gauge = gluon->produceParticle(momenta[3]); + PPtr incoming = b ->produceParticle(bProgenitor->momentum()); - // set momenta - emitter ->set5Momentum(momenta[1]); - spectator->set5Momentum(momenta[2]); - gauge ->set5Momentum(momenta[3]); - incoming ->set5Momentum(bProgenitor->progenitor()->momentum()); - Lorentz5Momentum parentMomentum(momenta[1]+momenta[3]); - parentMomentum.rescaleMass(); - parent->set5Momentum(parentMomentum); - - // create the vectors of HardBranchings to create the HardTree: - vector spaceBranchings,allBranchings; - // incoming particle b - spaceBranchings.push_back(new_ptr(HardBranching(incoming,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - // outgoing particles from hard emission: - HardBranchingPtr spectatorBranch(new_ptr(HardBranching(spectator,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr emitterBranch(new_ptr(HardBranching(parent,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(emitter,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(gauge,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - - if (emitterBranch->branchingParticle()->dataPtr()->hasColour() - && (! emitterBranch->branchingParticle()->dataPtr()->hasAntiColour())) { - emitterBranch->type(ShowerPartnerType::QCDColourLine); + // insert the particles + born->incoming().push_back(incoming); + unsigned int iemit(0),ispect(0); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(born->bornOutgoing()[ix]==finalEmitter) { + born->outgoing().push_back(emitter); + iemit = born->outgoing().size(); + } + else if(born->bornOutgoing()[ix]==finalSpectator) { + born->outgoing().push_back(spectator); + ispect = born->outgoing().size(); + } } - else if (emitterBranch->branchingParticle()->dataPtr()->hasAntiColour() - && (! emitterBranch->branchingParticle()->dataPtr()->hasColour())) { - emitterBranch->type(ShowerPartnerType::QCDAntiColourLine); - } - else - emitterBranch->type(UseRandom::rndbool() ? - ShowerPartnerType::QCDColourLine : - ShowerPartnerType::QCDAntiColourLine); - - allBranchings.push_back(spaceBranchings[0]); - allBranchings.push_back(emitterBranch); - allBranchings.push_back(spectatorBranch); - // make the HardTree from the HardBranching vectors. - HardTreePtr hardtree = new_ptr(HardTree(allBranchings,spaceBranchings, - ShowerInteraction::QCD)); - - // connect the particles with the branchings in the HardTree - hardtree->connect( bProgenitor ->progenitor(), spaceBranchings[0] ); - hardtree->connect( finalEmitter ->progenitor(), allBranchings[1] ); - hardtree->connect( finalSpectator->progenitor(), allBranchings[2] ); - + born->outgoing().push_back(gauge); + if(!spectator->dataPtr()->coloured() || + (finalType != FFa && finalType!=FFc) ) ispect = 0; + born->emitter(iemit); + born->spectator(ispect); + born->emitted(3); // set up colour lines - vector newline; - getColourLines(newline, hardtree, bProgenitor); - + getColourLines(born); // return the tree - return hardtree; + born->interaction(ShowerInteraction::QCD); + return born; } double GeneralTwoBodyDecayer::threeBodyME(const int , const Particle &, const ParticleVector &,MEOption) { throw Exception() << "Base class GeneralTwoBodyDecayer::threeBodyME() " << "called, should have an implementation in the inheriting class" << Exception::runerror; return 0.; } -vector GeneralTwoBodyDecayer::hardMomenta(const ShowerProgenitorPtr &in, - const ShowerProgenitorPtr &emitter, - const ShowerProgenitorPtr &spectator, +vector GeneralTwoBodyDecayer::hardMomenta(const PPtr &in, + const PPtr &emitter, + const PPtr &spectator, const vector &dipoles, int i) { double C = 6.3; double ymax = 10.; double ymin = -ymax; // get masses of the particles - mb_ = in ->progenitor()->momentum().mass(); - e_ = emitter ->progenitor()->momentum().mass()/mb_; - s_ = spectator->progenitor()->momentum().mass()/mb_; + mb_ = in ->momentum().mass(); + e_ = emitter ->momentum().mass()/mb_; + s_ = spectator->momentum().mass()/mb_; e2_ = sqr(e_); s2_ = sqr(s_); vector particleMomenta (4); Energy2 lambda = sqr(mb_)*sqrt(1.+sqr(s2_)+sqr(e2_)-2.*s2_-2.*e2_-2.*s2_*e2_); // calculate A double A = (ymax-ymin)*C*(coupling()->overestimateValue()/(2.*Constants::pi)); Energy pTmax = mb_*(sqr(1.-s_)-e2_)/(2.*(1.-s_)); // if no possible branching return if ( pTmax < pTmin_ ) { particleMomenta.clear(); return particleMomenta; } while (pTmax >= pTmin_) { // generate pT, y and phi values Energy pT = pTmax*pow(UseRandom::rnd(),(1./A)); if (pT < pTmin_) { particleMomenta.clear(); break; } double phi = UseRandom::rnd()*Constants::twopi; double y = ymin+UseRandom::rnd()*(ymax-ymin); double weight[2] = {0.,0.}; double xs[2], xe[2], xe_z[2], xg; for (unsigned int j=0; j<2; j++) { // check if the momenta are physical if (!calcMomenta(j, pT, y, phi, xg, xs[j], xe[j], xe_z[j], particleMomenta)) continue; // check if point lies within phase space if (!psCheck(xg, xs[j])) continue; // decay products for 3 body decay - PPtr inpart = in ->progenitor()->dataPtr()->produceParticle(particleMomenta[0]); + PPtr inpart = in ->dataPtr()->produceParticle(particleMomenta[0]); ParticleVector decay3; - decay3.push_back(emitter ->progenitor()->dataPtr()->produceParticle(particleMomenta[1])); - decay3.push_back(spectator->progenitor()->dataPtr()->produceParticle(particleMomenta[2])); + decay3.push_back(emitter ->dataPtr()->produceParticle(particleMomenta[1])); + decay3.push_back(spectator->dataPtr()->produceParticle(particleMomenta[2])); decay3.push_back(getParticleData(ParticleID::g )->produceParticle(particleMomenta[3])); // decay products for 2 body decay Lorentz5Momentum p1(ZERO,ZERO, lambda/2./mb_,(mb_/2.)*(1.+e2_-s2_),mb_*e_); Lorentz5Momentum p2(ZERO,ZERO,-lambda/2./mb_,(mb_/2.)*(1.+s2_-e2_),mb_*s_); ParticleVector decay2; - decay2.push_back(emitter ->progenitor()->dataPtr()->produceParticle(p1)); - decay2.push_back(spectator->progenitor()->dataPtr()->produceParticle(p2)); + decay2.push_back(emitter ->dataPtr()->produceParticle(p1)); + decay2.push_back(spectator->dataPtr()->produceParticle(p2)); if (decay2[0]->dataPtr()->iSpin()!=PDT::Spin1Half && decay2[1]->dataPtr()->iSpin()==PDT::Spin1Half) swap(decay2[0], decay2[1]); // calculate matrix element ratio R/B double meRatio = matrixElementRatio(*inpart,decay2,decay3,Initialize); // calculate dipole factor InvEnergy2 dipoleSum = ZERO; InvEnergy2 numerator = ZERO; for (int k=0; kratio(pT*pT)/C/Constants::twopi; } // accept point if weight > R if (weight[0] + weight[1] > UseRandom::rnd()) { if (weight[0] > (weight[0] + weight[1])*UseRandom::rnd()) { particleMomenta[1].setE( (mb_/2.)*xe [0]); particleMomenta[1].setZ( (mb_/2.)*xe_z[0]); particleMomenta[2].setE( (mb_/2.)*xs [0]); particleMomenta[2].setZ(-(mb_/2.)*sqrt(sqr(xs[0])-4.*s2_)); } else { particleMomenta[1].setE( (mb_/2.)*xe [1]); particleMomenta[1].setZ( (mb_/2.)*xe_z[1]); particleMomenta[2].setE( (mb_/2.)*xs [1]); particleMomenta[2].setZ(-(mb_/2.)*sqrt(sqr(xs[1])-4.*s2_)); } pT_ = pT; break; } // if there's no branching lower the pT pTmax = pT; } return particleMomenta; } double GeneralTwoBodyDecayer::matrixElementRatio(const Particle & inpart, const ParticleVector & decay2, const ParticleVector & decay3, MEOption meopt) { // calculate R/B double B = me2 (0, inpart, decay2, meopt); double R = threeBodyME(0, inpart, decay3, meopt); return R/B; } bool GeneralTwoBodyDecayer::calcMomenta(int j, Energy pT, double y, double phi, double& xg, double& xs, double& xe, double& xe_z, vector& particleMomenta){ // calculate xg xg = 2.*pT*cosh(y) / mb_; if (xg>(1. - sqr(e_ + s_)) || xg<0.) return false; // calculate the two values of xs double xT = 2.*pT / mb_; double A = 4.-4.*xg+sqr(xT); double B = 4.*(3.*xg-2.+2.*e2_-2.*s2_-sqr(xg)-xg*e2_+xg*s2_); double L = 1.+sqr(s2_)+sqr(e2_)-2.*s2_-2.*e2_-2.*s2_*e2_; double det = 16.*( -L*sqr(xT)+pow(xT,4)*s2_+2.*xg*sqr(xT)*(1.-s2_-e2_)+ L*sqr(xg)-sqr(xg*xT)*(1.+s2_)+pow(xg,4)+ 2.*pow(xg,3)*(-1.+s2_+e2_) ); if (det<0.) return false; if (j==0) xs = (-B+sqrt(det))/(2.*A); if (j==1) xs = (-B-sqrt(det))/(2.*A); // check value of xs is physical if (xs>(1.+s2_-e2_) || xs<2.*s_) return false; // calculate xe xe = 2.-xs-xg; // check value of xe is physical if (xe>(1.+e2_-s2_) || xe<2.*e_) return false; // calculate xe_z double root1 = sqrt(max(0.,sqr(xs)-4.*s2_)), root2 = sqrt(max(0.,sqr(xe)-4.*e2_-sqr(xT))); double epsilon_p = -root1+xT*sinh(y)+root2; double epsilon_m = -root1+xT*sinh(y)-root2; // find direction of emitter if (fabs(epsilon_p) < 1.e-10) xe_z = sqrt(sqr(xe)-4.*e2_-sqr(xT)); else if (fabs(epsilon_m) < 1.e-10) xe_z = -sqrt(sqr(xe)-4.*e2_-sqr(xT)); else return false; // check the emitter is on shell if (fabs((sqr(xe)-sqr(xT)-sqr(xe_z)-4.*e2_))>1.e-10) return false; // calculate 4 momenta particleMomenta[0].setE ( mb_); particleMomenta[0].setX ( ZERO); particleMomenta[0].setY ( ZERO); particleMomenta[0].setZ ( ZERO); particleMomenta[0].setMass( mb_); particleMomenta[1].setE ( mb_*xe/2.); particleMomenta[1].setX (-pT*cos(phi)); particleMomenta[1].setY (-pT*sin(phi)); particleMomenta[1].setZ ( mb_*xe_z/2.); particleMomenta[1].setMass( mb_*e_); particleMomenta[2].setE ( mb_*xs/2.); particleMomenta[2].setX ( ZERO); particleMomenta[2].setY ( ZERO); particleMomenta[2].setZ (-mb_*sqrt(sqr(xs)-4.*s2_)/2.); particleMomenta[2].setMass( mb_*s_); particleMomenta[3].setE ( pT*cosh(y)); particleMomenta[3].setX ( pT*cos(phi)); particleMomenta[3].setY ( pT*sin(phi)); particleMomenta[3].setZ ( pT*sinh(y)); particleMomenta[3].setMass( ZERO); return true; } bool GeneralTwoBodyDecayer::psCheck(const double xg, const double xs) { // check is point is in allowed region of phase space double xe_star = (1.-s2_+e2_-xg)/sqrt(1.-xg); double xg_star = xg/sqrt(1.-xg); if ((sqr(xe_star)-4.*e2_) < 1e-10) return false; double xs_max = (4.+4.*s2_-sqr(xe_star+xg_star)+ sqr(sqrt(sqr(xe_star)-4.*e2_)+xg_star))/ 4.; double xs_min = (4.+4.*s2_-sqr(xe_star+xg_star)+ sqr(sqrt(sqr(xe_star)-4.*e2_)-xg_star))/ 4.; if (xs < xs_min || xs > xs_max) return false; return true; } double GeneralTwoBodyDecayer::colourCoeff(const PDT::Colour emitter, const PDT::Colour spectator, const PDT::Colour other){ // calculate the colour factor of the dipole double numerator=1.; double denominator=1.; if (emitter!=PDT::Colour0 && spectator!=PDT::Colour0 && other!=PDT::Colour0){ if (emitter ==PDT::Colour3 || emitter ==PDT::Colour3bar) numerator=-4./3; else if (emitter ==PDT::Colour8) numerator=-3. ; denominator=-1.*numerator; if (spectator==PDT::Colour3 || spectator==PDT::Colour3bar) numerator-=4./3; else if (spectator==PDT::Colour8) numerator-=3. ; if (other ==PDT::Colour3 || other ==PDT::Colour3bar) numerator+=4./3; else if (other ==PDT::Colour8) numerator+=3. ; numerator*=(-1./2.); } if (emitter==PDT::Colour3 || emitter== PDT::Colour3bar) numerator*=4./3.; else if (emitter==PDT::Colour8 && spectator!=PDT::Colour8) numerator*=3.; else if (emitter==PDT::Colour8 && spectator==PDT::Colour8) numerator*=6.; return (numerator/denominator); } InvEnergy2 GeneralTwoBodyDecayer::calculateDipole(const dipoleType & dipoleId, const Particle & inpart, const ParticleVector & decay3, const dipoleType & emittingDipole){ // calculate dipole for decay b->ac InvEnergy2 dipole = ZERO; double xe = 2.*decay3[0]->momentum().e()/mb_; double xs = 2.*decay3[1]->momentum().e()/mb_; double xg = 2.*decay3[2]->momentum().e()/mb_; double coeff = 8.*Constants::pi*coupling()->value(mb_*mb_); // radiation from b with initial-final connection if (dipoleId==IFba || dipoleId==IFbc){ dipole = -2./sqr(mb_*xg); dipole *= colourCoeff(inpart.dataPtr()->iColour(), decay3[0]->dataPtr()->iColour(), decay3[1]->dataPtr()->iColour()); } // radiation from a/c with initial-final connection else if ((dipoleId==IFa && (emittingDipole==IFba || emittingDipole==IFa || emittingDipole==FFa)) || (dipoleId==IFc && (emittingDipole==IFbc || emittingDipole==IFc || emittingDipole==FFc))){ double z = 1. - xg/(1.-s2_+e2_); dipole = (-2.*e2_/sqr(1.-xs+s2_-e2_)/sqr(mb_) + (1./(1.-xs+s2_-e2_)/sqr(mb_))* (2./(1.-z)-dipoleSpinFactor(decay3[0],z))); dipole *= colourCoeff(decay3[0]->dataPtr()->iColour(),inpart.dataPtr()->iColour(), decay3[1]->dataPtr()->iColour()); } else if (dipoleId==IFa || dipoleId==IFc){ double z = 1. - xg/(1.-e2_+s2_); dipole = (-2.*s2_/sqr(1.-xe+e2_-s2_)/sqr(mb_)+(1./(1.-xe+e2_-s2_)/sqr(mb_))* (2./(1.-z)-dipoleSpinFactor(decay3[1],z))); dipole *= colourCoeff(decay3[1]->dataPtr()->iColour(),inpart.dataPtr()->iColour(), decay3[0]->dataPtr()->iColour()); } // radiation from a/c with final-final connection else if ((dipoleId==FFa && (emittingDipole==IFba || emittingDipole==IFa || emittingDipole==FFa)) || (dipoleId==FFc && (emittingDipole==IFbc || emittingDipole==IFc || emittingDipole==FFc))){ double z = 1. + ((xe-1.+s2_-e2_)/(xs-2.*s2_)); dipole = (1./(1.-xs+s2_-e2_)/sqr(mb_))*((2./(1.-z))-dipoleSpinFactor(decay3[0],z)- (2.*e2_/(1.+s2_-e2_-xs)) ); dipole *= colourCoeff(decay3[0]->dataPtr()->iColour(), decay3[1]->dataPtr()->iColour(), inpart.dataPtr()->iColour()); } else if (dipoleId==FFa || dipoleId==FFc) { double z = 1. + ((xs-1.+e2_-s2_)/(xe-2.*e2_)); dipole = (1./(1.-xe+e2_-s2_)/sqr(mb_))*((2./(1.-z))-dipoleSpinFactor(decay3[1],z)- (2.*s2_/(1.+e2_-s2_-xe)) ); dipole *= colourCoeff(decay3[1]->dataPtr()->iColour(), decay3[0]->dataPtr()->iColour(), inpart.dataPtr()->iColour()); } dipole *= coeff; return dipole; } double GeneralTwoBodyDecayer::dipoleSpinFactor(const PPtr & emitter, double z){ // calculate the spin dependent component of the dipole if (emitter->dataPtr()->iSpin()==PDT::Spin0) return 2.; else if (emitter->dataPtr()->iSpin()==PDT::Spin1Half) return (1. + z); else if (emitter->dataPtr()->iSpin()==PDT::Spin1) return (2.*z*(1.-z) - 1./(1.-z) + 1./z -2.); return 0.; } const vector & GeneralTwoBodyDecayer::getColourFactors(const Particle & inpart, const ParticleVector & decay, unsigned int & nflow){ // calculate the colour factors for the three-body decay vector sing,trip,atrip,oct; for(unsigned int it=0;itdataPtr()->iColour() == PDT::Colour0 ) sing. push_back(it); else if(decay[it]->dataPtr()->iColour() == PDT::Colour3 ) trip. push_back(it); else if(decay[it]->dataPtr()->iColour() == PDT::Colour3bar ) atrip.push_back(it); else if(decay[it]->dataPtr()->iColour() == PDT::Colour8 ) oct. push_back(it); } // require at least one gluon assert(oct.size()>=1); // identical particle symmetry factor double symFactor=1.; if (( sing.size()==2 && decay[ sing[0]]->id()==decay[ sing[1]]->id()) || ( trip.size()==2 && decay[ trip[0]]->id()==decay[ trip[1]]->id()) || (atrip.size()==2 && decay[atrip[0]]->id()==decay[atrip[1]]->id()) || ( oct.size()==2 && decay[ oct[0]]->id()==decay[ oct[1]]->id())) symFactor/=2.; else if (oct.size()==3 && decay[oct[0]]->id()==decay[oct[1]]->id() && decay[oct[0]]->id()==decay[oct[2]]->id()) symFactor/=6.; colour_ = vector(1,DVector(1,symFactor*1.)); // decaying colour singlet if(inpart.dataPtr()->iColour() == PDT::Colour0) { if(trip.size()==1 && atrip.size()==1 && oct.size()==1) { nflow = 1; colour_ = vector(1,DVector(1,symFactor*4.)); } else if (oct.size()==3){ nflow = 1.; colour_ = vector(1,DVector(1,symFactor*24.)); } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour scalar particle in " << "GeneralTwoBodyDecayer::getColourFactors() for " << inpart. dataPtr()->PDGName() << " -> " << decay[0]->dataPtr()->PDGName() << " " << decay[1]->dataPtr()->PDGName() << " " << decay[2]->dataPtr()->PDGName() << Exception::runerror; } // decaying colour triplet else if(inpart.dataPtr()->iColour() == PDT::Colour3) { if(trip.size()==1 && sing.size()==1 && oct.size()==1) { nflow = 1; colour_ = vector(1,DVector(1,symFactor*4./3.)); } else if(trip.size()==1 && oct.size()==2) { nflow = 2; colour_.clear(); colour_.resize(2,DVector(2,0.)); colour_[0][0] = symFactor*16./9.; colour_[0][1] = -symFactor*2./9.; colour_[1][0] = -symFactor*2./9.; colour_[1][1] = symFactor*16./9.; } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour triplet particle in " << "GeneralTwoBodyDecayer::getColourFactors() for " << inpart. dataPtr()->PDGName() << " -> " << decay[0]->dataPtr()->PDGName() << " " << decay[1]->dataPtr()->PDGName() << " " << decay[2]->dataPtr()->PDGName() << Exception::runerror; } // decaying colour anti-triplet else if(inpart.dataPtr()->iColour() == PDT::Colour3bar) { if(atrip.size()==1 && sing.size()==1 && oct.size()==1) { nflow = 1; colour_ = vector(1,DVector(1,symFactor*4./3.)); } else if(atrip.size()==1 && oct.size()==2){ nflow = 2; colour_.clear(); colour_ .resize(2,DVector(2,0.)); colour_[0][0] = symFactor*16./9.; colour_[0][1] = -symFactor*2./9.; colour_[1][0] = -symFactor*2./9.; colour_[1][1] = symFactor*16./9.; } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour anti-triplet particle in " << "GeneralTwoBodyDecayer::getColourFactors() for " << inpart. dataPtr()->PDGName() << " -> " << decay[0]->dataPtr()->PDGName() << " " << decay[1]->dataPtr()->PDGName() << " " << decay[2]->dataPtr()->PDGName() << Exception::runerror; } // decaying colour octet else if(inpart.dataPtr()->iColour() == PDT::Colour8) { if(oct.size()==1 && trip.size()==1 && atrip.size()==1) { nflow = 2; colour_.clear(); colour_.resize(2,DVector(2,0.)); colour_[0][0] = symFactor*2./3. ; colour_[0][1] = -symFactor*1./12.; colour_[1][0] = -symFactor*1./12.; colour_[1][1] = symFactor*2./3. ; } else if (oct.size()==2 && sing.size()==1){ nflow = 1; colour_ = vector(1,DVector(1,symFactor*3.)); } else throw Exception() << "Unknown colour for the outgoing particles" << " for decay colour octet particle in " << "GeneralTwoBodyDecayer::getColourFactors() for " << inpart. dataPtr()->PDGName() << " -> " << decay[0]->dataPtr()->PDGName() << " " << decay[1]->dataPtr()->PDGName() << " " << decay[2]->dataPtr()->PDGName() << Exception::runerror; } else throw Exception() << "Unknown colour for the decaying particle in " << "GeneralTwoBodyDecayer::getColourFactors() for " << inpart. dataPtr()->PDGName() << " -> " << decay[0]->dataPtr()->PDGName() << " " << decay[1]->dataPtr()->PDGName() << " " << decay[2]->dataPtr()->PDGName() << Exception::runerror; return colour_; } bool GeneralTwoBodyDecayer::identifyDipoles(vector & dipoles, - ShowerProgenitorPtr & aProgenitor, - ShowerProgenitorPtr & bProgenitor, - ShowerProgenitorPtr & cProgenitor) const { + PPtr & aProgenitor, + PPtr & bProgenitor, + PPtr & cProgenitor) const { - PDT::Colour bColour = bProgenitor->progenitor()->dataPtr()->iColour(); - PDT::Colour cColour = cProgenitor->progenitor()->dataPtr()->iColour(); - PDT::Colour aColour = aProgenitor->progenitor()->dataPtr()->iColour(); + PDT::Colour bColour = bProgenitor->dataPtr()->iColour(); + PDT::Colour cColour = cProgenitor->dataPtr()->iColour(); + PDT::Colour aColour = aProgenitor->dataPtr()->iColour(); // decaying colour singlet if (bColour==PDT::Colour0 ) { if ((cColour==PDT::Colour3 && aColour==PDT::Colour3bar) || (cColour==PDT::Colour3bar && aColour==PDT::Colour3) || (cColour==PDT::Colour8 && aColour==PDT::Colour8)){ dipoles.push_back(FFa); dipoles.push_back(FFc); } } // decaying colour triplet else if (bColour==PDT::Colour3 ) { if (cColour==PDT::Colour3 && aColour==PDT::Colour0){ dipoles.push_back(IFbc); dipoles.push_back(IFc ); } else if (cColour==PDT::Colour0 && aColour==PDT::Colour3){ dipoles.push_back(IFba); dipoles.push_back(IFa ); } else if (cColour==PDT::Colour8 && aColour==PDT::Colour3){ dipoles.push_back(IFbc); dipoles.push_back(IFc ); dipoles.push_back(FFc ); dipoles.push_back(FFa ); } else if (cColour==PDT::Colour3 && aColour==PDT::Colour8){ dipoles.push_back(IFba); dipoles.push_back(IFa ); dipoles.push_back(FFc ); dipoles.push_back(FFa ); } } // decaying colour anti-triplet else if (bColour==PDT::Colour3bar) { if ((cColour==PDT::Colour3bar && aColour==PDT::Colour0)){ dipoles.push_back(IFbc); dipoles.push_back(IFc ); } else if ((cColour==PDT::Colour0 && aColour==PDT::Colour3bar)){ dipoles.push_back(IFba); dipoles.push_back(IFa ); } else if (cColour==PDT::Colour8 && aColour==PDT::Colour3bar){ dipoles.push_back(IFbc); dipoles.push_back(IFc ); dipoles.push_back(FFc ); dipoles.push_back(FFa ); } else if (cColour==PDT::Colour3bar && aColour==PDT::Colour8){ dipoles.push_back(IFba); dipoles.push_back(IFa ); dipoles.push_back(FFc ); dipoles.push_back(FFa ); } } // decaying colour octet else if (bColour==PDT::Colour8){ if ((cColour==PDT::Colour3 && aColour==PDT::Colour3bar) || (cColour==PDT::Colour3bar && aColour==PDT::Colour3)){ dipoles.push_back(IFba); dipoles.push_back(IFbc); dipoles.push_back(IFa); dipoles.push_back(IFc); } else if (cColour==PDT::Colour8 && aColour==PDT::Colour0){ dipoles.push_back(IFbc); dipoles.push_back(IFc); } else if (cColour==PDT::Colour0 && aColour==PDT::Colour8){ dipoles.push_back(IFba); dipoles.push_back(IFa); } } // check colour structure is allowed return !dipoles.empty(); } const GeneralTwoBodyDecayer::CFlow & GeneralTwoBodyDecayer::colourFlows(const Particle & inpart, const ParticleVector & decay) { // static initialization of commonly used colour structures static const CFlow init = CFlow(3, CFlowPairVec(1, make_pair(0, 1.))); static CFlow tripflow = init; static CFlow atripflow = init; static CFlow octflow = init; static const CFlow fpflow = CFlow(4, CFlowPairVec(1, make_pair(0, 1.))); static bool initialized = false; if (! initialized) { tripflow[2].resize(2, make_pair(0,1.)); tripflow[2][0] = make_pair(0, 1.); tripflow[2][1] = make_pair(1,-1.); tripflow[1][0] = make_pair(1, 1.); atripflow[1].resize(2, make_pair(0,1.)); atripflow[1][0] = make_pair(0, 1.); atripflow[1][1] = make_pair(1,-1.); atripflow[2][0] = make_pair(1, 1.); octflow[0].resize(2, make_pair(0,1.)); octflow[0][0] = make_pair(0,-1.); octflow[0][1] = make_pair(1, 1.); octflow[2][0] = make_pair(1, 1.); initialized = true; } // main function body int sing=0,trip=0,atrip=0,oct=0; for (size_t it=0; itdataPtr()->iColour() ) { case PDT::Colour0: ++sing; break; case PDT::Colour3: ++trip; break; case PDT::Colour3bar: ++atrip; break; case PDT::Colour8: ++oct; break; /// @todo: handle these better case PDT::ColourUndefined: break; case PDT::Coloured: break; case PDT::Colour6: break; case PDT::Colour6bar: break; } } // require a gluon assert(oct>=1); const CFlow * retval = 0; bool inconsistent4PV = true; // decaying colour triplet if(inpart.dataPtr()->iColour() == PDT::Colour3 && trip==1 && oct==2) { retval = &tripflow; } // decaying colour anti-triplet else if(inpart.dataPtr()->iColour() == PDT::Colour3bar && atrip==1 && oct==2){ retval = &atripflow; } // decaying colour octet else if(inpart.dataPtr()->iColour() == PDT::Colour8 && oct==1 && trip==1 && atrip==1) { retval = &octflow; } else { inconsistent4PV = false; retval = &init; } // if a 4 point vertex exists, add a colour flow for it if ( fourPointVertex_ ) { if ( inconsistent4PV ) throw Exception() << "Unknown colour flows for 4 point vertex in " << "GeneralTwoBodyDecayer::colourFlows()" << Exception::runerror; else { retval = &fpflow; } } return *retval; } -void GeneralTwoBodyDecayer::getColourLines(vector & newline, - const HardTreePtr & hardtree, - const ShowerProgenitorPtr & bProgenitor){ - // set up the colour lines - vector branchingPart; - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) - branchingPart.push_back((**cit).branchingParticle()); +void GeneralTwoBodyDecayer::getColourLines(RealEmissionProcessPtr real) { + // extract the particles + vector branchingPart; + branchingPart.push_back(real->incoming()[0]); + for(unsigned int ix=0;ixoutgoing().size();++ix) + branchingPart.push_back(real->outgoing()[ix]); - static vector sing,trip,atrip,oct; - sing.clear(); trip.clear(); atrip.clear(); oct.clear(); - for (size_t ib=0;ib sing,trip,atrip,oct; + for (size_t ib=0;ibdataPtr()->iColour()==PDT::Colour0 ) sing. push_back(ib); else if(branchingPart[ib]->dataPtr()->iColour()==PDT::Colour3 ) trip. push_back(ib); else if(branchingPart[ib]->dataPtr()->iColour()==PDT::Colour3bar) atrip.push_back(ib); else if(branchingPart[ib]->dataPtr()->iColour()==PDT::Colour8 ) oct. push_back(ib); } // decaying colour singlet - if (bProgenitor->progenitor()->dataPtr()->iColour()==PDT::Colour0){ - if (trip.size()==1 && atrip.size()==1){ - newline.push_back(new_ptr(ColourLine())); - newline[0]->addColoured (branchingPart[trip [0]]); - newline[0]->addAntiColoured(branchingPart[atrip[0]]); + if (branchingPart[0]->dataPtr()->iColour()==PDT::Colour0) { + // 0 -> 3 3bar + if (trip.size()==1 && atrip.size()==1) { + branchingPart[atrip[0]]->colourConnect(branchingPart[ 3 ]); + branchingPart[ 3 ]->colourConnect(branchingPart[trip[0]]); } - else if (oct.size()==2){ - newline.push_back(new_ptr(ColourLine())); - newline.push_back(new_ptr(ColourLine())); - newline[0]->addColoured (branchingPart[oct[0]]); - newline[0]->addAntiColoured(branchingPart[oct[1]]); - newline[1]->addColoured (branchingPart[oct[1]]); - newline[1]->addAntiColoured(branchingPart[oct[0]]); + // 0 -> 8 8 + else if (oct.size()==2 ) { + bool col = UseRandom::rndbool(); + branchingPart[oct[0]]->colourConnect(branchingPart[ 3 ],col); + branchingPart[ 3 ]->colourConnect(branchingPart[oct[1]],col); + branchingPart[oct[1]]->colourConnect(branchingPart[oct[0]],col); } + else + assert(false); } // decaying colour triplet - else if (bProgenitor->progenitor()->dataPtr()->iColour()==PDT::Colour3 ){ - if (trip.size()==2 && sing.size()==1){ - newline.push_back(new_ptr(ColourLine())); - newline[0]->addColoured(branchingPart[trip[0]]); - newline[0]->addColoured(branchingPart[trip[1]]); + else if (branchingPart[0]->dataPtr()->iColour()==PDT::Colour3 ){ + // 3 -> 3 0 + if (trip.size()==2 && sing.size()==1) { + branchingPart[3]->incomingColour(branchingPart[trip[0]]); + branchingPart[3]-> colourConnect(branchingPart[trip[1]]); } - else if (trip.size()==2 && oct.size()==1){ - newline.push_back(new_ptr(ColourLine())); - newline.push_back(new_ptr(ColourLine())); - if (branchingPart[trip[0]]->id()==bProgenitor->progenitor()->id()){ - newline[0]->addColoured(branchingPart[trip[0]]); - newline[1]->addColoured(branchingPart[trip[1]]); + // 3 -> 3 8 + else if (trip.size()==2 && oct.size()==1) { + // 8 emit incoming partner + if(real->emitter()==oct[0]&&real->spectator()==0) { + branchingPart[ 3 ]->incomingColour(branchingPart[trip[0]]); + branchingPart[ 3 ]-> colourConnect(branchingPart[oct[0] ]); + branchingPart[oct[0]]-> colourConnect(branchingPart[trip[1]]); } + // 8 emit final spectator or vice veras else { - newline[0]->addColoured(branchingPart[trip[1]]); - newline[1]->addColoured(branchingPart[trip[0]]); + branchingPart[oct[0]]->incomingColour(branchingPart[trip[0]]); + branchingPart[oct[0]]-> colourConnect(branchingPart[ 3 ]); + branchingPart[ 3 ]-> colourConnect(branchingPart[trip[1]]); } - newline[0]->addColoured (branchingPart[ oct[0]]); - newline[1]->addAntiColoured(branchingPart[ oct[0]]); } + else + assert(false); } // decaying colour anti-triplet - else if (bProgenitor->progenitor()->dataPtr()->iColour()==PDT::Colour3bar){ - if (atrip.size()==2 && sing.size()==1){ - newline.push_back(new_ptr(ColourLine())); - newline[0]->addAntiColoured(branchingPart[atrip[0]]); - newline[0]->addAntiColoured(branchingPart[atrip[1]]); + else if (branchingPart[0]->dataPtr()->iColour()==PDT::Colour3bar) { + // 3bar -> 3bar 0 + if (atrip.size()==2 && sing.size()==1) { + branchingPart[3]->incomingColour(branchingPart[atrip[0]],true); + branchingPart[3]-> colourConnect(branchingPart[atrip[1]],true); } + // 3 -> 3 8 else if (atrip.size()==2 && oct.size()==1){ - newline.push_back(new_ptr(ColourLine())); - newline.push_back(new_ptr(ColourLine())); - if (branchingPart[atrip[0]]->id()==bProgenitor->progenitor()->id()){ - newline[0]->addAntiColoured(branchingPart[atrip[0]]); - newline[1]->addAntiColoured(branchingPart[atrip[1]]); + // 8 emit incoming partner + if(real->emitter()==oct[0]&&real->spectator()==0) { + branchingPart[ 3 ]->incomingColour(branchingPart[atrip[0]],true); + branchingPart[ 3 ]-> colourConnect(branchingPart[oct[0] ],true); + branchingPart[oct[0]]-> colourConnect(branchingPart[atrip[1]],true); } + // 8 emit final spectator or vice veras else { - newline[0]->addAntiColoured(branchingPart[atrip[1]]); - newline[1]->addAntiColoured(branchingPart[atrip[0]]); + branchingPart[oct[0]]->incomingColour(branchingPart[atrip[0]],true); + branchingPart[oct[0]]-> colourConnect(branchingPart[ 3 ],true); + branchingPart[3]-> colourConnect(branchingPart[atrip[1]] ,true); } - newline[0]->addAntiColoured(branchingPart[ oct[0]]); - newline[1]->addColoured (branchingPart[ oct[0]]); } + else + assert(false); } // decaying colour octet - else if(bProgenitor->progenitor()->dataPtr()->iColour()==PDT::Colour8 ){ + else if(branchingPart[0]->dataPtr()->iColour()==PDT::Colour8 ) { + // 8 -> 3 3bar if (trip.size()==1 && atrip.size()==1) { - newline.push_back(new_ptr(ColourLine())); - newline.push_back(new_ptr(ColourLine())); - newline[0]->addColoured (branchingPart[ oct[0]]); - newline[1]->addAntiColoured(branchingPart[ oct[0]]); - newline[0]->addColoured (branchingPart[ trip[0]]); - newline[1]->addAntiColoured(branchingPart[atrip[0]]); + // 3 emits + if(trip[0]==real->emitter()) { + branchingPart[3] ->incomingColour(branchingPart[oct[0]] ); + branchingPart[3] -> colourConnect(branchingPart[trip[0]]); + branchingPart[atrip[0]]->incomingColour(branchingPart[oct[0]],true); + } + // 3bar emits + else { + branchingPart[3] ->incomingColour(branchingPart[oct[0]] ,true); + branchingPart[3] -> colourConnect(branchingPart[atrip[0]],true); + branchingPart[trip[0]]->incomingColour(branchingPart[oct[0]] ); + } } - else if (sing.size()==1 && oct.size()==2){ - newline.push_back(new_ptr(ColourLine())); - newline.push_back(new_ptr(ColourLine())); - newline[0]->addColoured (branchingPart[oct[0]]); - newline[0]->addColoured (branchingPart[oct[1]]); - newline[1]->addAntiColoured(branchingPart[oct[0]]); - newline[1]->addAntiColoured(branchingPart[oct[1]]); + // 8 -> 8 0 + else if (sing.size()==1 && oct.size()==2) { + bool col = UseRandom::rndbool(); + branchingPart[ 3 ]->colourConnect (branchingPart[oct[1]], col); + branchingPart[ 3 ]->incomingColour(branchingPart[oct[0]], col); + branchingPart[oct[1]]->incomingColour(branchingPart[oct[0]],!col); } - } - // finally sort out the emitted particles - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) { - if((**cit).children().empty()) continue; - tPPtr emitter = (**cit).children()[0]->branchingParticle(); - tPPtr gauge = (**cit).children()[1]->branchingParticle(); - if(emitter->id()!=(**cit).branchingParticle()->id()) swap(emitter,gauge); - if((**cit).type()==ShowerPartnerType::QCDColourLine) { - (**cit).branchingParticle()->colourLine()->addColoured(gauge); - ColinePtr newline(new_ptr(ColourLine())); - newline-> addColoured(emitter); - newline->addAntiColoured(gauge ); - if((**cit).branchingParticle()->antiColourLine()) - (**cit).branchingParticle()->antiColourLine()->addAntiColoured(emitter); - } - else { - (**cit).branchingParticle()->antiColourLine()->addAntiColoured(gauge); - ColinePtr newline(new_ptr(ColourLine())); - newline->addAntiColoured(emitter); - newline-> addColoured(gauge ); - if((**cit).branchingParticle()->colourLine()) - (**cit).branchingParticle()->colourLine()->addColoured(emitter); - } + else + assert(false); } } diff --git a/Decay/General/GeneralTwoBodyDecayer.h b/Decay/General/GeneralTwoBodyDecayer.h --- a/Decay/General/GeneralTwoBodyDecayer.h +++ b/Decay/General/GeneralTwoBodyDecayer.h @@ -1,456 +1,456 @@ // -*- C++ -*- // // GeneralTwoBodyDecayer.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_GeneralTwoBodyDecayer_H #define HERWIG_GeneralTwoBodyDecayer_H // // This is the declaration of the GeneralTwoBodyDecayer class. // #include "Herwig/Decay/DecayIntegrator.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" #include "ThePEG/Helicity/Vertex/VertexBase.h" #include "GeneralTwoBodyDecayer.fh" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; using Helicity::VertexBasePtr; /** \ingroup Decay * The GeneralTwoBodyDecayer class is designed to be the base class * for 2 body decays for some general model. It inherits from * DecayIntegrator and implements the modeNumber() virtual function * that is the same for all of the decays. A decayer for * a specific spin configuration should inherit from this and implement * the me2() and partialWidth() member functions. The colourConnections() * member should be called from inside me2() in the inheriting decayer * to set up the colour lines. * * @see \ref GeneralTwoBodyDecayerInterfaces "The interfaces" * defined for GeneralTwoBodyDecayer. * @see DecayIntegrator */ class GeneralTwoBodyDecayer: public DecayIntegrator { public: /** A ParticleData ptr and (possible) mass pair.*/ typedef pair PMPair; public: /** * The default constructor. */ GeneralTwoBodyDecayer() : _maxweight(1.), mb_(ZERO), e_(0.), s_(0.), e2_(0.), s2_(0.), pTmin_(GeV), pT_(ZERO), colour_(1,DVector(1,1.)) {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * For a given decay mode and a given particle instance, perform the * decay and return the decay products. As this is the base class this * is not implemented. * @return The vector of particles produced in the decay. */ virtual ParticleVector decay(const Particle & parent, const tPDVector & children) const; /** * Which of the possible decays is required * @param cc Is this mode the charge conjugate * @param parent The decaying particle * @param children The decay products */ virtual int modeNumber(bool & cc, tcPDPtr parent,const tPDVector & children) const; /** * Return the matrix element squared for a given mode and phase-space channel * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int , const Particle & part, const ParticleVector & decay, MEOption meopt) const = 0; /** * Function to return partial Width * @param inpart The decaying particle. * @param outa One of the decay products. * @param outb The other decay product. */ virtual Energy partialWidth(PMPair inpart, PMPair outa, PMPair outb) const; /** * Specify the \f$1\to2\f$ matrix element to be used in the running width * calculation. * @param dm The DecayMode * @param mecode The code for the matrix element as described * in the GenericWidthGenerator class. * @param coupling The coupling for the matrix element. * @return True if the the order of the particles in the * decayer is the same as the DecayMode tag. */ virtual bool twoBodyMEcode(const DecayMode & dm, int & mecode, double & coupling) const; /** * An overidden member to calculate a branching ratio for a certain * particle instance. * @param dm The DecayMode of the particle * @param p The particle object * @param oldbrat The branching fraction given in the DecayMode object */ virtual double brat(const DecayMode & dm, const Particle & p, double oldbrat) const; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return No;} /** * Member to generate the hardest emission in the POWHEG scheme */ - virtual HardTreePtr generateHardest(ShowerTreePtr); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr); + /** * Three-body matrix element including additional QCD radiation */ virtual double threeBodyME(const int , const Particle & inpart, const ParticleVector & decay, MEOption meopt); //@} /** * Set the information on the decay */ void setDecayInfo(PDPtr incoming,PDPair outgoing, VertexBasePtr,VertexBasePtr, const vector &, VertexBasePtr); protected: /** @name Functions used by inheriting decayers. */ //@{ /** * Get vertex pointer * @return a pointer to the vertex */ VertexBasePtr getVertex() const { return vertex_; } /** * Get vertex pointer * @return a pointer to the vertex for QCD radiation off the decaying particle */ VertexBasePtr getIncomingVertex() const { return incomingVertex_; } /** * Get vertex pointer * @return a pointer to the vertex for QCD radiation off the decay products */ vector getOutgoingVertices() const { return outgoingVertices_; } /** * Get vertex pointer * @return a pointer to the vertex for QCD radiation from 4 point vertex */ VertexBasePtr getFourPointVertex() const { return fourPointVertex_; } /** * Set integration weight * @param wgt Maximum integration weight */ - void setWeight(const double & wgt) { _maxweight = wgt; } + void setWeight(double wgt) { _maxweight = wgt; } /** * Set colour connections * @param parent Parent particle * @param out Particle vector containing particles to * connect colour lines */ void colourConnections(const Particle & parent, const ParticleVector & out) const; /** * Type of dipole */ enum dipoleType {FFa, FFc, IFa, IFc, IFba, IFbc}; /** * Compute the spin and colour factor */ double colourFactor(tcPDPtr in, tcPDPtr out1, tcPDPtr out2) const; /** * Calculate matrix element ratio R/B */ double matrixElementRatio(const Particle & inpart, const ParticleVector & decay2, const ParticleVector & decay3, MEOption meopt); /** * Calculate momenta of all the particles */ bool calcMomenta(int j, Energy pT, double y, double phi, double& xg, double& xs, double& xe, double& xe_z, vector& particleMomenta); /** * Check the calculated momenta are physical */ bool psCheck(const double xg, const double xs); /** * Return the momenta including the hard emission */ - vector hardMomenta(const ShowerProgenitorPtr &in, - const ShowerProgenitorPtr &emitter, - const ShowerProgenitorPtr &spectator, + vector hardMomenta(const PPtr &in, + const PPtr &emitter, + const PPtr &spectator, const vector &dipoles, int i); /** * Return dipole corresponding to the dipoleType dipoleId */ InvEnergy2 calculateDipole(const dipoleType & dipoleId, const Particle & inpart, const ParticleVector & decay3, const dipoleType & emittingDipole); /** * Return contribution to dipole that depends on the spin of the emitter */ double dipoleSpinFactor(const PPtr & emitter, double z); /** * Work out the type of process */ bool identifyDipoles(vector & dipoles, - ShowerProgenitorPtr & aProgenitor, - ShowerProgenitorPtr & bProgenitor, - ShowerProgenitorPtr & cProgenitor) const; - + PPtr & aProgenitor, + PPtr & bProgenitor, + PPtr & cProgenitor) const; + /** * Set up the colour lines */ - void getColourLines(vector & newline, const HardTreePtr & hardtree, - const ShowerProgenitorPtr & bProgenitor); + void getColourLines(RealEmissionProcessPtr real); /** * Return the colour coefficient of the dipole */ double colourCoeff(const PDT::Colour emitter, const PDT::Colour spectator, const PDT::Colour other); /** * Coupling for the generation of hard radiation */ ShowerAlphaPtr coupling() {return coupling_;} //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} protected: /** * Member for the generation of additional hard radiation */ //@{ /** * Return the matrix of colour factors */ typedef vector > CFlowPairVec; typedef vector CFlow; const vector & getColourFactors(const Particle & inpart, const ParticleVector & decay, unsigned int & nflow); const CFlow & colourFlows(const Particle & inpart, const ParticleVector & decay); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initGeneralTwoBodyDecayer; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ GeneralTwoBodyDecayer & operator=(const GeneralTwoBodyDecayer &); private: /** * Store the incoming particle */ PDPtr _incoming; /** * Outgoing particles */ vector _outgoing; /** * Pointer to vertex */ VertexBasePtr vertex_; /** * Pointer to vertex for radiation from the incoming particle */ VertexBasePtr incomingVertex_; /** * Pointer to the vertices for radiation from the outgoing particles */ vector outgoingVertices_; /** * Pointer to vertex for radiation coming from 4 point vertex */ VertexBasePtr fourPointVertex_; /** * Maximum weight for integration */ double _maxweight; /** * Mass of decaying particle */ Energy mb_; /** * Reduced mass of emitter child particle */ double e_; /** * Reduced mass of spectator child particle */ double s_; /** * Reduced mass of emitter child particle squared */ double e2_; /** * Reduced mass of spectator child particle squared */ double s2_; /** * Minimum \f$p_T\f$ */ Energy pTmin_; /** * Transverse momentum of the emission */ Energy pT_; /** * Coupling for the generation of hard radiation */ ShowerAlphaPtr coupling_; /** * Store colour factors for ME calc. */ vector colour_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of GeneralTwoBodyDecayer. */ template <> struct BaseClassTrait { /** Typedef of the first base class of GeneralTwoBodyDecayer. */ typedef Herwig::DecayIntegrator NthBase; }; /** This template specialization informs ThePEG about the name of * the GeneralTwoBodyDecayer 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::GeneralTwoBodyDecayer"; } }; /** @endcond */ } #endif /* HERWIG_GeneralTwoBodyDecayer_H */ diff --git a/Decay/HwDecayerBase.cc b/Decay/HwDecayerBase.cc --- a/Decay/HwDecayerBase.cc +++ b/Decay/HwDecayerBase.cc @@ -1,140 +1,150 @@ // -*- C++ -*- // // HwDecayerBase.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 HwDecayerBase class. // #include "HwDecayerBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" -#include "Herwig/Shower/Base/HardTree.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; bool HwDecayerBase::accept(const DecayMode & dm) const { // get the primary products tPDVector products=dm.orderedProducts(); // add products for which the decay mode is all ready specified if(!dm.cascadeProducts().empty()) { for(ModeMSet::const_iterator mit=dm.cascadeProducts().begin(); mit!=dm.cascadeProducts().end();++mit) { products.push_back(const_ptr_cast((**mit).parent())); } } // can this mode be handled ? return accept(dm.parent(),products); } ParticleVector HwDecayerBase::decay(const DecayMode & dm, const Particle & p) const { // handling of the decay including the special features of the // DecayMode // get the primary products tPDVector products=dm.orderedProducts(); // add products for which the decay mode is all ready specified if(!dm.cascadeProducts().empty()) { for(ModeMSet::const_iterator mit=dm.cascadeProducts().begin(); mit!=dm.cascadeProducts().end();++mit) { products.push_back(const_ptr_cast((**mit).parent())); } } // perform the primary decay ParticleVector output=decay(p,products); // perform the secondary decays if(!dm.cascadeProducts().empty()) { unsigned int iloc=dm.orderedProducts().size(); for(ModeMSet::const_iterator mit=dm.cascadeProducts().begin(); mit!=dm.cascadeProducts().end();++mit) { if(!(*mit)->decayer()) throw Exception() << "Decay mode " << (**mit).tag() << "does not have a decayer, can't perform" << "decay in HwDecayerBase::decay()" << Exception::eventerror; ParticleVector children=(*mit)->decayer()->decay(**mit,*output[iloc]); for(unsigned int ix=0;ixaddChild(children[ix]); } ++iloc; } } return output; } void HwDecayerBase::persistentOutput(PersistentOStream & os) const { os << _initialize << _dbOutput; } void HwDecayerBase::persistentInput(PersistentIStream & is, int) { is >> _initialize >> _dbOutput; } AbstractClassDescription HwDecayerBase::initHwDecayerBase; // Definition of the static class description member. void HwDecayerBase::Init() { static ClassDocumentation documentation ("The HwDecayerBase class is the base class for Decayers in Hw++."); static Switch interfaceInitialize ("Initialize", "Initialization of the phase space calculation", &HwDecayerBase::_initialize, false, false, false); static SwitchOption interfaceInitializeon (interfaceInitialize, "Yes", "At initialisation find max weight and optimise the integration", true); static SwitchOption interfaceInitializeoff (interfaceInitialize, "No", "Use the maximum weight and channel weights supplied for the integration", false); static Switch interfaceDatabaseOutput ("DatabaseOutput", "Whether to print the database information", &HwDecayerBase::_dbOutput, false, false, false); static SwitchOption interfaceDatabaseOutputYes (interfaceDatabaseOutput, "Yes", "Output information on the decayer initialization", true); static SwitchOption interfaceDatabaseOutputNo (interfaceDatabaseOutput, "No", "Do not output information about the decayer initialization", false); } void HwDecayerBase::dofinish() { Decayer::dofinish(); if(initialize() && databaseOutput()) { string fname = CurrentGenerator::current().filename() + string("-") + name() + string(".output"); ofstream output(fname.c_str()); dataBaseOutput(output,true); } } bool HwDecayerBase::softMatrixElementVeto(ShowerProgenitorPtr, ShowerParticlePtr, Branching) { return false; } -HardTreePtr HwDecayerBase::generateHardest(ShowerTreePtr) { - return HardTreePtr(); +RealEmissionProcessPtr HwDecayerBase::generateHardest(RealEmissionProcessPtr) { + return RealEmissionProcessPtr(); } + +void HwDecayerBase::initializeMECorrection(RealEmissionProcessPtr , double & , + double & ) { + assert(false); +} + +RealEmissionProcessPtr HwDecayerBase::applyHardMatrixElementCorrection(RealEmissionProcessPtr) { + assert(false); + return RealEmissionProcessPtr(); +} diff --git a/Decay/HwDecayerBase.h b/Decay/HwDecayerBase.h --- a/Decay/HwDecayerBase.h +++ b/Decay/HwDecayerBase.h @@ -1,264 +1,263 @@ // -*- C++ -*- // // HwDecayerBase.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_HwDecayerBase_H #define HERWIG_HwDecayerBase_H // // This is the declaration of the HwDecayerBase class. // #include "ThePEG/PDT/Decayer.h" -#include "Herwig/Shower/Base/ShowerParticle.fh" -#include "Herwig/Shower/Base/ShowerProgenitor.fh" -#include "Herwig/Shower/Base/ShowerTree.fh" -#include "Herwig/Shower/Base/HardTree.fh" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.fh" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh" +#include "Herwig/Shower/RealEmissionProcess.fh" #include "HwDecayerBase.fh" namespace Herwig { struct Branching; using namespace ThePEG; /** * The HwDecayerBase class is the base class for Decayers in Herwig. It inherits * from the Decayer class of ThePEG and implements additional functionality for the * output of the results to the particle database and initialization of the datbase. * * It also provide the option of specifying a class based on the DecayRadiationGenerator * which should be used to generate QED radiation in the decay * * @see \ref HwDecayerBaseInterfaces "The interfaces" * defined for HwDecayerBase. */ class HwDecayerBase: public Decayer { public: /** * The default constructor. */ HwDecayerBase() : _initialize(false), _dbOutput(false) {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const; //@} public: /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Type of POWHEG correction */ enum POWHEGType {No, ISR, FSR, Both}; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return No;} /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return false;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr , double & , - double & ) {} + virtual void initializeMECorrection(RealEmissionProcessPtr , double & , + double & ); /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr) {} + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent, Branching br); /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr); //@} protected: /** @name Virtual functions to replaced those from the Decayer class. * This is so that the decay and accept members of this class can handle all * the more complicated features of the DecayMode class */ //@{ /** * Check if this decayer can perfom the decay for a particular mode * @param parent The decaying particle * @param children The decay products * @return true If this decayer can handle the given mode, otherwise false. */ virtual bool accept(tcPDPtr parent, const tPDVector & children) const = 0; /** * Perform the decay of the particle to the specified decay products * @param parent The decaying particle * @param children The decay products * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const Particle & parent, const tPDVector & children) 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(); public: /** * Functions for the Herwig decayer */ //@{ /** * Output the setup information for the particle database * @param os The stream to output the information to * @param header Whether or not to output the information for MySQL */ virtual void dataBaseOutput(ofstream & os,bool header) const = 0; /** * Access to the initialize variable */ bool initialize() const {return _initialize;} /** * Access the database output variable */ bool databaseOutput() const {return _dbOutput;} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initHwDecayerBase; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HwDecayerBase & operator=(const HwDecayerBase &); private: /** * perform initialisation */ bool _initialize; /** * Print out database */ bool _dbOutput; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of HwDecayerBase. */ template <> struct BaseClassTrait { /** Typedef of the first base class of HwDecayerBase. */ typedef Decayer NthBase; }; /** This template specialization informs ThePEG about the name of * the HwDecayerBase 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::HwDecayerBase"; } }; /** @endcond */ } #endif /* HERWIG_HwDecayerBase_H */ diff --git a/Decay/Perturbative/SMHiggsFermionsPOWHEGDecayer.cc b/Decay/Perturbative/SMHiggsFermionsPOWHEGDecayer.cc --- a/Decay/Perturbative/SMHiggsFermionsPOWHEGDecayer.cc +++ b/Decay/Perturbative/SMHiggsFermionsPOWHEGDecayer.cc @@ -1,522 +1,472 @@ //-*- // // This is the implementation of the non-inlined, non-templated member // functions of the SMHiggsFermionsPOWHEGDecayer class. // #include "SMHiggsFermionsPOWHEGDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/HardTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" using namespace Herwig; SMHiggsFermionsPOWHEGDecayer::SMHiggsFermionsPOWHEGDecayer() : CF_(4./3.), pTmin_(1.*GeV) {} IBPtr SMHiggsFermionsPOWHEGDecayer::clone() const { return new_ptr(*this); } IBPtr SMHiggsFermionsPOWHEGDecayer::fullclone() const { return new_ptr(*this); } void SMHiggsFermionsPOWHEGDecayer::persistentOutput(PersistentOStream & os) const { os << alphaS_ << gluon_ << ounit( pTmin_, GeV ); } void SMHiggsFermionsPOWHEGDecayer::persistentInput(PersistentIStream & is, int) { is >> alphaS_ >> gluon_ >> iunit( pTmin_, GeV ); } ClassDescription SMHiggsFermionsPOWHEGDecayer::initSMHiggsFermionsPOWHEGDecayer; // Definition of the static class description member. void SMHiggsFermionsPOWHEGDecayer::Init() { static ClassDocumentation documentation ("There is no documentation for the SMHiggsFermionsPOWHEGDecayer class"); static Reference interfaceCoupling ("Coupling", "The object calculating the strong coupling constant", &SMHiggsFermionsPOWHEGDecayer::alphaS_, false, false, true, false, false); static Parameter interfacePtMin ("minpT", "The pt cut on hardest emision generation", &SMHiggsFermionsPOWHEGDecayer::pTmin_, GeV, 1.*GeV, 0*GeV, 100000.0*GeV, false, false, Interface::limited); } -HardTreePtr SMHiggsFermionsPOWHEGDecayer:: -generateHardest(ShowerTreePtr tree) { - // Get the progenitors: Q and Qbar. - ShowerProgenitorPtr - QProgenitor = tree->outgoingLines().begin()->first, - QbarProgenitor = tree->outgoingLines().rbegin()->first; - if(QProgenitor->id()<0) swap( QProgenitor, QbarProgenitor ); +RealEmissionProcessPtr SMHiggsFermionsPOWHEGDecayer:: +generateHardest(RealEmissionProcessPtr born) { + assert(born->bornOutgoing().size()==2); + // check coloured + if(!born->bornOutgoing()[0]->dataPtr()->coloured()) return RealEmissionProcessPtr(); + // extract required info + higgs_ = born->bornIncoming()[0]; partons_.resize(2); - partons_[0] = QProgenitor->progenitor() ->dataPtr(); - partons_[1] = QbarProgenitor->progenitor()->dataPtr(); - if(!partons_[0]->coloured()) return HardTreePtr(); - // momentum of the partons quark_.resize(2); - quark_[0] = QProgenitor ->copy()->momentum(); - quark_[1] = QbarProgenitor->copy()->momentum(); - // Set the existing mass entries in partons 5 vectors with the - // once and for all. - quark_[0].setMass(partons_[0]->mass()); - quark_[1].setMass(partons_[1]->mass()); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + partons_[ix] = born->bornOutgoing()[ix]->dataPtr(); + quark_[ix] = born->bornOutgoing()[ix]->momentum(); + quark_[ix].setMass(partons_[ix]->mass()); + } + bool order = partons_[0]->id()<0; + if(order) { + swap(partons_[0] ,partons_[1] ); + swap(quark_[0] ,quark_[1] ); + } gauge_.setMass(0.*MeV); - // Get the Higgs boson. - higgs_ = tree->incomingLines().begin()->first->copy(); // Get the Higgs boson mass. mh2_ = (quark_[0] + quark_[1]).m2(); mHiggs_ = sqrt(mh2_); aS_ = SM().alphaS(sqr(mHiggs_)); - Energy particleMass = QProgenitor ->copy()->dataPtr()->mass(); + Energy particleMass = partons_[0]->mass(); mu_ = particleMass/mHiggs_; mu2_ = sqr(mu_); // Generate emission and set _quark[0,1] and _gauge to be the // momenta of q, qbar and g after the hardest emission: if(!getEvent()) { - QProgenitor ->maximumpT(pTmin_,ShowerInteraction::QCD); - QbarProgenitor->maximumpT(pTmin_,ShowerInteraction::QCD); - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = pTmin_; + return born; } // Ensure the energies are greater than the constituent masses: for (int i=0; i<2; i++) { - if (quark_[i].e() < partons_[i]->constituentMass()) return HardTreePtr(); - if (gauge_.e() < gluon_ ->constituentMass()) return HardTreePtr(); + if (quark_[i].e() < partons_[i]->constituentMass()) return RealEmissionProcessPtr(); } + if (gauge_.e() < gluon_ ->constituentMass()) return RealEmissionProcessPtr(); // set masses quark_[0].setMass( partons_[0]->mass() ); quark_[1].setMass( partons_[1]->mass() ); gauge_ .setMass( ZERO ); // assign the emitter based on evolution scales - unsigned int iemitter = quark_[0]*gauge_ > quark_[1]*gauge_ ? 1 : 0; - unsigned int ispectator = iemitter==1 ? 0 : 1; - // Make the particles for the HardTree: - ShowerParticlePtr emitter (new_ptr(ShowerParticle(partons_[iemitter ],true))); - ShowerParticlePtr spectator(new_ptr(ShowerParticle(partons_[ispectator],true))); - ShowerParticlePtr gauge (new_ptr(ShowerParticle(gluon_,true))); - ShowerParticlePtr hboson (new_ptr(ShowerParticle(higgs_->dataPtr(),false))); - ShowerParticlePtr parent (new_ptr(ShowerParticle(partons_[iemitter ],true))); - emitter ->set5Momentum(quark_[iemitter ]); - spectator->set5Momentum(quark_[ispectator]); - gauge ->set5Momentum(gauge_); - hboson->set5Momentum(higgs_->momentum()); - Lorentz5Momentum parentMomentum(quark_[iemitter]+gauge_); - parentMomentum.rescaleMass(); - parent->set5Momentum(parentMomentum); - // Create the vectors of HardBranchings to create the HardTree: - vector spaceBranchings,allBranchings; - // Incoming boson: - spaceBranchings.push_back(new_ptr(HardBranching(hboson,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - // Outgoing particles from hard emission: - HardBranchingPtr spectatorBranch(new_ptr(HardBranching(spectator,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr emitterBranch(new_ptr(HardBranching(parent,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(emitter,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(gauge,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->type(emitterBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - allBranchings.push_back(emitterBranch); - allBranchings.push_back(spectatorBranch); - if(iemitter==1) swap(allBranchings[0],allBranchings[1]); - // Add incoming boson to allBranchings - allBranchings.push_back( spaceBranchings.back() ); - // Make the HardTree from the HardBranching vectors. - HardTreePtr hardtree = new_ptr(HardTree(allBranchings,spaceBranchings, - ShowerInteraction::QCD)); - // Set the maximum pt for all other emissions - Energy ptveto(pT_); - QProgenitor ->maximumpT(ptveto,ShowerInteraction::QCD); - QbarProgenitor->maximumpT(ptveto,ShowerInteraction::QCD); - // Connect the particles with the branchings in the HardTree - hardtree->connect( QProgenitor->progenitor(), allBranchings[0] ); - hardtree->connect( QbarProgenitor->progenitor(), allBranchings[1] ); - // colour flow - ColinePtr newline=new_ptr(ColourLine()); - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) { - if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3) - newline->addColoured((**cit).branchingParticle()); - else if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3bar) - newline->addAntiColoured((**cit).branchingParticle()); - } - ColinePtr newLine2=new_ptr(ColourLine()); - if(emitterBranch->branchingParticle()->dataPtr()->iColour()==PDT::Colour3) { - emitterBranch->branchingParticle()->colourLine()->addColoured(gauge); - newLine2->addColoured(emitter); - newLine2->addAntiColoured(gauge); + unsigned int iemitter = quark_[0]*gauge_ > quark_[1]*gauge_ ? 2 : 1; + unsigned int ispectator = iemitter==1 ? 1 : 2; + // create new partices and insert + PPtr hboson = higgs_->dataPtr()->produceParticle(higgs_->momentum()); + born->incoming().push_back(hboson); + PPtr newq = partons_[0]->produceParticle(quark_[0]); + PPtr newa = partons_[1]->produceParticle(quark_[1]); + PPtr newg = gluon_->produceParticle(gauge_); + // make colour connections + newg->colourNeighbour(newq); + newa->colourNeighbour(newg); + // insert in output structure + if(!order) { + born->outgoing().push_back(newq); + born->outgoing().push_back(newa); } else { - emitterBranch->branchingParticle()->antiColourLine()->addAntiColoured(gauge); - newLine2->addAntiColoured(emitter); - newLine2->addColoured(gauge); + born->outgoing().push_back(newa); + born->outgoing().push_back(newq); + swap(iemitter,ispectator); } - // return the tree - return hardtree; + born->outgoing().push_back(newg); + born->emitter (iemitter ); + born->spectator(ispectator); + born->emitted (3); + born->pT()[ShowerInteraction::QCD] = pT_; + // return process + born->interaction(ShowerInteraction::QCD); + return born; } double SMHiggsFermionsPOWHEGDecayer:: me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const { // fermion mass Energy particleMass = decay[0]->dataPtr()->mass(); // leading-order result double output = SMHiggsFermionsDecayer::me2(ichan,part,decay,meopt); // check decay products coloured, otherwise return if(!decay[0]->dataPtr()->coloured()|| particleMass==ZERO) return output; // inital masses, couplings etc // higgs mass mHiggs_ = part.mass(); // strong coupling aS_ = SM().alphaS(sqr(mHiggs_)); // reduced mass mu_ = particleMass/mHiggs_; mu2_ = sqr(mu_); // generate y double yminus = 0.; double yplus = 1.-2.*mu_*(1.-mu_)/(1.-2*mu2_); double y = yminus + UseRandom::rnd()*(yplus-yminus); //generate z for D31,2 double v = sqrt(sqr(2.*mu2_+(1.-2.*mu2_)*(1.-y))-4.*mu2_)/(1.-2.*mu2_)/(1.-y); double zplus = (1.+v)*(1.-2.*mu2_)*y/2./(mu2_ +(1.-2.*mu2_)*y); double zminus = (1.-v)*(1.-2.*mu2_)*y/2./(mu2_ +(1.-2.*mu2_)*y); double z = zminus + UseRandom::rnd()*(zplus-zminus); // map y,z to x1,x2 for both possible emissions double x2 = 1. - y*(1.-2.*mu2_); double x1 = 1. - z*(x2-2.*mu2_); //get the dipoles InvEnergy2 D1 = dipoleSubtractionTerm( x1, x2); InvEnergy2 D2 = dipoleSubtractionTerm( x2, x1); InvEnergy2 dipoleSum = abs(D1) + abs(D2); //jacobian double jac = (1.-y)*(yplus-yminus)*(zplus-zminus); //calculate real Energy2 realPrefactor = 0.25*sqr(mHiggs_)*sqr(1.-2.*mu2_) /sqrt(calculateLambda(1,mu2_,mu2_))/sqr(Constants::twopi); InvEnergy2 realEmission = calculateRealEmission( x1, x2); // calculate the virtual double virtualTerm = calculateVirtualTerm(); // running mass correction virtualTerm += (8./3. - 2.*log(mu2_))*aS_/Constants::pi; //answer = (born + virtual + real)/born * LO output *= 1. + virtualTerm + 2.*jac*realPrefactor*(realEmission*abs(D1)/dipoleSum - D1); // return the answer return output; } //calculate lambda double SMHiggsFermionsPOWHEGDecayer::calculateLambda(double x, double y, double z) const{ return sqr(x)+sqr(y)+sqr(z)-2.*x*y-2.*x*z-2.*y*z; } //calculates the dipole subtraction term for x1, D31,2 (Dij,k), // 2 is the spectator anti-fermion and 3 is the gluon InvEnergy2 SMHiggsFermionsPOWHEGDecayer:: dipoleSubtractionTerm(double x1, double x2) const{ InvEnergy2 commonPrefactor = CF_*8.*Constants::pi*aS_/sqr(mHiggs_); return commonPrefactor/(1.-x2)* (2.*(1.-2.*mu2_)/(2.-x1-x2)- sqrt((1.-4.*mu2_)/(sqr(x2)-4.*mu2_))* (x2-2.*mu2_)*(2.+(x1-1.)/(x2-2.*mu2_)+2.*mu2_/(1.-x2))/(1.-2.*mu2_)); } //return ME for real emission InvEnergy2 SMHiggsFermionsPOWHEGDecayer:: calculateRealEmission(double x1, double x2) const { InvEnergy2 prefactor = CF_*8.*Constants::pi*aS_/sqr(mHiggs_)/(1.-4.*mu2_); return prefactor*(2. + (1.-x1)/(1.-x2) + (1.-x2)/(1.-x1) + 2.*(1.-2.*mu2_)*(1.-4.*mu2_)/(1.-x1)/(1.-x2) - 2.*(1.-4.*mu2_)*(1./(1.-x2)+1./(1.-x1)) - 2.*mu2_*(1.-4.*mu2_)*(1./sqr(1.-x2)+1./sqr(1.-x1))); } double SMHiggsFermionsPOWHEGDecayer:: calculateVirtualTerm() const { // logs and prefactors double beta = sqrt(1.-4.*mu2_); double L = log((1.+beta)/(1.-beta)); double prefactor = CF_*aS_/Constants::twopi; // non-singlet piece double nonSingletTerm = calculateNonSingletTerm(beta, L); double virtualTerm = -2.+4.*log(mu_)+(2./beta - 2.*beta)*L + (2.-4.*mu2_)/beta*(0.5*sqr(L) - 2.*L*log(beta) + 2.*Herwig::Math::ReLi2((1.-beta)/(1.+beta)) + 2.*sqr(Constants::pi)/3.); double iEpsilonTerm = 2.*(3.-sqr(Constants::pi)/2. + 0.5*log(mu2_) - 1.5*log(1.-2.*mu2_) -(1.-2.*mu2_)/beta*(0.5*sqr(L)+sqr(Constants::pi)/6. -2.*L*log(1.-2.*mu2_)) + nonSingletTerm); return prefactor*(virtualTerm+iEpsilonTerm); } //non-singlet piece of I(epsilon) insertion operator double SMHiggsFermionsPOWHEGDecayer:: calculateNonSingletTerm(double beta, double L) const { return 1.5*log(1.-2.*mu2_) + (1.-2.*mu2_)/beta*(- 2.*L*log(4.*(1.-2.*mu2_)/sqr(1.+beta))+ + 2.*Herwig::Math::ReLi2(sqr((1.-beta)/(1.+beta))) - 2.*Herwig::Math::ReLi2(2.*beta/(1.+beta)) - sqr(Constants::pi)/6.) + log(1.-mu_) - 2.*log(1.-2.*mu_) - 2.*mu2_/(1.-2.*mu2_)*log(mu_/(1.-mu_)) - mu_/(1.-mu_) + 2.*mu_*(2*mu_-1.)/(1.-2.*mu2_) + 0.5*sqr(Constants::pi); } void SMHiggsFermionsPOWHEGDecayer::doinit() { SMHiggsFermionsDecayer::doinit(); gluon_ = getParticleData(ParticleID::g); // Energy quarkMass = getParticleData(ParticleID::b )->mass(); // Energy higgsMass = getParticleData(ParticleID::h0)->mass(); // double mu = quarkMass/higgsMass; // double beta = sqrt(1.-4.*sqr(mu)); // double beta2 = sqr(beta); // double aS = SM().alphaS(sqr(higgsMass)); // double L = log((1.+beta)/(1.-beta)); // cerr << "testing " << beta << " " << mu << "\n"; // cerr << "testing " << aS << " " << L << "\n"; // double fact = // 6.-0.75*(1.+beta2)/beta2+12.*log(mu)-8.*log(beta) // +(5./beta-2.*beta+0.375*sqr(1.-beta2)/beta2/beta)*L // +(1.+beta2)/beta*(4.*L*log(0.5*(1.+beta)/beta) // -2.*log(0.5*(1.+beta))*log(0.5*(1.-beta)) // +8.*Herwig::Math::ReLi2((1.-beta)/(1.+beta)) // -4.*Herwig::Math::ReLi2(0.5*(1.-beta))); // cerr << "testing correction " // << 1.+4./3.*aS/Constants::twopi*fact // << "\n"; // double real = 4./3.*aS/Constants::twopi* // (8.-0.75*(1.+beta2)/beta2+8.*log(mu)-8.*log(beta) // +(3./beta+0.375*sqr(1.-beta2)/pow(beta,3))*L // +(1.+beta2)/beta*(-0.5*sqr(L)+4.*L*log(0.5*(1.+beta)) // -2.*L*log(beta)-2.*log(0.5*(1.+beta))*log(0.5*(1.-beta)) // +6.*Herwig::Math::ReLi2((1.-beta)/(1.+beta)) // -4.*Herwig::Math::ReLi2(0.5*(1.-beta)) // -2./3.*sqr(Constants::pi))); // double virt = 4./3.*aS/Constants::twopi* // (-2.+4.*log(mu)+(2./beta-2.*beta)*L // +(1.+beta2)/beta*(0.5*sqr(L)-2.*L*log(beta)+2.*sqr(Constants::pi)/3. // +2.*Herwig::Math::ReLi2((1.-beta)/(1.+beta)))); // cerr << "testing real " << real << "\n"; // cerr << "testing virtual " << virt << "\n"; // cerr << "testing total no mb corr " << 1.+real+virt << "\n"; // cerr << "testing total mb corr " << 1.+real+virt +(8./3. - 2.*log(sqr(mu)))*aS/Constants::pi << "\n"; // InvEnergy2 Gf = 1.166371e-5/GeV2; // Gf = sqrt(2.)*4*Constants::pi*SM().alphaEM(sqr(higgsMass))/8./SM().sin2ThetaW()/ // sqr(getParticleData(ParticleID::Wplus)->mass()); // cerr << "testing GF " << Gf*GeV2 << "\n"; // Energy LO = (3./8./Constants::pi)*sqrt(2)*sqr(quarkMass)*Gf*higgsMass*beta*beta*beta; // cerr << "testing LO " << LO/GeV << "\n"; // cerr << "testing quark mass " << quarkMass/GeV << "\n"; // cerr << "testing gamma " << (1.+real+virt)*LO/MeV << "\n"; } bool SMHiggsFermionsPOWHEGDecayer::getEvent() { // max pT Energy pTmax = 0.5*sqrt(mh2_); // Define over valued y_max & y_min according to the associated pt_min cut. double ymax = acosh(pTmax/pTmin_); double ymin = -ymax; // pt of the emmission pT_ = pTmax; // prefactor double overEst = 4.; double prefactor = overEst*alphaS_->overestimateValue()*4./3./Constants::twopi; // loop to generate the pt and rapidity bool reject; //arrays to hold the temporary probabilities whilst the for loop progresses double probTemp[2][2]={{0.,0.},{0.,0.}}; probTemp[0][0]=probTemp[0][1]=probTemp[1][0]=probTemp[1][1]=0.; double x1Solution[2][2] = {{0.,0.},{0.,0.}}; double x2Solution[2][2] = {{0.,0.},{0.,0.}}; double x3Solution[2] = {0.,0.}; Energy pT[2] = {pTmax,pTmax}; double yTemp[2] = {0.,0.}; for(int i=0; i<2; i++) { do { // reject the emission reject = true; // generate pt pT[i] *= pow(UseRandom::rnd(),1./(prefactor*(ymax-ymin))); Energy2 pT2 = sqr(pT[i]); if(pT[i] 0 if( discrim2 < ZERO) continue; Energy2 discriminant = sqrt(discrim2); Energy2 fact1 = 3.*mh2_*x3Solution[i]-2.*mh2_+2.*pT2*x3Solution[i]-4.*pT2-mh2_*sqr(x3Solution[i]); Energy2 fact2 = 2.*mh2_*(x3Solution[i]-1.)-2.*pT2; // two solns for x1 x1Solution[i][0] = (fact1 + discriminant)/fact2; x1Solution[i][1] = (fact1 - discriminant)/fact2; x2Solution[i][0] = 2.-x3Solution[i]-x1Solution[i][0]; x2Solution[i][1] = 2.-x3Solution[i]-x1Solution[i][1]; bool found = false; for(unsigned int j=0;j<2;++j) { if(x1Solution[i][j]>=x1Minus && x1Solution[i][j]<=x1Plus && checkZMomenta(x1Solution[i][j], x2Solution[i][j], x3Solution[i], yTemp[i], pT[i])) { InvEnergy2 D1 = dipoleSubtractionTerm( x1Solution[i][j], x2Solution[i][j]); InvEnergy2 D2 = dipoleSubtractionTerm( x2Solution[i][j], x1Solution[i][j]); double dipoleFactor = abs(D1)/(abs(D1) + abs(D2)); probTemp[i][j] = weightPrefactor*pT[i]*dipoleFactor* calculateJacobian(x1Solution[i][j], x2Solution[i][j], pT[i])* calculateRealEmission(x1Solution[i][j], x2Solution[i][j]); found = true; } else { probTemp[i][j] = 0.; } } if(!found) continue; // alpha S piece double wgt = (probTemp[i][0]+probTemp[i][1])*alphaS_->value(sqr(pT[i]))/aS_; // matrix element weight reject = UseRandom::rnd()>wgt; } while(reject); } //end of emitter for loop // no emission if(pT[0]pT[1]){ pT_ = pT[0]; y=yTemp[0]; if(probTemp[0][0]>UseRandom::rnd()*(probTemp[0][0]+probTemp[0][1])) { x1 = x1Solution[0][0]; x2 = x2Solution[0][0]; } else { x1 = x1Solution[0][1]; x2 = x2Solution[0][1]; } } //particle 2 emits, particle 1 spectates else { iemit=1; pT_ = pT[1]; y=yTemp[1]; if(probTemp[1][0]>UseRandom::rnd()*(probTemp[1][0]+probTemp[1][1])) { x1 = x1Solution[1][0]; x2 = x2Solution[1][0]; } else { x1 = x1Solution[1][1]; x2 = x2Solution[1][1]; } } // find spectator unsigned int ispect = iemit == 0 ? 1 : 0; // Find the boost from the lab to the c.o.m with the spectator // along the -z axis, and then invert it. LorentzRotation eventFrame( ( quark_[0] + quark_[1] ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*quark_[ispect]; eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() - Constants::pi ); eventFrame.invert(); //generation of phi double phi = UseRandom::rnd() * Constants::twopi; // spectator quark_[ispect].setT( 0.5*x2*mHiggs_ ); quark_[ispect].setX( ZERO ); quark_[ispect].setY( ZERO ); quark_[ispect].setZ( -sqrt(0.25*mh2_*x2*x2-mh2_*mu2_) ); // gluon gauge_.setT( pT_*cosh(y) ); gauge_.setX( pT_*cos(phi) ); gauge_.setY( pT_*sin(phi) ); gauge_.setZ( pT_*sinh(y) ); gauge_.setMass(ZERO); // emitter reconstructed from gluon & spectator quark_[iemit] = - gauge_ - quark_[ispect]; quark_[iemit].setT( 0.5*mHiggs_*x1 ); // boost constructed vectors into the event frame quark_[0] = eventFrame * quark_[0]; quark_[1] = eventFrame * quark_[1]; gauge_ = eventFrame * gauge_; // need to reset masses because for whatever reason the boost // touches the mass component of the five-vector and can make // zero mass objects acquire a floating point negative mass(!). gauge_.setMass( ZERO ); quark_[iemit] .setMass(partons_[iemit ]->mass()); quark_[ispect].setMass(partons_[ispect]->mass()); return true; } InvEnergy SMHiggsFermionsPOWHEGDecayer::calculateJacobian(double x1, double x2, Energy pT) const{ double xPerp = abs(2.*pT/mHiggs_); Energy jac = mHiggs_*fabs((x1*x2-2.*mu2_*(x1+x2)+sqr(x2)-x2)/xPerp/pow(sqr(x2)-4.*mu2_,1.5)); return 1./jac; //jacobian as defined is dptdy=jac*dx1dx2, therefore we have to divide by it } bool SMHiggsFermionsPOWHEGDecayer::checkZMomenta(double x1, double x2, double x3, double y, Energy pT) const { double xPerp2 = 4.*pT*pT/mHiggs_/mHiggs_; static double tolerance = 1e-6; bool isMomentaReconstructed = false; if(pT*sinh(y)>ZERO) { if(abs(-sqrt(sqr(x2)-4.*mu2_)+sqrt(sqr(x3)-xPerp2) + sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance || abs(-sqrt(sqr(x2)-4.*mu2_)+sqrt(sqr(x3)-xPerp2) - sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance) isMomentaReconstructed=true; } else if(pT*sinh(y) < ZERO){ if(abs(-sqrt(sqr(x2)-4.*mu2_)-sqrt(sqr(x3)-xPerp2) + sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance || abs(-sqrt(sqr(x2)-4.*mu2_)-sqrt(sqr(x3)-xPerp2) - sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance) isMomentaReconstructed=true; } else if(abs(-sqrt(sqr(x2)-4.*mu2_)+ sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance) isMomentaReconstructed=true; return isMomentaReconstructed; } diff --git a/Decay/Perturbative/SMHiggsFermionsPOWHEGDecayer.h b/Decay/Perturbative/SMHiggsFermionsPOWHEGDecayer.h --- a/Decay/Perturbative/SMHiggsFermionsPOWHEGDecayer.h +++ b/Decay/Perturbative/SMHiggsFermionsPOWHEGDecayer.h @@ -1,272 +1,272 @@ // -*- C++ -*- #ifndef HERWIG_SMHiggsFermionsPOWHEGDecayer_H #define HERWIG_SMHiggsFermionsPOWHEGDecayer_H // // This is the declaration of the SMHiggsFermionsPOWHEGDecayer class. // #include "SMHiggsFermionsDecayer.h" #include "Herwig/Utilities/Maths.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.fh" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.fh" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SMHiggsFermionsPOWHEGDecayer class. * * @see \ref SMHiggsFermionsPOWHEGDecayerInterfaces "The interfaces" * defined for SMHiggsFermionsPOWHEGDecayer. */ class SMHiggsFermionsPOWHEGDecayer: public SMHiggsFermionsDecayer { public: /** * The default constructor. */ SMHiggsFermionsPOWHEGDecayer(); /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr); //@} virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initSMHiggsFermionsPOWHEGDecayer; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SMHiggsFermionsPOWHEGDecayer & operator=(const SMHiggsFermionsPOWHEGDecayer &); /** * Calcluate the Kallen function */ double calculateLambda(double x, double y, double z) const; /** * Dipole subtraction term */ InvEnergy2 dipoleSubtractionTerm(double x1, double x2) const; /** * Real emission term */ InvEnergy2 calculateRealEmission(double x1, double x2) const; /** * Virtual term */ double calculateVirtualTerm() const; /** * Non-singlet term */ double calculateNonSingletTerm(double beta, double L) const; /** * Check the sign of the momentum in the \f$z\f$-direction is correct. */ bool checkZMomenta(double x1, double x2, double x3, double y, Energy pT) const; /** * Calculate the Jacobian */ InvEnergy calculateJacobian(double x1, double x2, Energy pT) const; /** * Generate a real emission event */ bool getEvent(); private: /** * The colour factor */ double CF_; /** * The Higgs mass */ mutable Energy mHiggs_; /** * The reduced mass */ mutable double mu_; /** * The square of the reduced mass */ mutable double mu2_; /** * The strong coupling */ mutable double aS_; /** * Stuff ofr the POWHEG correction */ //@{ /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alphaS_; /** * ParticleData object for the gluon */ tcPDPtr gluon_; /** * The cut off on pt, assuming massless quarks. */ Energy pTmin_; // radiative variables (pt,y) Energy pT_; /** * The ParticleData objects for the fermions */ vector partons_; /** * The fermion momenta */ vector quark_; /** * The momentum of the radiated gauge boson */ Lorentz5Momentum gauge_; /** * The Higgs boson */ PPtr higgs_; /** * Higgs mass squared */ Energy2 mh2_; //@} }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SMHiggsFermionsPOWHEGDecayer. */ template <> struct BaseClassTrait { /** Typedef of the first base class of SMHiggsFermionsPOWHEGDecayer. */ typedef Herwig::SMHiggsFermionsDecayer NthBase; }; /** This template specialization informs ThePEG about the name of * the SMHiggsFermionsPOWHEGDecayer 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::SMHiggsFermionsPOWHEGDecayer"; } /** * The name of a file containing the dynamic library where the class * SMHiggsFermionsPOWHEGDecayer is implemented. It may also include several, space-separated, * libraries if the class SMHiggsFermionsPOWHEGDecayer 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 "HwPerturbativeHiggsDecay.so"; } }; /** @endcond */ } #endif /* HERWIG_SMHiggsFermionsPOWHEGDecayer_H */ diff --git a/Decay/Perturbative/SMTopDecayer.cc b/Decay/Perturbative/SMTopDecayer.cc --- a/Decay/Perturbative/SMTopDecayer.cc +++ b/Decay/Perturbative/SMTopDecayer.cc @@ -1,1202 +1,1141 @@ // -*- C++ -*- // // SMTopDecayer.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 SMTopDecayer class. // #include "SMTopDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Decay/DecayVertex.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/PDT/ThreeBodyAllOn1IntegralCalculator.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; SMTopDecayer::SMTopDecayer() : _wquarkwgt(6,0.),_wleptonwgt(3,0.), _xg_sampling(1.5), _initialenhance(1.), _finalenhance(2.3), _useMEforT2(true) { _wleptonwgt[0] = 0.302583; _wleptonwgt[1] = 0.301024; _wleptonwgt[2] = 0.299548; _wquarkwgt[0] = 0.851719; _wquarkwgt[1] = 0.0450162; _wquarkwgt[2] = 0.0456962; _wquarkwgt[3] = 0.859839; _wquarkwgt[4] = 3.9704e-06; _wquarkwgt[5] = 0.000489657; generateIntermediates(true); } bool SMTopDecayer::accept(tcPDPtr parent, const tPDVector & children) const { if(abs(parent->id()) != ParticleID::t) return false; int id0(0),id1(0),id2(0); for(tPDVector::const_iterator it = children.begin(); it != children.end();++it) { int id=(**it).id(),absid(abs(id)); if(absid==ParticleID::b&&double(id)/double(parent->id())>0) { id0=id; } else { switch (absid) { case ParticleID::nu_e: case ParticleID::nu_mu: case ParticleID::nu_tau: id1 = id; break; case ParticleID::eminus: case ParticleID::muminus: case ParticleID::tauminus: id2 = id; break; case ParticleID::b: case ParticleID::d: case ParticleID::s: id1 = id; break; case ParticleID::u: case ParticleID::c: id2=id; break; default : break; } } } if(id0==0||id1==0||id2==0) return false; if(double(id1)/double(id2)>0) return false; return true; } ParticleVector SMTopDecayer::decay(const Particle & parent, const tPDVector & children) const { int id1(0),id2(0); for(tPDVector::const_iterator it = children.begin(); it != children.end();++it) { int id=(**it).id(),absid=abs(id); if(absid == ParticleID::b && double(id)/double(parent.id())>0) continue; //leptons if(absid > 10 && absid%2==0) id1=absid; if(absid > 10 && absid%2==1) id2=absid; //quarks if(absid < 10 && absid%2==0) id2=absid; if(absid < 10 && absid%2==1) id1=absid; } unsigned int imode(0); if(id2 >=11 && id2<=16) imode = (id1-12)/2; else imode = id1+1+id2/2; bool cc = parent.id() == ParticleID::tbar; ParticleVector out(generate(true,cc,imode,parent)); //arrange colour flow PPtr pparent=const_ptr_cast(&parent); out[1]->incomingColour(pparent,out[1]->id()<0); ParticleVector products = out[0]->children(); if(products[0]->hasColour()) products[0]->colourNeighbour(products[1],true); else if(products[0]->hasAntiColour()) products[0]->colourNeighbour(products[1],false); return out; } void SMTopDecayer::persistentOutput(PersistentOStream & os) const { os << _wvertex << _wquarkwgt << _wleptonwgt << _wplus << _alpha << _initialenhance << _finalenhance << _xg_sampling << _useMEforT2; } void SMTopDecayer::persistentInput(PersistentIStream & is, int) { is >> _wvertex >> _wquarkwgt >> _wleptonwgt >> _wplus >> _alpha >> _initialenhance >> _finalenhance >> _xg_sampling >> _useMEforT2; } ClassDescription SMTopDecayer::initSMTopDecayer; // Definition of the static class description member. void SMTopDecayer::Init() { static ClassDocumentation documentation ("This is the implementation of the SMTopDecayer which " "decays top quarks into bottom quarks and either leptons " "or quark-antiquark pairs including the matrix element for top decay", "The matrix element correction for top decay \\cite{Hamilton:2006ms}.", "%\\cite{Hamilton:2006ms}\n" "\\bibitem{Hamilton:2006ms}\n" " K.~Hamilton and P.~Richardson,\n" " ``A simulation of QCD radiation in top quark decays,''\n" " JHEP {\\bf 0702}, 069 (2007)\n" " [arXiv:hep-ph/0612236].\n" " %%CITATION = JHEPA,0702,069;%%\n"); static ParVector interfaceQuarkWeights ("QuarkWeights", "Maximum weights for the hadronic decays", &SMTopDecayer::_wquarkwgt, 6, 1.0, 0.0, 10.0, false, false, Interface::limited); static ParVector interfaceLeptonWeights ("LeptonWeights", "Maximum weights for the semi-leptonic decays", &SMTopDecayer::_wleptonwgt, 3, 1.0, 0.0, 10.0, false, false, Interface::limited); static Parameter interfaceEnhancementFactor ("InitialEnhancementFactor", "The enhancement factor for initial-state radiation in the shower to ensure" " the weight for the matrix element correction is less than one.", &SMTopDecayer::_initialenhance, 1.0, 1.0, 10000.0, false, false, Interface::limited); static Parameter interfaceFinalEnhancementFactor ("FinalEnhancementFactor", "The enhancement factor for final-state radiation in the shower to ensure" " the weight for the matrix element correction is less than one", &SMTopDecayer::_finalenhance, 1.6, 1.0, 1000.0, false, false, Interface::limited); static Parameter interfaceSamplingTopHardMEC ("SamplingTopHardMEC", "The importance sampling power for choosing an initial xg, " "to sample xg according to xg^-_xg_sampling", &SMTopDecayer::_xg_sampling, 1.5, 1.2, 2.0, false, false, Interface::limited); static Switch interfaceUseMEForT2 ("UseMEForT2", "Use the matrix element correction, if available to fill the T2" " region for the decay shower and don't fill using the shower", &SMTopDecayer::_useMEforT2, true, false, false); static SwitchOption interfaceUseMEForT2Shower (interfaceUseMEForT2, "Shower", "Use the shower to fill the T2 region", false); static SwitchOption interfaceUseMEForT2ME (interfaceUseMEForT2, "ME", "Use the Matrix element to fill the T2 region", true); static Reference interfaceCoupling ("Coupling", "Pointer to the object to calculate the coupling for the correction", &SMTopDecayer::_alpha, false, false, true, false, false); } double SMTopDecayer::me2(const int, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half))); // spinors etc for the decaying particle if(meopt==Initialize) { // spinors and rho if(inpart.id()>0) SpinorWaveFunction ::calculateWaveFunctions(_inHalf,_rho, const_ptr_cast(&inpart), incoming); else SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,_rho, const_ptr_cast(&inpart), incoming); } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()>0) { SpinorWaveFunction:: constructSpinInfo(_inHalf,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(_inHalfBar,decay[0],outgoing,true); SpinorWaveFunction ::constructSpinInfo(_outHalf ,decay[1],outgoing,true); SpinorBarWaveFunction::constructSpinInfo(_outHalfBar,decay[2],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(_inHalfBar,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(_inHalf,decay[0],outgoing,true); SpinorBarWaveFunction::constructSpinInfo(_outHalfBar,decay[1],outgoing,true); SpinorWaveFunction ::constructSpinInfo(_outHalf ,decay[2],outgoing,true); } } if ( ( decay[1]->momentum() + decay[2]->momentum() ).m() < decay[1]->data().constituentMass() + decay[2]->data().constituentMass() ) return 0.0; // spinors for the decay product if(inpart.id()>0) { SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar ,decay[0],outgoing); SpinorWaveFunction ::calculateWaveFunctions(_outHalf ,decay[1],outgoing); SpinorBarWaveFunction::calculateWaveFunctions(_outHalfBar,decay[2],outgoing); } else { SpinorWaveFunction ::calculateWaveFunctions(_inHalf ,decay[0],outgoing); SpinorBarWaveFunction::calculateWaveFunctions(_outHalfBar,decay[1],outgoing); SpinorWaveFunction ::calculateWaveFunctions(_outHalf ,decay[2],outgoing); } Energy2 scale(sqr(inpart.mass())); if(inpart.id() == ParticleID::t) { //Define intermediate vector wave-function for Wplus tcPDPtr Wplus(getParticleData(ParticleID::Wplus)); VectorWaveFunction inter; unsigned int thel,bhel,fhel,afhel; for(thel = 0;thel<2;++thel){ for(bhel = 0;bhel<2;++bhel){ inter = _wvertex->evaluate(scale,1,Wplus,_inHalf[thel], _inHalfBar[bhel]); for(afhel=0;afhel<2;++afhel){ for(fhel=0;fhel<2;++fhel){ (*ME())(thel,bhel,afhel,fhel) = _wvertex->evaluate(scale,_outHalf[afhel], _outHalfBar[fhel],inter); } } } } } else if(inpart.id() == ParticleID::tbar) { VectorWaveFunction inter; tcPDPtr Wminus(getParticleData(ParticleID::Wminus)); unsigned int tbhel,bbhel,afhel,fhel; for(tbhel = 0;tbhel<2;++tbhel){ for(bbhel = 0;bbhel<2;++bbhel){ inter = _wvertex-> evaluate(scale,1,Wminus,_inHalf[bbhel],_inHalfBar[tbhel]); for(afhel=0;afhel<2;++afhel){ for(fhel=0;fhel<2;++fhel){ (*ME())(tbhel,bbhel,fhel,afhel) = _wvertex->evaluate(scale,_outHalf[afhel], _outHalfBar[fhel],inter); } } } } } double output = (ME()->contract(_rho)).real(); if(abs(decay[1]->id())<=6) output *=3.; return output; } void SMTopDecayer::doinit() { DecayIntegrator::doinit(); //get vertices from SM object tcHwSMPtr hwsm = dynamic_ptr_cast(standardModel()); if(!hwsm) throw InitException() << "Must have Herwig::StandardModel in " << "SMTopDecayer::doinit()"; _wvertex = hwsm->vertexFFW(); //initialise _wvertex->init(); //set up decay modes _wplus = getParticleData(ParticleID::Wplus); DecayPhaseSpaceModePtr mode; DecayPhaseSpaceChannelPtr Wchannel; tPDVector extpart(4); vector wgt(1,1.0); extpart[0] = getParticleData(ParticleID::t); extpart[1] = getParticleData(ParticleID::b); //lepton modes for(int i=11; i<17;i+=2) { extpart[2] = getParticleData(-i); extpart[3] = getParticleData(i+1); mode = new_ptr(DecayPhaseSpaceMode(extpart,this)); Wchannel = new_ptr(DecayPhaseSpaceChannel(mode)); Wchannel->addIntermediate(extpart[0],0,0.0,-1,1); Wchannel->addIntermediate(_wplus,0,0.0,2,3); Wchannel->init(); mode->addChannel(Wchannel); addMode(mode,_wleptonwgt[(i-11)/2],wgt); } //quark modes unsigned int iz=0; for(int ix=1;ix<6;ix+=2) { for(int iy=2;iy<6;iy+=2) { // check that the combination of particles is allowed if(_wvertex->allowed(-ix,iy,ParticleID::Wminus)) { extpart[2] = getParticleData(-ix); extpart[3] = getParticleData( iy); mode = new_ptr(DecayPhaseSpaceMode(extpart,this)); Wchannel = new_ptr(DecayPhaseSpaceChannel(mode)); Wchannel->addIntermediate(extpart[0],0,0.0,-1,1); Wchannel->addIntermediate(_wplus,0,0.0,2,3); Wchannel->init(); mode->addChannel(Wchannel); addMode(mode,_wquarkwgt[iz],wgt); ++iz; } else { throw InitException() << "SMTopDecayer::doinit() the W vertex" << "cannot handle all the quark modes" << Exception::abortnow; } } } } void SMTopDecayer::dataBaseOutput(ofstream & os,bool header) const { if(header) os << "update decayers set parameters=\""; // parameters for the DecayIntegrator base class for(unsigned int ix=0;ix<_wquarkwgt.size();++ix) { os << "newdef " << name() << ":QuarkWeights " << ix << " " << _wquarkwgt[ix] << "\n"; } for(unsigned int ix=0;ix<_wleptonwgt.size();++ix) { os << "newdef " << name() << ":LeptonWeights " << ix << " " << _wleptonwgt[ix] << "\n"; } DecayIntegrator::dataBaseOutput(os,false); if(header) os << "\n\" where BINARY ThePEGName=\"" << fullName() << "\";" << endl; } void SMTopDecayer::doinitrun() { DecayIntegrator::doinitrun(); if(initialize()) { for(unsigned int ix=0;ixmaxWeight(); else _wquarkwgt [ix-3] = mode(ix)->maxWeight(); } } } WidthCalculatorBasePtr SMTopDecayer::threeBodyMEIntegrator(const DecayMode & dm) const { // identify W decay products int sign = dm.parent()->id() > 0 ? 1 : -1; int iferm(0),ianti(0); for(ParticleMSet::const_iterator pit=dm.products().begin(); pit!=dm.products().end();++pit) { int id = (**pit).id(); if(id*sign != ParticleID::b) { if (id*sign > 0 ) iferm = id*sign; else ianti = id*sign; } } assert(iferm!=0&&ianti!=0); // work out which mode we are doing int imode(-1); for(unsigned int ix=0;ixexternalParticles(2)->id() == ianti && mode(ix)->externalParticles(3)->id() == iferm ) { imode = ix; break; } } assert(imode>=0); // get the masses we need Energy m[3] = {mode(imode)->externalParticles(1)->mass(), mode(imode)->externalParticles(3)->mass(), mode(imode)->externalParticles(2)->mass()}; return new_ptr(ThreeBodyAllOn1IntegralCalculator (3,_wplus->mass(),_wplus->width(),0.0,*this,imode,m[0],m[1],m[2])); } InvEnergy SMTopDecayer::threeBodydGammads(const int imode, const Energy2 mt2, const Energy2 mffb2, const Energy mb, const Energy mf, const Energy mfb) const { Energy mffb(sqrt(mffb2)); Energy mw(_wplus->mass()); Energy2 mw2(sqr(mw)),gw2(sqr(_wplus->width())); Energy mt(sqrt(mt2)); Energy Eb = 0.5*(mt2-mffb2-sqr(mb))/mffb; Energy Ef = 0.5*(mffb2-sqr(mfb)+sqr(mf))/mffb; Energy Ebm = sqrt(sqr(Eb)-sqr(mb)); Energy Efm = sqrt(sqr(Ef)-sqr(mf)); Energy2 upp = sqr(Eb+Ef)-sqr(Ebm-Efm); Energy2 low = sqr(Eb+Ef)-sqr(Ebm+Efm); InvEnergy width=(dGammaIntegrand(mffb2,upp,mt,mb,mf,mfb,mw)- dGammaIntegrand(mffb2,low,mt,mb,mf,mfb,mw)) /32./mt2/mt/8/pow(Constants::pi,3)/(sqr(mffb2-mw2)+mw2*gw2); // couplings width *= 0.25*sqr(4.*Constants::pi*generator()->standardModel()->alphaEM(mt2)/ generator()->standardModel()->sin2ThetaW()); width *= generator()->standardModel()->CKM(*mode(imode)->externalParticles(0), *mode(imode)->externalParticles(1)); if(abs(mode(imode)->externalParticles(2)->id())<=6) { width *=3.; if(abs(mode(imode)->externalParticles(2)->id())%2==0) width *=generator()->standardModel()->CKM(*mode(imode)->externalParticles(2), *mode(imode)->externalParticles(3)); else width *=generator()->standardModel()->CKM(*mode(imode)->externalParticles(3), *mode(imode)->externalParticles(2)); } // final spin average assert(!isnan(width*GeV)); return 0.5*width; } Energy6 SMTopDecayer::dGammaIntegrand(Energy2 mffb2, Energy2 mbf2, Energy mt, Energy mb, Energy mf, Energy mfb, Energy mw) const { Energy2 mt2(sqr(mt)) ,mb2(sqr(mb)) ,mf2(sqr(mf )),mfb2(sqr(mfb )),mw2(sqr(mw )); Energy4 mt4(sqr(mt2)),mb4(sqr(mb2)),mf4(sqr(mf2)),mfb4(sqr(mfb2)),mw4(sqr(mw2)); return -mbf2 * ( + 6 * mb2 * mf2 * mfb2 * mffb2 + 6 * mb2 * mt2 * mfb2 * mffb2 + 6 * mb2 * mt2 * mf2 * mffb2 + 12 * mb2 * mt2 * mf2 * mfb2 - 3 * mb2 * mfb4 * mffb2 + 3 * mb2 * mf2 * mffb2 * mffb2 - 3 * mb2 * mf4 * mffb2 - 6 * mb2 * mt2 * mfb4 - 6 * mb2 * mt2 * mf4 - 3 * mb4 * mfb2 * mffb2 - 3 * mb4 * mf2 * mffb2 - 6 * mb4 * mf2 * mfb2 + 3 * mt4 * mf4 + 3 * mb4 * mfb4 + 3 * mb4 * mf4 + 3 * mt4 * mfb4 + 3 * mb2 * mfb2 * mffb2 * mffb2 + 3 * mt2 * mfb2 * mffb2 * mffb2 - 3 * mt2 * mfb4 * mffb2 + 3 * mt2 * mf2 * mffb2 * mffb2 - 3 * mt2 * mf4 * mffb2 - 3 * mt4 * mfb2 * mffb2 - 3 * mt4 * mf2 * mffb2 - 6 * mt4 * mf2 * mfb2 + 6 * mt2 * mf2 * mfb2 * mffb2 + 12 * mt2 * mf2 * mw4 + 12 * mb2 * mfb2 * mw4 + 12 * mb2 * mt2 * mw4 + 6 * mw2 * mt2 * mfb2 * mbf2 - 12 * mw2 * mt2 * mf2 * mffb2 - 6 * mw2 * mt2 * mf2 * mbf2 - 12 * mw2 * mt2 * mf2 * mfb2 - 12 * mw2 * mb2 * mfb2 * mffb2 - 6 * mw2 * mb2 * mfb2 * mbf2 + 6 * mw2 * mb2 * mf2 * mbf2 - 12 * mw2 * mb2 * mf2 * mfb2 - 12 * mw2 * mb2 * mt2 * mfb2 - 12 * mw2 * mb2 * mt2 * mf2 + 12 * mf2 * mfb2 * mw4 + 4 * mbf2 * mbf2 * mw4 - 6 * mfb2 * mbf2 * mw4 - 6 * mf2 * mbf2 * mw4 - 6 * mt2 * mbf2 * mw4 - 6 * mb2 * mbf2 * mw4 + 12 * mw2 * mt2 * mf4 + 12 * mw2 * mt4 * mf2 + 12 * mw2 * mb2 * mfb4 + 12 * mw2 * mb4 * mfb2) /mw4 / 3.; } -void SMTopDecayer::initializeMECorrection(ShowerTreePtr tree, double & initial, +void SMTopDecayer::initializeMECorrection(RealEmissionProcessPtr born, double & initial, double & final) { // check the outgoing particles - map::const_iterator cit; - ShowerParticlePtr part[2]; - unsigned int ix(0); - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - part[ix]=cit->first->progenitor(); - ++ix; + PPtr part[2]; + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + part[ix]= born->bornOutgoing()[ix]; } // check the final-state particles and get the masses if(abs(part[0]->id())==ParticleID::Wplus&&abs(part[1]->id())==ParticleID::b) { _ma=part[0]->mass(); _mc=part[1]->mass(); } else if(abs(part[1]->id())==ParticleID::Wplus&&abs(part[0]->id())==ParticleID::b) { _ma=part[1]->mass(); _mc=part[0]->mass(); } else { return; } // set the top mass - _mt=tree->incomingLines().begin()->first->progenitor()->mass(); + _mt=born->bornIncoming()[0]->mass(); // set the gluon mass _mg=getParticleData(ParticleID::g)->constituentMass(); // set the radiation enhancement factors initial = _initialenhance; final = _finalenhance; // reduced mass parameters _a=sqr(_ma/_mt); _g=sqr(_mg/_mt); _c=sqr(_mc/_mt); + double lambda = sqrt(1.+sqr(_a)+sqr(_c)-2.*_a-2.*_c-2.*_a*_c); + _ktb = 0.5*(3.-_a+_c+lambda); + _ktc = 0.5*(1.-_a+3.*_c+lambda); useMe(); } -void SMTopDecayer::applyHardMatrixElementCorrection(ShowerTreePtr tree) { +RealEmissionProcessPtr SMTopDecayer::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { // Get b and a and put them in particle vector ba in that order... ParticleVector ba; - map::const_iterator cit; - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) - ba.push_back(cit->first->copy()); - PPtr temp; + for(unsigned int ix=0;ixbornOutgoing().size();++ix) + ba.push_back(born->bornOutgoing()[ix]); if(abs(ba[0]->id())!=5) swap(ba[0],ba[1]); - // Get the starting scales for the showers $\tilde{\kappa}_{b}$ - // $\tilde{\kappa}_{c}$. These are needed in order to know the boundary - // of the dead zone. - _ktb = _ktc = -1.; - map::const_iterator cjt; - for(cjt = tree->incomingLines().begin(); - cjt!= tree->incomingLines().end();++cjt) { - if(abs(cjt->first->progenitor()->id())!=6) continue; - if(cjt->first->progenitor()->id()>0) - _ktb=sqr(cjt->first->progenitor()->scales().QCD_c /_mt); - else - _ktb=sqr(cjt->first->progenitor()->scales().QCD_ac/_mt); - } - for(cit = tree->outgoingLines().begin(); - cit!= tree->outgoingLines().end();++cit) { - if(abs(cit->first->progenitor()->id())!=5) continue; - if(cit->first->progenitor()->id()>0) - _ktc=sqr(cit->first->progenitor()->scales().QCD_c /_mt); - else - _ktc=sqr(cit->first->progenitor()->scales().QCD_ac/_mt); - } - if (_ktb<=0.||_ktc<=0.) { - throw Exception() - << "SMTopDecayer::applyHardMatrixElementCorrection()" - << " did not set ktb,ktc" - << Exception::abortnow; - } + assert(born->bornIncoming().size()==1); // Now decide if we get an emission into the dead region. // If there is an emission newfs stores momenta for a,c,g // according to NLO decay matrix element. vector newfs = applyHard(ba,_ktb,_ktc); // If there was no gluon emitted return. - if(newfs.size()!=3) return; + if(newfs.size()!=3) return RealEmissionProcessPtr(); // Sanity checks to ensure energy greater than mass etc :) bool check = true; tcPDPtr gluondata=getParticleData(ParticleID::g); if (newfs[0].e()data().constituentMass()) check = false; if (newfs[1].e()mass()) check = false; if (newfs[2].e()constituentMass()) check = false; // Return if insane: - if (!check) return; - // Set masses in 5-vectors: + if (!check) return RealEmissionProcessPtr(); + // // Set masses in 5-vectors: newfs[0].setMass(ba[0]->mass()); newfs[1].setMass(ba[1]->mass()); newfs[2].setMass(ZERO); // The next part of this routine sets the colour structure. // To do this for decays we assume that the gluon comes from c! // First create new particle objects for c, a and gluon: PPtr newg = gluondata->produceParticle(newfs[2]); - PPtr newc,newa; - newc = ba[0]->data().produceParticle(newfs[0]); - newa = ba[1]; - newa->set5Momentum(newfs[1]); - // set the colour lines - ColinePtr col; - if(ba[0]->id()>0) { - col=ba[0]->colourLine(); - col->addColoured(newg); - newg->colourNeighbour(newc); + PPtr newc = ba[0]->data().produceParticle(newfs[0]); + PPtr newa = ba[1]->data().produceParticle(newfs[1]); + born->spectator(0); + born->emitted(3); + // decaying particle + born->incoming().push_back(born->bornIncoming()[0]->dataPtr()-> + produceParticle(born->bornIncoming()[0]->momentum())); + // colour flow + newg->incomingColour(born->incoming()[0],ba[0]->id()<0); + newg->colourConnect(newc ,ba[0]->id()<0); + if(born->bornOutgoing()[0]->id()==newc->id()) { + born->outgoing().push_back(newc); + born->outgoing().push_back(newa); + born->emitter(1); } - else { - col=ba[0]->antiColourLine(); - col->addAntiColoured(newg); - newg->antiColourNeighbour(newc); + else { + born->outgoing().push_back(newa); + born->outgoing().push_back(newc); + born->emitter(2); } - // change the existing quark and antiquark - PPtr orig; - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(cit->first->progenitor()->id()==newc->id()) { - // remove old particles from colour line - if(newc->id()>0) { - col->removeColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - } - else { - col->removeAntiColoured(cit->first->copy()); - col->removeAntiColoured(cit->first->progenitor()); - } - // insert new particles - cit->first->copy(newc); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newc,2,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(false); - orig=cit->first->original(); - } - else { - cit->first->copy(newa); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newa,2,true))); - map >::const_iterator tit; - for(tit = tree->treelinks().begin(); - tit != tree->treelinks().end();++tit) { - if(tit->second.first && tit->second.second==cit->first->progenitor()) - break; - } - cit->first->progenitor(sp); - if(tit!=tree->treelinks().end()) - tree->updateLink(tit->first,make_pair(cit->first,sp)); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(true); - } - } - // Add the gluon to the shower: - ShowerParticlePtr sg =new_ptr(ShowerParticle(*newg,2,true)); - ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg)); - gluon->perturbative(false); - tree->outgoingLines().insert(make_pair(gluon,sg)); + born->outgoing().push_back(newg); + // boost for the W + LorentzRotation trans(ba[1]->momentum().findBoostToCM()); + trans.boost(newfs[1].boostVector()); + born->transformation(trans); if(!inTheDeadRegion(_xg,_xa,_ktb,_ktc)) { generator()->log() << "SMTopDecayer::applyHardMatrixElementCorrection()\n" << "Just found a point that escaped from the dead region!\n" << " _xg: " << _xg << " _xa: " << _xa << " newfs.size(): " << newfs.size() << endl; } - tree->hardMatrixElementCorrection(true); + born->interaction(ShowerInteraction::QCD); + return born; } vector SMTopDecayer:: applyHard(const ParticleVector &p,double ktb, double ktc) { // ********************************* // // First we see if we get a dead // // region event: _xa,_xg // // ********************************* // vector fs; // Return if there is no (NLO) gluon emission: double weight = getHard(ktb,ktc); if(weight>1.) { generator()->log() << "Weight greater than 1 for hard emission in " << "SMTopDecayer::applyHard xg = " << _xg << " xa = " << _xa << "\n"; weight=1.; } // Accept/Reject if (weightmomentum() + p[1]->momentum(); // Define/assign momenta of c,a and the gluon: if(abs(p[0]->id())==5) { pc_lab = p[0]->momentum(); pa_lab = p[1]->momentum(); } else { pc_lab = p[1]->momentum(); pa_lab = p[0]->momentum(); } // Calculate the boost to the b rest frame: SpinOneLorentzRotation rot0(pb_lab.findBoostToCM()); // Calculate the rotation matrix to position a along the +z direction // in the rest frame of b and does a random rotation about z: SpinOneLorentzRotation rot1 = rotateToZ(rot0*pa_lab); // Calculate the boost from the b rest frame back to the lab: // and the inverse of the random rotation about the z-axis and the // rotation required to align a with +z: SpinOneLorentzRotation invrot = rot0.inverse()*rot1.inverse(); // ************************************ // // Now we construct the momenta in the // // b rest frame using _xa,_xg. // // First we construct b, then c and g, // // finally we generate a by momentum // // conservation. // // ************************************ // Lorentz5Momentum pa_brf, pb_brf(_mt), pc_brf, pg_brf; // First we set the top quark to being on-shell and at rest. // Second we set the energies of c and g, pc_brf.setE(0.5*_mt*(2.-_xa-_xg)); pg_brf.setE(0.5*_mt*_xg); // then their masses, pc_brf.setMass(_mc); pg_brf.setMass(ZERO); // Now set the z-component of c and g. For pg we simply start from // _xa and _xg, while for pc we assume it is equal to minus the sum // of the z-components of a (assumed to point in the +z direction) and g. double root=sqrt(_xa*_xa-4.*_a); pg_brf.setZ(_mt*(1.-_xa-_xg+0.5*_xa*_xg-_c+_a)/root); pc_brf.setZ(-1.*( pg_brf.z()+_mt*0.5*root)); // Now set the y-component of c and g's momenta pc_brf.setY(ZERO); pg_brf.setY(ZERO); // Now set the x-component of c and g's momenta pg_brf.setX(sqrt(sqr(pg_brf.t())-sqr(pg_brf.z()))); pc_brf.setX(-pg_brf.x()); // Momenta b,c,g are now set. Now we obtain a from momentum conservation, pa_brf = pb_brf-pc_brf-pg_brf; pa_brf.setMass(pa_brf.m()); pa_brf.rescaleEnergy(); // ************************************ // // Now we orient the momenta and boost // // them back to the original lab frame. // // ************************************ // // As in herwig6507 we assume that, in the rest frame // of b, we have aligned the W boson momentum in the // +Z direction by rot1*rot0*pa_lab, therefore // we obtain the new pa_lab by applying: // invrot*pa_brf. pa_lab = invrot*pa_brf; pb_lab = invrot*pb_brf; pc_lab = invrot*pc_brf; pg_lab = invrot*pg_brf; fs.push_back(pc_lab); fs.push_back(pa_lab); fs.push_back(pg_lab); return fs; } double SMTopDecayer::getHard(double ktb, double ktc) { // zero the variables _xg = 0.; _xa = 0.; _xc = 0.; // Get a phase space point in the dead region: double volume_factor = deadRegionxgxa(ktb,ktc); // if outside region return -1 if(volume_factor<0) return volume_factor; // Compute the weight for this phase space point: double weight = volume_factor*me(_xa,_xg)*(1.+_a-_c-_xa); // Alpha_S and colour factors - this hard wired Alpha_S needs removing. weight *= (4./3.)/Constants::pi *(_alpha->value(_mt*_mt*_xg*(1.-_xa+_a-_c) /(2.-_xg-_xa-_c))); return weight; } bool SMTopDecayer::softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent,Branching br) { // check if we need to apply the full correction long id[2]={abs(initial->progenitor()->id()),abs(parent->id())}; // the initial-state correction if(id[0]==ParticleID::t&&id[1]==ParticleID::t) { Energy pt=br.kinematics->pT(); // check if hardest so far // if not just need to remove effect of enhancement bool veto(false); // if not hardest so far if(pthighestpT()) veto=!UseRandom::rndbool(1./_initialenhance); // if hardest so far do calculation else { // values of kappa and z double z(br.kinematics->z()),kappa(sqr(br.kinematics->scale()/_mt)); // parameters for the translation double w(1.-(1.-z)*(kappa-1.)),u(1.+_a-_c-(1.-z)*kappa),v(sqr(u)-4.*_a*w*z); // veto if outside phase space if(v<0.) veto=true; // otherwise calculate the weight else { v = sqrt(v); double xa((0.5*(u+v)/w+0.5*(u-v)/z)),xg((1.-z)*kappa); double f(me(xa,xg)), J(0.5*(u+v)/sqr(w)-0.5*(u-v)/sqr(z)+_a*sqr(w-z)/(v*w*z)); double wgt(f*J*2./kappa/(1.+sqr(z)-2.*z/kappa)/_initialenhance); // This next `if' prevents the hardest emission from the // top shower ever entering the so-called T2 region of the // phase space if that region is to be populated by the hard MEC. if(_useMEforT2&&xg>xgbcut(_ktb)) wgt = 0.; if(wgt>1.) { generator()->log() << "Violation of maximum for initial-state " << " soft veto in " << "SMTopDecayer::softMatrixElementVeto" << "xg = " << xg << " xa = " << xa << "weight = " << wgt << "\n"; wgt=1.; } // compute veto from weight veto = !UseRandom::rndbool(wgt); } // if not vetoed reset max if(!veto) initial->highestpT(pt); } // if vetoing reset the scale if(veto) parent->vetoEmission(br.type,br.kinematics->scale()); // return the veto return veto; } // final-state correction else if(id[0]==ParticleID::b&&id[1]==ParticleID::b) { Energy pt=br.kinematics->pT(); // check if hardest so far // if not just need to remove effect of enhancement bool veto(false); // if not hardest so far if(pthighestpT()) return !UseRandom::rndbool(1./_finalenhance); // if hardest so far do calculation // values of kappa and z double z(br.kinematics->z()),kappa(sqr(br.kinematics->scale()/_mt)); // momentum fractions double xa(1.+_a-_c-z*(1.-z)*kappa),r(0.5*(1.+_c/(1.+_a-xa))),root(sqr(xa)-4.*_a); if(root<0.) { generator()->log() << "Imaginary root for final-state veto in " << "SMTopDecayer::softMatrixElementVeto" << "\nz = " << z << "\nkappa = " << kappa << "\nxa = " << xa << "\nroot^2= " << root; parent->vetoEmission(br.type,br.kinematics->scale()); return true; } root=sqrt(root); double xg((2.-xa)*(1.-r)-(z-r)*root); // xfact (below) is supposed to equal xg/(1-z). double xfact(z*kappa/2./(z*(1.-z)*kappa+_c)*(2.-xa-root)+root); // calculate the full result double f(me(xa,xg)); // jacobian double J(z*root); double wgt(f*J*2.*kappa/(1.+sqr(z)-2.*_c/kappa/z)/sqr(xfact)/_finalenhance); if(wgt>1.) { generator()->log() << "Violation of maximum for final-state soft veto in " << "SMTopDecayer::softMatrixElementVeto" << "xg = " << xg << " xa = " << xa << "weight = " << wgt << "\n"; wgt=1.; } // compute veto from weight veto = !UseRandom::rndbool(wgt); // if vetoing reset the scale if(veto) parent->vetoEmission(br.type,br.kinematics->scale()); // return the veto return veto; } // otherwise don't veto else return !UseRandom::rndbool(1./_finalenhance); } double SMTopDecayer::me(double xw,double xg) { double prop(1.+_a-_c-xw),xg2(sqr(xg)); double lambda=sqrt(1.+_a*_a+_c*_c-2.*_a-2.*_c-2.*_a*_c); double denom=(1.-2*_a*_a+_a+_c*_a+_c*_c-2.*_c); double wgt=-_c*xg2/prop+(1.-_a+_c)*xg-(prop*(1 - xg)+xg2) +(0.5*(1.+2.*_a+_c)*sqr(prop-xg)*xg+2.*_a*prop*xg2)/denom; return wgt/(lambda*prop); } // This function is auxiliary to the xab function. double SMTopDecayer::xgbr(int toggle) { return 1.+toggle*sqrt(_a)-_c*(1.-toggle*sqrt(_a))/(1.-_a); } // This function is auxiliary to the xab function. double SMTopDecayer::ktr(double xgb, int toggle) { return 2.*xgb/ (xgb+toggle*sqrt((1.-1./_a) *(xgb-xgbr( 1)) *(xgb-xgbr(-1)))); } // Function xab determines xa (2*W energy fraction) for a given value // of xg (2*gluon energy fraction) and kappa tilde (q tilde squared over // m_top squared). Hence this function allows you to draw 1: the total // phase space volume in the xa vs xg plane 2: for a given value of // kappa tilde (i.e. starting evolution scale) the associated contour // in the xa vs xg plane (and hence the regions that either shower can // populate). This calculation is done assuming the emission came from // the top quark i.e. kappa tilde here is the q tilde squared of the TOP // quark divided by m_top squared. double SMTopDecayer::xab(double xgb, double kt, int toggle) { double xab; if(toggle==2) { // This applies for g==0.&&kt==ktr(a,c,0.,xgb,1). xab = -2.*_a*(xgb-2.)/(1.+_a-_c-xgb); } else if(toggle==1) { // This applies for kt==1&&g==0. double lambda = sqrt(sqr(xgb-1.+_a+_c)-4.*_a*_c); xab = (0.5/(kt-xgb))*(kt*(1.+_a-_c-xgb)-lambda) + (0.5/(kt+xgb*(1.-kt)))*(kt*(1.+_a-_c-xgb)+lambda); } else { // This is the form of xab FOR _g=0. double ktmktrpktmktrm = kt*kt - 4.*_a*(kt-1.)*xgb*xgb / (sqr(1.-_a-_c-xgb)-4.*_a*_c); if(fabs(kt-(2.*xgb-2.*_g)/(xgb-sqrt(xgb*xgb-4.*_g)))/kt>1.e-6) { double lambda = sqrt((sqr(1.-_a-_c-xgb)-4.*_a*_c)*ktmktrpktmktrm); xab = (0.5/(kt-xgb))*(kt*(1.+_a-_c-xgb)-lambda) + (0.5/(kt+xgb*(1.-kt)))*(kt*(1.+_a-_c-xgb)+lambda); } else { // This is the value of xa as a function of xb when kt->infinity. // Where we take any kt > (2.*xgb-2.*_g)/(xgb-sqrt(xgb*xgb-4.*_g)) // as being effectively infinite. This kt value is actually the // maximum allowed value kt can have if the phase space is calculated // without the approximation of _g=0 (massless gluon). This formula // for xab below is then valid for _g=0 AND kt=infinity only. xab = ( 2.*_c+_a*(xgb-2.) + 3.*xgb - xgb*(_c+xgb+sqrt(_a*_a-2.*(_c-xgb+1.)*_a+sqr(_c+xgb-1.))) - 2. )/2./(xgb-1.); } } if(isnan(xab)) { double ktmktrpktmktrm = ( sqr(xgb*kt-2.*(xgb-_g)) -kt*kt*(1.-1./_a)*(xgb-xgbr( 1)-_g/(1.+sqrt(_a))) *(xgb-xgbr(-1)-_g/(1.-sqrt(_a))) )/ (xgb*xgb-(1.-1./_a)*(xgb-xgbr( 1)-_g/(1.+sqrt(_a))) *(xgb-xgbr(-1)-_g/(1.-sqrt(_a))) ); double lambda = sqrt((xgb-1.+sqr(sqrt(_a)+sqrt(_c-_g))) *(xgb-1.+sqr(sqrt(_a)-sqrt(_c-_g)))* ktmktrpktmktrm); xab = (0.5/(kt-xgb+_g))*(kt*(1.+_a-_c+_g-xgb)-lambda) + (0.5/(kt+xgb*(1.-kt)-_g))*(kt*(1.+_a-_c+_g-xgb)+lambda); if(isnan(xab)) throw Exception() << "TopMECorrection::xab complex x_a value.\n" << " xgb = " << xgb << "\n" << " xab = " << xab << "\n" << " toggle = " << toggle << "\n" << " ktmktrpktmktrm = " << ktmktrpktmktrm << Exception::eventerror; } return xab; } // xgbcut is the point along the xg axis where the upper bound on the // top quark (i.e. b) emission phase space goes back on itself in the // xa vs xg plane i.e. roughly mid-way along the xg axis in // the xa vs xg Dalitz plot. double SMTopDecayer::xgbcut(double kt) { double lambda2 = 1.+_a*_a+_c*_c-2.*_a-2.*_c-2.*_a*_c; double num1 = kt*kt*(1.-_a-_c); double num2 = 2.*kt*sqrt(_a*(kt*kt*_c+lambda2*(kt-1.))); return (num1-num2)/(kt*kt-4.*_a*(kt-1.)); } double SMTopDecayer::xaccut(double kt) { return 1.+_a-_c-0.25*kt; } double SMTopDecayer::z(double xac, double kt, int toggle1, int toggle2) { double z = -1.0; if(toggle2==0) { z = (kt+toggle1*sqrt(kt*(kt-4.*(1.+_a-_c-xac))))/(2.*kt); } else if(toggle2==1) { z = ((1.+_a+_c-xac)+toggle1*(1.+_a-_c-xac)) /(2.*(1.+_a-xac)); } else if(toggle2==2) { z = 0.5; } else { throw Exception() << "Cannot determine z in SMTopDecayer::z()" << Exception::eventerror; } return z; } double SMTopDecayer::xgc(double xac, double kt, int toggle1, int toggle2) { double tiny(1.e-6); double xaToMinBoundary(xac*xac-4.*_a); if(xaToMinBoundary<0) { if(fabs(xaToMinBoundary/(1.-_a)/(1.-_a))0.&&(4.*v3+u2)<0.) output = cos( atan(sqrt(-4.*v3-u2)/u)/3.); else if(u>0.&&(4.*v3+u2)>0.) output = cosh(atanh(sqrt( 4.*v3+u2)/u)/3.); else output = cos(( atan(sqrt(-4.*v3-u2)/u) +Constants::pi)/3.); output *= 2.*sqrt(-v); } else { output = sinh(log((u+sqrt(4.*v3+u2))/(2.*sqrt(v3)))/3.); output *= 2.*sqrt(v); } if(isnan(output)||isinf(output)) { throw Exception() << "TopMECorrection::xginvc0:\n" << "possible numerical instability detected.\n" << "\n v = " << v << " u = " << u << "\n4.*v3+u2 = " << 4.*v3+u2 << "\n_a = " << _a << " ma = " << sqrt(_a*_mt*_mt/GeV2) << "\n_c = " << _c << " mc = " << sqrt(_c*_mt*_mt/GeV2) << "\n_g = " << _g << " mg = " << sqrt(_g*_mt*_mt/GeV2) << Exception::eventerror; } return ( 1.+_a +output)/3.; } double SMTopDecayer::approxDeadMaxxa(double xg,double ktb,double ktc) { double maxxa(0.); double x = min(xginvc0(xg,ktc), xab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0)); double y(-9999999999.); if(xg>2.*sqrt(_g)&&xg<=xgbcut(ktb)) { y = max(xab(xg,ktb,0),xab(xg,1.,1)); } else if(xg>=xgbcut(ktb)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) { y = max(xab(xg,ktr(xg,1),2),xab(xg,1.,1)); } if(xg>2.*sqrt(_g)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) { if(x>=y) { maxxa = x ; } else { maxxa = -9999999.; } } else { maxxa = -9999999.; } return maxxa; } double SMTopDecayer::approxDeadMinxa(double xg,double ktb,double ktc) { double minxa(0.); double x = min(xginvc0(xg,ktc), xab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0)); double y(-9999999999.); if(xg>2.*sqrt(_g)&&xg<=xgbcut(ktb)) { y = max(xab(xg,ktb,0),xab(xg,1.,1)); } else if(xg>=xgbcut(ktb)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) { if(_useMEforT2) y = xab(xg,1.,1); else y = max(xab(xg,ktr(xg,1),2),xab(xg,1.,1)); } if(xg>2.*sqrt(_g)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) { if(x>=y) { minxa = y ; } else { minxa = 9999999.; } } else { minxa = 9999999.; } return minxa; } // This function returns true if the phase space point (xg,xa) is in the // kinematically allowed phase space. bool SMTopDecayer::inTheAllowedRegion(double xg , double xa) { bool output(true); if(xg<2.*sqrt(_g)||xg>1.-sqr(sqrt(_a)+sqrt(_c))) output = false; if(xaxab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0)) output = false; return output; } // This function returns true if the phase space point (xg,xa) is in the // approximate (overestimated) dead region. bool SMTopDecayer::inTheApproxDeadRegion(double xg , double xa, double ktb, double ktc) { bool output(true); if(!inTheAllowedRegion(xg,xa)) output = false; if(xaapproxDeadMaxxa(xg,ktb,ktc)) output = false; return output; } // This function returns true if the phase space point (xg,xa) is in the // dead region. bool SMTopDecayer::inTheDeadRegion(double xg , double xa, double ktb, double ktc) { bool output(true); if(!inTheApproxDeadRegion(xg,xa,ktb,ktc)) output = false; if(xa>xaccut(ktc)) { if(xgxgc(xa,ktc, 1,0)) { output = false; } if(xg>xgc(max(xaccut(ktc),2.*sqrt(_a)),ktc,-1,2)&& xgxgmax) throw Exception() << "TopMECorrection::deadRegionxgxa:\n" << "upper xg bound is less than the lower xg bound.\n" << "\n_xg = " << _xg << "\n2.*sqrt(_g) = " << 2.*sqrt(_g) << "\n_a = " << _a << " ma = " << sqrt(_a*_mt*_mt/GeV2) << "\n_c = " << _c << " mc = " << sqrt(_c*_mt*_mt/GeV2) << "\n_g = " << _g << " mg = " << sqrt(_g*_mt*_mt/GeV2) << Exception::eventerror; double xamin(approxDeadMinxa(_xg,ktb,ktc)); double xamax(approxDeadMaxxa(_xg,ktb,ktc)); // Are the bounds sensible? If not return. if(xamax<=xamin) return -1.; _xa=1.+_a-(1.+_a-xamax)*pow((1.+_a-xamin)/(1.+_a-xamax),UseRandom::rnd()); // If outside the allowed region return -1. if(!inTheDeadRegion(_xg,_xa,ktb,ktc)) return -1.; // The integration volume for the weight double xg_vol,xa_vol; if(_xg_sampling==2.) { xg_vol = (xgmax-xgmin) / (xgmax*xgmin); } else { xg_vol = (pow(xgmax,_xg_sampling-1.)-pow(xgmin,_xg_sampling-1.)) / ((_xg_sampling-1.)*pow(xgmax*xgmin,_xg_sampling-1.)); } xa_vol = log((1.+_a-xamin)/(1.+_a-xamax)); // Here we return the integral volume factor multiplied by the part of the // weight left over which is not included in the BRACES function, i.e. // the part of _xg^-2 which is not absorbed in the integration measure. return xg_vol*xa_vol*pow(_xg,_xg_sampling-2.); } LorentzRotation SMTopDecayer::rotateToZ(Lorentz5Momentum v) { // compute the rotation matrix LorentzRotation trans; // rotate so in z-y plane trans.rotateZ(-atan2(v.y(),v.x())); // rotate so along Z trans.rotateY(-acos(v.z()/v.vect().mag())); // generate random rotation double c,s,cs; do { c = 2.*UseRandom::rnd()-1.; s = 2.*UseRandom::rnd()-1.; cs = c*c+s*s; } while(cs>1.||cs==0.); double cost=(c*c-s*s)/cs,sint=2.*c*s/cs; // apply random azimuthal rotation trans.rotateZ(atan2(sint,cost)); return trans; } diff --git a/Decay/Perturbative/SMTopDecayer.h b/Decay/Perturbative/SMTopDecayer.h --- a/Decay/Perturbative/SMTopDecayer.h +++ b/Decay/Perturbative/SMTopDecayer.h @@ -1,523 +1,523 @@ // -*- C++ -*- // // SMTopDecayer.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_SMTopDecayer_H #define HERWIG_SMTopDecayer_H // // This is the declaration of the SMTopDecayer class. // #include "Herwig/Decay/DecayIntegrator.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" #include "Herwig/Models/StandardModel/StandardModel.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.fh" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.fh" namespace Herwig { using namespace ThePEG; using namespace ThePEG::Helicity; /** * \ingroup Decay * * The SMTopDecayer performs decays of the top quark into * the bottom quark and qqbar pairs or to the bottom quark and lepton * neutrino pairs via W boson exchange. */ class SMTopDecayer: public DecayIntegrator { public: /** * The default constructor. */ SMTopDecayer(); public: /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return true;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr , double & , + virtual void initializeMECorrection(RealEmissionProcessPtr , double & , double & ); /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr); + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent,Branching br); //@} public: /** * Which of the possible decays is required */ virtual int modeNumber(bool & , tcPDPtr , const tPDVector & ) const {return -1;} /** * Check if this decayer can perfom the decay for a particular mode. * Uses the modeNumber member but can be overridden * @param parent The decaying particle * @param children The decay products */ virtual bool accept(tcPDPtr parent, const tPDVector & children) const; /** * For a given decay mode and a given particle instance, perform the * decay and return the decay products. As this is the base class this * is not implemented. * @return The vector of particles produced in the decay. */ virtual ParticleVector decay(const Particle & parent, const tPDVector & children) const; /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Method to return an object to calculate the 3 (or higher body) partial width * @param dm The DecayMode * @return A pointer to a WidthCalculatorBase object capable of calculating the width */ virtual WidthCalculatorBasePtr threeBodyMEIntegrator(const DecayMode & dm) const; /** * The differential three body decay rate with one integral performed. * @param imode The mode for which the matrix element is needed. * @param q2 The scale, \e i.e. the mass squared of the decaying particle. * @param s The invariant mass which still needs to be integrate over. * @param m1 The mass of the first outgoing particle. * @param m2 The mass of the second outgoing particle. * @param m3 The mass of the third outgoing particle. * @return The differential rate \f$\frac{d\Gamma}{ds}\f$ */ virtual InvEnergy threeBodydGammads(const int imode, const Energy2 q2, const Energy2 s, const Energy m1, const Energy m2, const Energy m3) const; /** * Output the setup information for the particle database * @param os The stream to output the information to * @param header Whether or not to output the information for MySQL */ virtual void dataBaseOutput(ofstream & os,bool header) 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: /** * The integrand for the integrate partial width */ Energy6 dGammaIntegrand(Energy2 mffb2, Energy2 mbf2, Energy mt, Energy mb, Energy mf, Energy mfb, Energy mw) const; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving and * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} protected: /** * Apply the hard matrix element */ vector applyHard(const ParticleVector &p,double,double); /** * Get the weight for hard emission */ double getHard(double, double); /** * This function is auxiliary to the function \f$x_{a}\f$ (hXAB). */ double xgbr(int); /** * This function is auxiliary to the function \f$x_{a}\f$ (hXAB). */ double ktr(double,int); /** * This function determines \f$x_{a}\f$ as a function of \f$x_{g}\f$ * and \f$\kappa\f$ where \f$\kappa\f$ pertains to emissions from the * b. */ double xab(double,double,int); /** * This function determines the point (\f$x_{g}\f$) where the condition that * \f$x_{a}\f$ be real supersedes that due to the external input * \f$\tilde{\kappa}\f$ where, again, \f$\kappa\f$ pertains to emissions from the * b. */ double xgbcut(double); /** * This function determines the minimum value of \f$x_{a}\f$ * for a given \f$\tilde{\kappa}\f$ where \f$\kappa\f$ pertains to * emissions from the c. */ double xaccut(double); /** * This function is auxiliary to the function \f$x_{g}\f$ (hXGC). */ double z(double,double,int,int); /** * This function determines \f$x_{g}\f$ as a function of \f$x_{a}\f$ * and \f$\kappa\f$ where \f$\kappa\f$ pertains to emissions from the * c. It is multivalued, one selects a branch according to the * second to last integer flag (+/-1). The last integer flag * is used to select whether (1) or not (0) you wish to have the * function for the special case of the full phase space, in which * case the fifth argument \f$\kappa\f$ is irrelevant. */ double xgc(double,double,int,int); /** * This function, \f$x_{g,c=0}^{-1}\f$, returns \f$x_{a}\f$ as a function * of \f$x_{g}\f$ for the special case of c=0, for emissions from c * (the b-quark). The third input is \f$\tilde{\kappa}\f$ which pertains * to emissions from c. */ double xginvc0(double,double); /** * For a given value of \f$x_{g}\f$ this returns the maximum value of \f$x_{a}\f$ * in the dead region. */ double approxDeadMaxxa(double,double,double); /** * For a given value of \f$x_{g}\f$ this returns the maximum value of \f$x_{a}\f$ * in the dead region. */ double approxDeadMinxa(double,double,double); /** * This function returns true or false according to whether the values * xg,xa are in the allowed region, the kinematically accessible phase * space. */ bool inTheAllowedRegion(double,double); /** * This function returns true or false according to whether the values * xg,xa are exactly in the approximate dead region. */ bool inTheApproxDeadRegion(double,double, double,double); /** * This function returns true or false according to whether the values * xg,xa are exactly in the dead region. */ bool inTheDeadRegion(double,double, double,double); /** * This function returns values of (\f$x_{g}\f$,\f$x_{a}\f$) distributed * according to \f$\left(1+a-x_{a}\right)^{-1}x_{g}^{-2}\f$ in the * approximate dead region. */ double deadRegionxgxa(double,double); /** * This rotation takes a 5-momentum and returns a rotation matrix * such that it acts on the input 5-momentum so as to * make it point in the +Z direction. Finally it performs a randomn * rotation about the z-axis. */ LorentzRotation rotateToZ(Lorentz5Momentum); /** * Full matrix element with a factor of \f$\frac{\alpha_SC_F}{x_g^2\pi}\f$ removed. * @param xw The momentum fraction of the W boson * @param xg The momentum fraction of the gluon. */ double me(double xw, double xg); /** * Access to the strong coupling */ ShowerAlphaPtr coupling() { return _alpha;} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initSMTopDecayer; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SMTopDecayer & operator=(const SMTopDecayer &); /** *Pointer to the W vertex */ AbstractFFVVertexPtr _wvertex; /** * Max weight for integration */ //@{ /** * Weight \f$W\to q\bar{q}'\f$ */ vector _wquarkwgt; /** * Weight \f$W\to \ell \nu\f$ */ vector _wleptonwgt; //@} /** * Pointer to the \f$W^\pm\f$ */ PDPtr _wplus; /** * Spin density matrix for the decay */ mutable RhoDMatrix _rho; /** * 1st spinor for the decay */ mutable vector _inHalf; /** * 2nd spinor for the decay */ mutable vector _outHalf; /** * 1st barred spinor for the decay */ mutable vector _inHalfBar; /** * 2nd barred spinor for the decay */ mutable vector _outHalfBar; /** * The mass of the W boson */ Energy _ma; /** * The mass of the bottom quark */ Energy _mc; /** * The top mass */ Energy _mt; /** * The gluon mass. */ Energy _mg; /** * The mass ratio for the W. */ double _a; /** * The mass ratio for the bottom. */ double _c; /** * The mass ratio for the gluon. */ double _g; /** * Two times the energy fraction of a. */ double _ktb; /** * Two times the energy fraction of the gluon. */ double _ktc; /** * Two times the energy fraction of the gluon. */ double _xg; /** * Two times the energy fraction of a. */ double _xa; /** * Two times the energy fraction of c. */ double _xc; /** * This determines the hard matrix element importance * sampling in _xg. _xg_sampling=2.0 samples as 1/xg^2. */ double _xg_sampling; /** * The enhancement factor for initial-state radiation */ double _initialenhance; /** * The enhancement factor for final-state radiation */ double _finalenhance; /** * This flag determines whether the T2 region in the decay shower * (JHEP12(2003)_045) is populated by the ME correction (true) or * the shower from the decaying particle. */ bool _useMEforT2; /** * Pointer to the coupling */ ShowerAlphaPtr _alpha; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SMTopDecayer. */ template <> struct BaseClassTrait { /** Typedef of the first base class of SMTopDecayer. */ typedef Herwig::DecayIntegrator NthBase; }; /** This template specialization informs ThePEG about the name of * the SMTopDecayer 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::SMTopDecayer"; } /** Return the name of the shared library be loaded to get * access to the SMTopDecayer class and every other class it uses * (except the base class). */ static string library() { return "HwPerturbativeDecay.so"; } }; /** @endcond */ } #endif /* HERWIG_SMTopDecayer_H */ diff --git a/Decay/Perturbative/SMTopPOWHEGDecayer.cc b/Decay/Perturbative/SMTopPOWHEGDecayer.cc --- a/Decay/Perturbative/SMTopPOWHEGDecayer.cc +++ b/Decay/Perturbative/SMTopPOWHEGDecayer.cc @@ -1,407 +1,347 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the SMTopPOWHEGDecayer class. // #include "SMTopPOWHEGDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/Base/HardTree.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" using namespace Herwig; -SMTopPOWHEGDecayer::SMTopPOWHEGDecayer() : mt_(ZERO), w_(0.), b_(0.), w2_(0.), b2_(0.), pTmin_(GeV), pT_(ZERO) +SMTopPOWHEGDecayer::SMTopPOWHEGDecayer() : mt_(ZERO), w_(0.), b_(0.), w2_(0.), + b2_(0.), pTmin_(GeV), pT_(ZERO) {} IBPtr SMTopPOWHEGDecayer::clone() const { return new_ptr(*this); } IBPtr SMTopPOWHEGDecayer::fullclone() const { return new_ptr(*this); } void SMTopPOWHEGDecayer::persistentOutput(PersistentOStream & os) const { os << ounit(pTmin_,GeV); } void SMTopPOWHEGDecayer::persistentInput(PersistentIStream & is, int) { is >> iunit(pTmin_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigSMTopPOWHEGDecayer("Herwig::SMTopPOWHEGDecayer", "HwPerturbativeDecay.so"); void SMTopPOWHEGDecayer::Init() { static ClassDocumentation documentation ("There is no documentation for the SMTopPOWHEGDecayer class"); static Parameter interfacepTmin ("pTmin", "Minimum transverse momentum from gluon radiation", &SMTopPOWHEGDecayer::pTmin_, GeV, 1.0*GeV, 0.0*GeV, 10.0*GeV, false, false, Interface::limited); } -HardTreePtr SMTopPOWHEGDecayer::generateHardest(ShowerTreePtr tree) { - +RealEmissionProcessPtr SMTopPOWHEGDecayer::generateHardest(RealEmissionProcessPtr born) { + PPtr top = born->bornIncoming()[0]; // get the bottom and W - assert(tree->outgoingLines().size()==2); - ShowerProgenitorPtr - bProgenitor = tree->outgoingLines(). begin()->first, - WProgenitor = tree->outgoingLines().rbegin()->first; - if(abs(WProgenitor->id())!=ParticleID::Wplus) - swap(bProgenitor,WProgenitor); - // Get the top quark - ShowerProgenitorPtr topProgenitor = tree->incomingLines().begin()->first; + assert(born->bornOutgoing().size()==2); + PPtr bottom = born->bornOutgoing()[0]; + PPtr Wboson = born->bornOutgoing()[1]; + bool order = bottom->id()!=ParticleID::b; + if(order) swap(bottom,Wboson); // masses of the particles - mt_ = topProgenitor->progenitor()->momentum().mass(); - w_ = WProgenitor ->progenitor()->momentum().mass() / mt_; - b_ = bProgenitor ->progenitor()->momentum().mass() / mt_; + mt_ = top ->momentum().mass(); + w_ = Wboson->momentum().mass() / mt_; + b_ = bottom->momentum().mass() / mt_; w2_ = sqr(w_); b2_ = sqr(b_); - - // find rotation fgrom lab to frame with W along -z - LorentzRotation eventFrame( topProgenitor->progenitor()->momentum().findBoostToCM() ); - Lorentz5Momentum pspectator = eventFrame*WProgenitor->progenitor()->momentum(); + LorentzRotation eventFrame( top->momentum().findBoostToCM() ); + Lorentz5Momentum pspectator = eventFrame*Wboson->momentum(); eventFrame.rotateZ( -pspectator.phi() ); eventFrame.rotateY( -pspectator.theta() - Constants::pi ); - //invert it eventFrame.invert(); //generate the hard emission vector momenta = hardMomenta(); - // if no emission return if(momenta.empty()) { - topProgenitor->maximumpT(pTmin_,ShowerInteraction::QCD); - bProgenitor ->maximumpT(pTmin_,ShowerInteraction::QCD); - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = pTmin_; + return born; } - // rotate momenta back to the lab for(unsigned int ix=0;ixprogenitor()->dataPtr(); - tcPDPtr bottom = bProgenitor ->progenitor()->dataPtr(); - tcPDPtr Wboson = WProgenitor ->progenitor()->dataPtr(); - tcPDPtr gluon = getParticleData(ParticleID::g); - // create new ShowerParticles - ShowerParticlePtr emitter (new_ptr(ShowerParticle(bottom,true ))); - ShowerParticlePtr spectator(new_ptr(ShowerParticle(Wboson,true ))); - ShowerParticlePtr gauge (new_ptr(ShowerParticle(gluon ,true ))); - ShowerParticlePtr incoming (new_ptr(ShowerParticle(top ,false))); - ShowerParticlePtr parent (new_ptr(ShowerParticle(bottom,true ))); - // set momenta - emitter ->set5Momentum(momenta[1]); - spectator->set5Momentum(momenta[2]); - gauge ->set5Momentum(momenta[3]); - incoming ->set5Momentum(topProgenitor->progenitor()->momentum()); - Lorentz5Momentum parentMomentum(momenta[1]+momenta[3]); - parentMomentum.rescaleMass(); - parent->set5Momentum(parentMomentum); - // Create the vectors of HardBranchings to create the HardTree: - vector spaceBranchings,allBranchings; - // Incoming top quark - spaceBranchings.push_back(new_ptr(HardBranching(incoming,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - // Outgoing particles from hard emission: - HardBranchingPtr spectatorBranch(new_ptr(HardBranching(spectator,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr emitterBranch(new_ptr(HardBranching(parent,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(emitter,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(gauge,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->type(emitterBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : - ShowerPartnerType::QCDAntiColourLine); - allBranchings.push_back(spaceBranchings[0]); - allBranchings.push_back(emitterBranch); - allBranchings.push_back(spectatorBranch); - // Make the HardTree from the HardBranching vectors. - HardTreePtr hardtree = new_ptr(HardTree(allBranchings,spaceBranchings, - ShowerInteraction::QCD)); - // Set the maximum pt for all other emissions - topProgenitor->maximumpT(pT_,ShowerInteraction::QCD); - bProgenitor ->maximumpT(pT_,ShowerInteraction::QCD); - // Connect the particles with the branchings in the HardTree - hardtree->connect( topProgenitor->progenitor(), spaceBranchings[0] ); - hardtree->connect( bProgenitor->progenitor(), allBranchings[1] ); - hardtree->connect( WProgenitor->progenitor(), allBranchings[2] ); + // create new Particles + PPtr newTop = top ->dataPtr()->produceParticle(top->momentum()); + born->incoming().push_back(newTop); + PPtr newb = bottom->dataPtr()->produceParticle(momenta[1]); + PPtr newW = Wboson->dataPtr()->produceParticle(momenta[2]); + PPtr newg = getParticleData(ParticleID::g)->produceParticle(momenta[3]); // colour flow - ColinePtr newline=new_ptr(ColourLine()); - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) { - - if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3) - newline->addColoured((**cit).branchingParticle()); - else if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3bar) - newline->addAntiColoured((**cit).branchingParticle()); - } - - ColinePtr newLine2=new_ptr(ColourLine()); - if(emitter->dataPtr()->iColour()==PDT::Colour3) { - allBranchings[1]->branchingParticle()->colourLine()->addColoured(gauge); - newLine2->addColoured(emitter); - newLine2->addAntiColoured(gauge); + newg->incomingColour(newTop,top->id()<0); + newg->colourConnect (newb ,top->id()<0); + // outgoing particles + if(!order) { + born->outgoing().push_back(newb); + born->outgoing().push_back(newW); + born->emitter(1); } else { - allBranchings[1]->branchingParticle()->antiColourLine()->addAntiColoured(gauge); - newLine2->addAntiColoured(emitter); - newLine2->addColoured(gauge); + born->outgoing().push_back(newW); + born->outgoing().push_back(newb); + born->emitter(2); } - //return the tree - return hardtree; + born->outgoing().push_back(newg); + // boost for the W + LorentzRotation trans(Wboson->momentum().findBoostToCM()); + trans.boost(momenta[2].boostVector()); + born->transformation(trans); + born->spectator(0); + born->emitted(3); + born->pT()[ShowerInteraction::QCD] = pT_; + born->interaction(ShowerInteraction::QCD); + return born; } vector SMTopPOWHEGDecayer::hardMomenta() { double C = 6.3; double ymax = 10.; double ymin = -ymax; vector particleMomenta (4); Energy2 lambda = sqr(mt_)* sqrt( 1. + sqr(w2_) + sqr(b2_) - 2.*w2_ - 2.*b2_ - 2.*w2_*b2_); //Calculate A double A = (ymax - ymin) * C * (coupling()->overestimateValue() / (2.*Constants::pi)); Energy pTmax = mt_* (sqr(1.-w_) - b2_) / (2.*(1.-w_)); if (pTmax < pTmin_) particleMomenta.clear(); while (pTmax >= pTmin_) { //Generate pT, y and phi values Energy pT = pTmax * pow(UseRandom::rnd() , (1./A)); if (pT < pTmin_) {particleMomenta.clear(); break;} double phi = UseRandom::rnd() * Constants::twopi; double y = ymin + UseRandom::rnd() * (ymax-ymin); double weight[2] = {0.,0.}; double xw[2], xb[2], xb_z[2], xg; for (unsigned int j=0; j<2; j++) { //Check if the momenta are physical bool physical = calcMomenta(j, pT, y, phi, xg, xw[j], xb[j], xb_z[j], particleMomenta); if (! physical) continue; //Check if point lies within phase space bool inPS = psCheck(xg, xw[j]); if (! inPS) continue; //Calculate the ratio R/B double meRatio = matrixElementRatio(particleMomenta); //Calculate jacobian Energy2 denom = (mt_ - particleMomenta[3].e()) * particleMomenta[2].vect().mag() - particleMomenta[2].e() * particleMomenta[3].z(); InvEnergy2 J = (particleMomenta[2].vect().mag2()) / (2.* lambda * denom); //Calculate weight weight[j] = meRatio * fabs(sqr(pT)*J) * coupling()->ratio(pT*pT) / C; } //Accept point if weight > R if (weight[0] + weight[1] > UseRandom::rnd()) { if (weight[0] > (weight[0] + weight[1])*UseRandom::rnd()) { particleMomenta[1].setE( (mt_/2.)*xb [0]); particleMomenta[1].setZ( (mt_/2.)*xb_z[0]); particleMomenta[2].setE( (mt_/2.)*xw [0]); particleMomenta[2].setZ(-(mt_/2.)*sqrt(sqr(xw[0])-4.*w2_)); } else { particleMomenta[1].setE( (mt_/2.)*xb [1]); particleMomenta[1].setZ( (mt_/2.)*xb_z[1]); particleMomenta[2].setE( (mt_/2.)*xw [1]); particleMomenta[2].setZ(-(mt_/2.)*sqrt(sqr(xw[1])-4.*w2_)); } pT_ = pT; break; } //If there's no splitting lower the pT pTmax = pT; } return particleMomenta; } bool SMTopPOWHEGDecayer::deadZoneCheck(double xw, double xg){ //veto events not in the dead cone double Lambda = sqrt(1. + sqr(w2_) + sqr(b2_) - 2.*w2_ - 2.*b2_ - 2.*w2_*b2_); double kappa = b2_ + 0.5*(1. - w2_ + b2_ + Lambda); //invert xw for z values double A = 1.; double B = -1.; double C = (1.+w2_-b2_-xw)/kappa; if((sqr(B) - 4.*A*C) >= 0.){ double z[2]; z[0] = (-B + sqrt(sqr(B) - 4.*A*C))/(2.*A); z[1] = (-B - sqrt(sqr(B) - 4.*A*C))/(2.*A); double r = 0.5*(1. + b2_/(1. + w2_- xw)); double xg_lims [2]; xg_lims[0] = (2. - xw)*(1.-r) - (z[0]-r)*sqrt(sqr(xw) - 4.*w2_); xg_lims[1] = (2. - xw)*(1.-r) - (z[1]-r)*sqrt(sqr(xw) - 4.*w2_); double xg_low_lim = min(xg_lims[0], xg_lims[1]); double xg_upp_lim = max(xg_lims[0], xg_lims[1]); if (xg>=xg_low_lim && xg<=xg_upp_lim) return false; } double kappa_t = 1. + 0.5*(1. - w2_ + b2_ + Lambda); double z = 1. - xg/kappa_t; double u = 1. + w2_ - b2_ - (1.-z)*kappa_t; double y = 1. - (1.-z)*(kappa_t-1.); if (sqr(u) - 4.*w2_*y*z >= 0.){ double v = sqrt(sqr(u) - 4.*w2_*y*z); double xw_lim = (u + v) / (2.*y) + (u - v) / (2.*z); if (xw <= xw_lim) return false; } else if (sqr(u) - 4.*w2_*y*z < 0.){ double xg_lim = (8.*w2_ -2.*xw*(1-b2_+w2_))/(4.*w2_-2.*xw); if (xg>=xg_lim) return false; } return true; } double SMTopPOWHEGDecayer::matrixElementRatio( vector particleMomenta) { double f = (1. + sqr(b2_) - 2.*sqr(w2_) + w2_ + w2_*b2_ - 2.*b2_); double Nc = standardModel()->Nc(); double Cf = (sqr(Nc) - 1.) / (2.*Nc); double B = f/w2_; Energy2 PbPg = particleMomenta[1]*particleMomenta[3]; Energy2 PtPg = particleMomenta[0]*particleMomenta[3]; Energy2 PtPb = particleMomenta[0]*particleMomenta[1]; double R = Cf *((-4.*sqr(mt_)*f/w2_) * ((sqr(mt_)*b2_/sqr(PbPg)) + (sqr(mt_)/sqr(PtPg)) - 2.*(PtPb/(PtPg*PbPg))) + (16. + 8./w2_ + 8.*b2_/w2_) * ((PtPg/PbPg) + (PbPg/PtPg)) - (16./w2_) * (1. + b2_)); return R/B; } bool SMTopPOWHEGDecayer::calcMomenta(int j, Energy pT, double y, double phi, double& xg, double& xw, double& xb, double& xb_z, vector& particleMomenta){ //Calculate xg xg = 2.*pT*cosh(y) / mt_; if (xg>(1. - sqr(b_ + w_)) || xg<0.) return false; //Calculate xw double xT = 2.*pT / mt_; double A = 4. - 4.*xg + sqr(xT); double B = 4.*(3.*xg - 2. + 2.*b2_ - 2.*w2_ - sqr(xg) - xg*b2_ + xg*w2_); double L = 1. + sqr(w2_) + sqr(b2_) - 2.*w2_ - 2.*b2_ - 2.*w2_*b2_; double det = 16.*( -L*sqr(xT) + pow(xT,4)*w2_ + 2.*xg*sqr(xT)*(1.-w2_-b2_) + L*sqr(xg) - sqr(xg*xT)*(1. + w2_) + pow(xg,4) + 2.*pow(xg,3)*(- 1. + w2_ + b2_) ); if (det<0.) return false; if (j==0) xw = (-B + sqrt(det))/(2.*A); if (j==1) xw = (-B - sqrt(det))/(2.*A); if (xw>(1. + w2_ - b2_) || xw<2.*w_) return false; //Calculate xb xb = 2. - xw - xg; if (xb>(1. + b2_ - w2_) || xb<2.*b_) return false; //Calculate xb_z double epsilon_p = -sqrt(sqr(xw) - 4.*w2_) + xT*sinh(y) + sqrt(sqr(xb) - 4.*b2_ - sqr(xT)); double epsilon_m = -sqrt(sqr(xw) - 4.*w2_) + xT*sinh(y) - sqrt(sqr(xb) - 4.*b2_ - sqr(xT)); if (fabs(epsilon_p) < 1.e-10){ xb_z = sqrt(sqr(xb) - 4.*b2_ - sqr(xT)); } else if (fabs(epsilon_m) < 1.e-10){ xb_z = -sqrt(sqr(xb) - 4.*b2_ - sqr(xT)); } else return false; //Check b is on shell if (fabs((sqr(xb) - sqr(xT) - sqr(xb_z) - 4.*b2_))>1.e-10) return false; //Calculate 4 momenta particleMomenta[0].setE ( mt_); particleMomenta[0].setX ( ZERO); particleMomenta[0].setY ( ZERO); particleMomenta[0].setZ ( ZERO); particleMomenta[0].setMass( mt_); particleMomenta[1].setE ( mt_*xb/2.); particleMomenta[1].setX (-pT*cos(phi)); particleMomenta[1].setY (-pT*sin(phi)); particleMomenta[1].setZ ( mt_*xb_z/2.); particleMomenta[1].setMass( mt_*b_); particleMomenta[2].setE ( mt_*xw/2.); particleMomenta[2].setX ( ZERO); particleMomenta[2].setY ( ZERO); particleMomenta[2].setZ (-mt_*sqrt(sqr(xw) - 4.*w2_)/2.); particleMomenta[2].setMass( mt_*w_); particleMomenta[3].setE ( pT*cosh(y)); particleMomenta[3].setX ( pT*cos(phi)); particleMomenta[3].setY ( pT*sin(phi)); particleMomenta[3].setZ ( pT*sinh(y)); particleMomenta[3].setMass( ZERO); return true; } bool SMTopPOWHEGDecayer::psCheck(double xg, double xw) { //Check is point is in allowed region of phase space double xb_star = (1. - w2_ + b2_ - xg) / sqrt(1. - xg); double xg_star = xg / sqrt(1. - xg); if ((sqr(xb_star) - 4.*b2_) < 1e-10) return false; double xw_max = (4. + 4.*w2_ - sqr(xb_star + xg_star) + sqr(sqrt(sqr(xb_star) - 4.*b2_) + xg_star)) / 4.; double xw_min = (4. + 4.*w2_ - sqr(xb_star + xg_star) + sqr(sqrt(sqr(xb_star) - 4.*b2_) - xg_star)) / 4.; if (xw < xw_min || xw > xw_max) return false; return true; } diff --git a/Decay/Perturbative/SMTopPOWHEGDecayer.h b/Decay/Perturbative/SMTopPOWHEGDecayer.h --- a/Decay/Perturbative/SMTopPOWHEGDecayer.h +++ b/Decay/Perturbative/SMTopPOWHEGDecayer.h @@ -1,166 +1,166 @@ // -*- C++ -*- #ifndef Herwig_SMTopPOWHEGDecayer_H #define Herwig_SMTopPOWHEGDecayer_H // // This is the declaration of the SMTopPOWHEGDecayer class. // #include "SMTopDecayer.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SMTopPOWHEGDecayer class. * * @see \ref SMTopPOWHEGDecayerInterfaces "The interfaces" * defined for SMTopPOWHEGDecayer. */ class SMTopPOWHEGDecayer: public SMTopDecayer { public: /** * The default constructor. */ SMTopPOWHEGDecayer(); /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr); /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly 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: /** * check if event is in dead region */ bool deadZoneCheck(double xw, double xg); protected: /** * Calculate matrix element ratio B/R */ double matrixElementRatio(vector particleMomenta); protected: /** * Calculate momenta of t, b, W, g */ bool calcMomenta(int j, Energy pT, double y, double phi, double& xg, double& xw, double& xb, double& xb_z, vector& particleMomenta); protected: /** * Check the calculated momenta are physical */ bool psCheck(double xg, double xw); protected: /** * Return the momenta including the hard emission */ vector hardMomenta(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SMTopPOWHEGDecayer & operator=(const SMTopPOWHEGDecayer &); private: /** * Top quark mass */ Energy mt_; /** * Reduced \f$W^\pm\f$ mass */ double w_; /** * Reduced bottom mass */ double b_; /** * Reduced \f$W^\pm\f$ mass squared */ double w2_; /** * Reduced bottom mass squared */ double b2_; /** * Minimum \f$p_T\f$ */ Energy pTmin_; /** * Transverse momentum of the emission */ Energy pT_; }; } #endif /* Herwig_SMTopPOWHEGDecayer_H */ diff --git a/Decay/Perturbative/SMWDecayer.cc b/Decay/Perturbative/SMWDecayer.cc --- a/Decay/Perturbative/SMWDecayer.cc +++ b/Decay/Perturbative/SMWDecayer.cc @@ -1,667 +1,635 @@ // -*- C++ -*- // // SMWDecayer.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 SMWDecayer class. // #include "SMWDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Decay/DecayVertex.h" #include "ThePEG/Helicity/VectorSpinInfo.h" #include "ThePEG/Helicity/FermionSpinInfo.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/Models/StandardModel/StandardModel.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; const double SMWDecayer::EPS_=0.00000001; SMWDecayer::SMWDecayer() : quarkWeight_(6,0.), leptonWeight_(3,0.) { quarkWeight_[0] = 1.01596; quarkWeight_[1] = 0.0537308; quarkWeight_[2] = 0.0538085; quarkWeight_[3] = 1.01377; quarkWeight_[4] = 1.45763e-05; quarkWeight_[5] = 0.0018143; leptonWeight_[0] = 0.356594; leptonWeight_[1] = 0.356593; leptonWeight_[2] = 0.356333; // intermediates generateIntermediates(false); } void SMWDecayer::doinit() { DecayIntegrator::doinit(); // get the vertices from the Standard Model object tcHwSMPtr hwsm=dynamic_ptr_cast(standardModel()); if(!hwsm) throw InitException() << "Must have Herwig StandardModel object in" << "SMWDecayer::doinit()" << Exception::runerror; FFWvertex_ = dynamic_ptr_cast(hwsm->vertexFFW()); // make sure they are initialized FFWvertex_->init(); // now set up the decay modes DecayPhaseSpaceModePtr mode; tPDVector extpart(3); vector wgt(0); // W modes extpart[0]=getParticleData(ParticleID::Wplus); // loop for the quarks unsigned int iz=0; for(int ix=1;ix<6;ix+=2) { for(int iy=2;iy<6;iy+=2) { // check that the combination of particles is allowed if(!FFWvertex_->allowed(-ix,iy,ParticleID::Wminus)) throw InitException() << "SMWDecayer::doinit() the W vertex" << "cannot handle all the quark modes" << Exception::abortnow; extpart[1] = getParticleData(-ix); extpart[2] = getParticleData( iy); mode = new_ptr(DecayPhaseSpaceMode(extpart,this)); addMode(mode,quarkWeight_[iz],wgt); ++iz; } } // loop for the leptons for(int ix=11;ix<17;ix+=2) { // check that the combination of particles is allowed // if(!FFWvertex_->allowed(-ix,ix+1,ParticleID::Wminus)) // throw InitException() << "SMWDecayer::doinit() the W vertex" // << "cannot handle all the lepton modes" // << Exception::abortnow; extpart[1] = getParticleData(-ix); extpart[2] = getParticleData(ix+1); mode = new_ptr(DecayPhaseSpaceMode(extpart,this)); addMode(mode,leptonWeight_[(ix-11)/2],wgt); } } int SMWDecayer::modeNumber(bool & cc,tcPDPtr parent, const tPDVector & children) const { int imode(-1); if(children.size()!=2) return imode; int id0=parent->id(); tPDVector::const_iterator pit = children.begin(); int id1=(**pit).id(); ++pit; int id2=(**pit).id(); if(abs(id0)!=ParticleID::Wplus) return imode; int idd(0),idu(0); if(abs(id1)%2==1&&abs(id2)%2==0) { idd=abs(id1); idu=abs(id2); } else if(abs(id1)%2==0&&abs(id2)%2==1) { idd=abs(id2); idu=abs(id1); } if(idd==0&&idu==0) { return imode; } else if(idd<=5) { imode=idd+idu/2-2; } else { imode=(idd-1)/2+1; } cc= (id0==ParticleID::Wminus); return imode; } void SMWDecayer::persistentOutput(PersistentOStream & os) const { os << FFWvertex_ << quarkWeight_ << leptonWeight_ << alpha_; } void SMWDecayer::persistentInput(PersistentIStream & is, int) { is >> FFWvertex_ >> quarkWeight_ >> leptonWeight_ >> alpha_; } ClassDescription SMWDecayer::initSMWDecayer; // Definition of the static class description member. void SMWDecayer::Init() { static ClassDocumentation documentation ("The SMWDecayer class is the implementation of the decay" " of the W boson to the Standard Model fermions."); static ParVector interfaceWquarkMax ("QuarkMax", "The maximum weight for the decay of the W to quarks", &SMWDecayer::quarkWeight_, 0, 0, 0, -10000, 10000, false, false, true); static ParVector interfaceWleptonMax ("LeptonMax", "The maximum weight for the decay of the W to leptons", &SMWDecayer::leptonWeight_, 0, 0, 0, -10000, 10000, false, false, true); static Reference interfaceCoupling ("Coupling", "Pointer to the object to calculate the coupling for the correction", &SMWDecayer::alpha_, false, false, true, false, false); } // return the matrix element squared double SMWDecayer::me2(const int, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); int iferm(1),ianti(0); if(decay[0]->id()>0) swap(iferm,ianti); if(meopt==Initialize) { VectorWaveFunction::calculateWaveFunctions(_vectors,_rho, const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { VectorWaveFunction::constructSpinInfo(_vectors,const_ptr_cast(&inpart), incoming,true,false); SpinorBarWaveFunction:: constructSpinInfo(_wavebar,decay[iferm],outgoing,true); SpinorWaveFunction:: constructSpinInfo(_wave ,decay[ianti],outgoing,true); return 0.; } SpinorBarWaveFunction:: calculateWaveFunctions(_wavebar,decay[iferm],outgoing); SpinorWaveFunction:: calculateWaveFunctions(_wave ,decay[ianti],outgoing); // compute the matrix element Energy2 scale(sqr(inpart.mass())); for(unsigned int ifm=0;ifm<2;++ifm) { for(unsigned int ia=0;ia<2;++ia) { for(unsigned int vhel=0;vhel<3;++vhel) { if(iferm>ianti) (*ME())(vhel,ia,ifm)= FFWvertex_->evaluate(scale,_wave[ia],_wavebar[ifm],_vectors[vhel]); else (*ME())(vhel,ifm,ia)= FFWvertex_->evaluate(scale,_wave[ia],_wavebar[ifm],_vectors[vhel]); } } } double output=(ME()->contract(_rho)).real()*UnitRemoval::E2/scale; if(abs(decay[0]->id())<=6) output*=3.; if(decay[0]->hasColour()) decay[0]->antiColourNeighbour(decay[1]); else if(decay[1]->hasColour()) decay[1]->antiColourNeighbour(decay[0]); return output; } void SMWDecayer::doinitrun() { DecayIntegrator::doinitrun(); if(initialize()) { for(unsigned int ix=0;ixmaxWeight(); else leptonWeight_[ix-6]=mode(ix)->maxWeight(); } } } void SMWDecayer::dataBaseOutput(ofstream & output, bool header) const { if(header) output << "update decayers set parameters=\""; for(unsigned int ix=0;ix::const_iterator cjt; // get the quark and antiquark ParticleVector qq; - for(cjt=tree->outgoingLines().begin();cjt!=tree->outgoingLines().end();++cjt) - qq.push_back(cjt->first->copy()); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) + qq.push_back(born->bornOutgoing()[ix]); // ensure quark first if(qq[0]->id()<0) swap(qq[0],qq[1]); // centre of mass energy d_Q_ = (qq[0]->momentum() + qq[1]->momentum()).m(); // quark mass d_m_ = 0.5*(qq[0]->momentum().m()+qq[1]->momentum().m()); // set the other parameters setRho(sqr(d_m_/d_Q_)); setKtildeSymm(); // otherwise can do it initial=1.; final =1.; } -void SMWDecayer:: -applyHardMatrixElementCorrection(ShowerTreePtr tree) { +RealEmissionProcessPtr SMWDecayer:: +applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { // get the quark and antiquark - ParticleVector qq; - map::const_iterator cit; - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) - qq.push_back(cit->first->copy()); - if(!qq[0]->dataPtr()->coloured()) return; + ParticleVector qq; + for(unsigned int ix=0;ixbornOutgoing().size();++ix) + qq.push_back(born->bornOutgoing()[ix]); + if(!qq[0]->dataPtr()->coloured()) return RealEmissionProcessPtr(); // ensure quark first - if(qq[0]->id()<0) swap(qq[0],qq[1]); + bool order = qq[0]->id()<0; + if(order) swap(qq[0],qq[1]); // get the momenta vector newfs = applyHard(qq); // return if no emission - if(newfs.size()!=3) return; + if(newfs.size()!=3) return RealEmissionProcessPtr(); // perform final check to ensure energy greater than constituent mass for (int i=0; i<2; i++) { - if (newfs[i].e() < qq[i]->data().constituentMass()) return; + if (newfs[i].e() < qq[i]->data().constituentMass()) return RealEmissionProcessPtr(); } if (newfs[2].e() < getParticleData(ParticleID::g)->constituentMass()) - return; + return RealEmissionProcessPtr(); // set masses for (int i=0; i<2; i++) newfs[i].setMass(qq[i]->mass()); newfs[2].setMass(ZERO); // decide which particle emits bool firstEmits= newfs[2].vect().perp2(newfs[0].vect())< newfs[2].vect().perp2(newfs[1].vect()); // create the new quark, antiquark and gluon PPtr newg = getParticleData(ParticleID::g)->produceParticle(newfs[2]); - PPtr newq,newa; - if(firstEmits) { - newq = qq[0]->dataPtr()->produceParticle(newfs[0]); - newa = new_ptr(Particle(*qq[1])); - qq[1]->antiColourLine()->removeAntiColoured(newa); - newa->set5Momentum(newfs[1]); + PPtr newq = qq[0]->dataPtr()->produceParticle(newfs[0]); + PPtr newa = qq[1]->dataPtr()->produceParticle(newfs[1]); + // create the output real emission process + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + born->incoming().push_back(born->bornIncoming()[ix]); + } + if(!order) { + born->outgoing().push_back(newq); + born->outgoing().push_back(newa); + born->outgoing().push_back(newg); } else { - newq = new_ptr(Particle(*qq[0])); - qq[0]->colourLine()->removeColoured(newq); - newq->set5Momentum(newfs[0]); - newa = qq[1]->dataPtr()->produceParticle(newfs[1]); + born->outgoing().push_back(newa); + born->outgoing().push_back(newq); + born->outgoing().push_back(newg); + firstEmits = !firstEmits; } - // get the original colour line - ColinePtr col; - if(qq[0]->id()>0) col=qq[0]->colourLine(); - else col=qq[0]->antiColourLine(); - // set the colour lines + // make colour connections + newg->colourNeighbour(newq); + newa->colourNeighbour(newg); if(firstEmits) { - col->addColoured(newq); - col->addAntiColoured(newg); - newa->colourNeighbour(newg); + born->emitter(1); + born->spectator(2); } else { - col->addAntiColoured(newa); - col->addColoured(newg); - newq->antiColourNeighbour(newg); + born->emitter(2); + born->spectator(1); } - // change the existing quark and antiquark - PPtr orig; - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(cit->first->progenitor()->id()==newq->id()) { - // remove old particles from colour line - col->removeColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newq); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newq,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(!firstEmits); - if(firstEmits) orig=cit->first->original(); - } - else { - // remove old particles from colour line - col->removeAntiColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newa); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newa,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(firstEmits); - if(!firstEmits) orig=cit->first->original(); - } - } - // add the gluon - ShowerParticlePtr sg=new_ptr(ShowerParticle(*newg,1,true)); - ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg)); - gluon->perturbative(false); - tree->outgoingLines().insert(make_pair(gluon,sg)); - tree->hardMatrixElementCorrection(true); + born->emitted(3); + born->interaction(ShowerInteraction::QCD); + return born; } vector SMWDecayer:: applyHard(const ParticleVector &p) { double x, xbar; vector fs; // return if no emission if (getHard(x, xbar) < UseRandom::rnd() || p.size() != 2) return fs; // centre of mass energy Lorentz5Momentum pcm = p[0]->momentum() + p[1]->momentum(); // momenta of quark,antiquark and gluon Lorentz5Momentum pq, pa, pg; if (p[0]->id() > 0) { pq = p[0]->momentum(); pa = p[1]->momentum(); } else { pa = p[0]->momentum(); pq = p[1]->momentum(); } // boost to boson rest frame Boost beta = (pcm.findBoostToCM()); pq.boost(beta); pa.boost(beta); // return if fails ????? double xg = 2.-x-xbar; if((1.-x)*(1.-xbar)*(1.-xg) < d_rho_*xg*xg) return fs; Axis u1, u2, u3; // moduli of momenta in units of Q and cos theta // stick to q direction? // p1 is the one that is kept, p2 is the other fermion, p3 the gluon. Energy e1, e2, e3; Energy pp1, pp2, pp3; bool keepq = true; if (UseRandom::rnd() > sqr(x)/(sqr(x)+sqr(xbar))) keepq = false; if (keepq) { pp1 = d_Q_*sqrt(sqr(x)-4.*d_rho_)/2.; pp2 = d_Q_*sqrt(sqr(xbar)-4.*d_rho_)/2.; e1 = d_Q_*x/2.; e2 = d_Q_*xbar/2.; u1 = pq.vect().unit(); } else { pp2 = d_Q_*sqrt(sqr(x)-4.*d_rho_)/2.; pp1 = d_Q_*sqrt(sqr(xbar)-4.*d_rho_)/2.; e2 = d_Q_*x/2.; e1 = d_Q_*xbar/2.; u1 = pa.vect().unit(); } pp3 = d_Q_*xg/2.; e3 = pp3; u2 = u1.orthogonal(); u2 /= u2.mag(); u3 = u1.cross(u2); u3 /= u3.mag(); double ct2=-2., ct3=-2.; if (pp1 == ZERO || pp2 == ZERO || pp3 == ZERO) { bool touched = false; if (pp1 == ZERO) { ct2 = 1; ct3 = -1; touched = true; } if (pp2 == ZERO || pp3 == ZERO) { ct2 = 1; ct3 = 1; touched = true; } if (!touched) throw Exception() << "SMWDecayer::applyHard()" << " did not set ct2/3" << Exception::abortnow; } else { ct3 = (sqr(pp1)+sqr(pp3)-sqr(pp2))/(2.*pp1*pp3); ct2 = (sqr(pp1)+sqr(pp2)-sqr(pp3))/(2.*pp1*pp2); } double phi = Constants::twopi*UseRandom::rnd(); double cphi = cos(phi); double sphi = sin(phi); double st2 = sqrt(1.-sqr(ct2)); double st3 = sqrt(1.-sqr(ct3)); ThreeVector pv1, pv2, pv3; pv1 = pp1*u1; pv2 = -ct2*pp2*u1 + st2*cphi*pp2*u2 + st2*sphi*pp2*u3; pv3 = -ct3*pp3*u1 - st3*cphi*pp3*u2 - st3*sphi*pp3*u3; if (keepq) { pq = Lorentz5Momentum(pv1, e1); pa = Lorentz5Momentum(pv2, e2); } else { pa = Lorentz5Momentum(pv1, e1); pq = Lorentz5Momentum(pv2, e2); } pg = Lorentz5Momentum(pv3, e3); pq.boost(-beta); pa.boost(-beta); pg.boost(-beta); fs.push_back(pq); fs.push_back(pa); fs.push_back(pg); return fs; } double SMWDecayer::getHard(double &x1, double &x2) { double w = 0.0; double y1 = UseRandom::rnd(),y2 = UseRandom::rnd(); // simply double MC efficiency // -> weight has to be divided by two (Jacobian) if (y1 + y2 > 1) { y1 = 1.-y1; y2 = 1.-y2; } bool inSoft = false; if (y1 < 0.25) { if (y2 < 0.25) { inSoft = true; if (y1 < y2) { y1 = 0.25-y1; y2 = y1*(1.5 - 2.*y2); } else { y2 = 0.25 - y2; y1 = y2*(1.5 - 2.*y1); } } else { if (y2 < y1 + 2.*sqr(y1)) return w; } } else { if (y2 < 0.25) { if (y1 < y2 + 2.*sqr(y2)) return w; } } // inside PS? x1 = 1.-y1; x2 = 1.-y2; if(y1*y2*(1.-y1-y2) < d_rho_*sqr(y1+y2)) return w; double k1 = getKfromX(x1, x2); double k2 = getKfromX(x2, x1); // Is it in the quark emission zone? if (k1 < d_kt1_) return 0.0; // No...is it in the anti-quark emission zone? if (k2 < d_kt2_) return 0.0; // Point is in dead zone: compute q qbar g weight w = MEV(x1, x2); // for axial: // w = MEA(x1, x2); // Reweight soft region if (inSoft) { if (y1 < y2) w *= 2.*y1; else w *= 2.*y2; } // alpha and colour factors Energy2 pt2 = sqr(d_Q_)*(1.-x1)*(1.-x2); w *= 1./3./Constants::pi*alpha_->value(pt2); return w; } bool SMWDecayer:: softMatrixElementVeto(ShowerProgenitorPtr initial,ShowerParticlePtr parent,Branching br) { // check we should be applying the veto if(parent->id()!=initial->progenitor()->id()|| br.ids[0]!=br.ids[1]|| br.ids[2]->id()!=ParticleID::g) return false; // calculate pt double d_z = br.kinematics->z(); Energy d_qt = br.kinematics->scale(); Energy2 d_m2 = parent->momentum().m2(); Energy2 pPerp2 = sqr(d_z*d_qt) - d_m2; if(pPerp2vetoEmission(br.type,br.kinematics->scale()); return true; } Energy pPerp = (1.-d_z)*sqrt(pPerp2); // if not hardest so far don't apply veto if(pPerphighestpT()) return false; // calculate the weight double weight = 0.; if(parent->id()>0) weight = qWeightX(d_qt, d_z); else weight = qbarWeightX(d_qt, d_z); // compute veto from weight bool veto = !UseRandom::rndbool(weight); // if vetoing reset the scale if(veto) parent->vetoEmission(br.type,br.kinematics->scale()); // return the veto return veto; } void SMWDecayer::setRho(double r) { d_rho_ = r; d_v_ = sqrt(1.-4.*d_rho_); } void SMWDecayer::setKtildeSymm() { d_kt1_ = (1. + sqrt(1. - 4.*d_rho_))/2.; setKtilde2(); } void SMWDecayer::setKtilde2() { double num = d_rho_ * d_kt1_ + 0.25 * d_v_ *(1.+d_v_)*(1.+d_v_); double den = d_kt1_ - d_rho_; d_kt2_ = num/den; } double SMWDecayer::getZfromX(double x1, double x2) { double uval = u(x2); double num = x1 - (2. - x2)*uval; double den = sqrt(x2*x2 - 4.*d_rho_); return uval + num/den; } double SMWDecayer::getKfromX(double x1, double x2) { double zval = getZfromX(x1, x2); return (1.-x2)/(zval*(1.-zval)); } double SMWDecayer::MEV(double x1, double x2) { // Vector part double num = (x1+2.*d_rho_)*(x1+2.*d_rho_) + (x2+2.*d_rho_)*(x2+2.*d_rho_) - 8.*d_rho_*(1.+2.*d_rho_); double den = (1.+2.*d_rho_)*(1.-x1)*(1.-x2); return (num/den - 2.*d_rho_/((1.-x1)*(1.-x1)) - 2*d_rho_/((1.-x2)*(1.-x2)))/d_v_; } double SMWDecayer::MEA(double x1, double x2) { // Axial part double num = (x1+2.*d_rho_)*(x1+2.*d_rho_) + (x2+2.*d_rho_)*(x2+2.*d_rho_) + 2.*d_rho_*((5.-x1-x2)*(5.-x1-x2) - 19.0 + 4*d_rho_); double den = d_v_*d_v_*(1.-x1)*(1.-x2); return (num/den - 2.*d_rho_/((1.-x1)*(1.-x1)) - 2*d_rho_/((1.-x2)*(1.-x2)))/d_v_; } double SMWDecayer::u(double x2) { return 0.5*(1. + d_rho_/(1.-x2+d_rho_)); } void SMWDecayer:: getXXbar(double kti, double z, double &x, double &xbar) { double w = sqr(d_v_) + kti*(-1. + z)*z*(2. + kti*(-1. + z)*z); if (w < 0) { x = -1.; xbar = -1; } else { x = (1. + sqr(d_v_)*(-1. + z) + sqr(kti*(-1. + z))*z*z*z + z*sqrt(w) - kti*(-1. + z)*z*(2. + z*(-2 + sqrt(w))))/ (1. - kti*(-1. + z)*z + sqrt(w)); xbar = 1. + kti*(-1. + z)*z; } } double SMWDecayer::qWeight(double x, double xbar) { double rval; double xg = 2. - xbar - x; // always return one in the soft gluon region if(xg < EPS_) return 1.0; // check it is in the phase space if((1.-x)*(1.-xbar)*(1.-xg) < d_rho_*xg*xg) return 0.0; double k1 = getKfromX(x, xbar); double k2 = getKfromX(xbar, x); // Is it in the quark emission zone? if(k1 < d_kt1_) { rval = MEV(x, xbar)/PS(x, xbar); // is it also in the anti-quark emission zone? if(k2 < d_kt2_) rval *= 0.5; return rval; } return 1.0; } double SMWDecayer::qbarWeight(double x, double xbar) { double rval; double xg = 2. - xbar - x; // always return one in the soft gluon region if(xg < EPS_) return 1.0; // check it is in the phase space if((1.-x)*(1.-xbar)*(1.-xg) < d_rho_*xg*xg) return 0.0; double k1 = getKfromX(x, xbar); double k2 = getKfromX(xbar, x); // Is it in the antiquark emission zone? if(k2 < d_kt2_) { rval = MEV(x, xbar)/PS(xbar, x); // is it also in the quark emission zone? if(k1 < d_kt1_) rval *= 0.5; return rval; } return 1.0; } double SMWDecayer::qWeightX(Energy qtilde, double z) { double x, xb; getXXbar(sqr(qtilde/d_Q_), z, x, xb); // if exceptionally out of phase space, leave this emission, as there // is no good interpretation for the soft ME correction. if (x < 0 || xb < 0) return 1.0; return qWeight(x, xb); } double SMWDecayer::qbarWeightX(Energy qtilde, double z) { double x, xb; getXXbar(sqr(qtilde/d_Q_), z, xb, x); // see above in qWeightX. if (x < 0 || xb < 0) return 1.0; return qbarWeight(x, xb); } double SMWDecayer::PS(double x, double xbar) { double u = 0.5*(1. + d_rho_ / (1.-xbar+d_rho_)); double z = u + (x - (2.-xbar)*u)/sqrt(xbar*xbar - 4.*d_rho_); double brack = (1.+z*z)/(1.-z)- 2.*d_rho_/(1-xbar); // interesting: the splitting function without the subtraction // term. Actually gives a much worse approximation in the collinear // limit. double brack = (1.+z*z)/(1.-z); double den = (1.-xbar)*sqrt(xbar*xbar - 4.*d_rho_); return brack/den; } diff --git a/Decay/Perturbative/SMWDecayer.h b/Decay/Perturbative/SMWDecayer.h --- a/Decay/Perturbative/SMWDecayer.h +++ b/Decay/Perturbative/SMWDecayer.h @@ -1,417 +1,417 @@ // -*- C++ -*- // // SMWDecayer.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_SMWDecayer_H #define HERWIG_SMWDecayer_H // // This is the declaration of the SMWDecayer class. // #include "Herwig/Decay/DecayIntegrator.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.fh" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.fh" namespace Herwig { using namespace ThePEG; using namespace ThePEG::Helicity; /** \ingroup Decay * * The SMWDecayer is designed to perform the decay of the * W boson to the Standard Model fermions, including the first order * electroweak corrections. * * @see DecayIntegrator * */ class SMWDecayer: public DecayIntegrator { public: /** * Default constructor. */ SMWDecayer(); public: /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return true;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr , double & , + virtual void initializeMECorrection(RealEmissionProcessPtr , double & , double & ); /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr); + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent,Branching br); //@} public: /** * Which of the possible decays is required * @param cc Is this mode the charge conjugate * @param parent The decaying particle * @param children The decay products */ virtual int modeNumber(bool & cc, tcPDPtr parent, const tPDVector & children) const; /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay,MEOption meopt) const; /** * Output the setup information for the particle database * @param os The stream to output the information to * @param header Whether or not to output the information for MySQL */ virtual void dataBaseOutput(ofstream & os,bool header) 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); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving and * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} protected: /** * Apply the hard matrix element */ vector applyHard(const ParticleVector &p); /** * Get the weight for hard emission */ double getHard(double &, double &); /** * Set the \f$\rho\f$ parameter */ void setRho(double); /** * Set the \f$\tilde{\kappa}\f$ parameters symmetrically */ void setKtildeSymm(); /** * Set second \f$\tilde{\kappa}\f$, given the first. */ void setKtilde2(); /** * Translate the variables from \f$x_q,x_{\bar{q}}\f$ to \f$\tilde{\kappa},z\f$ */ //@{ /** * Calculate \f$z\f$. */ double getZfromX(double, double); /** * Calculate \f$\tilde{\kappa}\f$. */ double getKfromX(double, double); //@} /** * Calculate \f$x_{q},x_{\bar{q}}\f$ from \f$\tilde{\kappa},z\f$. * @param kt \f$\tilde{\kappa}\f$ * @param z \f$z\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ void getXXbar(double kt, double z, double & x, double & xbar); /** * Soft weight */ //@{ /** * Soft quark weight calculated from \f$x_{q},x_{\bar{q}}\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ double qWeight(double x, double xbar); /** * Soft antiquark weight calculated from \f$x_{q},x_{\bar{q}}\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ double qbarWeight(double x, double xbar); /** * Soft quark weight calculated from \f$\tilde{q},z\f$ * @param qtilde \f$\tilde{q}\f$ * @param z \f$z\f$ */ double qWeightX(Energy qtilde, double z); /** * Soft antiquark weight calculated from \f$\tilde{q},z\f$ * @param qtilde \f$\tilde{q}\f$ * @param z \f$z\f$ */ double qbarWeightX(Energy qtilde, double z); //@} /** * ???? */ double u(double); /** * Vector and axial vector parts of the matrix element */ //@{ /** * Vector part of the matrix element */ double MEV(double, double); /** * Axial vector part of the matrix element */ double MEA(double, double); /** * The matrix element, given \f$x_1\f$, \f$x_2\f$. * @param x1 \f$x_1\f$ * @param x2 \f$x_2\f$ */ double PS(double x1, double x2); /** * Access to the strong coupling */ ShowerAlphaPtr alphaS() const {return alpha_;} //@} private: /** * Describe a concrete class with persistent data. */ static ClassDescription initSMWDecayer; /** * Private and non-existent assignment operator. */ SMWDecayer & operator=(const SMWDecayer &); private: /** * Pointer to the W fermions vertex */ FFVVertexPtr FFWvertex_; /** * maximum weights for the different integrations */ //@{ /** * Weights for the W to quarks decays. */ vector quarkWeight_; /** * Weights for the W to leptons decays. */ vector leptonWeight_; //@} /** * Spin density matrix for the decay */ mutable RhoDMatrix _rho; /** * Polarization vectors for the decay */ mutable vector _vectors; /** * Spinors for the decay */ mutable vector _wave; /** * Barred spinors for the decay */ mutable vector _wavebar; private: /** * CM energy */ Energy d_Q_; /** * Quark mass */ Energy d_m_; /** * The rho parameter */ double d_rho_; /** * The v parameter */ double d_v_; /** * The initial kappa-tilde values for radiation from the quark */ double d_kt1_; /** * The initial kappa-tilde values for radiation from the antiquark */ double d_kt2_; /** * Cut-off parameter */ static const double EPS_; /** * Pointer to the coupling */ ShowerAlphaPtr alpha_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * The following template specialization informs ThePEG about the * base class of SMWDecayer. */ template <> struct BaseClassTrait { /** Typedef of the base class of SMWDecayer. */ typedef Herwig::DecayIntegrator NthBase; }; /** * The following template specialization informs ThePEG about the * name of this class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return the class name.*/ static string className() { return "Herwig::SMWDecayer"; } /** * Return the name of the shared library to be loaded to get * access to this class and every other class it uses * (except the base class). */ static string library() { return "HwPerturbativeDecay.so"; } }; /** @endcond */ } #endif /* HERWIG_SMWDecayer_H */ diff --git a/Decay/Perturbative/SMWFermionsPOWHEGDecayer.cc b/Decay/Perturbative/SMWFermionsPOWHEGDecayer.cc --- a/Decay/Perturbative/SMWFermionsPOWHEGDecayer.cc +++ b/Decay/Perturbative/SMWFermionsPOWHEGDecayer.cc @@ -1,679 +1,627 @@ //-*- // // This is the implementation of the non-inlined, non-templated member // functions of the SMWFermionsPOWHEGDecayer class. // #include "SMWFermionsPOWHEGDecayer.h" #include #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/PDF/PolarizedBeamParticleData.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/Base/HardTree.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" using namespace Herwig; SMWFermionsPOWHEGDecayer::SMWFermionsPOWHEGDecayer() : CF_(4./3.), pTmin_(1.*GeV) { } IBPtr SMWFermionsPOWHEGDecayer::clone() const { return new_ptr(*this); } IBPtr SMWFermionsPOWHEGDecayer::fullclone() const { return new_ptr(*this); } void SMWFermionsPOWHEGDecayer::persistentOutput(PersistentOStream & os) const { os << FFGVertex_ << FFWVertex_ << gluon_ << ounit( pTmin_, GeV ); } void SMWFermionsPOWHEGDecayer::persistentInput(PersistentIStream & is, int) { is >> FFGVertex_ >> FFWVertex_ >> gluon_ >> iunit( pTmin_, GeV ); } ClassDescription SMWFermionsPOWHEGDecayer::initSMWFermionsPOWHEGDecayer; // Definition of the static class description member. void SMWFermionsPOWHEGDecayer::Init() { static ClassDocumentation documentation ("There is no documentation for the SMWFermionsPOWHEGDecayer class"); static Parameter interfacePtMin ("minpT", "The pt cut on hardest emision generation", &SMWFermionsPOWHEGDecayer::pTmin_, GeV, 1.*GeV, 0*GeV, 100000.0*GeV, false, false, Interface::limited); } -HardTreePtr SMWFermionsPOWHEGDecayer:: -generateHardest(ShowerTreePtr tree) { - // Get the progenitors: Q and Qbar. - ShowerProgenitorPtr - QProgenitor = tree->outgoingLines().begin()->first, - QbarProgenitor = tree->outgoingLines().rbegin()->first; - if(QProgenitor->id()<0) swap( QProgenitor, QbarProgenitor ); +RealEmissionProcessPtr SMWFermionsPOWHEGDecayer:: +generateHardest(RealEmissionProcessPtr born) { + assert(born->bornOutgoing().size()==2); + // check coloured + if(!born->bornOutgoing()[0]->dataPtr()->coloured()) return RealEmissionProcessPtr(); + // extract required info partons_.resize(2); - partons_[0] = QProgenitor->progenitor() ->dataPtr(); - partons_[1] = QbarProgenitor->progenitor()->dataPtr(); - if(!partons_[0]->coloured()) return HardTreePtr(); - // momentum of the partons quark_.resize(2); - quark_[0] = QProgenitor ->copy()->momentum(); - quark_[1] = QbarProgenitor->copy()->momentum(); - // Set the existing mass entries in partons 5 vectors with the - // once and for all. - quark_[0].setMass(partons_[0]->mass()); - quark_[1].setMass(partons_[1]->mass()); + vector hardProcess; + wboson_ = born->bornIncoming()[0]; + hardProcess.push_back(wboson_); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + partons_[ix] = born->bornOutgoing()[ix]->dataPtr(); + quark_[ix] = born->bornOutgoing()[ix]->momentum(); + quark_[ix].setMass(partons_[ix]->mass()); + hardProcess.push_back(born->bornOutgoing()[ix]); + } + bool order = partons_[0]->id()<0; + if(order) { + swap(partons_[0] ,partons_[1] ); + swap(quark_[0] ,quark_[1] ); + swap(hardProcess[1],hardProcess[2]); + } gauge_.setMass(0.*MeV); - // Get the W boson. - wboson_ = tree->incomingLines().begin()->first->copy(); - // copy the particle objects - vector hardProcess (3); - hardProcess[0] = wboson_; - hardProcess[1] = QbarProgenitor->copy(); - hardProcess[2] = QProgenitor ->copy(); // Get the W boson mass. mw2_ = (quark_[0] + quark_[1]).m2(); // Generate emission and set _quark[0,1] and _gauge to be the // momenta of q, qbar and g after the hardest emission: if(!getEvent(hardProcess)) { - QProgenitor ->maximumpT(pTmin_,ShowerInteraction::QCD); - QbarProgenitor->maximumpT(pTmin_,ShowerInteraction::QCD); - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = pTmin_; + return born; } // Ensure the energies are greater than the constituent masses: for (int i=0; i<2; i++) { - if (quark_[i].e() < partons_[i]->constituentMass()) return HardTreePtr(); - if (gauge_.e() < gluon_ ->constituentMass()) return HardTreePtr(); + if (quark_[i].e() < partons_[i]->constituentMass()) return RealEmissionProcessPtr(); } + if (gauge_.e() < gluon_ ->constituentMass()) return RealEmissionProcessPtr(); // set masses quark_[0].setMass( partons_[0]->mass() ); quark_[1].setMass( partons_[1]->mass() ); gauge_ .setMass( ZERO ); - // assign the emitter based on evolution scales - unsigned int iemitter = quark_[0]*gauge_ > quark_[1]*gauge_ ? 1 : 0; - unsigned int ispectator = iemitter==1 ? 0 : 1; - // Make the particles for the HardTree: - ShowerParticlePtr emitter (new_ptr(ShowerParticle(partons_[iemitter ],true))); - ShowerParticlePtr spectator(new_ptr(ShowerParticle(partons_[ispectator],true))); - ShowerParticlePtr gauge (new_ptr(ShowerParticle(gluon_ ,true))); - ShowerParticlePtr wboson (new_ptr(ShowerParticle(wboson_->dataPtr() ,false))); - ShowerParticlePtr parent (new_ptr(ShowerParticle(partons_[iemitter ],true))); - emitter ->set5Momentum(quark_[iemitter ] ); - spectator->set5Momentum(quark_[ispectator] ); - gauge ->set5Momentum(gauge_ ); - wboson ->set5Momentum(wboson_->momentum()); - Lorentz5Momentum parentMomentum(quark_[iemitter]+gauge_); - parentMomentum.rescaleMass(); - parent->set5Momentum(parentMomentum); - // Create the vectors of HardBranchings to create the HardTree: - vector spaceBranchings,allBranchings; - // Incoming boson: - spaceBranchings.push_back(new_ptr(HardBranching(wboson,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - // Outgoing particles from hard emission: - HardBranchingPtr spectatorBranch(new_ptr(HardBranching(spectator,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr emitterBranch(new_ptr(HardBranching(parent,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(emitter,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(gauge,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->type(emitterBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : - ShowerPartnerType::QCDAntiColourLine); - allBranchings.push_back(emitterBranch); - allBranchings.push_back(spectatorBranch); - if(iemitter==1) swap(allBranchings[0],allBranchings[1]); - // Add incoming boson to allBranchings - allBranchings.push_back( spaceBranchings.back() ); - // Make the HardTree from the HardBranching vectors. - HardTreePtr hardtree = new_ptr(HardTree(allBranchings,spaceBranchings, - ShowerInteraction::QCD)); - // Set the maximum pt for all other emissions - Energy ptveto(pT_); - QProgenitor ->maximumpT(ptveto,ShowerInteraction::QCD); - QbarProgenitor->maximumpT(ptveto,ShowerInteraction::QCD); - // Connect the particles with the branchings in the HardTree - hardtree->connect( QProgenitor->progenitor() , allBranchings[0] ); - hardtree->connect( QbarProgenitor->progenitor(), allBranchings[1] ); - // colour flow - ColinePtr newline=new_ptr(ColourLine()); - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) { - if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3) - newline->addColoured((**cit).branchingParticle()); - else if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3bar) - newline->addAntiColoured((**cit).branchingParticle()); - } - ColinePtr newLine2=new_ptr(ColourLine()); - if(emitterBranch->branchingParticle()->dataPtr()->iColour()==PDT::Colour3) { - emitterBranch->branchingParticle()->colourLine()->addColoured(gauge); - newLine2->addColoured(emitter); - newLine2->addAntiColoured(gauge); + // // assign the emitter based on evolution scales + unsigned int iemitter = quark_[0]*gauge_ > quark_[1]*gauge_ ? 2 : 1; + unsigned int ispectator = iemitter==1 ? 1 : 2; + // create new partices and insert + PPtr wboson = wboson_->dataPtr()->produceParticle(wboson_->momentum()); + born->incoming().push_back(wboson); + PPtr newq = partons_[0]->produceParticle(quark_[0]); + PPtr newa = partons_[1]->produceParticle(quark_[1]); + PPtr newg = gluon_->produceParticle(gauge_); + // make colour connections + newg->colourNeighbour(newq); + newa->colourNeighbour(newg); + // insert in output structure + if(!order) { + born->outgoing().push_back(newq); + born->outgoing().push_back(newa); } else { - emitterBranch->branchingParticle()->antiColourLine()->addAntiColoured(gauge); - newLine2->addAntiColoured(emitter); - newLine2->addColoured(gauge); + born->outgoing().push_back(newa); + born->outgoing().push_back(newq); + swap(iemitter,ispectator); } - // return the tree - return hardtree; + born->outgoing().push_back(newg); + born->emitter (iemitter ); + born->spectator(ispectator); + born->emitted (3); + born->pT()[ShowerInteraction::QCD] = pT_; + // return process + born->interaction(ShowerInteraction::QCD); + return born; } double SMWFermionsPOWHEGDecayer:: me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const { // leading-order result double output = SMWDecayer::me2(ichan,part,decay,meopt); // check decay products coloured, otherwise return if(!decay[0]->dataPtr()->coloured()) return output; // inital masses, couplings etc // W mass mW_ = part.mass(); // strong coupling aS_ = SM().alphaS(sqr(mW_)); // reduced mass double mu1_ = (decay[0]->dataPtr()->mass())/mW_; double mu2_ = (decay[1]->dataPtr()->mass())/mW_; // scale scale_ = sqr(mW_); // now for the nlo loop correction double virt = CF_*aS_/Constants::pi; // now for the real correction double realFact=0.; for(int iemit=0;iemit<2;++iemit) { double phi = UseRandom::rnd()*Constants::twopi; // set the emitter and the spectator double muj = iemit==0 ? mu1_ : mu2_; double muk = iemit==0 ? mu2_ : mu1_; double muj2 = sqr(muj); double muk2 = sqr(muk); // calculate y double yminus = 0.; double yplus = 1.-2.*muk*(1.-muk)/(1.-muj2-muk2); double y = yminus + UseRandom::rnd()*(yplus-yminus); double v = sqrt(sqr(2.*muk2 + (1.-muj2-muk2)*(1.-y))-4.*muk2) /(1.-muj2-muk2)/(1.-y); double zplus = (1.+v)*(1.-muj2-muk2)*y/2./(muj2+(1.-muj2-muk2)*y); double zminus = (1.-v)*(1.-muj2-muk2)*y/2./(muj2+(1.-muj2-muk2)*y); double z = zminus + UseRandom::rnd()*(zplus-zminus); double jac = (1.-y)*(yplus-yminus)*(zplus-zminus); // calculate x1,x2,x3,xT double x2 = 1.-y*(1.-muj2-muk2)-muj2+muk2; double x1 = 1.+muj2-muk2-z*(x2-2.*muk2); // copy the particle objects over for calculateRealEmission vector hardProcess(3); hardProcess[0] = const_ptr_cast(&part); hardProcess[1] = decay[0]; hardProcess[2] = decay[1]; realFact = 0.25*jac*sqr(1.-muj2-muk2)/ sqrt((1.-sqr(muj-muk))*(1.-sqr(muj+muk)))/Constants::twopi *2.*CF_*aS_*calculateRealEmission(x1, x2, hardProcess, phi, muj, muk, iemit, true); } // the born + virtual + real output = output*(1. + virt + realFact); return output; } double SMWFermionsPOWHEGDecayer::meRatio(vector partons, vector momenta, unsigned int iemitter, bool subtract) const { Lorentz5Momentum q = momenta[1]+momenta[2]+momenta[3]; Energy2 Q2=q.m2(); Energy2 lambda = sqrt((Q2-sqr(momenta[1].mass()+momenta[2].mass()))* (Q2-sqr(momenta[1].mass()-momenta[2].mass()))); InvEnergy2 D[2]; double lome[2]; for(unsigned int iemit=0;iemit<2;++iemit) { unsigned int ispect = iemit==0 ? 1 : 0; Energy2 pipj = momenta[3 ] * momenta[1+iemit ]; Energy2 pipk = momenta[3 ] * momenta[1+ispect]; Energy2 pjpk = momenta[1+iemit] * momenta[1+ispect]; double y = pipj/(pipj+pipk+pjpk); double z = pipk/( pipk+pjpk); Energy mij = sqrt(2.*pipj+sqr(momenta[1+iemit].mass())); Energy2 lamB = sqrt((Q2-sqr(mij+momenta[1+ispect].mass()))* (Q2-sqr(mij-momenta[1+ispect].mass()))); Energy2 Qpk = q*momenta[1+ispect]; Lorentz5Momentum pkt = lambda/lamB*(momenta[1+ispect]-Qpk/Q2*q) +0.5/Q2*(Q2+sqr(momenta[1+ispect].mass())-sqr(momenta[1+ispect].mass()))*q; Lorentz5Momentum pijt = q-pkt; double muj = momenta[1+iemit ].mass()/sqrt(Q2); double muk = momenta[1+ispect].mass()/sqrt(Q2); double vt = sqrt((1.-sqr(muj+muk))*(1.-sqr(muj-muk)))/(1.-sqr(muj)-sqr(muk)); double v = sqrt(sqr(2.*sqr(muk)+(1.-sqr(muj)-sqr(muk))*(1.-y))-4.*sqr(muk)) /(1.-y)/(1.-sqr(muj)-sqr(muk)); // dipole term D[iemit] = 0.5/pipj*(2./(1.-(1.-z)*(1.-y)) -vt/v*(2.-z+sqr(momenta[1+iemit].mass())/pipj)); // matrix element vector lomom(3); lomom[0] = momenta[0]; if(iemit==0) { lomom[1] = pijt; lomom[2] = pkt ; } else { lomom[2] = pijt; lomom[1] = pkt ; } lome[iemit] = loME(partons,lomom); } InvEnergy2 ratio = realME(partons,momenta)*abs(D[iemitter]) /(abs(D[0]*lome[0])+abs(D[1]*lome[1])); if(subtract) return Q2*(ratio-2.*D[iemitter]); else return Q2*ratio; } double SMWFermionsPOWHEGDecayer::loME(const vector & partons, const vector & momenta) const { // compute the spinors vector vin; vector aout; vector fout; VectorWaveFunction win (momenta[0],partons[0],incoming); SpinorBarWaveFunction qkout(momenta[1],partons[1],outgoing); SpinorWaveFunction qbout(momenta[2],partons[2],outgoing); for(unsigned int ix=0;ix<2;++ix){ qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); } for(unsigned int ix=0;ix<3;++ix){ win.reset(ix); vin.push_back(win); } // temporary storage of the different diagrams // sum over helicities to get the matrix element double total(0.); for(unsigned int inhel=0;inhel<3;++inhel) { for(unsigned int outhel1=0;outhel1<2;++outhel1) { for(unsigned int outhel2=0;outhel2<2;++outhel2) { Complex diag1 = FFWVertex()->evaluate(scale_,aout[outhel2],fout[outhel1],vin[inhel]); total += norm(diag1); } } } // return the answer return total; } InvEnergy2 SMWFermionsPOWHEGDecayer::realME(const vector & partons, const vector & momenta) const { // compute the spinors vector vin; vector aout; vector fout; vector gout; VectorWaveFunction win (momenta[0],partons[0],incoming); SpinorBarWaveFunction qkout(momenta[1],partons[1],outgoing); SpinorWaveFunction qbout(momenta[2],partons[2],outgoing); VectorWaveFunction gluon(momenta[3],partons[3],outgoing); for(unsigned int ix=0;ix<2;++ix){ qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); gluon.reset(2*ix); gout.push_back(gluon); } for(unsigned int ix=0;ix<3;++ix){ win.reset(ix); vin.push_back(win); } vector diag(2,0.); double total(0.); for(unsigned int inhel1=0;inhel1<3;++inhel1) { for(unsigned int outhel1=0;outhel1<2;++outhel1) { for(unsigned int outhel2=0;outhel2<2;++outhel2) { for(unsigned int outhel3=0;outhel3<2;++outhel3) { SpinorBarWaveFunction off1 = FFGVertex()->evaluate(scale_,3,partons[1],fout[outhel1],gout[outhel3]); diag[0] = FFWVertex()->evaluate(scale_,aout[outhel2],off1,vin[inhel1]); SpinorWaveFunction off2 = FFGVertex()->evaluate(scale_,3,partons[2],aout[outhel2],gout[outhel3]); diag[1] = FFWVertex()->evaluate(scale_,off2,fout[outhel1],vin[inhel1]); // sum of diagrams Complex sum = std::accumulate(diag.begin(),diag.end(),Complex(0.)); // me2 total += norm(sum); } } } } // divide out the coupling total /= norm(FFGVertex()->norm()); // return the total return total*UnitRemoval::InvE2; } void SMWFermionsPOWHEGDecayer::doinit() { // cast the SM pointer to the Herwig SM pointer tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); // do the initialisation if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "SMWFermionsPOWHEGDecayer::doinit() " << "the Herwig version must be used." << Exception::runerror; // cast the vertices FFWVertex_ = hwsm->vertexFFW(); FFWVertex_->init(); FFGVertex_ = hwsm->vertexFFG(); FFGVertex_->init(); SMWDecayer::doinit(); gluon_ = getParticleData(ParticleID::g); } bool SMWFermionsPOWHEGDecayer::getEvent(vector hardProcess) { vector particleMass; for(unsigned int ix=0;ixid())==ParticleID::Wplus) { mW_ = hardProcess[ix]->mass(); } else { particleMass.push_back(hardProcess[ix]->mass()); } } if (particleMass.size()!=2) { throw Exception() << "Number of outgoing particles is not equal to 2 in " << "SMWFermionPOWHEGDecayer::getEvent()" << Exception::runerror; } // reduced mass mu1_ = particleMass[0]/mW_; mu2_ = particleMass[1]/mW_; // scale scale_ = sqr(mW_); // max pT Energy pTmax = 0.5*sqrt(mw2_); if(pTmaxoverestimateValue()*CF_* (ymax-ymin)/Constants::twopi; // loop to generate the pt and rapidity bool reject; //arrays to hold the temporary probabilities whilst the for loop progresses double probTemp[2][2]={{0.,0.},{0.,0.}}; probTemp[0][0]=probTemp[0][1]=probTemp[1][0]=probTemp[1][1]=0.; double x1Solution[2][2] = {{0.,0.},{0.,0.}}; double x2Solution[2][2] = {{0.,0.},{0.,0.}}; double x3Solution[2] = {0.,0.}; Energy pT[2] = {pTmax,pTmax}; double yTemp[2] = {0.,0.}; double phi = 0.; // do the competition for(int i=0; i<2; i++) { // set the emitter and the spectator double muj = i==0 ? mu1_ : mu2_; double muk = i==0 ? mu2_ : mu1_; double muj2 = sqr(muj); double muk2 = sqr(muk); do { // generation of phi phi = UseRandom::rnd() * Constants::twopi; // reject the emission reject = true; // generate pt pT[i] *= pow(UseRandom::rnd(),1./prefactor); if(pT[i] 0 if( discrim2 < ZERO) continue; double fact1 =2.*sqr(x3Solution[i])-4.*muk2-6.*x3Solution[i]+4.*muj2-xT2*x3Solution[i] +2.*xT2-2.*muj2*x3Solution[i]+2.*muk2*x3Solution[i]+4.; double fact2 = (4.-4.*x3Solution[i]+xT2); double discriminant = sqrt(discrim2); // two solns for x1 x1Solution[i][0] = (fact1 + 2.*discriminant)/fact2; x1Solution[i][1] = (fact1 - 2.*discriminant)/fact2; bool found = false; for(unsigned int j=0;j<2;++j) { // calculate x2 x2Solution[i][j] = 2.-x3Solution[i]-x1Solution[i][j]; // set limits on x2 double root = max(0.,sqr(x1Solution[i][j])-4.*muj2); root = sqrt(root); double x2Plus = 1.+muk2-muj2 -0.5*(1.-x1Solution[i][j]+muj2-muk2)/(1.-x1Solution[i][j]+muj2) *(x1Solution[i][j]-2.*muj2-root); double x2Minus = 1.+muk2-muj2 -0.5*(1.-x1Solution[i][j]+muj2-muk2)/(1.-x1Solution[i][j]+muj2) *(x1Solution[i][j]-2.*muj2+root); if(x1Solution[i][j]>=x1Minus && x1Solution[i][j]<=x1Plus && x2Solution[i][j]>=x2Minus && x2Solution[i][j]<=x2Plus && checkZMomenta(x1Solution[i][j], x2Solution[i][j], x3Solution[i], yTemp[i], pT[i], muj, muk)) { probTemp[i][j] = weightPrefactor*pT[i]* calculateJacobian(x1Solution[i][j], x2Solution[i][j], pT[i], muj, muk)* calculateRealEmission(x1Solution[i][j], x2Solution[i][j], hardProcess, phi, muj, muk, i, false); found = true; } else { probTemp[i][j] = 0.; } } if(!found) continue; // alpha S piece double wgt = (probTemp[i][0]+probTemp[i][1])*alphaS()->ratio(sqr(pT[i])); // matrix element weight reject = UseRandom::rnd()>wgt; } while(reject); } // end of emitter for loop // no emission if(pT[0]pT[1]){ pT_ = pT[0]; y=yTemp[0]; if(probTemp[0][0]>UseRandom::rnd()*(probTemp[0][0]+probTemp[0][1])) { x1 = x1Solution[0][0]; x2 = x2Solution[0][0]; } else { x1 = x1Solution[0][1]; x2 = x2Solution[0][1]; } } // particle 2 emits, particle 1 spectates else { iemit=1; pT_ = pT[1]; y=yTemp[1]; if(probTemp[1][0]>UseRandom::rnd()*(probTemp[1][0]+probTemp[1][1])) { x1 = x1Solution[1][0]; x2 = x2Solution[1][0]; } else { x1 = x1Solution[1][1]; x2 = x2Solution[1][1]; } } // find spectator unsigned int ispect = iemit == 0 ? 1 : 0; double muk = iemit == 0 ? mu2_ : mu1_; double muk2 = sqr(muk); // Find the boost from the lab to the c.o.m with the spectator // along the -z axis, and then invert it. LorentzRotation eventFrame( ( quark_[0] + quark_[1] ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*quark_[ispect]; eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() - Constants::pi ); eventFrame.invert(); // spectator quark_[ispect].setT( 0.5*x2*mW_ ); quark_[ispect].setX( ZERO ); quark_[ispect].setY( ZERO ); quark_[ispect].setZ( -sqrt(0.25*mw2_*x2*x2-mw2_*muk2) ); // gluon gauge_.setT( pT_*cosh(y) ); gauge_.setX( pT_*cos(phi) ); gauge_.setY( pT_*sin(phi) ); gauge_.setZ( pT_*sinh(y) ); gauge_.setMass(ZERO); // emitter reconstructed from gluon & spectator quark_[iemit] = -gauge_ - quark_[ispect]; quark_[iemit].setT( 0.5*mW_*x1 ); // boost constructed vectors into the event frame quark_[0] = eventFrame * quark_[0]; quark_[1] = eventFrame * quark_[1]; gauge_ = eventFrame * gauge_; // need to reset masses because for whatever reason the boost // touches the mass component of the five-vector and can make // zero mass objects acquire a floating point negative mass(!). gauge_.setMass( ZERO ); quark_[iemit] .setMass(partons_[iemit ]->mass()); quark_[ispect].setMass(partons_[ispect]->mass()); return true; } InvEnergy SMWFermionsPOWHEGDecayer::calculateJacobian(double x1, double x2, Energy pT, double muj, double muk) const{ double xPerp = abs(2.*pT/mW_); Energy jac = mW_/xPerp*fabs((x2*sqr(muj)+2.*sqr(muk)*x1 +sqr(muk)*x2-x1*x2-sqr(x2)+x2)/pow((sqr(x2)-4.*sqr(muk)),1.5)); return 1./jac; //jacobian as defined is dptdy=jac*dx1dx2, therefore we have to divide by it } bool SMWFermionsPOWHEGDecayer::checkZMomenta(double x1, double x2, double x3, double y, Energy pT, double muj, double muk) const { double xPerp2 = 4.*pT*pT/mW_/mW_; double root1 = sqrt(max(0.,sqr(x2)-4.*sqr(muk))); double root2 = sqrt(max(0.,sqr(x1)-xPerp2 - 4.*sqr(muj))); static double tolerance = 1e-6; bool isMomentaReconstructed = false; if(pT*sinh(y) > ZERO) { if(abs(-root1 + sqrt(sqr(x3)-xPerp2) + root2) <= tolerance || abs(-root1 + sqrt(sqr(x3)-xPerp2) - root2) <= tolerance) isMomentaReconstructed=true; } else if(pT*sinh(y) < ZERO){ if(abs(-root1 - sqrt(sqr(x3)-xPerp2) + root2) <= tolerance || abs(-root1 - sqrt(sqr(x3)-xPerp2) - root2) <= tolerance) isMomentaReconstructed=true; } else if(abs(-root1+ sqrt(sqr(x1)-xPerp2 - 4.*(muj))) <= tolerance) isMomentaReconstructed=true; return isMomentaReconstructed; } double SMWFermionsPOWHEGDecayer::calculateRealEmission(double x1, double x2, vector hardProcess, double phi, double muj, double muk, int iemit, bool subtract) const { // make partons data object for meRatio vector partons (3); for(int ix=0; ix<3; ++ix) partons[ix] = hardProcess[ix]->dataPtr(); partons.push_back(gluon_); // calculate x3 double x3 = 2.-x1-x2; double xT = sqrt(max(0.,sqr(x3)-0.25*sqr(sqr(x2)+sqr(x3)-sqr(x1)-4.*sqr(muk)+4.*sqr(muj)) /(sqr(x2)-4.*sqr(muk)))); // calculate the momenta Energy M = mW_; Lorentz5Momentum pspect(ZERO,ZERO,-0.5*M*sqrt(max(sqr(x2)-4.*sqr(muk),0.)), 0.5*M*x2,M*muk); Lorentz5Momentum pemit (-0.5*M*xT*cos(phi),-0.5*M*xT*sin(phi), 0.5*M*sqrt(max(sqr(x1)-sqr(xT)-4.*sqr(muj),0.)), 0.5*M*x1,M*muj); Lorentz5Momentum pgluon(0.5*M*xT*cos(phi), 0.5*M*xT*sin(phi), 0.5*M*sqrt(max(sqr(x3)-sqr(xT),0.)),0.5*M*x3,ZERO); if(abs(pspect.z()+pemit.z()-pgluon.z())/M<1e-6) pgluon.setZ(-pgluon.z()); else if(abs(pspect.z()-pemit.z()+pgluon.z())/M<1e-6) pemit .setZ(- pemit.z()); // loop over the possible emitting partons double realwgt(0.); // boost and rotate momenta LorentzRotation eventFrame( ( hardProcess[1]->momentum() + hardProcess[2]->momentum() ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*hardProcess[iemit+1]->momentum(); eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() ); eventFrame.invert(); vector momenta(3); momenta[0] = hardProcess[0]->momentum(); if(iemit==0) { momenta[2] = eventFrame*pspect; momenta[1] = eventFrame*pemit ; } else { momenta[1] = eventFrame*pspect; momenta[2] = eventFrame*pemit ; } momenta.push_back(eventFrame*pgluon); // calculate the weight if(1.-x1>1e-5 && 1.-x2>1e-5) realwgt += meRatio(partons,momenta,iemit,subtract); return realwgt; } diff --git a/Decay/Perturbative/SMWFermionsPOWHEGDecayer.h b/Decay/Perturbative/SMWFermionsPOWHEGDecayer.h --- a/Decay/Perturbative/SMWFermionsPOWHEGDecayer.h +++ b/Decay/Perturbative/SMWFermionsPOWHEGDecayer.h @@ -1,309 +1,309 @@ // -*- C++ -*- #ifndef HERWIG_SMWFermionsPOWHEGDecayer_H #define HERWIG_SMWFermionsPOWHEGDecayer_H // // This is the declaration of the SMWFermionsPOWHEGDecayer class. // #include "SMWDecayer.h" #include "Herwig/Utilities/Maths.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SMWFermionsPOWHEGDecayer class. * * @see \ref SMWFermionsPOWHEGDecayerInterfaces "The interfaces" * defined for SMWFermionsPOWHEGDecayer. */ class SMWFermionsPOWHEGDecayer: public SMWDecayer { public: /** * The default constructor. */ SMWFermionsPOWHEGDecayer(); /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr); //@} virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initSMWFermionsPOWHEGDecayer; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SMWFermionsPOWHEGDecayer & operator=(const SMWFermionsPOWHEGDecayer &); /** * Pointer to the fermion-antifermion W vertex */ AbstractFFVVertexPtr FFWVertex() const {return FFWVertex_;} /** * Pointer to the fermion-antifermion G vertex */ AbstractFFVVertexPtr FFGVertex() const {return FFGVertex_;} /** * Real emission term, for use in generating the hardest emission */ double calculateRealEmission(double x1, double x2, vector hardProcess, double phi, double muj, double muk, int iemit, bool subtract) const; /** * Check the sign of the momentum in the \f$z\f$-direction is correct. */ bool checkZMomenta(double x1, double x2, double x3, double y, Energy pT, double muj, double muk) const; /** * Calculate the Jacobian */ InvEnergy calculateJacobian(double x1, double x2, Energy pT, double muj, double muk) const; /** * Calculate the ratio between NLO & LO ME */ double meRatio(vector partons, vector momenta, unsigned int iemitter,bool subtract) const; /** * Calculate the LO ME */ double loME(const vector & partons, const vector & momenta) const; /** * Calculate the NLO real emission piece of ME */ InvEnergy2 realME(const vector & partons, const vector & momenta) const; /** * Generate a real emission event */ bool getEvent(vector hardProcess); private: /** * Pointer to the fermion-antifermion W vertex */ AbstractFFVVertexPtr FFWVertex_; /** * Pointer to the fermion-antifermion G vertex */ AbstractFFVVertexPtr FFGVertex_; /** * The colour factor */ double CF_; /** * The W mass */ mutable Energy mW_; // TODO: delete this mutable double mu_; /** * The reduced mass of particle 1 */ mutable double mu1_; /** * The reduced mass of particle 1 squared */ mutable double mu12_; /** * The reduceed mass of particle 2 */ mutable double mu2_; /** * The reduceed mass of particle 2 squared */ mutable double mu22_; /** * The strong coupling */ mutable double aS_; /** * The scale */ mutable Energy2 scale_; /** * Stuff for the POWHEG correction */ //@{ /** * ParticleData object for the gluon */ tcPDPtr gluon_; /** * The cut off on pt, assuming massless quarks. */ Energy pTmin_; // radiative variables (pt,y) Energy pT_; /** * The ParticleData objects for the fermions */ vector partons_; /** * The fermion momenta */ vector quark_; /** * The momentum of the radiated gauge boson */ Lorentz5Momentum gauge_; /** * The W boson */ PPtr wboson_; /** * W mass squared */ Energy2 mw2_; //@} }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SMWFermionsPOWHEGDecayer. */ template <> struct BaseClassTrait { /** Typedef of the first base class of SMWFermionsPOWHEGDecayer. */ typedef Herwig::SMWDecayer NthBase; }; /** This template specialization informs ThePEG about the name of * the SMWFermionsPOWHEGDecayer 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::SMWFermionsPOWHEGDecayer"; } /** * The name of a file containing the dynamic library where the class * SMWFermionsPOWHEGDecayer is implemented. It may also include several, space-separated, * libraries if the class SMWFermionsPOWHEGDecayer 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 "HwPerturbativeDecay.so"; } }; /** @endcond */ } #endif /* HERWIG_SMWFermionsPOWHEGDecayer_H */ diff --git a/Decay/Perturbative/SMZDecayer.cc b/Decay/Perturbative/SMZDecayer.cc --- a/Decay/Perturbative/SMZDecayer.cc +++ b/Decay/Perturbative/SMZDecayer.cc @@ -1,925 +1,893 @@ // -*- C++ -*- // // SMZDecayer.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 SMZDecayer class. // #include "SMZDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Decay/DecayVertex.h" #include "ThePEG/Helicity/VectorSpinInfo.h" #include "ThePEG/Helicity/FermionSpinInfo.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/Models/StandardModel/StandardModel.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; const double SMZDecayer::EPS_=0.00000001; SMZDecayer::SMZDecayer() : quarkWeight_(5,0.), leptonWeight_(6,0.) { quarkWeight_[0] = 0.488029; quarkWeight_[1] = 0.378461; quarkWeight_[2] = 0.488019; quarkWeight_[3] = 0.378027; quarkWeight_[4] = 0.483207; leptonWeight_[0] = 0.110709; leptonWeight_[1] = 0.220276; leptonWeight_[2] = 0.110708; leptonWeight_[3] = 0.220276; leptonWeight_[4] = 0.110458; leptonWeight_[5] = 0.220276; // intermediates generateIntermediates(false); // QED corrections hasRealEmissionME(true); hasOneLoopME(true); } void SMZDecayer::doinit() { DecayIntegrator::doinit(); // get the vertices from the Standard Model object tcHwSMPtr hwsm=dynamic_ptr_cast(standardModel()); if(!hwsm) throw InitException() << "Must have Herwig StandardModel object in" << "SMZDecayer::doinit()" << Exception::runerror; FFZvertex_ = dynamic_ptr_cast(hwsm->vertexFFZ()); FFPvertex_ = hwsm->vertexFFP(); // make sure they are initialized FFZvertex_->init(); FFPvertex_->init(); // now set up the decay modes DecayPhaseSpaceModePtr mode; tPDVector extpart(3); vector wgt(0); // the Z decay modes extpart[0]=getParticleData(ParticleID::Z0); // loop over the quarks and the leptons for(int istep=0;istep<11;istep+=10) { for(int ix=1;ix<7;++ix) { int iy=istep+ix; if(iy==6) continue; extpart[1] = getParticleData(-iy); extpart[2] = getParticleData( iy); mode = new_ptr(DecayPhaseSpaceMode(extpart,this)); if(iy<=6) addMode(mode, quarkWeight_.at(ix-1),wgt); else addMode(mode,leptonWeight_.at(iy-11),wgt); } } } int SMZDecayer::modeNumber(bool & cc,tcPDPtr parent, const tPDVector & children) const { int imode(-1); if(children.size()!=2) return imode; int id0=parent->id(); tPDVector::const_iterator pit = children.begin(); int id1=(**pit).id(); ++pit; int id2=(**pit).id(); // Z to quarks or leptons cc =false; if(id0!=ParticleID::Z0) return imode; if(abs(id1)<6&&id1==-id2) { imode=abs(id1)-1; } else if(abs(id1)>=11&&abs(id1)<=16&&id1==-id2) { imode=abs(id1)-6; } cc = false; return imode; } void SMZDecayer::persistentOutput(PersistentOStream & os) const { os << FFZvertex_ << FFPvertex_ << quarkWeight_ << leptonWeight_ << alpha_; } void SMZDecayer::persistentInput(PersistentIStream & is, int) { is >> FFZvertex_ >> FFPvertex_ >> quarkWeight_ >> leptonWeight_ >> alpha_; } ClassDescription SMZDecayer::initSMZDecayer; // Definition of the static class description member. void SMZDecayer::Init() { static ClassDocumentation documentation ("The SMZDecayer class is the implementation of the decay" " Z boson to the Standard Model fermions."); static ParVector interfaceZquarkMax ("QuarkMax", "The maximum weight for the decay of the Z to quarks", &SMZDecayer::quarkWeight_, 0, 0, 0, -10000, 10000, false, false, true); static ParVector interfaceZleptonMax ("LeptonMax", "The maximum weight for the decay of the Z to leptons", &SMZDecayer::leptonWeight_, 0, 0, 0, -10000, 10000, false, false, true); static Reference interfaceCoupling ("Coupling", "Pointer to the object to calculate the coupling for the correction", &SMZDecayer::alpha_, false, false, true, false, false); } // return the matrix element squared double SMZDecayer::me2(const int, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); int iferm(1),ianti(0); if(decay[0]->id()>0) swap(iferm,ianti); if(meopt==Initialize) { VectorWaveFunction::calculateWaveFunctions(_vectors,_rho, const_ptr_cast(&inpart), incoming,false); } if(meopt==Terminate) { VectorWaveFunction::constructSpinInfo(_vectors,const_ptr_cast(&inpart), incoming,true,false); SpinorBarWaveFunction:: constructSpinInfo(_wavebar,decay[iferm],outgoing,true); SpinorWaveFunction:: constructSpinInfo(_wave ,decay[ianti],outgoing,true); return 0.; } SpinorBarWaveFunction:: calculateWaveFunctions(_wavebar,decay[iferm],outgoing); SpinorWaveFunction:: calculateWaveFunctions(_wave ,decay[ianti],outgoing); // compute the matrix element Energy2 scale(sqr(inpart.mass())); unsigned int ifm,ia,vhel; for(ifm=0;ifm<2;++ifm) { for(ia=0;ia<2;++ia) { for(vhel=0;vhel<3;++vhel) { if(iferm>ianti) (*ME())(vhel,ia,ifm)= FFZvertex_->evaluate(scale,_wave[ia],_wavebar[ifm],_vectors[vhel]); else (*ME())(vhel,ifm,ia)= FFZvertex_->evaluate(scale,_wave[ia],_wavebar[ifm],_vectors[vhel]); } } } double output=(ME()->contract(_rho)).real()*UnitRemoval::E2/scale; if(abs(decay[0]->id())<=6) output*=3.; if(decay[0]->hasColour()) decay[0]->antiColourNeighbour(decay[1]); else if(decay[1]->hasColour()) decay[1]->antiColourNeighbour(decay[0]); return output; } void SMZDecayer::doinitrun() { DecayIntegrator::doinitrun(); if(initialize()) { for(unsigned int ix=0;ixmaxWeight(); else if(ix<11) leptonWeight_[ix-5 ]=mode(ix)->maxWeight(); } } } void SMZDecayer::dataBaseOutput(ofstream & output, bool header) const { if(header) output << "update decayers set parameters=\""; for(unsigned int ix=0;ixmomentum().phi(); // wavefunctions for the decaying particle in the rotated dipole frame vector vec1 = _vectors; for(unsigned int ix=0;ix vec2 = _vectors; for(unsigned int ix=0;ixid()<0) swap(iferm,ianti); // wavefunctions for the particles before the radiation // wavefunctions for the outgoing fermion SpinorBarWaveFunction wavebartemp; Lorentz5Momentum ptemp = - _wavebar[0].momentum(); ptemp *= rot2; if(ptemp.perp()/ptemp.e()<1e-10) { ptemp.setX(ZERO); ptemp.setY(ZERO); } wavebartemp = SpinorBarWaveFunction(ptemp,_wavebar[0].particle(),outgoing); // wavefunctions for the outgoing antifermion SpinorWaveFunction wavetemp; ptemp = - _wave[0].momentum(); ptemp *= rot2; if(ptemp.perp()/ptemp.e()<1e-10) { ptemp.setX(ZERO); ptemp.setY(ZERO); } wavetemp = SpinorWaveFunction(ptemp,_wave[0].particle(),outgoing); // loop over helicities vector wf_old; vector wfb_old; for(unsigned int ihel=0;ihel<2;++ihel) { wavetemp.reset(ihel); wf_old.push_back(wavetemp); wavebartemp.reset(ihel); wfb_old.push_back(wavebartemp); } // calculate the wave functions for the new fermions // ensure the momenta have pT=0 for(unsigned int ix=0;ix<2;++ix) { Lorentz5Momentum ptemp = children[ix]->momentum(); if(ptemp.perp()/ptemp.e()<1e-10) { ptemp.setX(ZERO); ptemp.setY(ZERO); children[ix]->set5Momentum(ptemp); } } // calculate the wavefunctions vector wfb; SpinorBarWaveFunction::calculateWaveFunctions(wfb,children[iferm],outgoing); vector wf; SpinorWaveFunction::calculateWaveFunctions (wf ,children[ianti],outgoing); // wave functions for the photons vector photon; VectorWaveFunction::calculateWaveFunctions(photon,children[2],outgoing,true); // loop to calculate the matrix elements Complex lome[3][2][2],diffme[3][2][2][2],summe[3][2][2][2]; Energy2 scale(sqr(parent.mass())); Complex diff[2]={0.,0.}; Complex sum [2]={0.,0.}; for(unsigned int ifm=0;ifm<2;++ifm) { for(unsigned int ia=0;ia<2;++ia) { for(unsigned int vhel=0;vhel<3;++vhel) { // calculation of the leading-order matrix element Complex loamp = FFZvertex_->evaluate(scale,wf_old[ia], wfb_old[ifm],vec2[vhel]); Complex lotemp = FFZvertex_->evaluate(scale,wf[ia], wfb[ifm],vec1[vhel]); if(iferm>ianti) lome[vhel][ia][ifm] = loamp; else lome[vhel][ifm][ia] = loamp; // photon loop for the real emmision terms for(unsigned int phel=0;phel<2;++phel) { // radiation from the antifermion // normal case with small angle treatment if(children[2 ]->momentum().z()/ children[iferm]->momentum().z()>=ZERO && iemitter == iferm ) { Complex dipole = e*double(children[iferm]->dataPtr()->iCharge())/3.* UnitRemoval::E*loamp* (children[iferm]->momentum()*photon[2*phel].wave())/ (children[iferm]->momentum()*children[2]->momentum()); // sum and difference SpinorBarWaveFunction foff = FFPvertex_->evaluateSmall(ZERO,3,children[iferm]->dataPtr()->CC(), wfb[ifm],photon[2*phel], ifm,2*phel,ctheta,phi,stheta,false); diff[0] = FFZvertex_->evaluate(scale,wf[ia],foff,vec1[vhel]) + e*double(children[iferm]->dataPtr()->iCharge())/3.* UnitRemoval::E*(lotemp-loamp)* (children[iferm]->momentum()*photon[2*phel].wave())/ (children[iferm]->momentum()*children[2]->momentum()); sum [0] = diff[0]+2.*dipole; } // special if fermion backwards else { SpinorBarWaveFunction foff = FFPvertex_->evaluate(ZERO,3,children[iferm]->dataPtr()->CC(), wfb[ifm],photon[2*phel]); Complex diag = FFZvertex_->evaluate(scale,wf[ia],foff,vec1[vhel]); Complex dipole = e*double(children[iferm]->dataPtr()->iCharge())/3.* UnitRemoval::E*loamp* (children[iferm]->momentum()*photon[2*phel].wave())/ (children[iferm]->momentum()*children[2]->momentum()); diff[0] = diag-dipole; sum [0] = diag+dipole; } // radiation from the anti fermion // small angle case in general if(children[2 ]->momentum().z()/ children[ianti]->momentum().z()>=ZERO && iemitter == ianti ) { Complex dipole = e*double(children[ianti]->dataPtr()->iCharge())/3.* UnitRemoval::E*loamp* (children[ianti]->momentum()*photon[2*phel].wave())/ (children[ianti]->momentum()*children[2]->momentum()); // sum and difference SpinorWaveFunction foff = FFPvertex_->evaluateSmall(ZERO,3,children[ianti]->dataPtr()->CC(), wf[ia],photon[2*phel], ia,2*phel,ctheta,phi,stheta,false); diff[1] = FFZvertex_->evaluate(scale,foff ,wfb[ifm],vec1[vhel]) + e*double(children[ianti]->dataPtr()->iCharge())/3.* UnitRemoval::E*(lotemp-loamp)* (children[ianti]->momentum()*photon[2*phel].wave())/ (children[ianti]->momentum()*children[2]->momentum()); sum [1] = diff[1]+2.*dipole; } // special if fermion backwards after radiation else { SpinorWaveFunction foff = FFPvertex_->evaluate(ZERO,3,children[ianti]->dataPtr()->CC(), wf[ia],photon[2*phel]); Complex diag = FFZvertex_->evaluate(scale,foff ,wfb[ifm],vec1[vhel]); Complex dipole = e*double(children[ianti]->dataPtr()->iCharge())/3.* UnitRemoval::E*loamp* (children[ianti]->momentum()*photon[2*phel].wave())/ (children[ianti]->momentum()*children[2]->momentum()); // sum and difference diff[1] = diag - dipole; sum [1] = diag + dipole; } // add to me if(iferm>ianti) { diffme[vhel][ia][ifm][phel] = diff[0] + diff[1]; summe [vhel][ia][ifm][phel] = sum[0] + sum[1] ; } else { diffme [vhel][ifm][ia][phel] = diff[0] + diff[1]; summe [vhel][ifm][ia][phel] = sum[0] + sum[1] ; } } } } } // cerr << parent << "\n"; // for(unsigned int ix=0;ixdataPtr()->iCharge()* // children[1]->dataPtr()->iCharge()/9.; // Energy2 ubar = 2.*children[0]->momentum()*children[2]->momentum(); // Energy2 tbar = 2.*children[1]->momentum()*children[2]->momentum(); // double mu2 = sqr(children[1]->mass()/parent.mass()); // double gL = (FFZvertex_->left() *FFZvertex_->norm()).real(); // double gR = (FFZvertex_->right()*FFZvertex_->norm()).real(); // Energy2 den = sqr(parent.mass())*(((sqr(gL)+sqr(gR))*(1-mu2)+6.*mu2*gL*gR)); // InvEnergy2 anal = -iCharge*( 2.*(ubar/tbar+tbar/ubar)/sqr(parent.mass())+ // 4.*mu2/den*((sqr(gL)+sqr(gR))*(1+ubar/tbar+tbar/ubar) // -2.*gL*gR*(1.+2.*(ubar/tbar+tbar/ubar)))); // cerr << "testing ratio " << parent.PDGName() // << " " << difference.real()/sqr(e)/lo.real()*UnitRemoval::InvE2/(anal) << "\n" // << stheta << " " << ctheta << "\n"; return difference.real()/sqr(e)/lo.real()*UnitRemoval::InvE2; } double SMZDecayer::oneLoopVirtualME(unsigned int, const Particle & parent, const ParticleVector & children) { assert(children.size()==2); // velocities of the particles double beta = sqrt(1.-4.*sqr(children[0]->mass()/parent.mass())); double opb = 1.+beta; double omb = 4.*sqr(children[0]->mass()/parent.mass())/opb; // couplings double gL = (FFZvertex_->left() *FFZvertex_->norm()).real(); double gR = (FFZvertex_->right()*FFZvertex_->norm()).real(); double gA = 0.5*(gL-gR); double gV = 0.5*(gL+gR); // correction terms double ln = log(omb/opb); double f1 = 1. + ln*beta; double fA = 1. + ln/beta; InvEnergy f2 = 0.5*sqrt(omb*opb)/parent.mass()/beta*ln; // momentum difference for the loop Lorentz5Momentum q = children[0]->momentum()-children[1]->momentum(); if(children[0]->id()<0) q *= -1.; // spinors vector > sp; vector > sbar; for(unsigned int ix=0;ix<2;++ix) { sp .push_back( _wave[ix].dimensionedWave()); sbar.push_back(_wavebar[ix].dimensionedWave()); } // polarization vectors vector pol; for(unsigned int ix=0;ix<3;++ix) pol.push_back(_vectors[ix].wave()); // matrix elements complex lome[3][2][2],loopme[3][2][2]; for(unsigned int vhel=0;vhel<3;++vhel) { for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { complex vector = sp[ihel1].generalCurrent(sbar[ihel2], 1.,1.).dot(pol[vhel]); complex axial = sp[ihel1].generalCurrent(sbar[ihel2],-1.,1.).dot(pol[vhel]); complex scalar = sp[ihel1].scalar(sbar[ihel2])*(q*pol[vhel]); lome [vhel][ihel1][ihel2] = gV* vector-gA* axial; loopme[vhel][ihel1][ihel2] = gV*f1*vector-gA*fA*axial+scalar*f2*gV; } } } // sum sums complex den(ZERO),num(ZERO); for(unsigned int vhel1=0;vhel1<3;++vhel1) { for(unsigned int vhel2=0;vhel2<3;++vhel2) { for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { num += _rho(vhel1,vhel2)* ( lome[vhel1][ihel1][ihel2]*conj(loopme[vhel2][ihel1][ihel2])+ loopme[vhel1][ihel1][ihel2]*conj( lome[vhel2][ihel1][ihel2])); den += _rho(vhel1,vhel2)* lome[vhel1][ihel1][ihel2]*conj(lome[vhel2][ihel1][ihel2]); } } } } // prefactor double iCharge = children[0]->dataPtr()->iCharge()* children[1]->dataPtr()->iCharge()/9.; double pre = 0.5*SM().alphaEM()*iCharge/Constants::pi; // output return pre*num.real()/den.real(); } void SMZDecayer:: -initializeMECorrection(ShowerTreePtr tree, double & initial, +initializeMECorrection(RealEmissionProcessPtr born, double & initial, double & final) { - map::const_iterator cjt; // get the quark and antiquark ParticleVector qq; - for(cjt=tree->outgoingLines().begin();cjt!=tree->outgoingLines().end();++cjt) - qq.push_back(cjt->first->copy()); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) + qq.push_back(born->bornOutgoing()[ix]); // ensure quark first if(qq[0]->id()<0) swap(qq[0],qq[1]); // centre of mass energy d_Q_ = (qq[0]->momentum() + qq[1]->momentum()).m(); // quark mass d_m_ = 0.5*(qq[0]->momentum().m()+qq[1]->momentum().m()); // set the other parameters setRho(sqr(d_m_/d_Q_)); setKtildeSymm(); // otherwise can do it initial=1.; final =1.; } -void SMZDecayer:: -applyHardMatrixElementCorrection(ShowerTreePtr tree) { +RealEmissionProcessPtr SMZDecayer:: +applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { // get the quark and antiquark ParticleVector qq; - map::const_iterator cit; - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) - qq.push_back(cit->first->copy()); - if(!qq[0]->dataPtr()->coloured()) return; + for(unsigned int ix=0;ixbornOutgoing().size();++ix) + qq.push_back(born->bornOutgoing()[ix]); + if(!qq[0]->dataPtr()->coloured()) return RealEmissionProcessPtr(); // ensure quark first - if(qq[0]->id()<0) swap(qq[0],qq[1]); + bool order = qq[0]->id()<0; + if(order) swap(qq[0],qq[1]); // get the momenta vector newfs = applyHard(qq); // return if no emission - if(newfs.size()!=3) return; + if(newfs.size()!=3) return RealEmissionProcessPtr(); // perform final check to ensure energy greater than constituent mass for (int i=0; i<2; i++) { - if (newfs[i].e() < qq[i]->data().constituentMass()) return; + if (newfs[i].e() < qq[i]->data().constituentMass()) return RealEmissionProcessPtr(); } if (newfs[2].e() < getParticleData(ParticleID::g)->constituentMass()) - return; + return RealEmissionProcessPtr(); // set masses for (int i=0; i<2; i++) newfs[i].setMass(qq[i]->mass()); newfs[2].setMass(ZERO); // decide which particle emits bool firstEmits= newfs[2].vect().perp2(newfs[0].vect())< newfs[2].vect().perp2(newfs[1].vect()); // create the new quark, antiquark and gluon PPtr newg = getParticleData(ParticleID::g)->produceParticle(newfs[2]); - PPtr newq,newa; - if(firstEmits) { - newq = getParticleData(abs(qq[0]->id()))->produceParticle(newfs[0]); - newa = new_ptr(Particle(*qq[1])); - qq[1]->antiColourLine()->removeAntiColoured(newa); - newa->set5Momentum(newfs[1]); + PPtr newq = qq[0]->dataPtr()->produceParticle(newfs[0]); + PPtr newa = qq[1]->dataPtr()->produceParticle(newfs[1]); + // create the output real emission process + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + born->incoming().push_back(born->bornIncoming()[ix]); + } + if(!order) { + born->outgoing().push_back(newq); + born->outgoing().push_back(newa); + born->outgoing().push_back(newg); } else { - newq = new_ptr(Particle(*qq[0])); - qq[0]->colourLine()->removeColoured(newq); - newq->set5Momentum(newfs[0]); - newa = getParticleData(-abs(qq[0]->id()))->produceParticle(newfs[1]); + born->outgoing().push_back(newa); + born->outgoing().push_back(newq); + born->outgoing().push_back(newg); + firstEmits = !firstEmits; } - // get the original colour line - ColinePtr col; - if(qq[0]->id()>0) col=qq[0]->colourLine(); - else col=qq[0]->antiColourLine(); - // set the colour lines + // make colour connections + newg->colourNeighbour(newq); + newa->colourNeighbour(newg); if(firstEmits) { - col->addColoured(newq); - col->addAntiColoured(newg); - newa->colourNeighbour(newg); + born->emitter(1); + born->spectator(2); } else { - col->addAntiColoured(newa); - col->addColoured(newg); - newq->antiColourNeighbour(newg); + born->emitter(2); + born->spectator(1); } - // change the existing quark and antiquark - PPtr orig; - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(cit->first->progenitor()->id()==newq->id()) { - // remove old particles from colour line - col->removeColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newq); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newq,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(!firstEmits); - if(firstEmits) orig=cit->first->original(); - } - else { - // remove old particles from colour line - col->removeAntiColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newa); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newa,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(firstEmits); - if(!firstEmits) orig=cit->first->original(); - } - } - // add the gluon - ShowerParticlePtr sg=new_ptr(ShowerParticle(*newg,1,true)); - ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg)); - gluon->perturbative(false); - tree->outgoingLines().insert(make_pair(gluon,sg)); - tree->hardMatrixElementCorrection(true); + born->emitted(3); + born->interaction(ShowerInteraction::QCD); + return born; } vector SMZDecayer:: applyHard(const ParticleVector &p) { double x, xbar; vector fs; // return if no emission if (getHard(x, xbar) < UseRandom::rnd() || p.size() != 2) return fs; // centre of mass energy Lorentz5Momentum pcm = p[0]->momentum() + p[1]->momentum(); // momenta of quark,antiquark and gluon Lorentz5Momentum pq, pa, pg; if (p[0]->id() > 0) { pq = p[0]->momentum(); pa = p[1]->momentum(); } else { pa = p[0]->momentum(); pq = p[1]->momentum(); } // boost to boson rest frame Boost beta = (pcm.findBoostToCM()); pq.boost(beta); pa.boost(beta); // return if fails ????? double xg = 2.-x-xbar; if((1.-x)*(1.-xbar)*(1.-xg) < d_rho_*xg*xg) return fs; Axis u1, u2, u3; // moduli of momenta in units of Q and cos theta // stick to q direction? // p1 is the one that is kept, p2 is the other fermion, p3 the gluon. Energy e1, e2, e3; Energy pp1, pp2, pp3; bool keepq = true; if (UseRandom::rnd() > sqr(x)/(sqr(x)+sqr(xbar))) keepq = false; if (keepq) { pp1 = d_Q_*sqrt(sqr(x)-4.*d_rho_)/2.; pp2 = d_Q_*sqrt(sqr(xbar)-4.*d_rho_)/2.; e1 = d_Q_*x/2.; e2 = d_Q_*xbar/2.; u1 = pq.vect().unit(); } else { pp2 = d_Q_*sqrt(sqr(x)-4.*d_rho_)/2.; pp1 = d_Q_*sqrt(sqr(xbar)-4.*d_rho_)/2.; e2 = d_Q_*x/2.; e1 = d_Q_*xbar/2.; u1 = pa.vect().unit(); } pp3 = d_Q_*xg/2.; e3 = pp3; u2 = u1.orthogonal(); u2 /= u2.mag(); u3 = u1.cross(u2); u3 /= u3.mag(); double ct2=-2., ct3=-2.; if (pp1 == ZERO || pp2 == ZERO || pp3 == ZERO) { bool touched = false; if (pp1 == ZERO) { ct2 = 1; ct3 = -1; touched = true; } if (pp2 == ZERO || pp3 == ZERO) { ct2 = 1; ct3 = 1; touched = true; } if (!touched) throw Exception() << "SMZDecayer::applyHard()" << " did not set ct2/3" << Exception::abortnow; } else { ct3 = (sqr(pp1)+sqr(pp3)-sqr(pp2))/(2.*pp1*pp3); ct2 = (sqr(pp1)+sqr(pp2)-sqr(pp3))/(2.*pp1*pp2); } double phi = Constants::twopi*UseRandom::rnd(); double cphi = cos(phi); double sphi = sin(phi); double st2 = sqrt(1.-sqr(ct2)); double st3 = sqrt(1.-sqr(ct3)); ThreeVector pv1, pv2, pv3; pv1 = pp1*u1; pv2 = -ct2*pp2*u1 + st2*cphi*pp2*u2 + st2*sphi*pp2*u3; pv3 = -ct3*pp3*u1 - st3*cphi*pp3*u2 - st3*sphi*pp3*u3; if (keepq) { pq = Lorentz5Momentum(pv1, e1); pa = Lorentz5Momentum(pv2, e2); } else { pa = Lorentz5Momentum(pv1, e1); pq = Lorentz5Momentum(pv2, e2); } pg = Lorentz5Momentum(pv3, e3); pq.boost(-beta); pa.boost(-beta); pg.boost(-beta); fs.push_back(pq); fs.push_back(pa); fs.push_back(pg); return fs; } double SMZDecayer::getHard(double &x1, double &x2) { double w = 0.0; double y1 = UseRandom::rnd(),y2 = UseRandom::rnd(); // simply double MC efficiency // -> weight has to be divided by two (Jacobian) if (y1 + y2 > 1) { y1 = 1.-y1; y2 = 1.-y2; } bool inSoft = false; if (y1 < 0.25) { if (y2 < 0.25) { inSoft = true; if (y1 < y2) { y1 = 0.25-y1; y2 = y1*(1.5 - 2.*y2); } else { y2 = 0.25 - y2; y1 = y2*(1.5 - 2.*y1); } } else { if (y2 < y1 + 2.*sqr(y1)) return w; } } else { if (y2 < 0.25) { if (y1 < y2 + 2.*sqr(y2)) return w; } } // inside PS? x1 = 1.-y1; x2 = 1.-y2; if(y1*y2*(1.-y1-y2) < d_rho_*sqr(y1+y2)) return w; double k1 = getKfromX(x1, x2); double k2 = getKfromX(x2, x1); // Is it in the quark emission zone? if (k1 < d_kt1_) return 0.0; // No...is it in the anti-quark emission zone? if (k2 < d_kt2_) return 0.0; // Point is in dead zone: compute q qbar g weight w = MEV(x1, x2); // for axial: // w = MEA(x1, x2); // Reweight soft region if (inSoft) { if (y1 < y2) w *= 2.*y1; else w *= 2.*y2; } // alpha and colour factors Energy2 pt2 = sqr(d_Q_)*(1.-x1)*(1.-x2); w *= 1./3./Constants::pi*alpha_->value(pt2); return w; } bool SMZDecayer:: softMatrixElementVeto(ShowerProgenitorPtr initial,ShowerParticlePtr parent,Branching br) { // check we should be applying the veto if(parent->id()!=initial->progenitor()->id()|| br.ids[0]->id()!=br.ids[1]->id()|| br.ids[2]->id()!=ParticleID::g) return false; // calculate pt double d_z = br.kinematics->z(); Energy d_qt = br.kinematics->scale(); Energy2 d_m2 = parent->momentum().m2(); Energy pPerp = (1.-d_z)*sqrt( sqr(d_z*d_qt) - d_m2); // if not hardest so far don't apply veto if(pPerphighestpT()) return false; // calculate the weight double weight = 0.; if(parent->id()>0) weight = qWeightX(d_qt, d_z); else weight = qbarWeightX(d_qt, d_z); // compute veto from weight bool veto = !UseRandom::rndbool(weight); // if vetoing reset the scale if(veto) parent->vetoEmission(br.type,br.kinematics->scale()); // return the veto return veto; } void SMZDecayer::setRho(double r) { d_rho_ = r; d_v_ = sqrt(1.-4.*d_rho_); } void SMZDecayer::setKtildeSymm() { d_kt1_ = (1. + sqrt(1. - 4.*d_rho_))/2.; setKtilde2(); } void SMZDecayer::setKtilde2() { double num = d_rho_ * d_kt1_ + 0.25 * d_v_ *(1.+d_v_)*(1.+d_v_); double den = d_kt1_ - d_rho_; d_kt2_ = num/den; } double SMZDecayer::getZfromX(double x1, double x2) { double uval = u(x2); double num = x1 - (2. - x2)*uval; double den = sqrt(x2*x2 - 4.*d_rho_); return uval + num/den; } double SMZDecayer::getKfromX(double x1, double x2) { double zval = getZfromX(x1, x2); return (1.-x2)/(zval*(1.-zval)); } double SMZDecayer::MEV(double x1, double x2) { // Vector part double num = (x1+2.*d_rho_)*(x1+2.*d_rho_) + (x2+2.*d_rho_)*(x2+2.*d_rho_) - 8.*d_rho_*(1.+2.*d_rho_); double den = (1.+2.*d_rho_)*(1.-x1)*(1.-x2); return (num/den - 2.*d_rho_/((1.-x1)*(1.-x1)) - 2*d_rho_/((1.-x2)*(1.-x2)))/d_v_; } double SMZDecayer::MEA(double x1, double x2) { // Axial part double num = (x1+2.*d_rho_)*(x1+2.*d_rho_) + (x2+2.*d_rho_)*(x2+2.*d_rho_) + 2.*d_rho_*((5.-x1-x2)*(5.-x1-x2) - 19.0 + 4*d_rho_); double den = d_v_*d_v_*(1.-x1)*(1.-x2); return (num/den - 2.*d_rho_/((1.-x1)*(1.-x1)) - 2*d_rho_/((1.-x2)*(1.-x2)))/d_v_; } double SMZDecayer::u(double x2) { return 0.5*(1. + d_rho_/(1.-x2+d_rho_)); } void SMZDecayer:: getXXbar(double kti, double z, double &x, double &xbar) { double w = sqr(d_v_) + kti*(-1. + z)*z*(2. + kti*(-1. + z)*z); if (w < 0) { x = -1.; xbar = -1; } else { x = (1. + sqr(d_v_)*(-1. + z) + sqr(kti*(-1. + z))*z*z*z + z*sqrt(w) - kti*(-1. + z)*z*(2. + z*(-2 + sqrt(w))))/ (1. - kti*(-1. + z)*z + sqrt(w)); xbar = 1. + kti*(-1. + z)*z; } } double SMZDecayer::qWeight(double x, double xbar) { double rval; double xg = 2. - xbar - x; // always return one in the soft gluon region if(xg < EPS_) return 1.0; // check it is in the phase space if((1.-x)*(1.-xbar)*(1.-xg) < d_rho_*xg*xg) return 0.0; double k1 = getKfromX(x, xbar); double k2 = getKfromX(xbar, x); // Is it in the quark emission zone? if(k1 < d_kt1_) { rval = MEV(x, xbar)/PS(x, xbar); // is it also in the anti-quark emission zone? if(k2 < d_kt2_) rval *= 0.5; return rval; } return 1.0; } double SMZDecayer::qbarWeight(double x, double xbar) { double rval; double xg = 2. - xbar - x; // always return one in the soft gluon region if(xg < EPS_) return 1.0; // check it is in the phase space if((1.-x)*(1.-xbar)*(1.-xg) < d_rho_*xg*xg) return 0.0; double k1 = getKfromX(x, xbar); double k2 = getKfromX(xbar, x); // Is it in the antiquark emission zone? if(k2 < d_kt2_) { rval = MEV(x, xbar)/PS(xbar, x); // is it also in the quark emission zone? if(k1 < d_kt1_) rval *= 0.5; return rval; } return 1.0; } double SMZDecayer::qWeightX(Energy qtilde, double z) { double x, xb; getXXbar(sqr(qtilde/d_Q_), z, x, xb); // if exceptionally out of phase space, leave this emission, as there // is no good interpretation for the soft ME correction. if (x < 0 || xb < 0) return 1.0; return qWeight(x, xb); } double SMZDecayer::qbarWeightX(Energy qtilde, double z) { double x, xb; getXXbar(sqr(qtilde/d_Q_), z, xb, x); // see above in qWeightX. if (x < 0 || xb < 0) return 1.0; return qbarWeight(x, xb); } double SMZDecayer::PS(double x, double xbar) { double u = 0.5*(1. + d_rho_ / (1.-xbar+d_rho_)); double z = u + (x - (2.-xbar)*u)/sqrt(xbar*xbar - 4.*d_rho_); double brack = (1.+z*z)/(1.-z)- 2.*d_rho_/(1-xbar); // interesting: the splitting function without the subtraction // term. Actually gives a much worse approximation in the collinear // limit. double brack = (1.+z*z)/(1.-z); double den = (1.-xbar)*sqrt(xbar*xbar - 4.*d_rho_); return brack/den; } diff --git a/Decay/Perturbative/SMZDecayer.h b/Decay/Perturbative/SMZDecayer.h --- a/Decay/Perturbative/SMZDecayer.h +++ b/Decay/Perturbative/SMZDecayer.h @@ -1,456 +1,456 @@ // -*- C++ -*- // // SMZDecayer.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_SMZDecayer_H #define HERWIG_SMZDecayer_H // // This is the declaration of the SMZDecayer class. // #include "Herwig/Decay/DecayIntegrator.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.fh" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.fh" namespace Herwig { using namespace ThePEG; using namespace ThePEG::Helicity; /** \ingroup Decay * * The SMZDecayer is designed to perform the decay of the * Z boson to the Standard Model fermions. In principle it can also * be used for these decays in any model. * * @see DecayIntegrator * */ class SMZDecayer: public DecayIntegrator { public: /** * Default constructor. */ SMZDecayer(); /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return true;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr , double & , + virtual void initializeMECorrection(RealEmissionProcessPtr , double & , double & ); - + /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr); + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent,Branching br); //@} public: /** * Which of the possible decays is required * @param cc Is this mode the charge conjugate * @param parent The decaying particle * @param children The decay products */ virtual int modeNumber(bool & cc, tcPDPtr parent, const tPDVector & children) const; /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay,MEOption meopt) const; /** * Output the setup information for the particle database * @param os The stream to output the information to * @param header Whether or not to output the information for MySQL */ virtual void dataBaseOutput(ofstream & os,bool header) const; /** * Members for the generation of QED radiation in the decays */ //@{ /** * The one-loop virtual correction. * @param imode The mode required. * @param part The decaying particle. * @param products The decay products including the radiated photon. * @return Whether the correction is implemented */ virtual double oneLoopVirtualME(unsigned int imode, const Particle & part, const ParticleVector & products); /** * The real emission matrix element * @param imode The mode required * @param part The decaying particle * @param products The decay products including the radiated photon * @param iemitter The particle which emitted the photon * @param ctheta The cosine of the polar angle between the photon and the * emitter * @param stheta The sine of the polar angle between the photon and the * emitter * @param rot1 Rotation from rest frame to frame for real emission * @param rot2 Rotation to place emitting particle along z */ virtual InvEnergy2 realEmissionME(unsigned int imode, const Particle & part, ParticleVector & products, unsigned int iemitter, double ctheta, double stheta, const LorentzRotation & rot1, const LorentzRotation & rot2); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving and * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} protected: /** * Apply the hard matrix element */ vector applyHard(const ParticleVector &p); /** * Get the weight for hard emission */ double getHard(double &, double &); /** * Set the \f$\rho\f$ parameter */ void setRho(double); /** * Set the \f$\tilde{\kappa}\f$ parameters symmetrically */ void setKtildeSymm(); /** * Set second \f$\tilde{\kappa}\f$, given the first. */ void setKtilde2(); /** * Translate the variables from \f$x_q,x_{\bar{q}}\f$ to \f$\tilde{\kappa},z\f$ */ //@{ /** * Calculate \f$z\f$. */ double getZfromX(double, double); /** * Calculate \f$\tilde{\kappa}\f$. */ double getKfromX(double, double); //@} /** * Calculate \f$x_{q},x_{\bar{q}}\f$ from \f$\tilde{\kappa},z\f$. * @param kt \f$\tilde{\kappa}\f$ * @param z \f$z\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ void getXXbar(double kt, double z, double & x, double & xbar); /** * Soft weight */ //@{ /** * Soft quark weight calculated from \f$x_{q},x_{\bar{q}}\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ double qWeight(double x, double xbar); /** * Soft antiquark weight calculated from \f$x_{q},x_{\bar{q}}\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ double qbarWeight(double x, double xbar); /** * Soft quark weight calculated from \f$\tilde{q},z\f$ * @param qtilde \f$\tilde{q}\f$ * @param z \f$z\f$ */ double qWeightX(Energy qtilde, double z); /** * Soft antiquark weight calculated from \f$\tilde{q},z\f$ * @param qtilde \f$\tilde{q}\f$ * @param z \f$z\f$ */ double qbarWeightX(Energy qtilde, double z); //@} /** * ???? */ double u(double); /** * Vector and axial vector parts of the matrix element */ //@{ /** * Vector part of the matrix element */ double MEV(double, double); /** * Axial vector part of the matrix element */ double MEA(double, double); /** * The matrix element, given \f$x_1\f$, \f$x_2\f$. * @param x1 \f$x_1\f$ * @param x2 \f$x_2\f$ */ double PS(double x1, double x2); /** * Access to the strong coupling */ ShowerAlphaPtr alphaS() const {return alpha_;} //@} private: /** * Describe a concrete class with persistent data. */ static ClassDescription initSMZDecayer; /** * Private and non-existent assignment operator. */ SMZDecayer & operator=(const SMZDecayer &); private: /** * Pointer to the Z vertex */ FFVVertexPtr FFZvertex_; /** * Pointer to the photon vertex */ AbstractFFVVertexPtr FFPvertex_; /** * maximum weights for the different integrations */ //@{ /** * Weights for the Z to quarks decays. */ vector quarkWeight_; /** * Weights for the Z to leptons decays. */ vector leptonWeight_; //@} /** * Spin density matrix for the decay */ mutable RhoDMatrix _rho; /** * Polarization vectors for the decay */ mutable vector _vectors; /** * Spinors for the decay */ mutable vector _wave; /** * Barred spinors for the decay */ mutable vector _wavebar; private: /** * CM energy */ Energy d_Q_; /** * Quark mass */ Energy d_m_; /** * The rho parameter */ double d_rho_; /** * The v parameter */ double d_v_; /** * The initial kappa-tilde values for radiation from the quark */ double d_kt1_; /** * The initial kappa-tilde values for radiation from the antiquark */ double d_kt2_; /** * Cut-off parameter */ static const double EPS_; /** * Pointer to the coupling */ ShowerAlphaPtr alpha_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * The following template specialization informs ThePEG about the * base class of SMZDecayer. */ template <> struct BaseClassTrait { /** Typedef of the base class of SMZDecayer. */ typedef Herwig::DecayIntegrator NthBase; }; /** * The following template specialization informs ThePEG about the * name of this class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return the class name.*/ static string className() { return "Herwig::SMZDecayer"; } /** * Return the name of the shared library to be loaded to get * access to this class and every other class it uses * (except the base class). */ static string library() { return "HwPerturbativeDecay.so"; } }; /** @endcond */ } #endif /* HERWIG_SMZDecayer_H */ diff --git a/Decay/Perturbative/SMZFermionsPOWHEGDecayer.cc b/Decay/Perturbative/SMZFermionsPOWHEGDecayer.cc --- a/Decay/Perturbative/SMZFermionsPOWHEGDecayer.cc +++ b/Decay/Perturbative/SMZFermionsPOWHEGDecayer.cc @@ -1,792 +1,740 @@ //-*- // // This is the implementation of the non-inlined, non-templated member // functions of the SMZFermionsPOWHEGDecayer class. // #include "SMZFermionsPOWHEGDecayer.h" #include #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/PDF/PolarizedBeamParticleData.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/Base/HardTree.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" using namespace Herwig; SMZFermionsPOWHEGDecayer::SMZFermionsPOWHEGDecayer() : CF_(4./3.), pTmin_(1.*GeV) { } IBPtr SMZFermionsPOWHEGDecayer::clone() const { return new_ptr(*this); } IBPtr SMZFermionsPOWHEGDecayer::fullclone() const { return new_ptr(*this); } void SMZFermionsPOWHEGDecayer::persistentOutput(PersistentOStream & os) const { os << FFGVertex_ << FFZVertex_ << gluon_ << ounit( pTmin_, GeV ); } void SMZFermionsPOWHEGDecayer::persistentInput(PersistentIStream & is, int) { is >> FFGVertex_ >> FFZVertex_ >> gluon_ >> iunit( pTmin_, GeV ); } ClassDescription SMZFermionsPOWHEGDecayer::initSMZFermionsPOWHEGDecayer; // Definition of the static class description member. void SMZFermionsPOWHEGDecayer::Init() { static ClassDocumentation documentation ("There is no documentation for the SMZFermionsPOWHEGDecayer class"); static Parameter interfacePtMin ("minpT", "The pt cut on hardest emision generation", &SMZFermionsPOWHEGDecayer::pTmin_, GeV, 1.*GeV, 0*GeV, 100000.0*GeV, false, false, Interface::limited); } -HardTreePtr SMZFermionsPOWHEGDecayer:: -generateHardest(ShowerTreePtr tree) { - // Get the progenitors: Q and Qbar. - ShowerProgenitorPtr - QProgenitor = tree->outgoingLines().begin()->first, - QbarProgenitor = tree->outgoingLines().rbegin()->first; - if(QProgenitor->id()<0) swap( QProgenitor, QbarProgenitor ); +RealEmissionProcessPtr SMZFermionsPOWHEGDecayer:: +generateHardest(RealEmissionProcessPtr born) { + assert(born->bornOutgoing().size()==2); + // check coloured + if(!born->bornOutgoing()[0]->dataPtr()->coloured()) return RealEmissionProcessPtr(); + // extract required info partons_.resize(2); - partons_[0] = QProgenitor->progenitor() ->dataPtr(); - partons_[1] = QbarProgenitor->progenitor()->dataPtr(); - if(!partons_[0]->coloured()) return HardTreePtr(); - // momentum of the partons quark_.resize(2); - quark_[0] = QProgenitor ->copy()->momentum(); - quark_[1] = QbarProgenitor->copy()->momentum(); - // Set the existing mass entries in partons 5 vectors with the - // once and for all. - quark_[0].setMass(partons_[0]->mass()); - quark_[1].setMass(partons_[1]->mass()); + vector hardProcess; + zboson_ = born->bornIncoming()[0]; + hardProcess.push_back(zboson_); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + partons_[ix] = born->bornOutgoing()[ix]->dataPtr(); + quark_[ix] = born->bornOutgoing()[ix]->momentum(); + quark_[ix].setMass(partons_[ix]->mass()); + hardProcess.push_back(born->bornOutgoing()[ix]); + } + bool order = partons_[0]->id()<0; + if(order) { + swap(partons_[0] ,partons_[1] ); + swap(quark_[0] ,quark_[1] ); + swap(hardProcess[1],hardProcess[2]); + } gauge_.setMass(0.*MeV); - // Get the Z boson. - zboson_ = tree->incomingLines().begin()->first->copy(); - // copy the particle objects - vector hardProcess (3); - hardProcess[0] = zboson_; - hardProcess[1] = QbarProgenitor->copy(); - hardProcess[2] = QProgenitor ->copy(); // Get the Z boson mass. mz2_ = (quark_[0] + quark_[1]).m2(); // Generate emission and set _quark[0,1] and _gauge to be the // momenta of q, qbar and g after the hardest emission: if(!getEvent(hardProcess)) { - QProgenitor ->maximumpT(pTmin_,ShowerInteraction::QCD); - QbarProgenitor->maximumpT(pTmin_,ShowerInteraction::QCD); - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = pTmin_; + return born; } // Ensure the energies are greater than the constituent masses: for (int i=0; i<2; i++) { - if (quark_[i].e() < partons_[i]->constituentMass()) return HardTreePtr(); - if (gauge_.e() < gluon_ ->constituentMass()) return HardTreePtr(); + if (quark_[i].e() < partons_[i]->constituentMass()) return RealEmissionProcessPtr(); } + if (gauge_.e() < gluon_ ->constituentMass()) return RealEmissionProcessPtr(); // set masses quark_[0].setMass( partons_[0]->mass() ); quark_[1].setMass( partons_[1]->mass() ); gauge_ .setMass( ZERO ); // assign the emitter based on evolution scales - unsigned int iemitter = quark_[0]*gauge_ > quark_[1]*gauge_ ? 1 : 0; - unsigned int ispectator = iemitter==1 ? 0 : 1; - // Make the particles for the HardTree: - ShowerParticlePtr emitter (new_ptr(ShowerParticle(partons_[iemitter ],true))); - ShowerParticlePtr spectator(new_ptr(ShowerParticle(partons_[ispectator],true))); - ShowerParticlePtr gauge (new_ptr(ShowerParticle(gluon_ ,true))); - ShowerParticlePtr zboson (new_ptr(ShowerParticle(zboson_->dataPtr() ,false))); - ShowerParticlePtr parent (new_ptr(ShowerParticle(partons_[iemitter ],true))); - emitter ->set5Momentum(quark_[iemitter ] ); - spectator->set5Momentum(quark_[ispectator] ); - gauge ->set5Momentum(gauge_ ); - zboson ->set5Momentum(zboson_->momentum()); - Lorentz5Momentum parentMomentum(quark_[iemitter]+gauge_); - parentMomentum.rescaleMass(); - parent->set5Momentum(parentMomentum); - // Create the vectors of HardBranchings to create the HardTree: - vector spaceBranchings,allBranchings; - // Incoming boson: - spaceBranchings.push_back(new_ptr(HardBranching(zboson,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - // Outgoing particles from hard emission: - HardBranchingPtr spectatorBranch(new_ptr(HardBranching(spectator,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr emitterBranch(new_ptr(HardBranching(parent,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(emitter,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(gauge,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->type(emitterBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : - ShowerPartnerType::QCDAntiColourLine); - allBranchings.push_back(emitterBranch); - allBranchings.push_back(spectatorBranch); - if(iemitter==1) swap(allBranchings[0],allBranchings[1]); - // Add incoming boson to allBranchings - allBranchings.push_back( spaceBranchings.back() ); - // Make the HardTree from the HardBranching vectors. - HardTreePtr hardtree = new_ptr(HardTree(allBranchings,spaceBranchings, - ShowerInteraction::QCD)); - // Set the maximum pt for all other emissions - Energy ptveto(pT_); - QProgenitor ->maximumpT(ptveto,ShowerInteraction::QCD); - QbarProgenitor->maximumpT(ptveto,ShowerInteraction::QCD); - // Connect the particles with the branchings in the HardTree - hardtree->connect( QProgenitor->progenitor() , allBranchings[0] ); - hardtree->connect( QbarProgenitor->progenitor(), allBranchings[1] ); - // colour flow - ColinePtr newline=new_ptr(ColourLine()); - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) { - if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3) - newline->addColoured((**cit).branchingParticle()); - else if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3bar) - newline->addAntiColoured((**cit).branchingParticle()); - } - ColinePtr newLine2=new_ptr(ColourLine()); - if(emitterBranch->branchingParticle()->dataPtr()->iColour()==PDT::Colour3) { - emitterBranch->branchingParticle()->colourLine()->addColoured(gauge); - newLine2->addColoured(emitter); - newLine2->addAntiColoured(gauge); + unsigned int iemitter = quark_[0]*gauge_ > quark_[1]*gauge_ ? 2 : 1; + unsigned int ispectator = iemitter==1 ? 1 : 2; + // create new partices and insert + PPtr zboson = zboson_->dataPtr()->produceParticle(zboson_->momentum()); + born->incoming().push_back(zboson); + PPtr newq = partons_[0]->produceParticle(quark_[0]); + PPtr newa = partons_[1]->produceParticle(quark_[1]); + PPtr newg = gluon_->produceParticle(gauge_); + // make colour connections + newg->colourNeighbour(newq); + newa->colourNeighbour(newg); + // insert in output structure + if(!order) { + born->outgoing().push_back(newq); + born->outgoing().push_back(newa); } else { - emitterBranch->branchingParticle()->antiColourLine()->addAntiColoured(gauge); - newLine2->addAntiColoured(emitter); - newLine2->addColoured(gauge); + born->outgoing().push_back(newa); + born->outgoing().push_back(newq); + swap(iemitter,ispectator); } - // return the tree - return hardtree; + born->outgoing().push_back(newg); + born->emitter (iemitter ); + born->spectator(ispectator); + born->emitted (3); + born->pT()[ShowerInteraction::QCD] = pT_; + // return process + born->interaction(ShowerInteraction::QCD); + return born; } double SMZFermionsPOWHEGDecayer:: me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const { // leading-order result double output = SMZDecayer::me2(ichan,part,decay,meopt); // check decay products coloured, otherwise return if(!decay[0]->dataPtr()->coloured()) return output; // inital masses, couplings etc // fermion mass Energy particleMass = decay[0]->dataPtr()->mass(); // Z mass mZ_ = part.mass(); // strong coupling aS_ = SM().alphaS(sqr(mZ_)); // reduced mass mu_ = particleMass/mZ_; mu2_ = sqr(mu_); // scale scale_ = sqr(mZ_); // cast the vertices tcFFVVertexPtr Zvertex = dynamic_ptr_cast(FFZVertex()); // compute the spinors vector aout; vector fout; vector vin; SpinorBarWaveFunction qkout(decay[0]->momentum(),decay[0]->dataPtr(),outgoing); SpinorWaveFunction qbout(decay[1]->momentum(),decay[1]->dataPtr(),outgoing); VectorWaveFunction zin (part.momentum() ,part.dataPtr() ,incoming); for(unsigned int ix=0;ix<2;++ix){ qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); } for(unsigned int ix=0;ix<3;++ix){ zin.reset(ix); vin.push_back(zin); } // temporary storage of the different diagrams // sum over helicities to get the matrix element double total=0.; if(mu_!=0.) { LorentzPolarizationVector momDiff = (decay[0]->momentum()-decay[1]->momentum())/2./ (decay[0]->momentum().mass()+decay[1]->momentum().mass()); // scalars Complex scalar1 = zin.wave().dot(momDiff); for(unsigned int outhel1=0;outhel1<2;++outhel1) { for(unsigned int outhel2=0;outhel2<2;++outhel2) { for(unsigned int inhel=0;inhel<3;++inhel) { // first the LO bit Complex diag1 = FFZVertex()->evaluate(scale_,aout[outhel2],fout[outhel1],vin[inhel]); // extra stuff for NLO LorentzPolarizationVector left = aout[outhel2].wave().leftCurrent(fout[outhel1].wave()); LorentzPolarizationVector right = aout[outhel2].wave().rightCurrent(fout[outhel1].wave()); Complex scalar = aout[outhel2].wave().scalar(fout[outhel1].wave()); // nlo specific pieces Complex diag3 = Complex(0.,1.)*Zvertex->norm()* (Zvertex->right()*( left.dot(zin.wave())) + Zvertex-> left()*(right.dot(zin.wave())) - ( Zvertex-> left()+Zvertex->right())*scalar1*scalar); // nlo piece total += real(diag1*conj(diag3) + diag3*conj(diag1)); } } } // rescale total *= UnitRemoval::E2/scale_; } else { total = ZERO; } // now for the NLO bit double mu4 = sqr(mu2_); double lmu = mu_!=0. ? log(mu_) : 0.; double v = sqrt(1.-4.*mu2_),v2(sqr(v)); double omv = 4.*mu2_/(1.+v); double f1,f2,fNS,VNS; double r = omv/(1.+v); double lr = mu_!=0. ? log(r) : 0.; // normal form if(mu_>1e-4) { f1 = CF_*aS_/Constants::pi* ( +1. + 3.*log(0.5*(1.+v)) - 1.5*log(0.5*(1.+v2)) + sqr(Constants::pi)/6. - 0.5*sqr(lr) - (1.+v2)/v*(lr*log(1.+v2) + sqr(Constants::pi)/12. -0.5*log(4.*mu2_)*lr + 0.25*sqr(lr))); fNS = -0.5*(1.+2.*v2)*lr/v + 1.5*lr - 2./3.*sqr(Constants::pi) + 0.5*sqr(lr) + (1.+v2)/v*(Herwig::Math::ReLi2(r) + sqr(Constants::pi)/3. - 0.25*sqr(lr) + lr*log((2.*v/ (1.+v)))); VNS = 1.5*log(0.5*(1.+v2)) + 0.5*(1.+v2)/v*( 2.*lr*log(2.*(1.+v2)/sqr(1.+v)) + 2.*Herwig::Math::ReLi2(sqr(r)) - 2.*Herwig::Math::ReLi2(2.*v/(1.+v)) - sqr(Constants::pi)/6.) + log(1.-mu_) - 2.*log(1.-2.*mu_) - 4.*mu2_/(1.+v2)*log(mu_/(1.-mu_)) - mu_/(1.-mu_) + 4.*(2.*mu2_-mu_)/(1.+v2) + 0.5*sqr(Constants::pi); f2 = CF_*aS_/Constants::pi*mu2_*lr/v; } // small mass limit else { f1 = -CF_*aS_/Constants::pi/6.* ( - 6. - 24.*lmu*mu2_ - 15.*mu4 - 12.*mu4*lmu - 24.*mu4*sqr(lmu) + 2.*mu4*sqr(Constants::pi) - 12.*mu2_*mu4 - 96.*mu2_*mu4*sqr(lmu) + 8.*mu2_*mu4*sqr(Constants::pi) - 80.*mu2_*mu4*lmu); fNS = - mu2_/18.*( + 36.*lmu - 36. - 45.*mu2_ + 216.*lmu*mu2_ - 24.*mu2_*sqr(Constants::pi) + 72.*mu2_*sqr(lmu) - 22.*mu4 + 1032.*mu4 * lmu - 96.*mu4*sqr(Constants::pi) + 288.*mu4*sqr(lmu)); VNS = - mu2_/1260.*(-6930. + 7560.*lmu + 2520.*mu_ - 16695.*mu2_ + 1260.*mu2_*sqr(Constants::pi) + 12600.*lmu*mu2_ + 1344.*mu_*mu2_ - 52780.*mu4 + 36960.*mu4*lmu + 5040.*mu4*sqr(Constants::pi) - 12216.*mu_*mu4); f2 = CF_*aS_*mu2_/Constants::pi*( 2.*lmu + 4.*mu2_*lmu + 2.*mu2_ + 12.*mu4*lmu + 7.*mu4); } // add up bits for f1 f1 += CF_*aS_/Constants::pi*(fNS+VNS); // now for the real correction double phi = UseRandom::rnd()*Constants::twopi; // calculate y double yminus = 0.; double yplus = 1.-2.*mu_*(1.-mu_)/(1.-2*mu2_); double y = yminus + UseRandom::rnd()*(yplus-yminus); // calculate z double v1 = sqrt(sqr(2.*mu2_+(1.-2.*mu2_)*(1.-y))-4.*mu2_)/(1.-2.*mu2_)/(1.-y); double zplus = (1.+v1)*(1.-2.*mu2_)*y/2./(mu2_ +(1.-2.*mu2_)*y); double zminus = (1.-v1)*(1.-2.*mu2_)*y/2./(mu2_ +(1.-2.*mu2_)*y); double z = zminus + UseRandom::rnd()*(zplus-zminus); double jac = (1.-y)*(yplus-yminus)*(zplus-zminus); // calculate x1,x2 double x2 = 1. - y*(1.-2.*mu2_); double x1 = 1. - z*(x2-2.*mu2_); // copy the particle objects over for calculateRealEmission vector hardProcess(3); hardProcess[0] = const_ptr_cast(&part); hardProcess[1] = decay[0]; hardProcess[2] = decay[1]; // total real emission contribution double realFact = 0.25*jac*sqr(1.-2.*mu2_)/ sqrt(1.-4.*mu2_)/Constants::twopi *2.*CF_*aS_*calculateRealEmission(x1, x2, hardProcess, phi, true); // the born + virtual + real output = output*(1. + f1 + realFact) + f2*total; return output; } double SMZFermionsPOWHEGDecayer::meRatio(vector partons, vector momenta, unsigned int iemitter, bool subtract) const { Lorentz5Momentum q = momenta[1]+momenta[2]+momenta[3]; Energy2 Q2=q.m2(); Energy2 lambda = sqrt((Q2-sqr(momenta[1].mass()+momenta[2].mass()))* (Q2-sqr(momenta[1].mass()-momenta[2].mass()))); InvEnergy2 D[2]; double lome[2]; for(unsigned int iemit=0;iemit<2;++iemit) { unsigned int ispect = iemit==0 ? 1 : 0; Energy2 pipj = momenta[3 ] * momenta[1+iemit ]; Energy2 pipk = momenta[3 ] * momenta[1+ispect]; Energy2 pjpk = momenta[1+iemit] * momenta[1+ispect]; double y = pipj/(pipj+pipk+pjpk); double z = pipk/( pipk+pjpk); Energy mij = sqrt(2.*pipj+sqr(momenta[1+iemit].mass())); Energy2 lamB = sqrt((Q2-sqr(mij+momenta[1+ispect].mass()))* (Q2-sqr(mij-momenta[1+ispect].mass()))); Energy2 Qpk = q*momenta[1+ispect]; Lorentz5Momentum pkt = lambda/lamB*(momenta[1+ispect]-Qpk/Q2*q) +0.5/Q2*(Q2+sqr(momenta[1+ispect].mass())-sqr(momenta[1+ispect].mass()))*q; Lorentz5Momentum pijt = q-pkt; double muj = momenta[1+iemit ].mass()/sqrt(Q2); double muk = momenta[1+ispect].mass()/sqrt(Q2); double vt = sqrt((1.-sqr(muj+muk))*(1.-sqr(muj-muk)))/(1.-sqr(muj)-sqr(muk)); double v = sqrt(sqr(2.*sqr(muk)+(1.-sqr(muj)-sqr(muk))*(1.-y))-4.*sqr(muk)) /(1.-y)/(1.-sqr(muj)-sqr(muk)); // dipole term D[iemit] = 0.5/pipj*(2./(1.-(1.-z)*(1.-y)) -vt/v*(2.-z+sqr(momenta[1+iemit].mass())/pipj)); // matrix element vector lomom(3); lomom[0] = momenta[0]; if(iemit==0) { lomom[1] = pijt; lomom[2] = pkt ; } else { lomom[2] = pijt; lomom[1] = pkt ; } lome[iemit] = loME(partons,lomom); } InvEnergy2 ratio = realME(partons,momenta)*abs(D[iemitter]) /(abs(D[0]*lome[0])+abs(D[1]*lome[1])); if(subtract) return Q2*(ratio-2.*D[iemitter]); else return Q2*ratio; } double SMZFermionsPOWHEGDecayer::loME(const vector & partons, const vector & momenta) const { // compute the spinors vector vin; vector aout; vector fout; VectorWaveFunction zin (momenta[0],partons[0],incoming); SpinorBarWaveFunction qkout(momenta[1],partons[1],outgoing); SpinorWaveFunction qbout(momenta[2],partons[2],outgoing); for(unsigned int ix=0;ix<2;++ix){ qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); } for(unsigned int ix=0;ix<3;++ix){ zin.reset(ix); vin.push_back(zin); } // temporary storage of the different diagrams // sum over helicities to get the matrix element double total(0.); for(unsigned int inhel=0;inhel<3;++inhel) { for(unsigned int outhel1=0;outhel1<2;++outhel1) { for(unsigned int outhel2=0;outhel2<2;++outhel2) { Complex diag1 = FFZVertex()->evaluate(scale_,aout[outhel2],fout[outhel1],vin[inhel]); total += norm(diag1); } } } // return the answer return total; } InvEnergy2 SMZFermionsPOWHEGDecayer::realME(const vector & partons, const vector & momenta) const { // compute the spinors vector vin; vector aout; vector fout; vector gout; VectorWaveFunction zin (momenta[0],partons[0],incoming); SpinorBarWaveFunction qkout(momenta[1],partons[1],outgoing); SpinorWaveFunction qbout(momenta[2],partons[2],outgoing); VectorWaveFunction gluon(momenta[3],partons[3],outgoing); for(unsigned int ix=0;ix<2;++ix){ qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); gluon.reset(2*ix); gout.push_back(gluon); } for(unsigned int ix=0;ix<3;++ix){ zin.reset(ix); vin.push_back(zin); } vector diag(2,0.); double total(0.); for(unsigned int inhel1=0;inhel1<3;++inhel1) { for(unsigned int outhel1=0;outhel1<2;++outhel1) { for(unsigned int outhel2=0;outhel2<2;++outhel2) { for(unsigned int outhel3=0;outhel3<2;++outhel3) { SpinorBarWaveFunction off1 = FFGVertex()->evaluate(scale_,3,partons[1],fout[outhel1],gout[outhel3]); diag[0] = FFZVertex()->evaluate(scale_,aout[outhel2],off1,vin[inhel1]); SpinorWaveFunction off2 = FFGVertex()->evaluate(scale_,3,partons[2],aout[outhel2],gout[outhel3]); diag[1] = FFZVertex()->evaluate(scale_,off2,fout[outhel1],vin[inhel1]); // sum of diagrams Complex sum = std::accumulate(diag.begin(),diag.end(),Complex(0.)); // me2 total += norm(sum); } } } } // divide out the coupling total /= norm(FFGVertex()->norm()); // return the total return total*UnitRemoval::InvE2; } void SMZFermionsPOWHEGDecayer::doinit() { // cast the SM pointer to the Herwig SM pointer tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); // do the initialisation if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "SMZFermionsPOWHEGDecayer::doinit() " << "the Herwig version must be used." << Exception::runerror; // cast the vertices FFZVertex_ = hwsm->vertexFFZ(); FFZVertex_->init(); FFGVertex_ = hwsm->vertexFFG(); FFGVertex_->init(); SMZDecayer::doinit(); gluon_ = getParticleData(ParticleID::g); } bool SMZFermionsPOWHEGDecayer::getEvent(vector hardProcess) { Energy particleMass = ZERO; for(unsigned int ix=0;ixid()==ParticleID::Z0) { mZ_ = hardProcess[ix]->mass(); } else { particleMass = hardProcess[ix]->mass(); } } // reduced mass mu_ = particleMass/mZ_; mu2_ = sqr(mu_); // scale scale_ = sqr(mZ_); // max pT Energy pTmax = 0.5*sqrt(mz2_); if(pTmaxoverestimateValue()*CF_* (ymax-ymin)/Constants::twopi; // loop to generate the pt and rapidity bool reject; //arrays to hold the temporary probabilities whilst the for loop progresses double probTemp[2][2]={{0.,0.},{0.,0.}}; probTemp[0][0]=probTemp[0][1]=probTemp[1][0]=probTemp[1][1]=0.; double x1Solution[2][2] = {{0.,0.},{0.,0.}}; double x2Solution[2][2] = {{0.,0.},{0.,0.}}; double x3Solution[2] = {0.,0.}; Energy pT[2] = {pTmax,pTmax}; double yTemp[2] = {0.,0.}; double phi = 0.; // do the competition for(int i=0; i<2; i++) { do { //generation of phi phi = UseRandom::rnd() * Constants::twopi; // reject the emission reject = true; // generate pt pT[i] *= pow(UseRandom::rnd(),1./prefactor); Energy2 pT2 = sqr(pT[i]); if(pT[i] 0 if( discrim2 < ZERO) continue; Energy2 discriminant = sqrt(discrim2); Energy2 fact1 = 3.*mz2_*x3Solution[i]-2.*mz2_+2.*pT2*x3Solution[i] -4.*pT2-mz2_*sqr(x3Solution[i]); Energy2 fact2 = 2.*mz2_*(x3Solution[i]-1.)-2.*pT2; // two solns for x1 x1Solution[i][0] = (fact1 + discriminant)/fact2; x1Solution[i][1] = (fact1 - discriminant)/fact2; bool found = false; for(unsigned int j=0;j<2;++j) { x2Solution[i][0] = 2.-x3Solution[i]-x1Solution[i][0]; x2Solution[i][1] = 2.-x3Solution[i]-x1Solution[i][1]; // set limits on x2 double root = max(0.,sqr(x1Solution[i][j])-4.*mu2_); root = sqrt(root); double x2Plus = 1.-0.5*(1.-x1Solution[i][j])/(1.-x1Solution[i][j]+mu2_) *(x1Solution[i][j]-2.*mu2_-root); double x2Minus = 1.-0.5*(1.-x1Solution[i][j])/(1.-x1Solution[i][j]+mu2_) *(x1Solution[i][j]-2.*mu2_+root); if(x1Solution[i][j]>=x1Minus && x1Solution[i][j]<=x1Plus && x2Solution[i][j]>=x2Minus && x2Solution[i][j]<=x2Plus && checkZMomenta(x1Solution[i][j], x2Solution[i][j], x3Solution[i], yTemp[i], pT[i])) { probTemp[i][j] = weightPrefactor*pT[i]* calculateJacobian(x1Solution[i][j], x2Solution[i][j], pT[i])* calculateRealEmission(x1Solution[i][j], x2Solution[i][j], hardProcess, phi, false, i); found = true; } else { probTemp[i][j] = 0.; } } if(!found) continue; // alpha S piece double wgt = (probTemp[i][0]+probTemp[i][1])*alphaS()->ratio(sqr(pT[i])); // matrix element weight reject = UseRandom::rnd()>wgt; } while(reject); } //end of emitter for loop // no emission if(pT[0]pT[1]){ pT_ = pT[0]; y=yTemp[0]; if(probTemp[0][0]>UseRandom::rnd()*(probTemp[0][0]+probTemp[0][1])) { x1 = x1Solution[0][0]; x2 = x2Solution[0][0]; } else { x1 = x1Solution[0][1]; x2 = x2Solution[0][1]; } } // particle 2 emits, particle 1 spectates else { iemit=1; pT_ = pT[1]; y=yTemp[1]; if(probTemp[1][0]>UseRandom::rnd()*(probTemp[1][0]+probTemp[1][1])) { x1 = x1Solution[1][0]; x2 = x2Solution[1][0]; } else { x1 = x1Solution[1][1]; x2 = x2Solution[1][1]; } } // find spectator unsigned int ispect = iemit == 0 ? 1 : 0; // Find the boost from the lab to the c.o.m with the spectator // along the -z axis, and then invert it. LorentzRotation eventFrame( ( quark_[0] + quark_[1] ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*quark_[ispect]; eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() - Constants::pi ); eventFrame.invert(); // spectator quark_[ispect].setT( 0.5*x2*mZ_ ); quark_[ispect].setX( ZERO ); quark_[ispect].setY( ZERO ); quark_[ispect].setZ( -sqrt(0.25*mz2_*x2*x2-mz2_*mu2_) ); // gluon gauge_.setT( pT_*cosh(y) ); gauge_.setX( pT_*cos(phi) ); gauge_.setY( pT_*sin(phi) ); gauge_.setZ( pT_*sinh(y) ); gauge_.setMass(ZERO); // emitter reconstructed from gluon & spectator quark_[iemit] = - gauge_ - quark_[ispect]; quark_[iemit].setT( 0.5*mZ_*x1 ); // boost constructed vectors into the event frame quark_[0] = eventFrame * quark_[0]; quark_[1] = eventFrame * quark_[1]; gauge_ = eventFrame * gauge_; // need to reset masses because for whatever reason the boost // touches the mass component of the five-vector and can make // zero mass objects acquire a floating point negative mass(!). gauge_.setMass( ZERO ); quark_[iemit] .setMass(partons_[iemit ]->mass()); quark_[ispect].setMass(partons_[ispect]->mass()); return true; } InvEnergy SMZFermionsPOWHEGDecayer::calculateJacobian(double x1, double x2, Energy pT) const{ double xPerp = abs(2.*pT/mZ_); Energy jac = mZ_*fabs((x1*x2-2.*mu2_*(x1+x2)+sqr(x2)-x2)/xPerp/pow(sqr(x2)-4.*mu2_,1.5)); return 1./jac; //jacobian as defined is dptdy=jac*dx1dx2, therefore we have to divide by it } bool SMZFermionsPOWHEGDecayer::checkZMomenta(double x1, double x2, double x3, double y, Energy pT) const { double xPerp2 = 4.*pT*pT/mZ_/mZ_; static double tolerance = 1e-6; bool isMomentaReconstructed = false; if(pT*sinh(y)>ZERO) { if(abs(-sqrt(sqr(x2)-4.*mu2_)+sqrt(sqr(x3)-xPerp2) + sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance || abs(-sqrt(sqr(x2)-4.*mu2_)+sqrt(sqr(x3)-xPerp2) - sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance) isMomentaReconstructed=true; } else if(pT*sinh(y) < ZERO){ if(abs(-sqrt(sqr(x2)-4.*mu2_)-sqrt(sqr(x3)-xPerp2) + sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance || abs(-sqrt(sqr(x2)-4.*mu2_)-sqrt(sqr(x3)-xPerp2) - sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance) isMomentaReconstructed=true; } else if(abs(-sqrt(sqr(x2)-4.*mu2_)+ sqrt(sqr(x1)-xPerp2 - 4.*mu2_)) <= tolerance) isMomentaReconstructed=true; return isMomentaReconstructed; } double SMZFermionsPOWHEGDecayer::calculateRealEmission(double x1, double x2, vector hardProcess, double phi, bool subtract) const { // make partons data object for meRatio vector partons (3); for(int ix=0; ix<3; ++ix) partons[ix] = hardProcess[ix]->dataPtr(); partons.push_back(gluon_); // calculate x3 double x3 = 2.-x1-x2; double xT = sqrt(max(0.,sqr(x3) -0.25*sqr(sqr(x2)+sqr(x3)-sqr(x1))/(sqr(x2)-4.*mu2_))); // calculate the momenta Energy M = mZ_; Lorentz5Momentum pspect(ZERO,ZERO,-0.5*M*sqrt(max(sqr(x2)-4.*mu2_,0.)),0.5*M*x2,M*mu_); Lorentz5Momentum pemit (-0.5*M*xT*cos(phi),-0.5*M*xT*sin(phi), 0.5*M*sqrt(max(sqr(x1)-sqr(xT)-4.*mu2_,0.)),0.5*M*x1,M*mu_); Lorentz5Momentum pgluon(0.5*M*xT*cos(phi), 0.5*M*xT*sin(phi), 0.5*M*sqrt(max(sqr(x3)-sqr(xT),0.)),0.5*M*x3,ZERO); if(abs(pspect.z()+pemit.z()-pgluon.z())/M<1e-6) pgluon.setZ(-pgluon.z()); else if(abs(pspect.z()-pemit.z()+pgluon.z())/M<1e-6) pemit .setZ(- pemit.z()); // loop over the possible emitting partons double realwgt(0.); for(unsigned int iemit=0;iemit<2;++iemit) { // boost and rotate momenta LorentzRotation eventFrame( ( hardProcess[1]->momentum() + hardProcess[2]->momentum() ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*hardProcess[iemit+1]->momentum(); eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() ); eventFrame.invert(); vector momenta(3); momenta[0] = hardProcess[0]->momentum(); if(iemit==0) { momenta[2] = eventFrame*pspect; momenta[1] = eventFrame*pemit ; } else { momenta[1] = eventFrame*pspect; momenta[2] = eventFrame*pemit ; } momenta.push_back(eventFrame*pgluon); // calculate the weight if(1.-x1>1e-5 && 1.-x2>1e-5) realwgt += meRatio(partons,momenta,iemit,subtract); } // total real emission contribution return realwgt; } double SMZFermionsPOWHEGDecayer::calculateRealEmission(double x1, double x2, vector hardProcess, double phi, bool subtract, int emitter) const { // make partons data object for meRatio vector partons (3); for(int ix=0; ix<3; ++ix) partons[ix] = hardProcess[ix]->dataPtr(); partons.push_back(gluon_); // calculate x3 double x3 = 2.-x1-x2; double xT = sqrt(max(0.,sqr(x3) -0.25*sqr(sqr(x2)+sqr(x3)-sqr(x1))/(sqr(x2)-4.*mu2_))); // calculate the momenta Energy M = mZ_; Lorentz5Momentum pspect(ZERO,ZERO,-0.5*M*sqrt(max(sqr(x2)-4.*mu2_,0.)),0.5*M*x2,M*mu_); Lorentz5Momentum pemit (-0.5*M*xT*cos(phi),-0.5*M*xT*sin(phi), 0.5*M*sqrt(max(sqr(x1)-sqr(xT)-4.*mu2_,0.)),0.5*M*x1,M*mu_); Lorentz5Momentum pgluon( 0.5*M*xT*cos(phi), 0.5*M*xT*sin(phi), 0.5*M*sqrt(max(sqr(x3)-sqr(xT),0.)),0.5*M*x3,ZERO); if(abs(pspect.z()+pemit.z()-pgluon.z())/M<1e-6) pgluon.setZ(-pgluon.z()); else if(abs(pspect.z()-pemit.z()+pgluon.z())/M<1e-6) pemit .setZ(- pemit.z()); // loop over the possible emitting partons double realwgt(0.); // boost and rotate momenta LorentzRotation eventFrame( ( hardProcess[1]->momentum() + hardProcess[2]->momentum() ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*hardProcess[emitter+1]->momentum(); eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() ); eventFrame.invert(); vector momenta(3); momenta[0] = hardProcess[0]->momentum(); if(emitter==0) { momenta[2] = eventFrame*pspect; momenta[1] = eventFrame*pemit ; } else { momenta[1] = eventFrame*pspect; momenta[2] = eventFrame*pemit ; } momenta.push_back(eventFrame*pgluon); // calculate the weight if(1.-x1>1e-5 && 1.-x2>1e-5) realwgt += meRatio(partons,momenta,emitter,subtract); // total real emission contribution return realwgt; } diff --git a/Decay/Perturbative/SMZFermionsPOWHEGDecayer.h b/Decay/Perturbative/SMZFermionsPOWHEGDecayer.h --- a/Decay/Perturbative/SMZFermionsPOWHEGDecayer.h +++ b/Decay/Perturbative/SMZFermionsPOWHEGDecayer.h @@ -1,300 +1,300 @@ // -*- C++ -*- #ifndef HERWIG_SMZFermionsPOWHEGDecayer_H #define HERWIG_SMZFermionsPOWHEGDecayer_H // // This is the declaration of the SMZFermionsPOWHEGDecayer class. // #include "SMZDecayer.h" #include "Herwig/Utilities/Maths.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the SMZFermionsPOWHEGDecayer class. * * @see \ref SMZFermionsPOWHEGDecayerInterfaces "The interfaces" * defined for SMZFermionsPOWHEGDecayer. */ class SMZFermionsPOWHEGDecayer: public SMZDecayer{ public: /** * The default constructor. */ SMZFermionsPOWHEGDecayer(); /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr); /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initSMZFermionsPOWHEGDecayer; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SMZFermionsPOWHEGDecayer & operator=(const SMZFermionsPOWHEGDecayer &); /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFZVertex() const {return FFZVertex_;} /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFGVertex() const {return FFGVertex_;} /** * Real emission term, for use in generating the hardest emission */ double calculateRealEmission(double x1, double x2, vector hardProcess, double phi, bool subtract, int emitter) const; /** * Real emission term, for use in generating the hardest emission */ double calculateRealEmission(double x1, double x2, vector hardProcess, double phi, bool subtract) const; /** * Check the sign of the momentum in the \f$z\f$-direction is correct. */ bool checkZMomenta(double x1, double x2, double x3, double y, Energy pT) const; /** * Calculate the Jacobian */ InvEnergy calculateJacobian(double x1, double x2, Energy pT) const; /** * Calculate the ratio between NLO & LO ME */ double meRatio(vector partons, vector momenta, unsigned int iemitter,bool subtract) const; /** * Calculate the LO ME */ double loME(const vector & partons, const vector & momenta) const; /** * Calculate the NLO real emission piece of ME */ InvEnergy2 realME(const vector & partons, const vector & momenta) const; /** * Generate a real emission event */ bool getEvent(vector hardProcess); private: /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFZVertex_; /** * Pointer to the fermion-antifermion G vertex */ AbstractFFVVertexPtr FFGVertex_; /** * The colour factor */ double CF_; /** * The Z mass */ mutable Energy mZ_; /** * The reduced mass */ mutable double mu_; /** * The square of the reduced mass */ mutable double mu2_; /** * The strong coupling */ mutable double aS_; /** * The scale */ mutable Energy2 scale_; /** * Stuff for the POWHEG correction */ //@{ /** * ParticleData object for the gluon */ tcPDPtr gluon_; /** * The cut off on pt, assuming massless quarks. */ Energy pTmin_; // radiative variables (pt,y) Energy pT_; /** * The ParticleData objects for the fermions */ vector partons_; /** * The fermion momenta */ vector quark_; /** * The momentum of the radiated gauge boson */ Lorentz5Momentum gauge_; /** * The Z boson */ PPtr zboson_; /** * Higgs mass squared */ Energy2 mz2_; //@} }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SMZFermionsPOWHEGDecayer. */ template <> struct BaseClassTrait { /** Typedef of the first base class of SMZFermionsPOWHEGDecayer. */ typedef Herwig::SMZDecayer NthBase; }; /** This template specialization informs ThePEG about the name of * the SMZFermionsPOWHEGDecayer 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::SMZFermionsPOWHEGDecayer"; } /** * The name of a file containing the dynamic library where the class * SMZFermionsPOWHEGDecayer is implemented. It may also include several, space-separated, * libraries if the class SMZFermionsPOWHEGDecayer 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 "HwPerturbativeDecay.so"; } }; /** @endcond */ } #endif /* HERWIG_SMZFermionsPOWHEGDecayer_H */ diff --git a/DipoleShower/Base/DipoleEventRecord.cc b/DipoleShower/Base/DipoleEventRecord.cc deleted file mode 100644 --- a/DipoleShower/Base/DipoleEventRecord.cc +++ /dev/null @@ -1,948 +0,0 @@ -// -*- C++ -*- -// -// DipoleEventRecord.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 DipoleEventRecord class. -// - -#include "DipoleEventRecord.h" -#include "Herwig/DipoleShower/Utility/DipolePartonSplitter.h" -#include "Herwig/Shower/ShowerHandler.h" - -#include "ThePEG/Repository/EventGenerator.h" -#include "ThePEG/PDF/PartonExtractor.h" - -#include - -#include - -using namespace Herwig; - -PList DipoleEventRecord::colourOrdered() { - - PList colour_ordered; - - size_t done_size = outgoing().size(); - if (incoming().first->coloured()) - ++done_size; - if (incoming().second->coloured()) - ++done_size; - - while (colour_ordered.size() != done_size) { - - PPtr current; - - // start with singlets, as long as we have some - - if (find(colour_ordered.begin(),colour_ordered.end(),incoming().first) == - colour_ordered.end() && incoming().first->coloured()) { - if (!incoming().first->hasColour() || !incoming().first->hasAntiColour()) - current = incoming().first; - } - - if (!current) { - for (PList::iterator p = outgoing().begin(); - p != outgoing().end(); ++p) { - if (find(colour_ordered.begin(),colour_ordered.end(),*p) == - colour_ordered.end() && (**p).coloured()) { - if (!(**p).hasColour() || !(**p).hasAntiColour()) { - current = *p; - break; - } - } - } - } - - if (!current) { - if (find(colour_ordered.begin(),colour_ordered.end(),incoming().second) == - colour_ordered.end() && incoming().second->coloured()) { - if (!incoming().second->hasColour() || !incoming().second->hasAntiColour()) - current = incoming().second; - } - } - - // then go on with anything else - - if (!current) { - if (find(colour_ordered.begin(),colour_ordered.end(),incoming().first) == - colour_ordered.end() && incoming().first->coloured()) { - current = incoming().first; - } - } - - if (!current) { - for (PList::iterator p = outgoing().begin(); - p != outgoing().end(); ++p) { - if (find(colour_ordered.begin(),colour_ordered.end(),*p) == - colour_ordered.end() && (**p).coloured()) { - current = *p; - break; - } - } - } - - if (!current) { - if (find(colour_ordered.begin(),colour_ordered.end(),incoming().second) == - colour_ordered.end() && incoming().second->coloured()) { - current = incoming().second; - } - } - - assert(current); - - PPtr next; - Ptr::ptr walk_the_line; - - while (true) { - - if (!walk_the_line) { - if (current->hasColour()) { - walk_the_line = current->colourLine(); - } - else if (current->hasAntiColour()) { - walk_the_line = current->antiColourLine(); - } - } - - if (!next) - for (tPVector::const_iterator p = walk_the_line->coloured().begin(); - p != walk_the_line->coloured().end(); ++p) { - if (*p == current) - continue; - if (find(outgoing().begin(),outgoing().end(),*p) != outgoing().end() || - *p == incoming().first || - *p == incoming().second) { - next = *p; - if (next->hasColour() && next->hasAntiColour()) { - walk_the_line = walk_the_line == next->colourLine() ? next->antiColourLine() : next->colourLine(); - } - break; - } - } - - if (!next) - for (tPVector::const_iterator p = walk_the_line->antiColoured().begin(); - p != walk_the_line->antiColoured().end(); ++p) { - if (*p == current) - continue; - if (find(outgoing().begin(),outgoing().end(),*p) != outgoing().end() || - *p == incoming().first || - *p == incoming().second) { - next = *p; - if (next->hasColour() && next->hasAntiColour()) { - walk_the_line = walk_the_line == next->colourLine() ? next->antiColourLine() : next->colourLine(); - } - break; - } - } - - assert(next); - - colour_ordered.push_back(current); - current = next; - - // done if next is not a gluon or next is already in colour_ordered - - if ((current->hasColour() && !current->hasAntiColour()) || - (!current->hasColour() && current->hasAntiColour())) { - colour_ordered.push_back(current); - break; - } - - if (next->hasColour() && next->hasAntiColour()) { - if (find(colour_ordered.begin(),colour_ordered.end(),next) != colour_ordered.end()) - break; - } - - next = PPtr(); - - } - - } - - return colour_ordered; - -} - -void DipoleEventRecord::popChain() { - assert(!theChains.empty()); - theDoneChains.push_back(DipoleChain()); - theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),theChains.front().dipoles()); - theChains.pop_front(); -} - -void DipoleEventRecord::popChain(list::iterator ch) { - assert(!theChains.empty()); - theDoneChains.push_back(DipoleChain()); - theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),ch->dipoles()); - theChains.erase(ch); -} - -void DipoleEventRecord::popChains(const list::iterator>& chs) { - - assert(!theChains.empty()); - - for ( list::iterator>::const_iterator ch = - chs.begin(); ch != chs.end(); ++ch ) { - theDoneChains.push_back(DipoleChain()); - theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),(*ch)->dipoles()); - } - - for ( list::iterator>::const_iterator ch = - chs.begin(); ch != chs.end(); ++ch ) - theChains.erase(*ch); - -} - -DipoleIndex -DipoleEventRecord::mergeIndex(list::iterator firstDipole, const pair& whichFirst, - list::iterator secondDipole, const pair& whichSecond) const { - tcPDPtr emitterData = - whichFirst.first ? firstDipole->leftParticle()->dataPtr() : firstDipole->rightParticle()->dataPtr(); - tcPDPtr spectatorData = - whichSecond.first ? secondDipole->leftParticle()->dataPtr() : secondDipole->rightParticle()->dataPtr(); - const PDF& emitterPDF = - whichFirst.first ? firstDipole->leftPDF() : firstDipole->rightPDF(); - const PDF& spectatorPDF = - whichSecond.first ? secondDipole->leftPDF() : secondDipole->rightPDF(); - return DipoleIndex(emitterData,spectatorData,emitterPDF,spectatorPDF); -} - - -SubleadingSplittingInfo -DipoleEventRecord::mergeSplittingInfo(list::iterator firstChain, list::iterator firstDipole, - const pair& whichFirst, - list::iterator secondChain, list::iterator secondDipole, - const pair& whichSecond) const { - SubleadingSplittingInfo res; - res.index(mergeIndex(firstDipole,whichFirst,secondDipole,whichSecond)); - res.emitter(whichFirst.first ? firstDipole->leftParticle() : firstDipole->rightParticle()); - res.spectator(whichSecond.first ? secondDipole->leftParticle() : secondDipole->rightParticle()); - res.emitterX(whichFirst.first ? firstDipole->leftFraction() : firstDipole->rightFraction()); - res.spectatorX(whichSecond.first ? secondDipole->leftFraction() : secondDipole->rightFraction()); - res.configuration(whichFirst); - res.spectatorConfiguration(whichSecond); - res.emitterChain(firstChain); - res.emitterDipole(firstDipole); - res.spectatorChain(secondChain); - res.spectatorDipole(secondDipole); - return res; -} - -void DipoleEventRecord::getSubleadingSplittings(list& res) { - static pair left(true,false); - static pair right(false,true); - res.clear(); - for ( list::iterator cit = theChains.begin(); - cit != theChains.end(); ++cit ) { - for ( list::iterator dit = cit->dipoles().begin(); - dit != cit->dipoles().end(); ++dit ) { - for ( list::iterator djt = dit; - djt != cit->dipoles().end(); ++djt ) { - res.push_back(mergeSplittingInfo(cit,dit,left,cit,djt,left)); - res.push_back(mergeSplittingInfo(cit,dit,right,cit,djt,right)); - if ( dit != djt ) { - res.push_back(mergeSplittingInfo(cit,dit,left,cit,djt,right)); - res.push_back(mergeSplittingInfo(cit,dit,right,cit,djt,left)); - } - } - } - list::iterator cjt = cit; ++cjt; - for ( ; cjt != theChains.end(); ++cjt ) { - for ( list::iterator dit = cit->dipoles().begin(); - dit != cit->dipoles().end(); ++dit ) { - for ( list::iterator djt = cjt->dipoles().begin(); - djt != cjt->dipoles().end(); ++djt ) { - res.push_back(mergeSplittingInfo(cit,dit,left,cjt,djt,left)); - res.push_back(mergeSplittingInfo(cit,dit,right,cjt,djt,right)); - res.push_back(mergeSplittingInfo(cit,dit,left,cjt,djt,right)); - res.push_back(mergeSplittingInfo(cit,dit,right,cjt,djt,left)); - } - } - } - } -} - -void DipoleEventRecord::splitSubleading(SubleadingSplittingInfo& dsplit, - pair::iterator,list::iterator>& childIterators, - DipoleChain*& firstChain, DipoleChain*& secondChain) { - if ( dsplit.emitterDipole() == dsplit.spectatorDipole() ) { - assert(dsplit.emitterChain() == dsplit.spectatorChain()); - split(dsplit.emitterDipole(),dsplit.emitterChain(),dsplit, - childIterators,firstChain,secondChain,false); - } else { - // first need to recoil, then split - recoil(dsplit.spectatorDipole(),dsplit.spectatorChain(),dsplit); - split(dsplit.emitterDipole(),dsplit.emitterChain(),dsplit, - childIterators,firstChain,secondChain,true); - } -} - -void DipoleEventRecord::findChains(const PList& ordered) { - - theChains.clear(); - theDoneChains.clear(); - - DipoleChain current_chain; - - // this whole thing needs to have a more elegant implementation at some point - - bool startIsTriplet = - (ordered.front()->hasColour() && !ordered.front()->hasAntiColour()) || - (!ordered.front()->hasColour() && ordered.front()->hasAntiColour()); - bool endIsTriplet = - (ordered.back()->hasColour() && !ordered.back()->hasAntiColour()) || - (!ordered.back()->hasColour() && ordered.back()->hasAntiColour()); - - bool is33bar = - ordered.size() == 2 && startIsTriplet && endIsTriplet; - - if (!is33bar) { - - PList::const_iterator theStart = ordered.begin(); - bool onceMore = false; - - for (PList::const_iterator p = ordered.begin(); - p != ordered.end(); ++p) { - - PList::const_iterator next_it = - p != --ordered.end() ? boost::next(p) : ordered.begin(); - - if (!DipolePartonSplitter::colourConnected(*p,*next_it)) { - // it may have happened that we need to close the chain due to another - // chain starting right now; see the above global comment for this fix - bool startIsOctet = - (**theStart).hasColour() && (**theStart).hasAntiColour(); - bool endIsOctet = - (**p).hasColour() && (**p).hasAntiColour(); - if ( DipolePartonSplitter::colourConnected(*p,*theStart) && - startIsOctet && endIsOctet ) { - swap(next_it,theStart); - onceMore = true; - } else { - theStart = next_it; - current_chain.check(); - theChains.push_back(current_chain); - current_chain.dipoles().clear(); - continue; - } - } - - pair initial_state (false,false); - initial_state.first = (*p == incoming().first || *p == incoming().second); - initial_state.second = (*next_it == incoming().first || *next_it == incoming().second); - - pair which_in (-1,-1); - if (initial_state.first) - which_in.first = *p == incoming().first ? 0 : 1; - if (initial_state.second) - which_in.second = *next_it == incoming().first ? 0 : 1; - - pair xs (1.,1.); - if (initial_state.first) - xs.first = *p == incoming().first ? fractions().first : fractions().second; - if (initial_state.second) - xs.second = *next_it == incoming().first ? fractions().first : fractions().second; - - pair pdf; - - if ( which_in.first == 0 ) - pdf.first = pdfs().first; - else if ( which_in.first == 1 ) - pdf.first = pdfs().second; - - if ( which_in.second == 0 ) - pdf.second = pdfs().first; - else if ( which_in.second == 1 ) - pdf.second = pdfs().second; - - current_chain.dipoles().push_back(Dipole(make_pair(*p,*next_it),pdf,xs)); - - if ( onceMore ) { - next_it = theStart; - current_chain.check(); - theChains.push_back(current_chain); - current_chain.dipoles().clear(); - onceMore = false; - } - - } - } else { - - // treat 2 -> singlet, singlet -> 2 and 1 + singlet -> 1 + singlet special - // to prevent duplicate dipole - - assert(DipolePartonSplitter::colourConnected(ordered.front(),ordered.back())); - - pair initial_state (false,false); - initial_state.first = (ordered.front() == incoming().first || ordered.front() == incoming().second); - initial_state.second = (ordered.back() == incoming().first || ordered.back() == incoming().second); - - pair which_in (-1,-1); - if (initial_state.first) - which_in.first = ordered.front() == incoming().first ? 0 : 1; - if (initial_state.second) - which_in.second = ordered.back() == incoming().first ? 0 : 1; - - pair xs (1.,1.); - if (initial_state.first) - xs.first = ordered.front() == incoming().first ? fractions().first : fractions().second; - if (initial_state.second) - xs.second = ordered.back() == incoming().first ? fractions().first : fractions().second; - - pair pdf; - - if ( which_in.first == 0 ) - pdf.first = pdfs().first; - else if ( which_in.first == 1 ) - pdf.first = pdfs().second; - - if ( which_in.second == 0 ) - pdf.second = pdfs().first; - else if ( which_in.second == 1 ) - pdf.second = pdfs().second; - - current_chain.dipoles().push_back(Dipole(make_pair(ordered.front(),ordered.back()),pdf,xs)); - - } - - if (!current_chain.dipoles().empty()) { - current_chain.check(); - theChains.push_back(current_chain); - } - -} - -void DipoleEventRecord::getAll(const ParticleVector& childs, - set& hardSet, - set& outgoingSet) { - - for ( ParticleVector::const_iterator p = childs.begin(); - p != childs.end(); ++p ) { - if ( ShowerHandler::currentHandler()->eventHandler()->currentCollision()->isRemnant(*p) ) - continue; - if ( (**p).children().empty() ) { - if ( (**p).coloured() && - outgoingSet.find(*p) == outgoingSet.end() ) - outgoingSet.insert(*p); - else if ( !(**p).coloured() && - hardSet.find(*p) == hardSet.end() ) - hardSet.insert(*p); - } else { - getAll((**p).children(),hardSet,outgoingSet); - } - } - -} - -// shamelessly stolen from ShowerTree -void DipoleEventRecord::colourIsolate(const vector & original, - const vector & copy) { - // vectors must have same size - assert(original.size()==copy.size()); - // create a temporary map with all the particles to make looping easier - vector particles; - particles.reserve(original.size()); - for(unsigned int ix=0;ix::const_iterator cit,cjt; - for(cit=particles.begin();cit!=particles.end();++cit) - if((*cit).first->colourInfo()) (*cit).first->colourInfo(new_ptr(ColourBase())); - map cmap; - // make the colour connections of the copies - for(cit=particles.begin();cit!=particles.end();++cit) { - ColinePtr c1,newline; - // if particle has a colour line - if((*cit).second->colourLine()&&!(*cit).first->colourLine()) { - c1=(*cit).second->colourLine(); - newline=ColourLine::create((*cit).first); - cmap[c1]=newline; - for(cjt=particles.begin();cjt!=particles.end();++cjt) { - if(cjt==cit) continue; - if((*cjt).second->colourLine()==c1) - newline->addColoured((*cjt).first); - else if((*cjt).second->antiColourLine()==c1) - newline->addColoured((*cjt).first,true); - } - } - // if anticolour line - if((*cit).second->antiColourLine()&&!(*cit).first->antiColourLine()) { - c1=(*cit).second->antiColourLine(); - newline=ColourLine::create((*cit).first,true); - cmap[c1]=newline; - for(cjt=particles.begin();cjt!=particles.end();++cjt) { - if(cjt==cit) continue; - if((*cjt).second->colourLine()==c1) - newline->addColoured((*cjt).first); - else if((*cjt).second->antiColourLine()==c1) - newline->addColoured((*cjt).first,true); - } - } - } - for ( map::const_iterator c = cmap.begin(); - c != cmap.end(); ++c ) { - theColourLines[c->second] = c->first; - } - // sort out sinks and sources - for(cit=particles.begin();cit!=particles.end();++cit) { - tColinePtr cline[2]; - tColinePair cpair; - for(unsigned int ix=0;ix<4;++ix) { - cline[0] = ix<2 ? cit->second->colourLine() : cit->second->antiColourLine(); - cline[1] = ix<2 ? cit->first ->colourLine() : cit->first ->antiColourLine(); - if(cline[0]) { - switch (ix) { - case 0: case 2: - cpair = cline[0]->sinkNeighbours(); - break; - case 1: case 3: - cpair = cline[0]->sourceNeighbours(); - break; - }; - } - else { - cpair = make_pair(tColinePtr(),tColinePtr()); - } - if(cline[0]&&cpair.first) { - map::const_iterator - mit[2] = {cmap.find(cpair.first),cmap.find(cpair.second)}; - if(mit[0]!=cmap.end()&&mit[1]!=cmap.end()) { - if(ix==0||ix==2) { - cline[1]->setSinkNeighbours(mit[0]->second,mit[1]->second); - } - else { - cline[1]->setSourceNeighbours(mit[0]->second,mit[1]->second); - } - } - } - } - } -} - -// shamelessly stolen from ShowerTree -void DipoleEventRecord::updateColour(PPtr particle) { - // if attached to a colour line - if(particle->colourLine()) { - bool reset=false; - // if colour line from hard process reconnect - if(theColourLines.find(particle->colourLine())!=theColourLines.end()) { - ColinePtr c1=particle->colourLine(); - c1->removeColoured(particle); - theColourLines[c1]->addColoured(particle); - reset=true; - } - // ensure properly connected to the line - if(!reset) { - ColinePtr c1=particle->colourLine(); - c1->removeColoured(particle); - c1->addColoured(particle); - } - } - // if attached to an anticolour line - if(particle->antiColourLine()) { - bool reset=false; - // if anti colour line from hard process reconnect - if(theColourLines.find(particle->antiColourLine())!=theColourLines.end()) { - ColinePtr c1=particle->antiColourLine(); - c1->removeColoured(particle,true); - theColourLines[c1]->addColoured(particle,true); - reset=true; - } - if(!reset) { - ColinePtr c1=particle->antiColourLine(); - c1->removeColoured(particle,true); - c1->addColoured(particle,true); - } - } - for ( ParticleVector::const_iterator c = particle->children().begin(); - c != particle->children().end(); ++c ) { - updateColour(*c); - } -} - - -const map& -DipoleEventRecord::prepare(tSubProPtr subpro, - tStdXCombPtr xc, - const pair& pdf, - bool dipoles) { - - theSubProcess = subpro; - - theOutgoing.clear(); - theHard.clear(); - theColourLines.clear(); - theOriginals.clear(); - - PPair in = subpro->incoming(); - - assert(ShowerHandler::currentHandler()); - tPPair beam = ShowerHandler::currentHandler()->generator()->currentEvent()->incoming(); - - // don't take these from the XComb as it may be null - pair xs; - Direction<0> dir(true); - xs.first = in.first->momentum().dirPlus()/beam.first->momentum().dirPlus(); - dir.reverse(); - xs.second = in.second->momentum().dirPlus()/beam.second->momentum().dirPlus(); - - theXComb = xc; - thePDFs = pdf; - theFractions = xs; - - set allHard; - set allOutgoing; - - getAll(in.first->children(),allHard,allOutgoing); - getAll(in.second->children(),allHard,allOutgoing); - - vector original; - vector copies; - original.push_back(in.first); - original.push_back(in.second); - copy(allOutgoing.begin(),allOutgoing.end(),back_inserter(original)); - for ( vector::const_iterator p = original.begin(); - p != original.end(); ++p ) { - PPtr copy = new_ptr(Particle(**p)); - copies.push_back(copy); - theOriginals[*p] = copy; - } - - colourIsolate(original,copies); - - theIncoming.first = copies[0]; - ParticleVector children = theIncoming.first->children(); - for ( ParticleVector::const_iterator c = children.begin(); - c != children.end(); ++c ) - theIncoming.first->abandonChild(*c); - theIncoming.second = copies[1]; - children = theIncoming.second->children(); - for ( ParticleVector::const_iterator c = children.begin(); - c != children.end(); ++c ) - theIncoming.second->abandonChild(*c); - copy(copies.begin()+2,copies.end(),back_inserter(theOutgoing)); - - for ( set::const_iterator p = allHard.begin(); p != allHard.end(); ++p ) { - PPtr copy = new_ptr(Particle(**p)); - theHard.push_back(copy); - theOriginals[*p] = copy; - } - - if ( dipoles ) { - PList cordered = colourOrdered(); - findChains(cordered); - } - - PList::const_iterator XFirst, XLast; - - if ( !theHard.empty() ) { - XFirst = theHard.begin(); - XLast = theHard.end(); - } else { - XFirst = theOutgoing.begin(); - XLast = theOutgoing.end(); - } - - thePX = (**XFirst).momentum(); - ++XFirst; - for ( ; XFirst != XLast; ++XFirst ) - thePX += (**XFirst).momentum(); - - return theOriginals; - -} - -void DipoleEventRecord::clear() { - theSubProcess = SubProPtr(); - theXComb = StdXCombPtr(); - thePDFs = pair(); - theIncoming = PPair(); - theOutgoing.clear(); - theIntermediates.clear(); - theHard.clear(); - theChains.clear(); - theDoneChains.clear(); - theOriginals.clear(); - theColourLines.clear(); -} - -void DipoleEventRecord::update(DipoleSplittingInfo& dsplit) { - - if ( incoming().first == dsplit.emitter() ) { - theIntermediates.push_back(dsplit.emitter()); - theIncoming.first = dsplit.splitEmitter(); - theFractions.first /= dsplit.lastEmitterZ(); - } else if ( incoming().first == dsplit.spectator() ) { - theIntermediates.push_back(dsplit.spectator()); - theIncoming.first = dsplit.splitSpectator(); - theFractions.first /= dsplit.lastSpectatorZ(); - } - - if ( incoming().second == dsplit.emitter() ) { - theIntermediates.push_back(dsplit.emitter()); - theIncoming.second = dsplit.splitEmitter(); - theFractions.second /= dsplit.lastEmitterZ(); - } else if ( incoming().second == dsplit.spectator() ) { - theIntermediates.push_back(dsplit.spectator()); - theIncoming.second = dsplit.splitSpectator(); - theFractions.second /= dsplit.lastSpectatorZ(); - } - - PList::iterator pos; - - pos = find(theOutgoing.begin(), theOutgoing.end(), dsplit.emitter()); - if (pos != theOutgoing.end()) { - theIntermediates.push_back(*pos); - *pos = dsplit.splitEmitter(); - } - - pos = find(theOutgoing.begin(), theOutgoing.end(), dsplit.spectator()); - if (pos != theOutgoing.end()) { - theIntermediates.push_back(*pos); - *pos = dsplit.splitSpectator(); - } - - theOutgoing.push_back(dsplit.emission()); - - if (dsplit.splittingKinematics()->doesTransform()) { - - for (PList::iterator p = theIntermediates.begin(); - p != theIntermediates.end(); ++p) { - (**p).set5Momentum(dsplit.splittingKinematics()->transform((**p).momentum())); - } - - for (PList::iterator h = theHard.begin(); - h != theHard.end(); ++h) { - (**h).set5Momentum(dsplit.splittingKinematics()->transform((**h).momentum())); - } - - for (PList::iterator p = theOutgoing.begin(); - p != theOutgoing.end(); ++p) - if ((*p) != dsplit.splitEmitter() && - (*p) != dsplit.splitSpectator() && - (*p) != dsplit.emission()) - (**p).set5Momentum(dsplit.splittingKinematics()->transform((**p).momentum())); - - } - -} - -void -DipoleEventRecord::split(list::iterator dip, - list::iterator ch, - DipoleSplittingInfo& dsplit, - pair::iterator,list::iterator>& childIterators, - DipoleChain*& firstChain, DipoleChain*& secondChain, - bool colourSpectator) { - - static DipoleChain empty; - - pair children = dip->split(dsplit,colourSpectator); - - list::iterator breakup = - ch->insertSplitting(dip,children,childIterators); - - if ( breakup == ch->dipoles().end() ) { - firstChain = &(*ch); - secondChain = ∅ - } else { - - DipoleChain other; - other.dipoles().splice(other.dipoles().end(),ch->dipoles(),breakup,ch->dipoles().end()); - - chains().push_back(other); - firstChain = &(*ch); - secondChain = &(chains().back()); - - // explicitly fix iterators in case the splice implementation - // at hand does invalidate iterators (the SGI docu says, it doesn't, - // but it seems that this behaviour is not part of the standard) - childIterators.first = --firstChain->dipoles().end(); - childIterators.second = secondChain->dipoles().begin(); - - } - - if ( !colourSpectator ) - update(dsplit); // otherwise done by recoil(...) - -} - -void DipoleEventRecord::recoil(list::iterator dip, - list::iterator ch, - DipoleSplittingInfo& dsplit) { - - dip->recoil(dsplit); - ch->updateDipole(dip); - - update(dsplit); - -} - -list::iterator,list::iterator> > -DipoleEventRecord::inDipoles() { - - list::iterator,list::iterator> > res; - - for ( list::iterator chit = theDoneChains.begin(); - chit != theDoneChains.end(); ++chit ) { - - bool haveOne = false; - - for ( list::iterator dit = chit->dipoles().begin(); - dit != chit->dipoles().end(); ++dit ) { - if ( dit->leftPDF().pdf() || dit->rightPDF().pdf() ) { - haveOne = true; - break; - } - } - - if ( haveOne ) { - theChains.splice(theChains.begin(),theDoneChains,chit); - for ( list::iterator dit = theChains.front().dipoles().begin(); - dit != theChains.front().dipoles().end(); ++dit ) { - if ( dit->leftPDF().pdf() || dit->rightPDF().pdf() ) { - res.push_back(make_pair(dit,theChains.begin())); - } - } - } - - } - - return res; - -} - -void DipoleEventRecord::transform(const SpinOneLorentzRotation& rot) { - - - Lorentz5Momentum tmp; - - for (PList::iterator p = theIntermediates.begin(); - p != theIntermediates.end(); ++p) { - tmp = (**p).momentum(); tmp = rot * tmp; - (**p).set5Momentum(tmp); - } - - for (PList::iterator h = theHard.begin(); - h != theHard.end(); ++h) { - tmp = (**h).momentum(); tmp = rot * tmp; - (**h).set5Momentum(tmp); - } - - for (PList::iterator p = theOutgoing.begin(); - p != theOutgoing.end(); ++p) { - tmp = (**p).momentum(); tmp = rot * tmp; - (**p).set5Momentum(tmp); - } - -} - -tPPair DipoleEventRecord::fillEventRecord(StepPtr step, bool firstInteraction, bool) { - - PPtr inSubPro = subProcess()->incoming().first; - PPtr inParticle; - if ( !(inSubPro->parents().empty()) ) - inParticle = inSubPro->parents()[0]; - else - inParticle = inSubPro; - PPtr inParton = theOriginals[inSubPro]; - theOriginals.erase(inSubPro); - updateColour(incoming().first); - if ( inParticle != inSubPro ) - inParticle->abandonChild(inSubPro); - inParton->addChild(inSubPro); - if ( inParticle != inSubPro ) - inParticle->addChild(incoming().first); - theIntermediates.push_back(inSubPro); - theIntermediates.push_back(inParton); - - inSubPro = subProcess()->incoming().second; - if ( !(inSubPro->parents().empty()) ) - inParticle = inSubPro->parents()[0]; - else - inParticle = inSubPro; - inParton = theOriginals[inSubPro]; - theOriginals.erase(inSubPro); - updateColour(incoming().second); - if ( inParticle != inSubPro ) - inParticle->abandonChild(inSubPro); - inParton->addChild(inSubPro); - if ( inParticle != inSubPro ) - inParticle->addChild(incoming().second); - theIntermediates.push_back(inSubPro); - theIntermediates.push_back(inParton); - - while ( !theOriginals.empty() ) { - PPtr outSubPro = theOriginals.begin()->first; - PPtr outParton = theOriginals.begin()->second; - // workaround for OS X Mavericks LLVM libc++ -#ifdef _LIBCPP_VERSION - map::const_iterator beg = theOriginals.begin(); -#else - map::iterator beg = theOriginals.begin(); -#endif - theOriginals.erase(beg); - updateColour(outParton); - outSubPro->addChild(outParton); - theIntermediates.push_back(outSubPro); - } - - step->addIntermediates(theIntermediates.begin(),theIntermediates.end()); - - for (PList::const_iterator p = theOutgoing.begin(); - p != theOutgoing.end(); ++p) - step->addDecayProduct(*p); - - for (PList::const_iterator p = theHard.begin(); - p != theHard.end(); ++p) - step->addDecayProduct(*p); - - if ( firstInteraction && - (theIncoming.first->coloured() || - theIncoming.second->coloured() ) ) { - ShowerHandler::currentHandler()->lastExtractor()->newRemnants(theSubProcess->incoming(),theIncoming,step); - } - - step->addIntermediate(theIncoming.first); - step->addIntermediate(theIncoming.second); - - return theIncoming; - -} - -void DipoleEventRecord::debugLastEvent(ostream& os) const { - - bool first = ShowerHandler::currentHandler()->firstInteraction(); - - os << "--- DipoleEventRecord ----------------------------------------------------------\n"; - - os << " the " << (first ? "hard" : "secondary") << " subprocess is:\n" - << (*theSubProcess); - - os << " using PDF's " << thePDFs.first.pdf() << " and " - << thePDFs.second.pdf() << "\n"; - - os << " chains showering currently:\n"; - - for ( list::const_iterator chit = theChains.begin(); - chit != theChains.end(); ++chit ) - os << (*chit); - - os << " chains which finished showering:\n"; - - for ( list::const_iterator chit = theDoneChains.begin(); - chit != theDoneChains.end(); ++chit ) - os << (*chit); - - os << "--------------------------------------------------------------------------------\n"; - - os << flush; - -} diff --git a/DipoleShower/Base/DipoleEventRecord.h b/DipoleShower/Base/DipoleEventRecord.h deleted file mode 100644 --- a/DipoleShower/Base/DipoleEventRecord.h +++ /dev/null @@ -1,502 +0,0 @@ -// -*- C++ -*- -// -// DipoleEventRecord.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_DipoleEventRecord_H -#define HERWIG_DipoleEventRecord_H -// -// This is the declaration of the DipoleEventRecord class. -// - -#include "ThePEG/PDF/PDF.h" -#include "ThePEG/Handlers/StandardXComb.h" -#include "Dipole.h" -#include "DipoleChain.h" - -namespace Herwig { - -using namespace ThePEG; - -/** - * \ingroup DipoleShower - * \author Simon Platzer - * - * \brief Generalized dipole splitting info to deal with subleading-N - * splittings. - */ -class SubleadingSplittingInfo - : public DipoleSplittingInfo { - -public: - - /** - * Default constructor - */ - SubleadingSplittingInfo() - : DipoleSplittingInfo() {} - - /** - * Get the iterator of the emitter dipole chain - */ - list::iterator emitterChain() const { return theEmitterChain; } - - /** - * Get the iterator of the emitter dipole - */ - list::iterator emitterDipole() const { return theEmitterDipole; } - - /** - * Get the iterator of the spectator dipole chain - */ - list::iterator spectatorChain() const { return theSpectatorChain; } - - /** - * Get the iterator of the spectator dipole - */ - list::iterator spectatorDipole() const { return theSpectatorDipole; } - - /** - * Get the starting scale - */ - Energy startScale() const { return theStartScale; } - - /** - * Set the iterator of the emitter dipole chain - */ - void emitterChain(list::iterator it) { theEmitterChain = it; } - - /** - * Set the iterator of the emitter dipole - */ - void emitterDipole(list::iterator it) { theEmitterDipole = it; } - - /** - * Set the iterator of the spectator dipole chain - */ - void spectatorChain(list::iterator it) { theSpectatorChain = it; } - - /** - * Set the iterator of the spectator dipole - */ - void spectatorDipole(list::iterator it) { theSpectatorDipole = it; } - - /** - * Set the starting scale - */ - void startScale(Energy s) { theStartScale = s; } - -private: - - /** - * Iterator of the emitter dipole chain - */ - list::iterator theEmitterChain; - - /** - * Iterator of the emitter dipole - */ - list::iterator theEmitterDipole; - - /** - * Iterator of the spectator dipole chain - */ - list::iterator theSpectatorChain; - - /** - * Iterator of the spectator dipole - */ - list::iterator theSpectatorDipole; - - /** - * The starting scale - */ - Energy theStartScale; - -}; - -/** - * \ingroup DipoleShower - * \author Simon Platzer - * - * \brief The DipoleEventRecord class is - * used internally by the dipole shower. - */ -class DipoleEventRecord { - -public: - - /** - * The default constructor. - */ - DipoleEventRecord() {} - - /** - * The default destructor just cleans up. - */ - ~DipoleEventRecord() { clear(); } - -public: - - /** - * Return the incoming partons at the current - * stage of the evolution. - */ - PPair& incoming() { return theIncoming; } - - /** - * Return the incoming partons at the current - * stage of the evolution. - */ - const PPair& incoming() const { return theIncoming; } - - /** - * Return the outgoing partons at the current - * stage of the evolution. - */ - PList& outgoing() { return theOutgoing; } - - /** - * Return the outgoing partons at the current - * stage of the evolution. - */ - const PList& outgoing() const { return theOutgoing; } - - /** - * Return the intermediate particles at the current - * stage of the evolution. - */ - PList& intermediates() { return theIntermediates; } - - /** - * Return the intermediate particles at the current - * stage of the evolution. - */ - const PList& intermediates() const { return theIntermediates; } - - /** - * Return any non-coloured outgoing particles in the - * current subprocess. - */ - PList& hard() { return theHard; } - - /** - * Return any non-coloured outgoing particles in the - * current subprocess. - */ - const PList& hard() const { return theHard; } - - /** - * Return the subprocess currently showered - */ - tSubProPtr subProcess() const { return theSubProcess; } - - /** - * Return the XComb describing the hard process. - */ - tStdXCombPtr xcombPtr() const { return theXComb; } - - /** - * Return the XComb describing the hard process. - */ - const StandardXComb& xcomb() const { return *theXComb; } - - /** - * Return the momentum fractions. - */ - const pair& fractions() const { return theFractions; } - - /** - * Return the PDFs - */ - const pair& pdfs() const { return thePDFs; } - - /** - * Return the momentum of the hard system - */ - const Lorentz5Momentum& pX() const { return thePX; } - - /** - * Transform all intermediate, hard and outgoing - * partciles using the given transformation. - */ - void transform(const SpinOneLorentzRotation& rot); - -public: - - /** - * Return the dipole chains to be showered. - */ - const list& chains() const { return theChains; } - - /** - * Access the dipole chains to be showered. - */ - list& chains() { return theChains; } - - /** - * Return the dipole chains which ceased evolving. - */ - const list& doneChains() const { return theDoneChains; } - - /** - * Access the dipole chains which ceased evolving. - */ - list& doneChains() { return theDoneChains; } - - /** - * Return true, if there are chains to be - * showered. - */ - bool haveChain() const { return !theChains.empty(); } - - /** - * Return the current dipole chain - */ - DipoleChain& currentChain() { assert(haveChain()); return theChains.front(); } - - /** - * Pop the current dipole chain - */ - void popChain(); - - /** - * Remove the given chain. - */ - void popChain(list::iterator); - - /** - * Remove the given chains. - */ - void popChains(const list::iterator>&); - - /** - * Create a merged dipole index given two independent dipoles; - * the first dipole is to provide the emitter. - */ - DipoleIndex - mergeIndex(list::iterator firstDipole, const pair& whichFirst, - list::iterator secondDipole, const pair& whichSecond) const; - - /** - * Create a SubleadingSplitingInfo given two independent dipoles; - * the first dipole is to provide the emitter. - */ - SubleadingSplittingInfo - mergeSplittingInfo(list::iterator firstChain, list::iterator firstDipole, - const pair& whichFirst, - list::iterator secondChain, list::iterator secondDipole, - const pair& whichSecond) const; - - /** - * Return a list of all possible subleading-N emitting pairs - */ - void getSubleadingSplittings(list&); - -public: - - /** - * Split the dipole pointed to by the given iterator. - * Return references to the affected chains, and update - * iterators pointing to the children in the returned - * chains. - */ - - void split(list::iterator dip, - DipoleSplittingInfo& dsplit, - pair::iterator,list::iterator>& childIterators, - DipoleChain*& firstChain, DipoleChain*& secondChain) { - split(dip,theChains.begin(),dsplit,childIterators,firstChain,secondChain,false); - } - - /** - * Split the dipole pointed to by the given iterator - * in the indicated chain, indicating a splitting with - * a colour spectator. - * Return references to the affected chains, and update - * iterators pointing to the children in the returned - * chains. - */ - void split(list::iterator dip, - list::iterator ch, - DipoleSplittingInfo& dsplit, - pair::iterator,list::iterator>& childIterators, - DipoleChain*& firstChain, DipoleChain*& secondChain, - bool colourSpectator = true); - - /** - * Let the given dipole take the recoil of - * the indicated splitting. - */ - void recoil(list::iterator dip, - list::iterator ch, - DipoleSplittingInfo& dsplit); - - /** - * Peform a subleading-N splitting - */ - void splitSubleading(SubleadingSplittingInfo& dsplit, - pair::iterator,list::iterator>& childIterators, - DipoleChain*& firstChain, DipoleChain*& secondChain); - - /** - * Update the particles upon insertion of the - * given splitting. - */ - void update(DipoleSplittingInfo& dsplit); - - /** - * Return the dipole(s) containing the incoming - * partons after the evolution has ended. Put back - * the chains containing these to the chains to be - * showered. - */ - list::iterator,list::iterator> > - inDipoles(); - - /** - * Fill the given step and return incoming partons. - */ - tPPair fillEventRecord(StepPtr step, bool firstInteraction, bool realigned); - -public: - - /** - * Prepare the event record for the given - * subprocess. - */ - const map& prepare(tSubProPtr subpro, - tStdXCombPtr xc, - const pair& pdf, - bool dipoles = true); - - /** - * Clear the event record: Give up ownership - * on any object involved in the evolution. - */ - void clear(); - -public: - - /** - * Print event record at current state. - */ - void debugLastEvent(ostream&) const; - -protected: - - /** - * Sort the coloured partons into a colour ordered ensemble. - */ - PList colourOrdered(); - - /** - * Find the chains to be showered. - */ - void findChains(const PList& ordered); - - /** - * Add all particles to the relevant sets - */ - void getAll(const ParticleVector& childs, - set& hardSet, - set& outgoingSet); - - /** - * Isolate the colour of the process from the rest of the event. - * Called in the constructor - */ - void colourIsolate(const vector & original, const vector & copy); - - /** - * Update the colour information of a particle prior to insertion into the - * event record. - */ - void updateColour(PPtr particle); - -private: - - struct getMomentum { - const Lorentz5Momentum& operator() (PPtr particle) const { - return particle->momentum(); - } - }; - - /** - * The subprocess currently showered. - */ - SubProPtr theSubProcess; - - /** - * Pointer to the XComb which generated the hard process. - */ - StdXCombPtr theXComb; - - /** - * The PDFs to be considered. - */ - pair thePDFs; - - /** - * The momentum of the hard system - */ - Lorentz5Momentum thePX; - - /** - * Momentum fractions of the incoming partons. - */ - pair theFractions; - - /** - * The incoming partons at the current - * stage of the evolution. - */ - PPair theIncoming; - - /** - * The outgoing partons at the current - * stage of the evolution. - */ - PList theOutgoing; - - /** - * The intermediate particles at the current - * stage of the evolution. - */ - PList theIntermediates; - - /** - * Any non-coloured outgoing particles in the - * current subprocess. - */ - PList theHard; - - /** - * Map originals to copies. - */ - map theOriginals; - - /** - * Map colour lines from copies to originals. - */ - map theColourLines; - - /** - * The dipole chains currently showered. - */ - list theChains; - - /** - * The dipole chains which ceased evolving. - */ - list theDoneChains; - -}; - - -} - -#endif /* HERWIG_DipoleEventRecord_H */ diff --git a/DipoleShower/Base/DipoleSplittingGenerator.cc b/DipoleShower/Base/DipoleSplittingGenerator.cc deleted file mode 100644 --- a/DipoleShower/Base/DipoleSplittingGenerator.cc +++ /dev/null @@ -1,606 +0,0 @@ -// -*- 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), theSplittingWeight(1.) { - if ( ShowerHandler::currentHandler() ) - setGenerator(ShowerHandler::currentHandler()->generator()); -} - -DipoleSplittingGenerator::~DipoleSplittingGenerator() { - if ( theExponentialGenerator ) { - delete theExponentialGenerator; - theExponentialGenerator = 0; - } -} - -IBPtr DipoleSplittingGenerator::clone() const { - return new_ptr(*this); -} - -IBPtr DipoleSplittingGenerator::fullclone() const { - return new_ptr(*this); -} - -void DipoleSplittingGenerator::wrap(Ptr::ptr other) { - assert(!prepared); - theOtherGenerator = other; -} - -void DipoleSplittingGenerator::resetVariations() { - for ( map::iterator w = currentWeights.begin(); - w != currentWeights.end(); ++w ) - w->second = 1.; -} - -void DipoleSplittingGenerator::veto(const vector&, double p, double r) { - double factor = 1.; - if ( splittingReweight() ) { - if ( ( ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->firstInteraction() ) || - ( !ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->secondaryInteractions() ) ) { - factor = splittingReweight()->evaluate(generatedSplitting); - theSplittingWeight *= (r-factor*p)/(r-p); - } - } - splittingKernel()->veto(generatedSplitting, factor*p, r, currentWeights); -} - -void DipoleSplittingGenerator::accept(const vector&, double p, double r) { - double factor = 1.; - if ( splittingReweight() ) { - if ( ( ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->firstInteraction() ) || - ( !ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->secondaryInteractions() ) ) { - factor = splittingReweight()->evaluate(generatedSplitting); - theSplittingWeight *= factor; - } - } - splittingKernel()->accept(generatedSplitting, factor*p, r, currentWeights); -} - -void DipoleSplittingGenerator::prepare(const DipoleSplittingInfo& sp) { - - generatedSplitting = sp; - - generatedSplitting.splittingKinematics(splittingKernel()->splittingKinematics()); - generatedSplitting.splittingParameters().resize(splittingKernel()->nDimAdditional()); - - if ( wrapping() ) { - generatedSplitting.emitterData(theSplittingKernel->emitter(generatedSplitting.index())); - generatedSplitting.spectatorData(theSplittingKernel->spectator(generatedSplitting.index())); - generatedSplitting.emissionData(theSplittingKernel->emission(generatedSplitting.index())); - parameters.resize(theOtherGenerator->nDim()); - prepared = true; - return; - } - - generatedSplitting.emitterData(splittingKernel()->emitter(generatedSplitting.index())); - generatedSplitting.spectatorData(splittingKernel()->spectator(generatedSplitting.index())); - generatedSplitting.emissionData(splittingKernel()->emission(generatedSplitting.index())); - - presampledSplitting = generatedSplitting; - - prepared = true; - - parameters.resize(nDim()); - - theExponentialGenerator = - new exsample::exponential_generator(); - - 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 ( 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; - } - - 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; - - 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) ); - -} - -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 ( 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); - double jac = split.splittingKinematics()->jacobian(); - - // multiply in the profile scales when relevant - assert(ShowerHandler::currentHandler()); - if ( ShowerHandler::currentHandler()->firstInteraction() && - ShowerHandler::currentHandler()->profileScales() && - !presampling ) { - Energy hard = ShowerHandler::currentHandler()->hardScale(); - if ( hard > ZERO ) - kernel *= ShowerHandler::currentHandler()->profileScales()->hardScaleProfile(hard,split.lastPt()); - } - - split.lastValue( abs(jac) * kernel ); - - if ( isnan(split.lastValue()) || isinf(split.lastValue()) ) { - generator()->log() << "DipoleSplittingGenerator:evaluate(): problematic splitting kernel encountered for " - << splittingKernel()->name() << "\n" << flush; - split.lastValue(0.0); - } - - if ( kernel < 0. ) - return 0.; - - return split.lastValue(); - -} - -void DipoleSplittingGenerator::doGenerate(map& variations, - Energy optCutoff) { - - assert(!wrapping()); - - double res = 0.; - - Energy startPt = generatedSplitting.hardPt(); - double optKappaCutoff = 0.0; - if ( optCutoff > splittingKinematics()->IRCutoff() ) { - optKappaCutoff = splittingKinematics()->ptToRandom(optCutoff, - generatedSplitting.scale(), - generatedSplitting.emitterX(), - generatedSplitting.spectatorX(), - generatedSplitting.index(), - *splittingKernel()); - } - - resetVariations(); - theSplittingWeight = 1.; - - while (true) { - try { - if ( optKappaCutoff == 0.0 ) { - res = theExponentialGenerator->generate(); - } else { - res = theExponentialGenerator->generate(optKappaCutoff); - } - } catch (exsample::exponential_regenerate&) { - resetVariations(); - theSplittingWeight = 1.; - generatedSplitting.hardPt(startPt); - continue; - } catch (exsample::hit_and_miss_maxtry&) { - throw DipoleShowerHandler::RedoShower(); - } catch (exsample::selection_maxtry&) { - throw DipoleShowerHandler::RedoShower(); - } - break; - } - - for ( map::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,variations,optHardPt,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(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 deleted file mode 100644 --- a/DipoleShower/Base/DipoleSplittingGenerator.h +++ /dev/null @@ -1,491 +0,0 @@ -// -*- 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(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); - - /** - * Indicate that an accept with the given kernel value and overestimate has occured. - */ - void accept(const vector&, double p, double r); - - /** - * Return the weight associated to the currently generated splitting - */ - double splittingWeight() const { - if ( wrapping() ) - return theOtherGenerator->splittingWeight(); - return theSplittingWeight; - } - - /** - * True, if sampler should apply compensation - */ - void doCompensate(bool yes = true) { theDoCompensate = yes; } - -public: - - /**@name Wrap to the exsample2 interface until this is finally cleaned up. */ - //@{ - - inline const vector& 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; - - /** - * The weight associated to the currently generated splitting - */ - double theSplittingWeight; - -private: - - /** - * The static object used to initialize the description of this class. - * Indicates that this is a concrete class with persistent data. - */ - static ClassDescription 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/Base/DipoleSplittingReweight.cc b/DipoleShower/Base/DipoleSplittingReweight.cc deleted file mode 100644 --- a/DipoleShower/Base/DipoleSplittingReweight.cc +++ /dev/null @@ -1,65 +0,0 @@ -// -*- C++ -*- -// -// DipoleSplittingReweight.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 DipoleSplittingReweight class. -// - -#include -#include "DipoleSplittingReweight.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; - -DipoleSplittingReweight::DipoleSplittingReweight() - : HandlerBase() {} - -DipoleSplittingReweight::~DipoleSplittingReweight() {} - -void DipoleSplittingReweight::updateCurrentHandler() { - if ( ShowerHandler::currentHandler() != theCurrentHandler ) { - Ptr::tptr sptr = ShowerHandler::currentHandler(); - theCurrentHandler = - dynamic_ptr_cast::tptr>(sptr); - } -} - -Ptr::tptr DipoleSplittingReweight::currentHandler() const { - return theCurrentHandler; -} - - -// If needed, insert default implementations of virtual function defined -// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). - - -void DipoleSplittingReweight::persistentOutput(PersistentOStream & ) const { -} - -void DipoleSplittingReweight::persistentInput(PersistentIStream &, int) { -} - -AbstractClassDescription DipoleSplittingReweight::initDipoleSplittingReweight; -// Definition of the static class description member. - -void DipoleSplittingReweight::Init() { - - static ClassDocumentation documentation - ("DipoleSplittingReweight is used by the dipole shower " - "to reweight splittings from a given dipole splitting kernel."); - -} - diff --git a/DipoleShower/Base/DipoleSplittingReweight.h b/DipoleShower/Base/DipoleSplittingReweight.h deleted file mode 100644 --- a/DipoleShower/Base/DipoleSplittingReweight.h +++ /dev/null @@ -1,167 +0,0 @@ -// -*- C++ -*- -// -// DipoleSplittingReweight.h is a part of Herwig - A multi-purpose Monte Carlo event generator -// Copyright (C) 2002-2007 The Herwig Collaboration -// -// Herwig is licenced under version 2 of the GPL, see COPYING for details. -// Please respect the MCnet academic guidelines, see GUIDELINES for details. -// -#ifndef HERWIG_DipoleSplittingReweight_H -#define HERWIG_DipoleSplittingReweight_H -// -// This is the declaration of the DipoleSplittingReweight class. -// - -#include "ThePEG/Handlers/HandlerBase.h" -#include "DipoleSplittingInfo.h" - -#include "Herwig/DipoleShower/DipoleShowerHandler.fh" - -namespace Herwig { - -using namespace ThePEG; - -/** - * \ingroup DipoleShower - * \author Simon Platzer - * - * \brief DipoleSplittingReweight is used by the dipole shower - * to reweight splittings from a given dipole splitting kernel. - * - * @see \ref DipoleSplittingReweightInterfaces "The interfaces" - * defined for DipoleSplittingReweight. - */ -class DipoleSplittingReweight: public HandlerBase { - -public: - - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - DipoleSplittingReweight(); - - /** - * The destructor. - */ - virtual ~DipoleSplittingReweight(); - //@} - -public: - - /** - * Return true, if the reweighting should be applied to the first - * interaction - */ - virtual bool firstInteraction() const { return true; } - - /** - * Return true, if the reweighting should be applied to the secondary - * interactions - */ - virtual bool secondaryInteractions() const { return false; } - - /** - * Update the pointer to the currently active dipole shower handler object. - */ - void updateCurrentHandler(); - - /** - * Return the pointer to the currently active dipole shower handler object. - */ - Ptr::tptr currentHandler() const; - - /** - * Return the reweighting factor for the given splitting type. - */ - virtual double evaluate(const DipoleSplittingInfo&) const = 0; - -public: - - /** @name Functions used by the persistent I/O system. */ - //@{ - /** - * Function used to write out object persistently. - * @param os the persistent output stream written to. - */ - void persistentOutput(PersistentOStream & os) const; - - /** - * Function used to read in object persistently. - * @param is the persistent input stream read from. - * @param version the version number of the object when written. - */ - void persistentInput(PersistentIStream & is, int version); - //@} - - /** - * The standard Init function used to initialize the interfaces. - * Called exactly once for each class by the class description system - * before the main function starts or - * when this class is dynamically loaded. - */ - static void Init(); - -// If needed, insert declarations of virtual function defined in the -// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). - -private: - - /** - * The static object used to initialize the description of this class. - * Indicates that this is a concrete class with persistent data. - */ - static AbstractClassDescription initDipoleSplittingReweight; - - /** - * The assignment operator is private and must never be called. - * In fact, it should not even be implemented. - */ - DipoleSplittingReweight & operator=(const DipoleSplittingReweight &); - - /** - * A pointer to the currently active dipole shower handler object. - */ - Ptr::tptr theCurrentHandler; - -}; - -} - -#include "ThePEG/Utilities/ClassTraits.h" - -namespace ThePEG { - -/** @cond TRAITSPECIALIZATIONS */ - -/** This template specialization informs ThePEG about the - * base classes of DipoleSplittingReweight. */ -template <> -struct BaseClassTrait { - /** Typedef of the first base class of DipoleSplittingReweight. */ - typedef HandlerBase NthBase; -}; - -/** This template specialization informs ThePEG about the name of - * the DipoleSplittingReweight class and the shared object where it is defined. */ -template <> -struct ClassTraits - : public ClassTraitsBase { - /** Return a platform-independent class name */ - static string className() { return "Herwig::DipoleSplittingReweight"; } - /** - * The name of a file containing the dynamic library where the class - * DipoleSplittingReweight is implemented. It may also include several, space-separated, - * libraries if the class DipoleSplittingReweight depends on other classes (base classes - * excepted). In this case the listed libraries will be dynamically - * linked in the order they are specified. - */ - static string library() { return "HwDipoleShower.so"; } -}; - -/** @endcond */ - -} - -#endif /* HERWIG_DipoleSplittingReweight_H */ diff --git a/DipoleShower/DipoleShowerHandler.cc b/DipoleShower/DipoleShowerHandler.cc deleted file mode 100644 --- a/DipoleShower/DipoleShowerHandler.cc +++ /dev/null @@ -1,1119 +0,0 @@ -// -*- 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), theDetuning(1.0), - maxPt(ZERO), muPt(ZERO) {} - -DipoleShowerHandler::~DipoleShowerHandler() {} - -IBPtr DipoleShowerHandler::clone() const { - return new_ptr(*this); -} - -IBPtr DipoleShowerHandler::fullclone() const { - return new_ptr(*this); -} - -tPPair DipoleShowerHandler::cascade(tSubProPtr sub, XCPtr, - Energy optHardPt, Energy optCutoff) { - - useMe(); - - prepareCascade(sub); - resetWeights(); - - if ( !doFSR && ! doISR ) - return sub->incoming(); - - eventRecord().clear(); - eventRecord().prepare(sub,dynamic_ptr_cast(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); - candidate.emitter(emitter); - candidate.spectator(spectator); - - if ( generators().find(candidate.index()) == generators().end() ) - getGenerators(candidate.index(),theSplittingReweight); - - // - // NOTE -- needs proper fixing at some point - // - // For some very strange reason, equal_range gives back - // key ranges it hasn't been asked for. This particularly - // happens e.g. for FI dipoles of the same kind, but different - // PDF (hard vs MPI PDF). I can't see a reason for this, - // as DipoleIndex properly implements comparison for equality - // and (lexicographic) ordering; for the time being, we - // use equal_range, extented by an explicit check for wether - // the key is indeed what we wanted. See line after (*) comment - // below. - // - - 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,currentWeights_,optHardPt,optCutoff); - Energy nextScale = evolutionOrdering()->evolutionScale(gen->second->lastSplitting(),*(gen->second->splittingKernel())); - - if ( nextScale > winnerScale ) { - winner.fill(candidate); - gen->second->completeSplitting(winner); - winnerGen = gen; - winnerScale = nextScale; - } - - reweight_ *= gen->second->splittingWeight(); - - } - - if ( winnerGen == generators().end() ) { - winner.didStopEvolving(); - return 0.0*GeV; - } - - if ( winner.stoppedEvolving() ) - return 0.0*GeV; - - return winnerScale; - -} - -void DipoleShowerHandler::doCascade(unsigned int& emDone, - Energy optHardPt, - Energy optCutoff) { - - if ( nEmissions ) - if ( emDone == nEmissions ) - return; - - DipoleSplittingInfo winner; - DipoleSplittingInfo dipoleWinner; - - while ( eventRecord().haveChain() ) { - - if ( verbosity > 2 ) { - generator()->log() << "DipoleShowerHandler selecting splittings for the chain:\n" - << eventRecord().currentChain() << flush; - } - - list::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() ) { - 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 ) - 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 ) { - if ( !(**k).alphaS() ) - (**k).alphaS(as); - (**k).renormalizationScaleFreeze(theRenormalizationScaleFreeze); - (**k).factorizationScaleFreeze(theFactorizationScaleFreeze); - } - - // clear the generators to be rebuild - // actually, there shouldn't be any generators - // when this happens. - generators().clear(); - -} - -void DipoleShowerHandler::resetReweight(Ptr::tptr rw) { - for ( 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); - if ( renormalizationScaleFactor() != 1. ) - nGenerator->splittingKernel()->renormalizationScaleFactor(renormalizationScaleFactor()); - if ( factorizationScaleFactor() != 1. ) - nGenerator->splittingKernel()->factorizationScaleFactor(factorizationScaleFactor()); - if ( !nGenerator->splittingReweight() ) - nGenerator->splittingReweight(rw); - nGenerator->splittingKernel()->freezeGrid(theFreezeGrid); - nGenerator->splittingKernel()->detuning(theDetuning); - - GeneratorMap::const_iterator equivalent = generators().end(); - - for ( GeneratorMap::const_iterator eq = generators().begin(); - eq != generators().end(); ++eq ) { - if ( !eq->second->wrapping() ) - if ( (**k).canHandleEquivalent(ind,*(eq->second->splittingKernel()),eq->first) ) { - - equivalent = eq; - - if ( verbosity > 0 ) { - generator()->log() << "The dipole configuration " - << ind - << " can equivalently be handled by the existing\n" - << "generator for configuration " - << eq->first << " using the kernel '" - << eq->second->splittingKernel()->name() - << "'\n" << flush; - } - - break; - - } - } - - if ( equivalent != generators().end() ) { - nGenerator->wrap(equivalent->second); - } - - DipoleSplittingInfo dummy; - dummy.index(ind); - nGenerator->prepare(dummy); - - generators().insert(make_pair(ind,nGenerator)); - - - } - } - - if ( !gotone ) { - generator()->logWarning(Exception() - << "DipoleShowerHandler could not " - << "find a splitting kernel which is able " - << "to handle splittings off the dipole " - << ind << ".\n" - << "Please check the input files." - << Exception::warning); - } - -} - -// If needed, insert default implementations of virtual function defined -// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). - -void DipoleShowerHandler::doinit() { - ShowerHandler::doinit(); - if ( theGlobalAlphaS ) - resetAlphaS(theGlobalAlphaS); -} - -void DipoleShowerHandler::dofinish() { - ShowerHandler::dofinish(); -} - -void DipoleShowerHandler::doinitrun() { - ShowerHandler::doinitrun(); -} - -void DipoleShowerHandler::persistentOutput(PersistentOStream & os) const { - os << kernels << theEvolutionOrdering - << constituentReshuffler << intrinsicPtGenerator - << theGlobalAlphaS << chainOrderVetoScales - << nEmissions << discardNoEmissions << firstMCatNLOEmission << doFSR << doISR - << realignmentScheme << verbosity << printEvent - << ounit(theRenormalizationScaleFreeze,GeV) - << ounit(theFactorizationScaleFreeze,GeV) - << isMCatNLOSEvent << isMCatNLOHEvent << theShowerApproximation - << theDoCompensate << theFreezeGrid << theDetuning - << theEventReweight << theSplittingReweight << ounit(maxPt,GeV) - << ounit(muPt,GeV); -} - -void DipoleShowerHandler::persistentInput(PersistentIStream & is, int) { - is >> kernels >> theEvolutionOrdering - >> constituentReshuffler >> intrinsicPtGenerator - >> theGlobalAlphaS >> chainOrderVetoScales - >> nEmissions >> discardNoEmissions >> firstMCatNLOEmission >> doFSR >> doISR - >> realignmentScheme >> verbosity >> printEvent - >> iunit(theRenormalizationScaleFreeze,GeV) - >> iunit(theFactorizationScaleFreeze,GeV) - >> isMCatNLOSEvent >> isMCatNLOHEvent >> theShowerApproximation - >> theDoCompensate >> theFreezeGrid >> theDetuning - >> theEventReweight >> theSplittingReweight >> 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 Parameter interfaceDetuning - ("Detuning", - "A value to detune the overestimate kernel.", - &DipoleShowerHandler::theDetuning, 1.0, 1.0, 0, - false, false, Interface::lowerlim); - - static Reference interfaceEventReweight - ("EventReweight", - "", - &DipoleShowerHandler::theEventReweight, false, false, true, true, false); - - static Reference interfaceSplittingReweight - ("SplittingReweight", - "Set the splitting reweight.", - &DipoleShowerHandler::theSplittingReweight, false, false, true, true, false); - -} - diff --git a/DipoleShower/DipoleShowerHandler.h b/DipoleShower/DipoleShowerHandler.h deleted file mode 100644 --- a/DipoleShower/DipoleShowerHandler.h +++ /dev/null @@ -1,516 +0,0 @@ -// -*- C++ -*- -// -// DipoleShowerHandler.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_DipoleShowerHandler_H -#define HERWIG_DipoleShowerHandler_H -// -// This is the declaration of the DipoleShowerHandler class. -// - -#include "Herwig/Shower/ShowerHandler.h" - -#include "Herwig/DipoleShower/DipoleShowerHandler.fh" - -#include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" -#include "Herwig/DipoleShower/Base/DipoleSplittingReweight.h" -#include "Herwig/DipoleShower/Kernels/DipoleSplittingKernel.h" -#include "Herwig/DipoleShower/Base/DipoleSplittingGenerator.h" -#include "Herwig/DipoleShower/Base/DipoleEventRecord.h" -#include "Herwig/DipoleShower/Base/DipoleEvolutionOrdering.h" -#include "Herwig/DipoleShower/Base/DipoleEventReweight.h" -#include "Herwig/DipoleShower/Utility/ConstituentReshuffler.h" -#include "Herwig/DipoleShower/Utility/IntrinsicPtGenerator.h" -#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" - -namespace Herwig { - -using namespace ThePEG; - -/** - * \ingroup DipoleShower - * \author Simon Platzer - * - * \brief The DipoleShowerHandler class manages the showering using - * the dipole shower algorithm. - * - * @see \ref DipoleShowerHandlerInterfaces "The interfaces" - * defined for DipoleShowerHandler. - */ -class DipoleShowerHandler: public ShowerHandler { - -public: - - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - DipoleShowerHandler(); - - /** - * The destructor. - */ - virtual ~DipoleShowerHandler(); - //@} - -public: - - /** - * Indicate a problem in the shower. - */ - struct RedoShower {}; - - /** - * Insert an additional splitting kernel. - */ - void addSplitting(Ptr::ptr sp) { - kernels.push_back(sp); - } - - /** - * Reset the alpha_s for all splitting kernels. - */ - void resetAlphaS(Ptr::tptr); - - /** - * Reset the splitting reweight for all splitting kernels. - */ - void resetReweight(Ptr::tptr); - - /** - * Return true, if the shower handler can generate a truncated - * shower for POWHEG style events generated using Matchbox - */ - virtual bool canHandleMatchboxTrunc() const { return false; } - - /** - * Return true, if this cascade handler will perform reshuffling from hard - * process masses. - */ - virtual bool isReshuffling() const { return false; } - - /** - * Return the relevant hard scale to be used in the profile scales - */ - virtual Energy hardScale() const { - return muPt; - } - -protected: - - typedef multimap::ptr> GeneratorMap; - - /** - * The main method which manages the showering of a subprocess. - */ - virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb) { - return cascade(sub,xcomb,ZERO,ZERO); - } - - /** - * The main method which manages the showering of a subprocess. - */ - tPPair cascade(tSubProPtr sub, XCPtr xcomb, - Energy optHardPt, Energy optCutoff); - - /** - * Build splitting generators for the given - * dipole index. - */ - void getGenerators(const DipoleIndex&, - Ptr::tptr rw = - Ptr::tptr()); - - /** - * Setup the hard scales. - */ - void hardScales(Energy2 scale); - - /** - * Return the evolution ordering - */ - Ptr::tptr evolutionOrdering() const { return theEvolutionOrdering; } - - /** - * Reshuffle to constituent mass shells - */ - void constituentReshuffle(); - - /** - * Access the generator map - */ - GeneratorMap& generators() { return theGenerators; } - - /** - * Access the event record - */ - DipoleEventRecord& eventRecord() { return theEventRecord; } - - /** - * Return the event record - */ - const DipoleEventRecord& eventRecord() const { return theEventRecord; } - - /** - * Return the splitting kernels. - */ - const vector::ptr>& splittingKernels() const { - return kernels; - } - - /** - * Realign the event such as to have the incoming partons along thre - * beam axes. - */ - bool realign(); - -private: - - /** - * Perform the cascade. - */ - void doCascade(unsigned int& emDone, - Energy optHardPt = ZERO, - Energy optCutoff = ZERO); - - /** - * Get the winning splitting for the - * given dipole and configuration. - */ - Energy getWinner(DipoleSplittingInfo& winner, - const Dipole& dip, - pair conf, - Energy optHardPt = ZERO, - Energy optCutoff = ZERO); - - /** - * Get the winning splitting for the - * given dipole and configuration. - */ - Energy getWinner(SubleadingSplittingInfo& winner, - Energy optHardPt = ZERO, - Energy optCutoff = ZERO); - - /** - * Get the winning splitting for the - * given dipole and configuration. - */ - Energy getWinner(DipoleSplittingInfo& winner, - const DipoleIndex& index, - double emitterX, double spectatorX, - pair conf, - tPPtr emitter, tPPtr spectator, - Energy startScale, - Energy optHardPt = ZERO, - Energy optCutoff = ZERO); - -public: - - /** @name Functions used by the persistent I/O system. */ - //@{ - /** - * Function used to write out object persistently. - * @param os the persistent output stream written to. - */ - void persistentOutput(PersistentOStream & os) const; - - /** - * Function used to read in object persistently. - * @param is the persistent input stream read from. - * @param version the version number of the object when written. - */ - void persistentInput(PersistentIStream & is, int version); - //@} - - /** - * The standard Init function used to initialize the interfaces. - * Called exactly once for each class by the class description system - * before the main function starts or - * when this class is dynamically loaded. - */ - static void Init(); - -protected: - - /** @name Clone Methods. */ - //@{ - /** - * Make a simple clone of this object. - * @return a pointer to the new object. - */ - virtual IBPtr clone() const; - - /** Make a clone of this object, possibly modifying the cloned object - * to make it sane. - * @return a pointer to the new object. - */ - virtual IBPtr fullclone() const; - //@} - - -// If needed, insert declarations of virtual function defined in the -// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). - - -protected: - - /** @name Standard Interfaced functions. */ - //@{ - /** - * Initialize this object after the setup phase before saving an - * EventGenerator to disk. - * @throws InitException if object could not be initialized properly. - */ - virtual void doinit(); - - /** - * Initialize this object. Called in the run phase just before - * a run begins. - */ - virtual void doinitrun(); - - /** - * Finalize this object. Called in the run phase just after a - * run has ended. Used eg. to write out statistics. - */ - virtual void dofinish(); - //@} - - -private: - - /** - * The splitting kernels to be used. - */ - vector::ptr> kernels; - - /** - * The evolution ordering considered - */ - Ptr::ptr theEvolutionOrdering; - - /** - * The ConstituentReshuffler to be used - */ - Ptr::ptr constituentReshuffler; - - /** - * The intrinsic pt generator to be used. - */ - Ptr::ptr intrinsicPtGenerator; - - /** - * A global alpha_s to be used for all splitting kernels. - */ - Ptr::ptr theGlobalAlphaS; - - /** - * Apply chain ordering to events from matrix - * element corrections. - */ - bool chainOrderVetoScales; - - /** - * Limit the number of emissions. - * Limit applied if > 0. - */ - unsigned int nEmissions; - - /** - * Discard events which did not radiate. - */ - bool discardNoEmissions; - - /** - * Perform the first MC@NLO emission only. - */ - bool firstMCatNLOEmission; - - /** - * Switch on or off final state radiation. - */ - bool doFSR; - - /** - * Switch on or off initial state radiation. - */ - bool doISR; - - /** - * The realignment scheme - */ - int realignmentScheme; - -private: - - /** - * The verbosity level. - * 0 - print no info - * 1 - print diagnostic information on setting up - * splitting generators etc. - * 2 - print detailed event information for up to - * printEvent events. - * 3 - print dipole chains after each splitting. - */ - int verbosity; - - /** - * See verbosity. - */ - int printEvent; - -private: - - /** - * The splitting generators indexed by the dipole - * indices they can work on. - */ - GeneratorMap theGenerators; - - /** - * The evnt record used. - */ - DipoleEventRecord theEventRecord; - - /** - * The number of shoer tries so far. - */ - unsigned int nTries; - - /** - * Whether or not we did radiate anything - */ - bool didRadiate; - - /** - * Whether or not we did realign the event - */ - bool didRealign; - -private: - - /** - * A freezing value for the renormalization scale - */ - Energy theRenormalizationScaleFreeze; - - /** - * A freezing value for the factorization scale - */ - Energy theFactorizationScaleFreeze; - - /** - * True, if we are showering on a MC@NLO S event - */ - bool isMCatNLOSEvent; - - /** - * True, if we are showering on a MC@NLO H event - */ - bool isMCatNLOHEvent; - - /** - * The matching subtraction, if appropriate - */ - Ptr::tptr theShowerApproximation; - - /** - * True, if sampler should apply compensation - */ - bool theDoCompensate; - - /** - * Return the number of accepted points after which the grid should - * be frozen - */ - unsigned long theFreezeGrid; - - /** - * The detuning factor applied to the sampling overestimate kernel - */ - double theDetuning; - - /** - * A pointer to the dipole event reweight object - */ - Ptr::ptr theEventReweight; - - /** - * A pointer to a global dipole splitting reweight - */ - Ptr::ptr theSplittingReweight; - - /** - * True if no warnings have been issued yet - */ - static bool firstWarn; - - /** - * The shower starting scale for the last event encountered - */ - Energy maxPt; - - /** - * The shower hard scale for the last event encountered - */ - Energy muPt; - -private: - - /** - * The static object used to initialize the description of this class. - * Indicates that this is a concrete class with persistent data. - */ - static ClassDescription initDipoleShowerHandler; - - /** - * The assignment operator is private and must never be called. - * In fact, it should not even be implemented. - */ - DipoleShowerHandler & operator=(const DipoleShowerHandler &); - -}; - -} - -#include "ThePEG/Utilities/ClassTraits.h" - -namespace ThePEG { - -/** @cond TRAITSPECIALIZATIONS */ - -/** This template specialization informs ThePEG about the - * base classes of DipoleShowerHandler. */ -template <> -struct BaseClassTrait { - /** Typedef of the first base class of DipoleShowerHandler. */ - typedef Herwig::ShowerHandler NthBase; -}; - -/** This template specialization informs ThePEG about the name of - * the DipoleShowerHandler class and the shared object where it is defined. */ -template <> -struct ClassTraits - : public ClassTraitsBase { - /** Return a platform-independent class name */ - static string className() { return "Herwig::DipoleShowerHandler"; } - /** - * The name of a file containing the dynamic library where the class - * DipoleShowerHandler is implemented. It may also include several, space-separated, - * libraries if the class DipoleShowerHandler depends on other classes (base classes - * excepted). In this case the listed libraries will be dynamically - * linked in the order they are specified. - */ - static string library() { return "HwDipoleShower.so"; } -}; - -/** @endcond */ - -} - -#endif /* HERWIG_DipoleShowerHandler_H */ diff --git a/DipoleShower/Kernels/DipoleSplittingKernel.cc b/DipoleShower/Kernels/DipoleSplittingKernel.cc deleted file mode 100644 --- a/DipoleShower/Kernels/DipoleSplittingKernel.cc +++ /dev/null @@ -1,369 +0,0 @@ -// -*- 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), - 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 << 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 >> theDetuning - >> theFlavour >> theMCCheck >> theStrictLargeN - >> theFactorizationScaleFactor - >> theRenormalizationScaleFactor - >> iunit(theRenormalizationScaleFreeze,GeV) - >> iunit(theFactorizationScaleFreeze,GeV) - >> theVirtualitySplittingScale; -} - -double DipoleSplittingKernel::alphaPDF(const DipoleSplittingInfo& split, - Energy optScale, - double rScaleFactor, - double fScaleFactor) const { - - Energy pt = optScale == ZERO ? split.lastPt() : optScale; - - Energy2 scale = ZERO; - if ( !virtualitySplittingScale() ) { - scale = sqr(pt) + sqr(theScreeningScale); - } else { - scale = sqr(splittingKinematics()->QFromPt(pt,split)) + sqr(theScreeningScale); - } - - Energy2 rScale = sqr(theRenormalizationScaleFactor*rScaleFactor)*scale; - rScale = rScale > sqr(renormalizationScaleFreeze()) ? rScale : sqr(renormalizationScaleFreeze()); - - Energy2 fScale = sqr(theFactorizationScaleFactor*fScaleFactor)*scale; - fScale = fScale > sqr(factorizationScaleFreeze()) ? fScale : sqr(factorizationScaleFreeze()); - - double alphas = 1.0; - double pdf = 1.0; - - // check if we are potentially reweighting and cache evaluations - bool evaluatePDF = true; - bool evaluateAlphaS = true; - bool variations = - !ShowerHandler::currentHandler()->showerVariations().empty() && - !presampling; - if ( variations ) { - /* - 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 ( 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/Kinematics/IFLightKinematics.cc b/DipoleShower/Kinematics/IFLightKinematics.cc deleted file mode 100644 --- a/DipoleShower/Kinematics/IFLightKinematics.cc +++ /dev/null @@ -1,256 +0,0 @@ -// -*- 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(true) {} - -IFLightKinematics::~IFLightKinematics() {} - -IBPtr IFLightKinematics::clone() const { - return new_ptr(*this); -} - -IBPtr IFLightKinematics::fullclone() const { - return new_ptr(*this); -} - -Energy IFLightKinematics::ptMax(Energy dScale, - double emX, double, - const DipoleIndex&, - const DipoleSplittingKernel&) const { - return dScale * sqrt((1.-emX)/emX) /2.; -} - -Energy IFLightKinematics::QMax(Energy, - double, double, - const DipoleIndex&, - const DipoleSplittingKernel&) const { - assert(false && "add this"); - return 0.0*GeV; -} - -Energy IFLightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { - double z = split.lastZ(); - return scale*sqrt(1.-z); -} - -Energy IFLightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { - double z = split.lastZ(); - return scale/sqrt(1.-z); -} - -pair IFLightKinematics::zBoundaries(Energy pt, - const DipoleSplittingInfo& dInfo, - const DipoleSplittingKernel&) const { - double x = dInfo.emitterX(); - double s = sqrt(1.-sqr(pt/dInfo.hardPt())); - return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); -} - - -bool IFLightKinematics::generateSplitting(double kappa, double xi, double rphi, - DipoleSplittingInfo& info, - const DipoleSplittingKernel& split) { - - if ( info.emitterX() < xMin() ) { - jacobian(0.0); - return false; - } - - double weight = 1.0; - - Energy pt = generatePt(kappa,info.scale(), - info.emitterX(),info.spectatorX(), - info.index(),split, - weight); - - if ( pt < IRCutoff() || pt > info.hardPt() ) { - jacobian(0.0); - return false; - } - - double z = 0.0; - - if ( info.index().emitterData()->id() == ParticleID::g ) { - if ( info.emitterData()->id() == ParticleID::g ) { - z = generateZ(xi,pt,OneOverZOneMinusZ, - info,split,weight); - } else { - z = generateZ(xi,pt,OneOverZ, - info,split,weight); - } - } - - if ( info.index().emitterData()->id() != ParticleID::g ) { - if ( info.emitterData()->id() != ParticleID::g ) { - z = generateZ(xi,pt,OneOverOneMinusZ, - info,split,weight); - } else { - z = generateZ(xi,pt,FlatZ, - info,split,weight); - } - } - - if ( weight == 0. && z == -1. ) { - jacobian(0.0); - return false; - } - - double ratio = sqr(pt/info.scale()); - - double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); - if ( rho < 0.0 ) { - jacobian(0.0); - return false; - } - - double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); - double u = 0.5*((1.-z+ratio)/(1.-z))*(1.-sqrt(rho)); - - if ( x < info.emitterX() || x > 1. || - u < 0. || u > 1. ) { - jacobian(0.0); - return false; - } - - double phi = 2.*Constants::pi*rphi; - - jacobian(weight*(1./z)); - - lastPt(pt); - lastZ(z); - lastPhi(phi); - lastEmitterZ(x); - - if ( theMCCheck ) - theMCCheck->book(info.emitterX(),1.,info.scale(),info.hardPt(),pt,z,jacobian()); - - return true; - -} - -void IFLightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, - const Lorentz5Momentum& pSpectator, - const DipoleSplittingInfo& dInfo) { - - Energy pt = dInfo.lastPt(); - double z = dInfo.lastZ(); - - double ratio = sqr(pt)/(2.*pEmitter*pSpectator); - double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); - - double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); - double u = 0.5*((1.-z+ratio)/(1.-z))*(1.-sqrt(rho)); - - Lorentz5Momentum kt = - getKt (pEmitter, pSpectator, pt, dInfo.lastPhi(),true); - - Lorentz5Momentum em; - Lorentz5Momentum emm; - Lorentz5Momentum spe; - - if ( !theCollinearScheme && - x > u && (1.-x)/(x-u) < 1. ) { - - assert(false); - - em = - ((1.-u)/(x-u))*pEmitter + ((u/x)*(1.-x)/(x-u))*pSpectator - kt/(x-u); - em.setMass(0.*GeV); - em.rescaleEnergy(); - - emm = - ((1.-x)/(x-u))*pEmitter + ((u/x)*(1.-u)/(x-u))*pSpectator - kt/(x-u); - emm.setMass(0.*GeV); - emm.rescaleEnergy(); - - spe = - (1.-u/x)*pSpectator; - spe.setMass(0.*GeV); - spe.rescaleEnergy(); - - } else { - - em = (1./x)*pEmitter; - - emm = ((1.-x)*(1.-u)/x)*pEmitter + u*pSpectator + kt; - emm.setMass(0.*GeV); - emm.rescaleEnergy(); - - spe = ((1.-x)*u/x)*pEmitter + (1.-u)*pSpectator - kt; - spe.setMass(0.*GeV); - spe.rescaleEnergy(); - - } - - emitterMomentum(em); - emissionMomentum(emm); - spectatorMomentum(spe); - -} - -// If needed, insert default implementations of function defined -// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). - - -void IFLightKinematics::persistentOutput(PersistentOStream &) const { - //os << theCollinearScheme; -} - -void IFLightKinematics::persistentInput(PersistentIStream &, int) { - //is >> theCollinearScheme; -} - -ClassDescription IFLightKinematics::initIFLightKinematics; -// Definition of the static class description member. - -void IFLightKinematics::Init() { - - static ClassDocumentation documentation - ("IFLightKinematics implements massless splittings " - "off a initial-final dipole."); - - /* - static Switch interfaceCollinearScheme - ("CollinearScheme", - "[experimental] Switch on or off the collinear scheme", - &IFLightKinematics::theCollinearScheme, false, false, false); - static SwitchOption interfaceCollinearSchemeOn - (interfaceCollinearScheme, - "On", - "Switch on the collinear scheme.", - true); - static SwitchOption interfaceCollinearSchemeOff - (interfaceCollinearScheme, - "Off", - "Switch off the collinear scheme", - false); - - interfaceCollinearScheme.rank(-1); - */ - -} - diff --git a/DipoleShower/Kinematics/IFMassiveKinematics.cc b/DipoleShower/Kinematics/IFMassiveKinematics.cc deleted file mode 100644 --- a/DipoleShower/Kinematics/IFMassiveKinematics.cc +++ /dev/null @@ -1,315 +0,0 @@ -// -*- C++ -*- -// -// IFMassiveKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator -// Copyright (C) 2002-2007 The Herwig Collaboration -// -// Herwig is licenced under version 2 of the GPL, see COPYING for details. -// Please respect the MCnet academic guidelines, see GUIDELINES for details. -// -// -// This is the implementation of the non-inlined, non-templated member -// functions of the IFMassiveKinematics class. -// - -#include "IFMassiveKinematics.h" -#include "ThePEG/Interface/ClassDocumentation.h" -#include "ThePEG/Interface/Switch.h" - -#include "ThePEG/Persistency/PersistentOStream.h" -#include "ThePEG/Persistency/PersistentIStream.h" - -#include "ThePEG/Repository/UseRandom.h" -#include "ThePEG/Repository/EventGenerator.h" -#include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" - -using namespace Herwig; - -IFMassiveKinematics::IFMassiveKinematics() - : DipoleSplittingKinematics(), theCollinearScheme(true) {} - -IFMassiveKinematics::~IFMassiveKinematics() {} - -IBPtr IFMassiveKinematics::clone() const { - return new_ptr(*this); -} - -IBPtr IFMassiveKinematics::fullclone() const { - return new_ptr(*this); -} - -pair IFMassiveKinematics::kappaSupport(const DipoleSplittingInfo&) const { - return make_pair(0.0,1.0); -} - -pair IFMassiveKinematics::xiSupport(const DipoleSplittingInfo& split) const { - - double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); - - if ( split.index().emitterData()->id() == ParticleID::g ) { - if ( split.emitterData()->id() == ParticleID::g ) { - double b = log((1.+c)/(1.-c)); - return make_pair(-b,b); - } else { - return make_pair(log(0.5*(1.-c)),log(0.5*(1.+c))); - } - } - - if ( split.index().emitterData()->id() != ParticleID::g && - split.emitterData()->id() != ParticleID::g ) { - return make_pair(-log(0.5*(1.+c)),-log(0.5*(1.-c))); - } - - return make_pair(0.5*(1.-c),0.5*(1.+c)); - -} - -// sbar -Energy IFMassiveKinematics::dipoleScale(const Lorentz5Momentum& pEmitter, - const Lorentz5Momentum& pSpectator) const { - return sqrt(2.*(pEmitter*pSpectator)); -} - -Energy IFMassiveKinematics::ptMax(Energy dScale, - double emX, double, - const DipoleIndex&, - const DipoleSplittingKernel&) const { - return dScale * sqrt(1.-emX) /2.; -} - -Energy IFMassiveKinematics::QMax(Energy, - double, double, - const DipoleIndex&, - const DipoleSplittingKernel&) const { - assert(false && "add this"); - return 0.0*GeV; -} - -Energy IFMassiveKinematics::PtFromQ(Energy, const DipoleSplittingInfo&) const { - assert(false && "add this"); - return 0.0*GeV; -} - -Energy IFMassiveKinematics::QFromPt(Energy, const DipoleSplittingInfo&) const { - assert(false && "add this"); - return 0.0*GeV; -} - - -double IFMassiveKinematics::ptToRandom(Energy pt, Energy, - double,double, - const DipoleIndex&, - const DipoleSplittingKernel&) const { - return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); -} - -bool IFMassiveKinematics::generateSplitting(double kappa, double xi, double rphi, - DipoleSplittingInfo& info, - const DipoleSplittingKernel&) { - - if ( info.emitterX() < xMin() ) { - jacobian(0.0); - return false; - } - - Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); - - if ( sqr(pt) > sqr(info.hardPt())/(1.+4.*sqr(info.hardPt()/info.scale())) ) { - jacobian(0.0); - return false; - } - - double z = 0.; - double mapZJacobian = 0.; - - if ( info.index().emitterData()->id() == ParticleID::g ) { - if ( info.emitterData()->id() == ParticleID::g ) { - z = exp(xi)/(1.+exp(xi)); - mapZJacobian = z*(1.-z); - } else { - z = exp(xi); - mapZJacobian = z; - } - } - - if ( info.index().emitterData()->id() != ParticleID::g ) { - if ( info.emitterData()->id() != ParticleID::g ) { - z = 1.-exp(-xi); - mapZJacobian = 1.-z; - } else { - z = xi; - mapZJacobian = 1.; - } - } - - double ratio = sqr(pt/info.scale()); - - double x = ( z*(1.-z) - ratio ) / ( 1. - z - ratio ); - double u = ratio/(1.-z); - - double up = (1.-x) / - ( 1.-x + x*sqr(info.spectatorData()->mass()/info.scale()) ); - - if ( x < 0. || x > 1. || u > up ) { - jacobian(0.0); - return false; - } - - double xe = info.emitterX(); - double zmx = 0.5*(1.+xe-(1.-xe)*sqrt(1.-sqr(pt/info.hardPt())) ); - double zpx = 0.5*(1.+xe+(1.-xe)*sqrt(1.-sqr(pt/info.hardPt())) ); - - double xq = sqr(pt/info.hardPt()); - double zpq = 0.5*( 1.+ xq + (1.-xq)*sqrt(1.-sqr(2.*pt/info.scale())/(1.-xq) ) ); - double zmq = 0.5*( 1.+ xq - (1.-xq)*sqrt(1.-sqr(2.*pt/info.scale())/(1.-xq) ) ); - - double zp = min(zpx,zpq); - double zm = max(zmx,zmq); - - if ( pt < IRCutoff() || - pt > info.hardPt() || - z > zp || z < zm || - x < xe ) { - jacobian(0.0); - return false; - } - - double phi = 2.*Constants::pi*rphi; - - jacobian(2. * mapZJacobian * log(0.5 * generator()->maximumCMEnergy()/IRCutoff()) * (1.-z-ratio)/sqr(z*(1.-z)-ratio) ); - - lastPt(pt); - lastZ(z); - lastPhi(phi); - lastEmitterZ(x); - - if ( theMCCheck ) - theMCCheck->book(info.emitterX(),1.,info.scale(),info.hardPt(),pt,z,jacobian()); - - return true; - -} - -void IFMassiveKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, - const Lorentz5Momentum& pSpectator, - const DipoleSplittingInfo& dInfo) { - Energy2 sbar = 2.*pEmitter*pSpectator; - Energy pt = dInfo.lastPt(); - double ratio = pt*pt/sbar; - double z = dInfo.lastZ(); - double x = (z*(1.-z)-ratio)/(1.-z-ratio); - double u = ratio / (1.-z); - - pt = sqrt(sbar*u*(1.-u)*(1.-x)); - Energy magKt = - sqrt(sbar*u*(1.-u)*(1.-x)/x - sqr(u*dInfo.spectatorData()->mass())); - Lorentz5Momentum kt = - getKt (pEmitter, pSpectator, magKt, dInfo.lastPhi(),true); - - Lorentz5Momentum em; - Lorentz5Momentum emm; - Lorentz5Momentum spe; - - Energy2 mj2 = dInfo.spectatorData()->mass()*dInfo.spectatorData()->mass(); - double alpha = 1. - 2.*mj2/sbar; - - // TODO: adjust phasespace boundary condition - if (!theCollinearScheme) - assert(false); - if ( !theCollinearScheme && - x > u && (1.-x)/(x-u) < 1. ) { - - double fkt = sqrt(sqr(x-u)+4.*x*u*mj2/sbar); - - // em = - // ((1.-u)/(x-u))*pEmitter + ((u/x)*(1.-x)/(x-u))*pSpectator - kt/(x-u); - Energy2 fa = (sbar*(x+u-2.*x*z)+2.*mj2*x*u) / sqrt(sqr(x-u)+4.*x*u*mj2/sbar); - double a = (-sbar+fa) / (2.*x*(sbar-mj2)); - double ap = (sbar+alpha*fa) / (2.*x*(sbar-mj2)); - em = ap*pEmitter + a*pSpectator - fkt*kt; - em.setMass(ZERO); - em.rescaleEnergy(); - - // emm = - // ((1.-x)/(x-u))*pEmitter + ((u/x)*(1.-u)/(x-u))*pSpectator - kt/(x-u); - Energy2 fb = abs(sbar*(u*(1.-u)-x*(1.-x))+2.*mj2*x*u) / sqrt(sqr(x-u)+4.*x*u*mj2/sbar); - double b = (-sbar*(1.-x-u)+fb) / (2.*x*(sbar-mj2)); - double bp = (sbar*(1.-x-u)+alpha*fb) / (2.*x*(sbar-mj2)); - emm = bp*pEmitter + b*pSpectator + fkt*kt; - emm.setMass(ZERO); - emm.rescaleEnergy(); - - // spe = - // (1.-u/x)*pSpectator; - Energy2 fc = sqrt(sqr(sbar*(x-u))+4.*sbar*mj2*x*u); - double c = (sbar*(x-u)-2.*x*mj2+fc) / (2.*x*(sbar-mj2)); - double cp = (-sbar*(x-u)+2.*x*mj2+alpha*fc) / (2.*x*(sbar-mj2)); - spe = cp*pEmitter + c*pSpectator; - spe.setMass(dInfo.spectatorData()->mass()); - spe.rescaleEnergy(); - - } else { - - em = (1./x)*pEmitter; - em.setMass(ZERO); - em.rescaleEnergy(); - - emm = (-kt*kt-u*u*mj2)/(u*sbar)*pEmitter + - u*pSpectator - kt; - emm.setMass(ZERO); - emm.rescaleEnergy(); - - spe = (-kt*kt + mj2*u*(2.-u))/((1.-u)*sbar)*pEmitter + - (1.-u)*pSpectator + kt; - spe.setMass(dInfo.spectatorData()->mass()); - spe.rescaleEnergy(); - - } - - emitterMomentum(em); - emissionMomentum(emm); - spectatorMomentum(spe); - -} - -// If needed, insert default implementations of function defined -// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). - - -void IFMassiveKinematics::persistentOutput(PersistentOStream &) const { - //os << theCollinearScheme; -} - -void IFMassiveKinematics::persistentInput(PersistentIStream &, int) { - //is >> theCollinearScheme; -} - -ClassDescription IFMassiveKinematics::initIFMassiveKinematics; -// Definition of the static class description member. - -void IFMassiveKinematics::Init() { - - static ClassDocumentation documentation - ("IFMassiveKinematics implements massless splittings " - "off a initial-final dipole."); - - /* - static Switch interfaceCollinearScheme - ("CollinearScheme", - "[experimental] Switch on or off the collinear scheme", - &IFMassiveKinematics::theCollinearScheme, false, false, false); - static SwitchOption 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 deleted file mode 100644 --- a/DipoleShower/Kinematics/IILightKinematics.cc +++ /dev/null @@ -1,290 +0,0 @@ -// -*- 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(true), didCollinear(false) {} - -IILightKinematics::~IILightKinematics() {} - -IBPtr IILightKinematics::clone() const { - return new_ptr(*this); -} - -IBPtr IILightKinematics::fullclone() const { - return new_ptr(*this); -} - -Energy IILightKinematics::ptMax(Energy dScale, - double emX, double specX, - const DipoleIndex&, - const DipoleSplittingKernel&) const { - double tau = - !theCollinearScheme ? emX*specX : emX; - return (1.-tau) * dScale / (2.*sqrt(tau)); -} - -Energy IILightKinematics::QMax(Energy, - double, double, - const DipoleIndex&, - const DipoleSplittingKernel&) const { - assert(false && "add this"); - return 0.0*GeV; -} - -Energy IILightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { - double z = split.lastZ(); - return scale*sqrt(1.-z); -} - -Energy IILightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { - double z = split.lastZ(); - return scale/sqrt(1.-z); -} - -pair IILightKinematics::zBoundaries(Energy pt, - const DipoleSplittingInfo& dInfo, - const DipoleSplittingKernel&) const { - double x = - !theCollinearScheme ? - dInfo.emitterX()*dInfo.spectatorX() : - dInfo.emitterX(); - double s = sqrt(1.-sqr(pt/dInfo.hardPt())); - return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); -} - -bool IILightKinematics::generateSplitting(double kappa, double xi, double rphi, - DipoleSplittingInfo& info, - const DipoleSplittingKernel& split) { - - if ( info.emitterX() < xMin() || - info.spectatorX() < xMin() ) { - jacobian(0.0); - return false; - } - - double weight = 1.0; - - Energy pt = generatePt(kappa,info.scale(), - info.emitterX(),info.spectatorX(), - info.index(),split, - weight); - - if ( pt < IRCutoff() || pt > info.hardPt() ) { - jacobian(0.0); - return false; - } - - double z = 0.0; - - if ( info.index().emitterData()->id() == ParticleID::g ) { - if ( info.emitterData()->id() == ParticleID::g ) { - z = generateZ(xi,pt,OneOverZOneMinusZ, - info,split,weight); - } else { - z = generateZ(xi,pt,OneOverZ, - info,split,weight); - } - } - - if ( info.index().emitterData()->id() != ParticleID::g ) { - if ( info.emitterData()->id() != ParticleID::g ) { - z = generateZ(xi,pt,OneOverOneMinusZ, - info,split,weight); - } else { - z = generateZ(xi,pt,FlatZ, - info,split,weight); - } - } - - if ( weight == 0. && z == -1. ) { - jacobian(0.0); - return false; - } - - double ratio = sqr(pt/info.scale()); - - double x = z*(1.-z)/(1.-z+ratio); - double v = ratio*z /(1.-z+ratio); - - if ( x < 0. || x > 1. || v < 0. || v > 1.-x ) { - jacobian(0.0); - return false; - } - - if ( !theCollinearScheme && - (1.-v-x)/(v+x) < 1. ) { - if ( (x+v) < info.emitterX() || - x/(x+v) < info.spectatorX() ) { - jacobian(0.0); - return false; - } - } else { - if ( x < info.emitterX() ) { - jacobian(0.0); - return false; - } - } - - double phi = 2.*Constants::pi*rphi; - - jacobian(weight*(1./z)); - - lastPt(pt); - lastZ(z); - lastPhi(phi); - - if ( !theCollinearScheme && - (1.-v-x)/(v+x) < 1. ) { - lastEmitterZ(x+v); - lastSpectatorZ(x/(x+v)); - } else { - lastEmitterZ(x); - lastSpectatorZ(1.); - } - - if ( theMCCheck ) - theMCCheck->book(info.emitterX(),info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); - - return true; - -} - -void IILightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, - const Lorentz5Momentum& pSpectator, - const DipoleSplittingInfo& dInfo) { - - Energy pt = dInfo.lastPt(); - double z = dInfo.lastZ(); - - double ratio = sqr(pt)/(2.*pEmitter*pSpectator); - - double x = z*(1.-z)/(1.-z+ratio); - double v = ratio*z /(1.-z+ratio); - - Lorentz5Momentum kt = - getKt (pEmitter, pSpectator, pt, dInfo.lastPhi()); - - if ( !theCollinearScheme && - (1.-v-x)/(v+x) < 1. ) { - - assert(false); - - Lorentz5Momentum em = - (1./(v+x))*pEmitter+(v*(1.-v-x)/(x*(x+v)))*pSpectator+kt/(x+v); - em.setMass(0.*GeV); - em.rescaleEnergy(); - - Lorentz5Momentum emm = - ((1.-v-x)/(v+x))*pEmitter+(v/(x*(x+v)))*pSpectator+kt/(x+v); - emm.setMass(0.*GeV); - emm.rescaleEnergy(); - - Lorentz5Momentum spe = - (1.+v/x)*pSpectator; - spe.setMass(0.*GeV); - spe.rescaleEnergy(); - - emitterMomentum(em); - emissionMomentum(emm); - spectatorMomentum(spe); - - didCollinear = false; - - } else { - - Lorentz5Momentum em = - (1./x)*pEmitter; - em.setMass(0.*GeV); - em.rescaleEnergy(); - - Lorentz5Momentum emm = - ((1.-x-v)/x)*pEmitter+v*pSpectator+kt; - emm.setMass(0.*GeV); - emm.rescaleEnergy(); - - Lorentz5Momentum spe = - pSpectator; - - emitterMomentum(em); - emissionMomentum(emm); - spectatorMomentum(spe); - - K = em + spe - emm; - K2 = K.m2(); - - Ktilde = pEmitter + pSpectator; - KplusKtilde = K + Ktilde; - - KplusKtilde2 = KplusKtilde.m2(); - - didCollinear = true; - - } - -} - -// If needed, insert default implementations of function defined -// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). - - -void IILightKinematics::persistentOutput(PersistentOStream &) const { - //os << theCollinearScheme; -} - -void IILightKinematics::persistentInput(PersistentIStream &, 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 deleted file mode 100644 --- a/DipoleShower/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -SUBDIRS = Base Kernels Kinematics Utility AlphaS - -pkglib_LTLIBRARIES = HwDipoleShower.la - -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.fh DipoleShowerHandler.cc diff --git a/Makefile.am b/Makefile.am --- a/Makefile.am +++ b/Makefile.am @@ -1,29 +1,29 @@ SUBDIRS = include \ Utilities PDT Decay PDF Models \ - Shower DipoleShower Hadronization MatrixElement \ + Shower Hadronization MatrixElement \ UnderlyingEvent Analysis Looptools Sampling \ lib src Doc Contrib Tests EXTRA_DIST = GUIDELINES ## DISTCHECK_CONFIGURE_FLAGS = --enable-debug --with-thepeg=$(THEPEGPATH) --with-gsl=$(GSLPATH) ACLOCAL_AMFLAGS = -I m4 DISTCLEANFILES = config.herwig libclean: find . -name '*.la' -print0 | xargs -0 rm -rf cd lib && $(MAKE) $(AM_MAKEFLAGS) clean cd src && $(MAKE) $(AM_MAKEFLAGS) clean tests: cd Tests && $(MAKE) $(AM_MAKEFLAGS) tests ## ThePEG registration unregister: cd src && $(MAKE) $(AM_MAKEFLAGS) unregister register: cd src && $(MAKE) $(AM_MAKEFLAGS) register diff --git a/MatrixElement/DIS/DISBase.cc b/MatrixElement/DIS/DISBase.cc --- a/MatrixElement/DIS/DISBase.cc +++ b/MatrixElement/DIS/DISBase.cc @@ -1,1359 +1,1180 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the DISBase class. // #include "DISBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/Utilities/Maths.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" #include "Herwig/PDT/StandardMatchers.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/Branching.h" -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" using namespace Herwig; using namespace ThePEG::Helicity; // namespace { // using namespace Herwig; // using namespace ThePEG::Helicity; // // void debuggingMatrixElement(bool BGF,const Lorentz5Momentum & pin, // const Lorentz5Momentum & p1, // const Lorentz5Momentum & p2, // tcPDPtr gluon, // const Lorentz5Momentum & pl1, // const Lorentz5Momentum & pl2, // const Lorentz5Momentum & pq1, // const Lorentz5Momentum & pq2, // tcPDPtr lepton1,tcPDPtr lepton2, // tcPDPtr quark1 ,tcPDPtr quark2, // Energy2 Q2,double phi, double x2, double x3, // double xperp, double zp, double xp, // const vector & azicoeff, // bool normalize) { // tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast // (CurrentGenerator::current().standardModel()); // assert(hwsm); // vector weakVertex; // vector bosons; // AbstractFFVVertexPtr strongVertex = hwsm->vertexFFG(); // if(lepton1->id()==lepton2->id()) { // weakVertex.push_back(hwsm->vertexFFZ()); // bosons.push_back(hwsm->getParticleData(ParticleID::Z0)); // weakVertex.push_back(hwsm->vertexFFP()); // bosons.push_back(hwsm->getParticleData(ParticleID::gamma)); // } // else { // weakVertex.push_back(hwsm->vertexFFW()); // bosons.push_back(hwsm->getParticleData(ParticleID::Wplus)); // } // if(!BGF) { // SpinorWaveFunction l1,q1,qp1; // SpinorBarWaveFunction l2,q2,qp2; // VectorWaveFunction gl(p2,gluon,outgoing); // if(lepton1->id()>0) { // l1 = SpinorWaveFunction (pl1,lepton1,incoming); // l2 = SpinorBarWaveFunction(pl2,lepton2,outgoing); // } // else { // l1 = SpinorWaveFunction (pl2,lepton2,outgoing); // l2 = SpinorBarWaveFunction(pl1,lepton1,incoming); // } // if(quark1->id()>0) { // q1 = SpinorWaveFunction (pq1,quark1,incoming); // q2 = SpinorBarWaveFunction(pq2,quark2,outgoing); // qp1 = SpinorWaveFunction (pin,quark1,incoming); // qp2 = SpinorBarWaveFunction(p1 ,quark2,outgoing); // } // else { // q1 = SpinorWaveFunction (pq2,quark2,outgoing); // q2 = SpinorBarWaveFunction(pq1,quark1,incoming); // qp1 = SpinorWaveFunction (p1 ,quark2,outgoing); // qp2 = SpinorBarWaveFunction(pin,quark1,incoming); // } // double lome(0.),realme(0.); // for(unsigned int lhel1=0;lhel1<2;++lhel1) { // l1.reset(lhel1); // for(unsigned int lhel2=0;lhel2<2;++lhel2) { // l2.reset(lhel2); // for(unsigned int qhel1=0;qhel1<2;++qhel1) { // q1.reset(qhel1); // qp1.reset(qhel1); // for(unsigned int qhel2=0;qhel2<2;++qhel2) { // q2.reset(qhel2); // qp2.reset(qhel2); // // leading order matrix element // Complex diagLO(0.); // for(unsigned int ix=0;ixevaluate(Q2,3,bosons[ix],l1,l2); // diagLO += weakVertex[ix]->evaluate(Q2,q1,q2,inter); // } // lome += norm(diagLO); // // real emission matrix element // for(unsigned int ghel=0;ghel<2;++ghel) { // gl.reset(2*ghel); // Complex diagReal(0.); // for(unsigned int ix=0;ixevaluate(Q2,3,bosons[ix],l1,l2); // SpinorWaveFunction off1 = // strongVertex->evaluate(Q2,5,qp1.particle(),qp1,gl); // Complex diag1 = weakVertex[ix]->evaluate(Q2,off1,qp2,inter); // SpinorBarWaveFunction off2 = // strongVertex->evaluate(Q2,5,qp2.particle(),qp2,gl); // Complex diag2 = weakVertex[ix]->evaluate(Q2,qp1,off2,inter); // diagReal += diag1+diag2; // } // realme += norm(diagReal); // } // } // } // } // } // double test1 = realme/lome/hwsm->alphaS(Q2)*Q2*UnitRemoval::InvE2; // double cphi(cos(phi)); // double test2; // if(normalize) { // test2 = 8.*Constants::pi/(1.-xp)/(1.-zp)* // (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi))* // (1.+sqr(xp)*(sqr(x2)+1.5*sqr(xperp))); // } // else { // test2 = 8.*Constants::pi/(1.-xp)/(1.-zp)* // (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi)); // } // cerr << "testing RATIO A " << test1/test2 << "\n"; // } // else { // SpinorWaveFunction l1,q1,qp1; // SpinorBarWaveFunction l2,q2,qp2; // VectorWaveFunction gl(pin,gluon,incoming); // if(lepton1->id()>0) { // l1 = SpinorWaveFunction (pl1,lepton1,incoming); // l2 = SpinorBarWaveFunction(pl2,lepton2,outgoing); // } // else { // l1 = SpinorWaveFunction (pl2,lepton2,outgoing); // l2 = SpinorBarWaveFunction(pl1,lepton1,incoming); // } // if(quark1->id()>0) { // q1 = SpinorWaveFunction (pq1,quark1 ,incoming); // q2 = SpinorBarWaveFunction(pq2,quark2 ,outgoing); // qp2 = SpinorBarWaveFunction(p1 ,quark2 ,outgoing); // qp1 = SpinorWaveFunction (p2 ,quark1->CC(),outgoing); // } // else { // q1 = SpinorWaveFunction (pq2,quark2 ,outgoing); // q2 = SpinorBarWaveFunction(pq1,quark1 ,incoming); // qp2 = SpinorBarWaveFunction(p2 ,quark1->CC(),outgoing); // qp1 = SpinorWaveFunction (p1 ,quark2 ,outgoing); // } // double lome(0.),realme(0.); // for(unsigned int lhel1=0;lhel1<2;++lhel1) { // l1.reset(lhel1); // for(unsigned int lhel2=0;lhel2<2;++lhel2) { // l2.reset(lhel2); // for(unsigned int qhel1=0;qhel1<2;++qhel1) { // q1.reset(qhel1); // qp1.reset(qhel1); // for(unsigned int qhel2=0;qhel2<2;++qhel2) { // q2.reset(qhel2); // qp2.reset(qhel2); // // leading order matrix element // Complex diagLO(0.); // for(unsigned int ix=0;ixevaluate(Q2,3,bosons[ix],l1,l2); // diagLO += weakVertex[ix]->evaluate(Q2,q1,q2,inter); // } // lome += norm(diagLO); // // real emission matrix element // for(unsigned int ghel=0;ghel<2;++ghel) { // gl.reset(2*ghel); // Complex diagReal(0.); // for(unsigned int ix=0;ixevaluate(Q2,3,bosons[ix],l1,l2); // SpinorWaveFunction off1 = // strongVertex->evaluate(Q2,5,qp1.particle(),qp1,gl); // Complex diag1 = weakVertex[ix]->evaluate(Q2,off1,qp2,inter); // SpinorBarWaveFunction off2 = // strongVertex->evaluate(Q2,5,qp2.particle(),qp2,gl); // Complex diag2 = weakVertex[ix]->evaluate(Q2,qp1,off2,inter); // diagReal += diag1+diag2; // } // realme += norm(diagReal); // } // } // } // } // } // double test1 = realme/lome/hwsm->alphaS(Q2)*Q2*UnitRemoval::InvE2; // double cphi(cos(phi)); // double test2; // if(normalize) { // test2 = 8.*Constants::pi/zp/(1.-zp)* // (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi))* // sqr(xp)*(sqr(x3)+sqr(x2)+3.*sqr(xperp)); // } // else { // test2 = 8.*Constants::pi/zp/(1.-zp)* // (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi)); // } // cerr << "testing RATIO B " << test1/test2 << "\n"; // } // } // // } DISBase::DISBase() : initial_(6.), final_(3.), procProb_(0.35), comptonInt_(0.), bgfInt_(0.), comptonWeight_(50.), BGFWeight_(150.), pTmin_(0.1*GeV), scaleOpt_(1), muF_(100.*GeV), scaleFact_(1.), contrib_(0), power_(0.1) {} DISBase::~DISBase() {} void DISBase::persistentOutput(PersistentOStream & os) const { os << comptonInt_ << bgfInt_ << procProb_ << initial_ << final_ << alpha_ << ounit(pTmin_,GeV) << comptonWeight_ << BGFWeight_ << gluon_ << ounit(muF_,GeV) << scaleFact_ << scaleOpt_ << contrib_<< power_; } void DISBase::persistentInput(PersistentIStream & is, int) { is >> comptonInt_ >> bgfInt_ >> procProb_ >> initial_ >> final_ >> alpha_ >> iunit(pTmin_,GeV) >> comptonWeight_ >> BGFWeight_ >> gluon_ >> iunit(muF_,GeV) >> scaleFact_ >> scaleOpt_ >> contrib_ >> power_; } AbstractClassDescription DISBase::initDISBase; // Definition of the static class description member. void DISBase::Init() { static ClassDocumentation documentation ("The DISBase class provides the base class for the " "implementation of DIS type processes including the " "hard corrections in either the old-fashioned matrix " "element correction of POWHEG approaches"); static Parameter interfaceProcessProbability ("ProcessProbability", "The probabilty of the QCD compton process for the process selection", &DISBase::procProb_, 0.3, 0.0, 1., false, false, Interface::limited); static Reference interfaceCoupling ("Coupling", "Pointer to the object to calculate the coupling for the correction", &DISBase::alpha_, false, false, true, false, false); static Parameter interfacepTMin ("pTMin", "The minimum pT", &DISBase::pTmin_, GeV, 1.*GeV, 0.0*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceComptonWeight ("ComptonWeight", "Weight for the overestimate ofthe compton channel", &DISBase::comptonWeight_, 50.0, 0.0, 100.0, false, false, Interface::limited); static Parameter interfaceBGFWeight ("BGFWeight", "Weight for the overestimate of the BGF channel", &DISBase::BGFWeight_, 100.0, 0.0, 1000.0, false, false, Interface::limited); static Switch interfaceContribution ("Contribution", "Which contributions to the cross section to include", &DISBase::contrib_, 0, false, false); static SwitchOption interfaceContributionLeadingOrder (interfaceContribution, "LeadingOrder", "Just generate the leading order cross section", 0); static SwitchOption interfaceContributionPositiveNLO (interfaceContribution, "PositiveNLO", "Generate the positive contribution to the full NLO cross section", 1); static SwitchOption interfaceContributionNegativeNLO (interfaceContribution, "NegativeNLO", "Generate the negative contribution to the full NLO cross section", 2); static Switch interfaceScaleOption ("ScaleOption", "Option for the choice of factorization (and renormalization) scale", &DISBase::scaleOpt_, 1, false, false); static SwitchOption interfaceDynamic (interfaceScaleOption, "Dynamic", "Dynamic factorization scale equal to the current sqrt(sHat())", 1); static SwitchOption interfaceFixed (interfaceScaleOption, "Fixed", "Use a fixed factorization scale set with FactorizationScaleValue", 2); static Parameter interfaceFactorizationScale ("FactorizationScale", "Value to use in the event of a fixed factorization scale", &DISBase::muF_, GeV, 100.0*GeV, 1.0*GeV, 500.0*GeV, true, false, Interface::limited); static Parameter interfaceScaleFactor ("ScaleFactor", "The factor used before Q2 if using a running scale", &DISBase::scaleFact_, 1.0, 0.0, 10.0, false, false, Interface::limited); static Parameter interfaceSamplingPower ("SamplingPower", "Power for the sampling of xp", &DISBase::power_, 0.6, 0.0, 1., false, false, Interface::limited); } void DISBase::doinit() { HwMEBase::doinit(); // integrals of me over phase space double r5=sqrt(5.),darg((r5-1.)/(r5+1.)),ath(0.5*log((1.+1./r5)/(1.-1./r5))); comptonInt_ = 2.*(-21./20.-6./(5.*r5)*ath+sqr(Constants::pi)/3. -2.*Math::ReLi2(1.-darg)-2.*Math::ReLi2(1.-1./darg)); bgfInt_ = 121./9.-56./r5*ath; // extract the gluon ParticleData objects gluon_ = getParticleData(ParticleID::g); } -void DISBase::initializeMECorrection(ShowerTreePtr tree, double & initial, +void DISBase::initializeMECorrection(RealEmissionProcessPtr born, double & initial, double & final) { initial = initial_; final = final_; // incoming particles - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) { - partons_[0] = cit->first->progenitor()->dataPtr(); - pq_[0] = cit->first->progenitor()->momentum(); + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) { + partons_[0] = born->bornIncoming()[ix]->dataPtr(); + pq_[0] = born->bornIncoming()[ix]->momentum(); } - else if(LeptonMatcher::Check(cit->first->progenitor()->data())) { - leptons_[0] = cit->first->progenitor()->dataPtr(); - pl_[0] = cit->first->progenitor()->momentum(); + else if(LeptonMatcher::Check(born->bornIncoming()[ix]->data())) { + leptons_[0] = born->bornIncoming()[ix]->dataPtr(); + pl_[0] = born->bornIncoming()[ix]->momentum(); } } // outgoing particles - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) { - partons_[1] = cit->first->progenitor()->dataPtr(); - pq_[1] = cit->first->progenitor()->momentum(); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data())) { + partons_[1] = born->bornOutgoing()[ix]->dataPtr(); + pq_[1] = born->bornOutgoing()[ix]->momentum(); } - else if(LeptonMatcher::Check(cit->first->progenitor()->data())) { - leptons_[1] = cit->first->progenitor()->dataPtr(); - pl_[1] = cit->first->progenitor()->momentum(); + else if(LeptonMatcher::Check(born->bornOutgoing()[ix]->data())) { + leptons_[1] = born->bornOutgoing()[ix]->dataPtr(); + pl_[1] = born->bornOutgoing()[ix]->momentum(); } } // extract the born variables q_ =pl_[0]-pl_[1]; q2_ = -q_.m2(); double yB = (q_*pq_[0])/(pl_[0]*pq_[0]); l_ = 2./yB-1.; // calculate the A coefficient for the correlations acoeff_ = A(leptons_[0],leptons_[1], - partons_[0],partons_[1],q2_); + partons_[0],partons_[1],q2_); } -void DISBase::applyHardMatrixElementCorrection(ShowerTreePtr tree) { +RealEmissionProcessPtr DISBase::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { static const double eps=1e-6; // find the incoming and outgoing quarks and leptons - ShowerParticlePtr quark[2],lepton[2]; + PPtr quark[2],lepton[2]; PPtr hadron; + unsigned int iqIn(0),iqOut(0); // incoming particles - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) { - hadron = cit->first->original()->parents()[0]; - quark [0] = cit->first->progenitor(); - beam_ = cit->first->beam(); + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) { + iqIn=ix; + quark[0] = born->bornIncoming()[ix]; + hadron = born->hadrons()[ix]; + beam_ = dynamic_ptr_cast(hadron->dataPtr()); + xB_ = quark[0]->momentum().rho()/hadron->momentum().rho(); } - else if(LeptonMatcher::Check(cit->first->progenitor()->data())) { - lepton[0] = cit->first->progenitor(); + else if(LeptonMatcher::Check(born->bornIncoming()[ix]->data())) { + lepton[0] = born->bornIncoming()[ix]; } } pdf_ = beam_->pdf(); assert(beam_&&pdf_&&quark[0]&&lepton[0]); // outgoing particles - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) - quark [1] = cit->first->progenitor(); - else if(LeptonMatcher::Check(cit->first->progenitor()->data())) { - lepton[1] = cit->first->progenitor(); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data())) { + iqOut=ix; + quark [1] = born->bornOutgoing()[ix]; + } + else if(LeptonMatcher::Check(born->bornOutgoing()[ix]->data())) { + lepton[1] = born->bornOutgoing()[ix]; } } // momentum fraction assert(quark[1]&&lepton[1]); - xB_ = quark[0]->x(); // calculate the matrix element vector azicoeff; // select the type of process bool BGF = UseRandom::rnd()>procProb_; double xp,zp,wgt,x1,x2,x3,xperp; // generate a QCD compton process if(!BGF) { wgt = generateComptonPoint(xp,zp); - if(xpvalue(scale)/procProb_; // PDF piece wgt *= pdf_->xfx(beam_,quark[0]->dataPtr(),scale,xB_/xp)/ pdf_->xfx(beam_,quark[0]->dataPtr(),q2_ ,xB_); // other bits xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); x1 = -1./xp; x2 = 1.-(1.-zp)/xp; x3 = 2.+x1-x2; // matrix element pieces azicoeff = ComptonME(xp,x2,xperp,true); } // generate a BGF process else { wgt = generateBGFPoint(xp,zp); - if(xpvalue(scale)/(1.-procProb_); // PDF piece wgt *= pdf_->xfx(beam_,gluon_ ,scale,xB_/xp)/ pdf_->xfx(beam_,quark[0]->dataPtr(),q2_ ,xB_); // other bits xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); x1 = -1./xp; x2 = 1.-(1.-zp)/xp; x3 = 2.+x1-x2; // matrix element pieces azicoeff = BGFME(xp,x2,x3,xperp,true); } // compute the azimuthal average of the weight wgt *= (azicoeff[0]+0.5*azicoeff[2]); // decide whether or not to accept the weight - if(UseRandom::rnd()>wgt) return; + if(UseRandom::rnd()>wgt) return RealEmissionProcessPtr(); // if generate generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)); phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in DISMECorrection" << "::applyHardMatrixElementCorrection() to" << " generate phi" << Exception::eventerror; // construct lorentz transform from lab to breit frame Lorentz5Momentum phadron = hadron->momentum(); phadron.setMass(0.*GeV); phadron.rescaleEnergy(); Lorentz5Momentum pcmf = phadron+0.5/xB_*q_; pcmf.rescaleMass(); LorentzRotation rot(-pcmf.boostVector()); Lorentz5Momentum pbeam = rot*phadron; Axis axis(pbeam.vect().unit()); double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); Lorentz5Momentum pl = rot*pl_[0]; rot.rotateZ(-atan2(pl.y(),pl.x())); pl_[0] *= rot; pl_[1] *= rot; pq_[0] *= rot; pq_[1] *= rot; // compute the new incoming and outgoing momenta Energy Q(sqrt(q2_)); Lorentz5Momentum p1 = Lorentz5Momentum( 0.5*Q*xperp*cos(phi), 0.5*Q*xperp*sin(phi), -0.5*Q*x2,0.*GeV,0.*GeV); p1.rescaleEnergy(); Lorentz5Momentum p2 = Lorentz5Momentum(-0.5*Q*xperp*cos(phi),-0.5*Q*xperp*sin(phi), -0.5*Q*x3,0.*GeV,0.*GeV); p2.rescaleEnergy(); Lorentz5Momentum pin(0.*GeV,0.*GeV,-0.5*x1*Q,-0.5*x1*Q,0.*GeV); // debuggingMatrixElement(BGF,pin,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1], // lepton[0]->dataPtr(),lepton[1]->dataPtr(), // quark [0]->dataPtr(),quark [1]->dataPtr(), // q2_,phi,x2,x3,xperp,zp,xp,azicoeff,true); // we need the Lorentz transform back to the lab rot.invert(); // transform the momenta to lab frame pin *= rot; p1 *= rot; p2 *= rot; // test to ensure outgoing particles can be put on-shell if(!BGF) { - if(p1.e()dataPtr()->constituentMass()) return; - if(p2.e()constituentMass()) return; + if(p1.e()dataPtr()->constituentMass()) return RealEmissionProcessPtr(); + if(p2.e()constituentMass()) return RealEmissionProcessPtr(); } else { - if(p1.e()dataPtr() ->constituentMass()) return; - if(p2.e()dataPtr()->CC()->constituentMass()) return; + if(p1.e()dataPtr() ->constituentMass()) return RealEmissionProcessPtr(); + if(p2.e()dataPtr()->CC()->constituentMass()) return RealEmissionProcessPtr(); } - // create the new particles and add to ShowerTree - bool isquark = quark[0]->colourLine(); + // create the new particles and real emission process + bool isQuark = quark[0]->colourLine(); + bool FSR = false; + // incoming lepton if first + if(iqIn==1) + born->incoming().push_back(born->bornIncoming()[0]->dataPtr()-> + produceParticle(born->bornIncoming()[0]->momentum())); + // outgoing lepton if first + if(iqOut==1) + born->outgoing().push_back(born->bornOutgoing()[0]->dataPtr()-> + produceParticle(born->bornOutgoing()[0]->momentum())); + PPtr newin,newout,emitted; + // radiating system if(!BGF) { - PPtr newin = new_ptr(Particle(*quark[0])); - newin->set5Momentum(pin); - PPtr newg = gluon_ ->produceParticle(p2 ); - PPtr newout = quark[1]->dataPtr()->produceParticle(p1 ); - ColinePtr col=isquark ? - quark[0]->colourLine() : quark[0]->antiColourLine(); - ColinePtr newline=new_ptr(ColourLine()); - // final-state emission - if(xp>zp) { - col->removeColoured(newout,!isquark); - col->addColoured(newin,!isquark); - col->addColoured(newg,!isquark); - newline->addColoured(newg,isquark); - newline->addColoured(newout,!isquark); - } - // initial-state emission - else { - col->removeColoured(newin ,!isquark); - col->addColoured(newout,!isquark); - col->addColoured(newg,isquark); - newline->addColoured(newg,!isquark); - newline->addColoured(newin,!isquark); - } - PPtr orig; - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(cit->first->progenitor()!=quark[0]) continue; - // remove old particles from colour line - col->removeColoured(cit->first->copy(),!isquark); - col->removeColoured(cit->first->progenitor(),!isquark); - // insert new particles - cit->first->copy(newin); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newin,1,false))); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - sp->x(xB_/xp); - cit->first->perturbative(xp>zp); - if(xp<=zp) orig=cit->first->original(); - } - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(cit->first->progenitor()!=quark[1]) continue; - // remove old particles from colour line - col->removeColoured(cit->first->copy(),!isquark); - col->removeColoured(cit->first->progenitor(),!isquark); - // insert new particles - cit->first->copy(newout); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newout,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(xp<=zp); - if(xp>zp) orig=cit->first->original(); - } - assert(orig); - // add the gluon - ShowerParticlePtr sg=new_ptr(ShowerParticle(*newg,1,true)); - ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg)); - gluon->perturbative(false); - tree->outgoingLines().insert(make_pair(gluon,sg)); - tree->hardMatrixElementCorrection(true); + newin = quark[0]->dataPtr()->produceParticle(pin); + emitted = gluon_ ->produceParticle(p2 ); + newout = quark[1]->dataPtr()->produceParticle(p1 ); + emitted->incomingColour(newin,!isQuark); + emitted->colourConnect(newout,!isQuark); + FSR = xp>zp; } else { - PPtr newin = gluon_ ->produceParticle(pin); - PPtr newqbar = quark[0]->dataPtr()->CC()->produceParticle(p2 ); - PPtr newout = quark[1]->dataPtr() ->produceParticle(p1 ); - ColinePtr col=isquark ? quark[0]->colourLine() : quark[0]->antiColourLine(); - ColinePtr newline=new_ptr(ColourLine()); - col ->addColoured(newin ,!isquark); - newline->addColoured(newin , isquark); - col ->addColoured(newout ,!isquark); - newline->addColoured(newqbar, isquark); - PPtr orig; - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(cit->first->progenitor()!=quark[0]) continue; - // remove old particles from colour line - col->removeColoured(cit->first->copy(),!isquark); - col->removeColoured(cit->first->progenitor(),!isquark); - // insert new particles - cit->first->copy(newin); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newin,1,false))); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - sp->x(xB_/xp); - cit->first->perturbative(false); - orig=cit->first->original(); - } - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(cit->first->progenitor()!=quark[1]) continue; - // remove old particles from colour line - col->removeColoured(cit->first->copy(),!isquark); - col->removeColoured(cit->first->progenitor(),!isquark); - // insert new particles - cit->first->copy(newout); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newout,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(true); - } - assert(orig); - // add the (anti)quark - ShowerParticlePtr sqbar=new_ptr(ShowerParticle(*newqbar,1,true)); - ShowerProgenitorPtr qbar=new_ptr(ShowerProgenitor(orig,newqbar,sqbar)); - qbar->perturbative(false); - tree->outgoingLines().insert(make_pair(qbar,sqbar)); - tree->hardMatrixElementCorrection(true); + newin = gluon_ ->produceParticle(pin); + emitted = quark[0]->dataPtr()->CC()->produceParticle(p2 ); + newout = quark[1]->dataPtr() ->produceParticle(p1 ); + emitted->incomingColour(newin, isQuark); + newout ->incomingColour(newin,!isQuark); + FSR = false; } + // set x + double x(xB_/xp); + if(born->incoming().size()==0) + born->x(make_pair(x,1.)); + else + born->x(make_pair(1.,x)); + if(FSR) { + born->emitter(born->outgoing().size()+2); + born->spectator(born->incoming().size()); + } + else { + born->emitter(born->incoming().size()); + born->spectator(born->outgoing().size()+2); + } + born->emitted(4); + // radiating particles + born->incoming().push_back(newin ); + born->outgoing().push_back(newout); + // incoming lepton if second + if(iqIn==0) + born->incoming().push_back(born->bornIncoming()[1]->dataPtr()-> + produceParticle(born->bornIncoming()[1]->momentum())); + // outgoing lepton if second + if(iqOut==0) + born->outgoing().push_back(born->bornOutgoing()[1]->dataPtr()-> + produceParticle(born->bornOutgoing()[1]->momentum())); + // radiated particle + born->outgoing().push_back(emitted); + born->interaction(ShowerInteraction::QCD); + return born; } bool DISBase::softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent, Branching br) { bool veto = !UseRandom::rndbool(parent->isFinalState() ? 1./final_ : 1./initial_); // check if me correction should be applied long id[2]={initial->id(),parent->id()}; if(id[0]!=id[1]||id[1]==ParticleID::g) return veto; // get the pT Energy pT=br.kinematics->pT(); // check if hardest so far if(pThighestpT()) return veto; double kappa(sqr(br.kinematics->scale())/q2_),z(br.kinematics->z()); double zk((1.-z)*kappa); // final-state double wgt(0.); if(parent->isFinalState()) { double zp=z,xp=1./(1.+z*zk); double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); double x2 = 1.-(1.-zp)/xp; vector azicoeff = ComptonME(xp,x2,xperp,false); wgt = (azicoeff[0]+0.5*azicoeff[2])*xp/(1.+sqr(z))/final_; if(wgt<.0||wgt>1.) { ostringstream wstring; wstring << "Soft ME correction weight too large or " << "negative for FSR in DISBase::" << "softMatrixElementVeto() soft weight " << " xp = " << xp << " zp = " << zp << " weight = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } else { double xp = 2.*z/(1.+zk+sqrt(sqr(1.+zk)-4.*z*zk)); double zp = 0.5* (1.-zk+sqrt(sqr(1.+zk)-4.*z*zk)); double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); double x1 = -1./xp, x2 = 1.-(1.-zp)/xp, x3 = 2.+x1-x2; // compton if(br.ids[0]->id()!=ParticleID::g) { vector azicoeff = ComptonME(xp,x2,xperp,false); wgt = (azicoeff[0]+0.5*azicoeff[2])*xp*(1.-z)/(1.-xp)/(1.+sqr(z))/ (1.-zp+xp-2.*xp*(1.-zp)); } // BGF else { vector azicoeff = BGFME(xp,x2,x3,xperp,true); wgt = (azicoeff[0]+0.5*azicoeff[2])*xp/(1.-zp+xp-2.*xp*(1.-zp))/(sqr(z)+sqr(1.-z)); } wgt /=initial_; if(wgt<.0||wgt>1.) { ostringstream wstring; wstring << "Soft ME correction weight too large or " << "negative for ISR in DISBase::" << "softMatrixElementVeto() soft weight " << " xp = " << xp << " zp = " << zp << " weight = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } // if not vetoed if(UseRandom::rndbool(wgt)) return false; // otherwise parent->vetoEmission(br.type,br.kinematics->scale()); return true; } double DISBase::generateComptonPoint(double &xp, double & zp) { static const double maxwgt = 1.; double wgt; do { xp = UseRandom::rnd(); double zpmin = xp, zpmax = 1./(1.+xp*(1.-xp)); zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax); wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp); if(UseRandom::rndbool()) swap(xp,zp); double xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp,x2=1.-(1.-zp)/xp; wgt *= 2.*(1.+sqr(xp)*(sqr(x2)+1.5*xperp2))/(1.-xp)/(1.-zp); if(wgt>maxwgt) { ostringstream wstring; wstring << "DISBase::generateComptonPoint " << "Weight greater than maximum " << "wgt = " << wgt << " maxwgt = 1\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(wgtmaxwgt) { ostringstream wstring; wstring << "DISBase::generateBGFPoint " << "Weight greater than maximum " << "wgt = " << wgt << " maxwgt = 1\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(wgt1.+ac) cerr << "testing violates BGF maxA " << wgt << "\n"; // } // while(wgtmaxwgt*zpwgt) cerr << "testing violates BGF maxB " << wgt/xpwgt << "\n"; // } // while(wgt DISBase::ComptonME(double xp, double x2, double xperp, bool norm) { vector output(3,0.); double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp)); double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp)); double root = sqrt(sqr(l_)-1.); output[0] = sqr(cos2)+acoeff_*cos2*l_+sqr(l_); output[1] = -acoeff_*cos2*root*sin2-2.*l_*root*sin2; output[2] = sqr(root)*sqr(sin2); double lo(1+acoeff_*l_+sqr(l_)); double denom = norm ? 1.+sqr(xp)*(sqr(x2)+1.5*sqr(xperp)) : 1.; double fact = sqr(xp)*(sqr(x2)+sqr(xperp))/lo; for(unsigned int ix=0;ix DISBase::BGFME(double xp, double x2, double x3, double xperp, bool norm) { vector output(3,0.); double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp)); double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp)); double fact2 = sqr(xp)*(sqr(x2)+sqr(xperp)); double cos3 = x3 /sqrt(sqr(x3)+sqr(xperp)); double sin3 = xperp/sqrt(sqr(x3)+sqr(xperp)); double fact3 = sqr(xp)*(sqr(x3)+sqr(xperp)); double root = sqrt(sqr(l_)-1.); output[0] = fact2*(sqr(cos2)+acoeff_*cos2*l_+sqr(l_)) + fact3*(sqr(cos3)-acoeff_*cos3*l_+sqr(l_)); output[1] = - fact2*(acoeff_*cos2*root*sin2+2.*l_*root*sin2) - fact3*(acoeff_*cos3*root*sin3-2.*l_*root*sin3); output[2] = fact2*(sqr(root)*sqr(sin2)) + fact3*(sqr(root)*sqr(sin3)); double lo(1+acoeff_*l_+sqr(l_)); double denom = norm ? sqr(xp)*(sqr(x3)+sqr(x2)+3.*sqr(xperp))*lo : lo; for(unsigned int ix=0;ix::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) { - hadron = cit->first->original()->parents()[0]; - quark [0] = cit->first->progenitor(); - beam_ = cit->first->beam(); - } - else if(LeptonMatcher::Check(cit->first->progenitor()->data())) { - lepton[0] = cit->first->progenitor(); + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) { + iqIn=ix; + hadron = born->hadrons()[ix]; + quark [0] = born->bornIncoming()[ix]; + beam_ = dynamic_ptr_cast(hadron->dataPtr()); + xB_ = quark[0]->momentum().rho()/hadron->momentum().rho(); + } + else if(LeptonMatcher::Check(born->bornIncoming()[ix]->data())) { + lepton[0] = born->bornIncoming()[ix]; leptons_[0] = lepton[0]->dataPtr(); } } pdf_=beam_->pdf(); assert(beam_&&pdf_&&quark[0]&&lepton[0]); // outgoing particles - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) - quark [1] = cit->first->progenitor(); - else if(LeptonMatcher::Check(cit->first->progenitor()->data())) { - lepton[1] = cit->first->progenitor(); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data())) { + iqOut=ix; + quark [1] = born->bornOutgoing()[ix]; + } + else if(LeptonMatcher::Check(born->bornOutgoing()[ix]->data())) { + lepton[1] = born->bornOutgoing()[ix]; leptons_[1] = lepton[1]->dataPtr(); } } assert(quark[1]&&lepton[1]); // Particle data objects for(unsigned int ix=0;ix<2;++ix) partons_[ix] = quark[ix]->dataPtr(); // extract the born variables q_ =lepton[0]->momentum()-lepton[1]->momentum(); q2_ = -q_.m2(); - xB_ = quark[0]->x(); double yB = ( q_*quark[0]->momentum())/ (lepton[0]->momentum()*quark[0]->momentum()); l_ = 2./yB-1.; // construct lorentz transform from lab to breit frame Lorentz5Momentum phadron = hadron->momentum(); phadron.setMass(0.*GeV); phadron.rescaleRho(); Lorentz5Momentum pb = quark[0]->momentum(); Axis axis(q_.vect().unit()); double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); LorentzRotation rot_ = LorentzRotation(); if(axis.perp2()>1e-20) { rot_.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot_.rotateX(Constants::pi); } if(abs(1.-q_.e()/q_.vect().mag())>1e-6) rot_.boostZ( q_.e()/q_.vect().mag()); pb *= rot_; if(pb.perp2()/GeV2>1e-20) { Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot_.boost(trans); } Lorentz5Momentum pl = rot_*lepton[0]->momentum(); rot_.rotateZ(-atan2(pl.y(),pl.x())); // momenta of the particles pl_[0]=rot_*lepton[0]->momentum(); pl_[1]=rot_*lepton[1]->momentum(); pq_[0]=rot_* quark[0]->momentum(); pq_[1]=rot_* quark[1]->momentum(); q_ *= rot_; // coefficient for the matrix elements acoeff_ = A(lepton[0]->dataPtr(),lepton[1]->dataPtr(), quark [0]->dataPtr(),quark [1]->dataPtr(),q2_); // generate a compton point generateCompton(); generateBGF(); // no valid emission, return - if(pTCompton_pT()[ShowerInteraction::QCD] = pTmin_; + return born; + } // type of emission, pick highest pT bool isCompton=pTCompton_>pTBGF_; -// // find the sudakov for the branching -// SudakovPtr sudakov; -// // ISR -// if(ComptonISFS_||!isCompton) { -// BranchingList branchings=evolver()->splittingGenerator()->initialStateBranchings(); -// long index = abs(partons_[0]->id()); -// IdList br(3); -// if(isCompton) { -// br[0] = index; -// br[1] = index; -// br[2] = ParticleID::g; -// } -// else { -// br[0] = ParticleID::g; -// br[1] = abs(partons_[0]->id()); -// br[2] = -abs(partons_[0]->id()); -// } -// for(BranchingList::const_iterator cit = branchings.lower_bound(index); -// cit != branchings.upper_bound(index); ++cit ) { -// IdList ids = cit->second.second; -// if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) { -// sudakov=cit->second.first; -// break; -// } -// } -// } -// // FSR -// else { -// BranchingList branchings = -// evolver()->splittingGenerator()->finalStateBranchings(); -// long index=abs(partons_[1]->id()); -// for(BranchingList::const_iterator cit = branchings.lower_bound(index); -// cit != branchings.upper_bound(index); ++cit ) { -// IdList ids = cit->second.second; -// if(ids[0]==index&&ids[1]==index&&ids[2]==ParticleID::g) { -// sudakov = cit->second.first; -// break; -// } -// } -// } -// if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in " -// << "DISBase::generateHardest()" -// << Exception::runerror; - // add the leptons - vector spaceBranchings,allBranchings; - spaceBranchings.push_back(new_ptr(HardBranching(lepton[0],SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - allBranchings.push_back(spaceBranchings.back()); - allBranchings.push_back(new_ptr(HardBranching(lepton[1],SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); + // create the process with real emission + bool isQuark = quark[0]->colourLine(); + bool FSR = false; + // incoming lepton if first + if(iqIn==1) + born->incoming().push_back(born->bornIncoming()[0]->dataPtr()-> + produceParticle(born->bornIncoming()[0]->momentum())); + // outgoing lepton if first + if(iqOut==1) + born->outgoing().push_back(born->bornOutgoing()[0]->dataPtr()-> + produceParticle(born->bornOutgoing()[0]->momentum())); + PPtr newout,newin,emitted; // compton hardest if(isCompton) { rot_.invert(); for(unsigned int ix=0;ixset5Momentum(ComptonMomenta_[1]); - ShowerParticlePtr newg(new_ptr(ShowerParticle(gluon_,true))); - newg->set5Momentum(ComptonMomenta_[2]); - ShowerParticlePtr newqin (new_ptr(ShowerParticle(partons_[0],false ))); - newqin->set5Momentum(ComptonMomenta_[0]); - if(ComptonISFS_) { - ShowerParticlePtr newspace(new_ptr(ShowerParticle(partons_[0],false))); - newspace->set5Momentum(ComptonMomenta_[0]-ComptonMomenta_[2]); - HardBranchingPtr spaceBranch(new_ptr(HardBranching(newqin,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - HardBranchingPtr offBranch(new_ptr(HardBranching(newspace,SudakovPtr(), - spaceBranch, - HardBranching::Incoming))); - spaceBranch->addChild(offBranch); - HardBranchingPtr g(new_ptr(HardBranching(newg,SudakovPtr(),spaceBranch, - HardBranching::Outgoing))); - spaceBranch->addChild(g); - spaceBranch->type(offBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - HardBranchingPtr outBranch(new_ptr(HardBranching(newqout,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - spaceBranchings.push_back(spaceBranch); - allBranchings.push_back(offBranch); - allBranchings.push_back(outBranch); - ColinePtr newin(new_ptr(ColourLine())),newout(new_ptr(ColourLine())); - newin ->addColoured(newqin ,partons_[0]->id()<0); - newin ->addColoured(newg ,partons_[0]->id()<0); - newout->addColoured(newspace,partons_[0]->id()<0); - newout->addColoured(newqout ,partons_[1]->id()<0); - newout->addColoured(newg ,partons_[1]->id()>0); - } - else { - ShowerParticlePtr newtime(new_ptr(ShowerParticle(partons_[1],true))); - newtime->set5Momentum(ComptonMomenta_[1]+ComptonMomenta_[2]); - HardBranchingPtr spaceBranch(new_ptr(HardBranching(newqin,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - HardBranchingPtr offBranch(new_ptr(HardBranching(newtime,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr g(new_ptr(HardBranching(newg,SudakovPtr(),offBranch, - HardBranching::Outgoing))); - HardBranchingPtr outBranch(new_ptr(HardBranching(newqout,SudakovPtr(),offBranch, - HardBranching::Outgoing))); - offBranch->addChild(outBranch); - offBranch->addChild(g); - offBranch->type(offBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - spaceBranchings.push_back(spaceBranch); - allBranchings.push_back(spaceBranch); - allBranchings.push_back(offBranch); - ColinePtr newin(new_ptr(ColourLine())),newout(new_ptr(ColourLine())); - newin ->addColoured(newqin ,newqin->dataPtr()->iColour()!=PDT::Colour3); - newin ->addColoured(newtime,newqin->dataPtr()->iColour()!=PDT::Colour3); - newin ->addColoured(newg ,newqin->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newg ,newqin->dataPtr()->iColour()==PDT::Colour3); - newout->addColoured(newqout,newqin->dataPtr()->iColour()!=PDT::Colour3); - } + newout = partons_[1]->produceParticle(ComptonMomenta_[1]); + emitted = gluon_ ->produceParticle(ComptonMomenta_[2]); + newin = partons_[0]->produceParticle(ComptonMomenta_[0]); + emitted->incomingColour(newin,!isQuark); + emitted->colourConnect(newout,!isQuark); + FSR = !ComptonISFS_; + born->pT()[ShowerInteraction::QCD] = pTCompton_; } // BGF hardest else { rot_.invert(); for(unsigned int ix=0;ixset5Momentum(BGFMomenta_[1]); - ShowerParticlePtr newqbar(new_ptr(ShowerParticle(partons_[0]->CC(),true))); - newqbar->set5Momentum(BGFMomenta_[2]); - ShowerParticlePtr newg (new_ptr(ShowerParticle(gluon_,false))); - newg->set5Momentum(BGFMomenta_[0]); - ShowerParticlePtr newspace(new_ptr(ShowerParticle(partons_[0],false))); - newspace->set5Momentum(BGFMomenta_[0]-BGFMomenta_[2]); - HardBranchingPtr spaceBranch(new_ptr(HardBranching(newg,SudakovPtr(),HardBranchingPtr(), - HardBranching::Incoming))); - HardBranchingPtr offBranch(new_ptr(HardBranching(newspace,SudakovPtr(),spaceBranch, - HardBranching::Incoming))); - HardBranchingPtr qbar(new_ptr(HardBranching(newqbar,SudakovPtr(),spaceBranch, - HardBranching::Outgoing))); - spaceBranch->addChild(offBranch); - spaceBranch->addChild(qbar); - spaceBranch->type(offBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - HardBranchingPtr outBranch(new_ptr(HardBranching(newq,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - spaceBranchings.push_back(spaceBranch); - allBranchings.push_back(offBranch); - allBranchings.push_back(outBranch); - ColinePtr newin(new_ptr(ColourLine())),newout(new_ptr(ColourLine())); - newout->addColoured(newspace,newspace->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newq ,newspace->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newg ,newspace->dataPtr()->iColour()!=PDT::Colour3); - newin ->addColoured(newg ,newspace->dataPtr()->iColour()==PDT::Colour3); - newin ->addColoured(newqbar ,newspace->dataPtr()->iColour()==PDT::Colour3); + newin = gluon_ ->produceParticle(BGFMomenta_[0]); + emitted = quark[0]->dataPtr()->CC()->produceParticle(BGFMomenta_[2]); + newout = quark[1]->dataPtr() ->produceParticle(BGFMomenta_[1]); + emitted->incomingColour(newin, isQuark); + newout ->incomingColour(newin,!isQuark); + FSR = false; + born->pT()[ShowerInteraction::QCD] = pTBGF_; } - allBranchings[2]->colourPartner(allBranchings[3]); - allBranchings[3]->colourPartner(allBranchings[2]); - HardTreePtr newTree(new_ptr(HardTree(allBranchings,spaceBranchings, - ShowerInteraction::QCD))); - // Set the maximum pt for all other emissions and connect hard and shower tree - Energy pT = isCompton ? pTCompton_ : pTBGF_; - // incoming particles - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - // set maximum pT - if(QuarkMatcher::Check(cit->first->progenitor()->data())) - cit->first->maximumpT(pT,ShowerInteraction::QCD); - for(set::iterator cjt=newTree->branchings().begin(); - cjt!=newTree->branchings().end();++cjt) { - if(!(*cjt)->branchingParticle()->isFinalState()&& - (*cjt)->branchingParticle()->id()==cit->first->progenitor()->id()) { - newTree->connect(cit->first->progenitor(),*cjt); - tPPtr beam =cit->first->original(); - if(!beam->parents().empty()) beam=beam->parents()[0]; - (*cjt)->beam(beam); - HardBranchingPtr parent=(*cjt)->parent(); - while(parent) { - parent->beam(beam); - parent=parent->parent(); - }; - } - } + double x = newin->momentum().rho()/hadron->momentum().rho(); + if(born->incoming().size()==0) + born->x(make_pair(x,1.)); + else + born->x(make_pair(1.,x)); + if(FSR) { + born->emitter(born->outgoing().size()+2); + born->spectator(born->incoming().size()); } - // outgoing particles - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - // set maximum pT - if(QuarkMatcher::Check(cit->first->progenitor()->data())) - cit->first->maximumpT(pT,ShowerInteraction::QCD); - for(set::iterator cjt=newTree->branchings().begin(); - cjt!=newTree->branchings().end();++cjt) { - if((*cjt)->branchingParticle()->isFinalState()&& - (*cjt)->branchingParticle()->id()==cit->first->progenitor()->id()) { - newTree->connect(cit->first->progenitor(),*cjt); - } - } + else { + born->emitter(born->incoming().size()); + born->spectator(born->outgoing().size()+2); } - return newTree; + born->emitted(4); + // radiating particles + born->incoming().push_back(newin ); + born->outgoing().push_back(newout); + // incoming lepton if second + if(iqIn==0) + born->incoming().push_back(born->bornIncoming()[1]->dataPtr()-> + produceParticle(born->bornIncoming()[1]->momentum())); + // outgoing lepton if second + if(iqOut==0) + born->outgoing().push_back(born->bornOutgoing()[1]->dataPtr()-> + produceParticle(born->bornOutgoing()[1]->momentum())); + // radiated particle + born->outgoing().push_back(emitted); + born->interaction(ShowerInteraction::QCD); + return born; } void DISBase::generateCompton() { // maximum value of the xT double xT = sqrt((1.-xB_)/xB_); double xTMin = 2.*pTmin_/sqrt(q2_); double zp; // prefactor double a = alpha_->overestimateValue()*comptonWeight_/Constants::twopi; // loop to generate kinematics double wgt(0.),xp(0.); vector azicoeff; do { wgt = 0.; // intergration variables dxT/xT^3 xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT)); // zp zp = UseRandom::rnd(); xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp)); // check allowed if(xp1.) continue; // phase-space piece of the weight wgt = 8.*(1.-xp)*zp/comptonWeight_; // PDF piece of the weight Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1.); wgt *= pdf_->xfx(beam_,partons_[0],scale,xB_/xp)/ pdf_->xfx(beam_,partons_[0],q2_ ,xB_); // me piece of the weight double x2 = 1.-(1.-zp)/xp; azicoeff = ComptonME(xp,x2,xT,false); wgt *= 4./3.*alpha_->ratio(0.25*q2_*sqr(xT))*(azicoeff[0]+0.5*azicoeff[2]); if(wgt>1.||wgt<0.) { ostringstream wstring; wstring << "DISBase::generateCompton() " << "Weight greater than one or less than zero" << "wgt = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(xT>xTMin&&UseRandom::rnd()>wgt); if(xT<=xTMin) { pTCompton_=-GeV; return; } // generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)); phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in DISMECorrection" << "::generateCompton() to" << " generate phi" << Exception::eventerror; // momenta for the configuration Energy Q(sqrt(q2_)); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); pTCompton_ = 0.5*Q*xT; ComptonMomenta_.resize(3); ComptonMomenta_[0] = p0; ComptonMomenta_[1] = p1; ComptonMomenta_[2] = p2; ComptonISFS_ = zp>xp; // debuggingMatrixElement(false,p0,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1], // leptons_[0],leptons_[1], // partons_[0],partons_[1], // q2_,phi,x2,x3,xT,zp,xp,azicoeff,false); } void DISBase::generateBGF() { // maximum value of the xT double xT = (1.-xB_)/xB_; double xTMin = 2.*max(pTmin_,pTCompton_)/sqrt(q2_); double zp; // prefactor double a = alpha_->overestimateValue()*BGFWeight_/Constants::twopi; // loop to generate kinematics double wgt(0.),xp(0.); vector azicoeff; do { wgt = 0.; // intergration variables dxT/xT^3 xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT)); // zp zp = UseRandom::rnd(); xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp)); // check allowed if(xp1.) continue; // phase-space piece of the weight wgt = 8.*sqr(1.-xp)*zp/BGFWeight_; // PDF piece of the weight Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1.); wgt *= pdf_->xfx(beam_,gluon_ ,scale,xB_/xp)/ pdf_->xfx(beam_,partons_[0],q2_ ,xB_); // me piece of the weight double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; azicoeff = BGFME(xp,x2,x3,xT,false); wgt *= 0.5*alpha_->ratio(0.25*q2_*sqr(xT))* (azicoeff[0]+0.5*azicoeff[2]); if(wgt>1.||wgt<0.) { ostringstream wstring; wstring << "DISBase::generateBGF() " << "Weight greater than one or less than zero" << "wgt = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(xT>xTMin&&UseRandom::rnd()>wgt); if(xT<=xTMin) { pTBGF_=-GeV; return; } // generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)); phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in DISMECorrection" << "::generateBGF() to" << " generate phi" << Exception::eventerror; // momenta for the configuration Energy Q(sqrt(q2_)); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); pTBGF_=0.5*Q*xT; BGFMomenta_.resize(3); BGFMomenta_[0]=p0; BGFMomenta_[1]=p1; BGFMomenta_[2]=p2; // debuggingMatrixElement(true,p0,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1], // leptons_[0],leptons_[1], // partons_[0],partons_[1], // q2_,phi,x2,x3,xT,zp,xp,azicoeff,false); } int DISBase::nDim() const { return HwMEBase::nDim() + (contrib_>0 ? 1 : 0 ); } bool DISBase::generateKinematics(const double * r) { // Born kinematics if(!HwMEBase::generateKinematics(r)) return false; if(contrib_!=0) { // hadron and momentum fraction if(HadronMatcher::Check(*lastParticles().first->dataPtr())) { hadron_ = dynamic_ptr_cast(lastParticles().first->dataPtr()); xB_ = lastX1(); } else { hadron_ = dynamic_ptr_cast(lastParticles().second->dataPtr()); xB_ = lastX2(); } // Q2 q2_ = -(meMomenta()[0]-meMomenta()[2]).m2(); // xp int ndim=nDim(); double rhomin = pow(1.-xB_,1.-power_); double rho = r[ndim-1]*rhomin; xp_ = 1.-pow(rho,1./(1.-power_)); jac_ = rhomin/(1.-power_)*pow(1.-xp_,power_); jacobian(jacobian()*jac_); } return true; } Energy2 DISBase::scale() const { return scaleOpt_ == 1 ? -sqr(scaleFact_)*tHat() : sqr(scaleFact_*muF_); } CrossSection DISBase::dSigHatDR() const { return NLOWeight()*HwMEBase::dSigHatDR(); } double DISBase::NLOWeight() const { // If only leading order is required return 1: if(contrib_==0) return 1.; // scale and prefactors Energy2 mu2(scale()); double aS = SM().alphaS(mu2); double CFfact = 4./3.*aS/Constants::twopi; double TRfact = 1./2.*aS/Constants::twopi; // LO + dipole subtracted virtual + collinear quark bit with LO pdf double virt = 1.+CFfact*(-4.5-1./3.*sqr(Constants::pi)+1.5*log(q2_/mu2/(1.-xB_)) +2.*log(1.-xB_)*log(q2_/mu2)+sqr(log(1.-xB_))); virt /= jac_; // PDF from leading-order double loPDF = hadron_->pdf()->xfx(hadron_,mePartonData()[1],mu2,xB_)/xB_; // NLO gluon PDF tcPDPtr gluon = getParticleData(ParticleID::g); double gPDF = hadron_->pdf()->xfx(hadron_,gluon,mu2,xB_/xp_)*xp_/xB_; // NLO quark PDF double qPDF = hadron_->pdf()->xfx(hadron_,mePartonData()[1],mu2,xB_/xp_)*xp_/xB_; // collinear counterterms // gluon double collg = TRfact/xp_*gPDF*(2.*xp_*(1.-xp_)+(sqr(xp_)+sqr(1.-xp_))*log((1.-xp_)*q2_/xp_/mu2)); // quark double collq = CFfact/xp_*qPDF*(1-xp_-2./(1.-xp_)*log(xp_)-(1.+xp_)*log((1.-xp_)/xp_*q2_/mu2))+ CFfact/xp_*(qPDF-xp_*loPDF)*(2./(1.-xp_)*log(q2_*(1.-xp_)/mu2)-1.5/(1.-xp_)); // calculate the A coefficient for the real pieces double a(A(mePartonData()[0],mePartonData()[2], mePartonData()[1],mePartonData()[3],q2_)); // cacluate lepton kinematic variables Lorentz5Momentum q = meMomenta()[0]-meMomenta()[2]; double yB = (q*meMomenta()[1])/(meMomenta()[0]*meMomenta()[1]); double l = 2./yB-1.; // q -> qg term double realq = CFfact/xp_/(1.+a*l+sqr(l))*qPDF/loPDF* (2.+2.*sqr(l)-xp_+3.*xp_*sqr(l)+a*l*(2.*xp_+1.)); // g -> q qbar term double realg =-TRfact/xp_/(1.+a*l+sqr(l))*gPDF/loPDF* ((1.+sqr(l)+2.*(1.-3.*sqr(l))*xp_*(1.-xp_)) +2.*a*l*(1.-2.*xp_*(1.-xp_))); // return the full result double wgt = virt+((collq+collg)/loPDF+realq+realg); // double f2g = gPDF/xp_*TRfact*((sqr(1-xp_)+sqr(xp_))*log((1-xp_)/xp_)+ // 8*xp_*(1.-xp_)-1.); // double f2q = // loPDF/jac_*(1.+CFfact*(-1.5*log(1.-xB_)+sqr(log(1.-xB_)) // -sqr(Constants::pi)/3.-4.5)) // +qPDF *CFfact/xp_*(3.+2.*xp_-(1.+xp_)*log(1.-xp_) // -(1.+sqr(xp_))/(1.-xp_)*log(xp_)) // +(qPDF-xp_*loPDF)*CFfact/xp_*(2.*log(1.-xp_)/(1.-xp_)-1.5/(1.-xp_)); // double wgt = (f2g+f2q)/loPDF; return contrib_ == 1 ? max(0.,wgt) : max(0.,-wgt); } diff --git a/MatrixElement/DIS/DISBase.h b/MatrixElement/DIS/DISBase.h --- a/MatrixElement/DIS/DISBase.h +++ b/MatrixElement/DIS/DISBase.h @@ -1,468 +1,469 @@ // -*- C++ -*- #ifndef HERWIG_DISBase_H #define HERWIG_DISBase_H // // This is the declaration of the DISBase class. // #include "Herwig/MatrixElement/HwMEBase.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; /** * The DISBase class is the base class for the implementation * of DIS type processes including corrections in both the old * fashioned matrix element and POWHEG approaches * * @see \ref DISBaseInterfaces "The interfaces" * defined for DISBase. */ class DISBase: public HwMEBase { public: /** * The default constructor. */ DISBase(); /** * The default constructor. */ virtual ~DISBase(); /** * Members for the old-fashioned matrix element correction */ //@{ /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return true;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr, double &, + virtual void initializeMECorrection(RealEmissionProcessPtr, double &, double & ); /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr); + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr, ShowerParticlePtr,Branching); //@} /** * Members for the POWHEG stype correction */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return Both;} /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr,ShowerInteraction::Type); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, + ShowerInteraction::Type); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * The number of internal degrees of freedom used in the matrix * element. */ virtual int nDim() const; /** * Generate internal degrees of freedom given nDim() uniform * random numbers in the interval \f$ ]0,1[ \f$. To help the phase space * generator, the dSigHatDR should be a smooth function of these * numbers, although this is not strictly necessary. * @param r a pointer to the first of nDim() consecutive random numbers. * @return true if the generation succeeded, otherwise false. */ virtual bool generateKinematics(const double * r); /** * Return the matrix element squared differential in the variables * given by the last call to generateKinematics(). */ virtual CrossSection dSigHatDR() 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(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initDISBase; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DISBase & operator=(const DISBase &); protected: /** * The NLO weight */ double NLOWeight() const; /** * Calculate the coefficient A for the correlations */ virtual double A(tcPDPtr lin, tcPDPtr lout, tcPDPtr qin, tcPDPtr qout, Energy2 scale) const =0; /** * Members for the matrix element correction */ //@{ /** * Generate the values of \f$x_p\f$ and \f$z_p\f$ * @param xp The value of xp, output * @param zp The value of zp, output */ double generateComptonPoint(double &xp, double & zp); /** * Generate the values of \f$x_p\f$ and \f$z_p\f$ * @param xp The value of xp, output * @param zp The value of zp, output */ double generateBGFPoint(double &xp, double & zp); /** * Return the coefficients for the matrix element piece for * the QCD compton case. The output is the \f$a_i\f$ coefficients to * give the function as * \f$a_0+a_1\cos\phi+a_2\sin\phi+a_3\cos^2\phi+a_4\sin^2\phi\f$ * @param xp \f$x_p\f$ * @param x2 \f$x_2\f$ * @param xperp \f$x_\perp\f$ * @param norm Normalise to the large $l$ value of the ME */ vector ComptonME(double xp, double x2, double xperp, bool norm); /** * Return the coefficients for the matrix element piece for * the QCD compton case. The output is the \f$a_i\f$ coefficients to * give the function as * \f$a_0+a_1\cos\phi+a_2\sin\phi+a_3\cos^2\phi+a_4\sin^2\phi\f$ * @param xp \f$x_p\f$ * @param x2 \f$x_3\f$ * @param x3 \f$x_2\f$ * @param xperp \f$x_\perp\f$ * @param norm Normalise to the large $l$ value of the ME */ vector BGFME(double xp, double x2, double x3, double xperp, bool norm); //@} /** * Members for the POWHEG correction */ //@{ /** * Generate a Compton process */ void generateCompton(); /** * Generate a BGF process */ void generateBGF(); //@} private: /** * Parameters for the matrix element correction */ //@{ /** * Enchancement factor for ISR */ double initial_; /** * Enchancement factor for FSR */ double final_; /** * Relative fraction of compton and BGF processes to generate */ double procProb_; /** * Integral for compton process */ double comptonInt_; /** * Integral for BGF process */ double bgfInt_; //@} /** * Parameters for the POWHEG correction */ //@{ /** * Weight for the compton channel */ double comptonWeight_; /** * Weight for the BGF channel */ double BGFWeight_; /** * Minimum value of \f$p_T\f$ */ Energy pTmin_; //@} /** * Parameters for the point being generated */ //@{ /** * \f$Q^2\f$ */ Energy2 q2_; /** * */ double l_; /** * Borm momentum fraction */ double xB_; /** * Beam particle */ tcBeamPtr beam_; /** * Partons */ tcPDPtr partons_[2]; /** * Leptons */ tcPDPtr leptons_[2]; /** * PDF object */ tcPDFPtr pdf_; /** * Rotation to the Breit frame */ LorentzRotation rot_; /** * Lepton momenta */ Lorentz5Momentum pl_[2]; /** * Quark momenta */ Lorentz5Momentum pq_[2]; /** * q */ Lorentz5Momentum q_; /** * Compton parameters */ Energy pTCompton_; bool ComptonISFS_; vector ComptonMomenta_; /** * BGF parameters */ Energy pTBGF_; vector BGFMomenta_; //@} /** * The coefficient for the correlations */ double acoeff_; /** * Coupling */ ShowerAlphaPtr alpha_; /** * Gluon particle data object */ PDPtr gluon_; private: /** * The radiative variables */ //@{ /** * The \f$x_p\f$ or \f$z\f$ real integration variable */ double xp_; //@} /** * The hadron */ tcBeamPtr hadron_; /** * Selects a dynamic or fixed factorization scale */ unsigned int scaleOpt_; /** * The factorization scale */ Energy muF_; /** * Prefactor if variable scale used */ double scaleFact_; /** * Whether to generate the positive, negative or leading order contribution */ unsigned int contrib_; /** * Power for sampling \f$x_p\f$ */ double power_; /** * Jacobian for \f$x_p\f$ integral */ double jac_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DISBase. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DISBase. */ typedef Herwig::HwMEBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DISBase 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::DISBase"; } /** * The name of a file containing the dynamic library where the class * MENeutralCurrentDIS is implemented. It may also include several, space-separated, * libraries if the class MENeutralCurrentDIS 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 "HwMEDIS.so"; } }; /** @endcond */ } #endif /* HERWIG_DISBase_H */ diff --git a/MatrixElement/DrellYanBase.cc b/MatrixElement/DrellYanBase.cc --- a/MatrixElement/DrellYanBase.cc +++ b/MatrixElement/DrellYanBase.cc @@ -1,1060 +1,914 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the DrellYanBase class. // #include "DrellYanBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/HardTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; DrellYanBase::DrellYanBase() : _channelwgtA(0.12), _channelwgtB(2.00), _nover(0), _maxwgt(0.), _power(2.0),_preqqbar(6.5),_preqg(4.0),_pregqbar(4.0), _min_pt(2.*GeV) {} void DrellYanBase::persistentOutput(PersistentOStream & os) const { os << _channelwgtA << _channelwgtB << _channelweights << _alpha << _power << _preqqbar << _preqg << _pregqbar << ounit( _min_pt, GeV ) << _prefactor; } void DrellYanBase::persistentInput(PersistentIStream & is, int) { is >> _channelwgtA >> _channelwgtB >> _channelweights >> _alpha >> _power >> _preqqbar >> _preqg >> _pregqbar >> iunit( _min_pt, GeV ) >> _prefactor; } AbstractClassDescription DrellYanBase::initDrellYanBase; // Definition of the static class description member. void DrellYanBase::Init() { static ClassDocumentation documentation ("The DrellYanBase class provides a base class for the" " corrections to Drell-Yan type processes"); static Parameter interfaceQQbarChannelWeight ("QQbarChannelWeight", "The relative weights of the q qbar abd q g channels for selection." " This is a technical parameter for the phase-space generation and " "should not affect the results only the efficiency and fraction" " of events with weight > 1.", &DrellYanBase::_channelwgtA, 0.12, 0.01, 100., false, false, Interface::limited); static Parameter interfaceQGChannelWeight ("QGChannelWeight", "The relative weights of the qg abd qbar g channels for selection." " This is a technical parameter for the phase-space generation and " "should not affect the results only the efficiency and fraction", &DrellYanBase::_channelwgtB, 2., 0.01, 100., false, false, Interface::limited); static Reference interfaceCoupling ("Coupling", "Pointer to the object to calculate the coupling for the correction", &DrellYanBase::_alpha, false, false, true, false, false); static Parameter interfacePower ("Power", "The power for the sampling of the matrix elements", &DrellYanBase::_power, 2.0, 1.0, 10.0, false, false, Interface::limited); static Parameter interfacePrefactorqqbar ("Prefactorqqbar", "The prefactor for the sampling of the q qbar channel", &DrellYanBase::_preqqbar, 5.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorqg ("Prefactorqg", "The prefactor for the sampling of the q g channel", &DrellYanBase::_preqg, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorgqbar ("Prefactorgqbar", "The prefactor for the sampling of the g qbar channel", &DrellYanBase::_pregqbar, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePtMin ("minPt", "The pt cut on hardest emision generation" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &DrellYanBase::_min_pt, GeV, 2.*GeV, ZERO, 100000.0*GeV, false, false, Interface::limited); } void DrellYanBase::doinit() { HwMEBase::doinit(); _channelweights.push_back(_channelwgtA/(1.+_channelwgtA)); _channelweights.push_back(_channelweights[0]+1./(1.+_channelwgtA)/(1+_channelwgtB)); _channelweights.push_back(1.0); _prefactor.push_back(_preqqbar); _prefactor.push_back(_preqg); _prefactor.push_back(_pregqbar); } void DrellYanBase::dofinish() { HwMEBase::dofinish(); if(_nover==0) return; generator()->log() << "DrellYanBase when applying the hard correction " << _nover << " weights larger than one were generated of which" << " the largest was " << _maxwgt << "\n"; } -void DrellYanBase::applyHardMatrixElementCorrection(ShowerTreePtr tree) { - // get the quark,antiquark and the gauge boson - // get the quarks - map::const_iterator cit; - ShowerParticleVector incoming; +RealEmissionProcessPtr DrellYanBase::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { + // get the quark,antiquark + ParticleVector incoming; vector beams; - for(cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - incoming.push_back(cit->first->progenitor()); - beams.push_back(cit->first->beam()); + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + incoming.push_back(born->bornIncoming()[ix]); + tPPtr beam = born->hadrons()[ix]; + beams.push_back(dynamic_ptr_cast(beam->dataPtr())); } + pair xnew = born->x(); // ensure that the quark is first if(incoming[0]->id()id()) { swap(incoming[0],incoming[1]); swap(beams[0],beams[1]); - } + swap(xnew.first,xnew.second); + } + // and the gauge boson Lorentz5Momentum pboson; - for( map::const_iterator - cjt= tree->outgoingLines().begin(); - cjt != tree->outgoingLines().end();++cjt ) { - pboson += cjt->first->original()->momentum(); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + pboson += born->bornOutgoing()[ix]->momentum(); } pboson.rescaleMass(); // calculate the momenta unsigned int iemit,itype; vector pnew; LorentzRotation trans; - pair xnew; // if not accepted return - if(!applyHard(incoming,beams,pboson,iemit,itype,pnew,trans,xnew)) return; + if(!applyHard(incoming,beams,pboson,iemit,itype,pnew,trans,xnew)) return RealEmissionProcessPtr(); // if applying ME correction create the new particles + // first the final-state particles + Boost boostv=pboson.findBoostToCM(); + trans *=LorentzRotation(boostv); + born->transformation(trans); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + Lorentz5Momentum pnew = trans*(born->bornOutgoing()[ix]->momentum()); + born->outgoing().push_back(born->bornOutgoing()[ix]->dataPtr()->produceParticle(pnew)); + } + // then emitter, spectator and emitted + // emission of a final-state gluon if(itype==0) { // get the momenta of the new particles Lorentz5Momentum pquark(pnew[0]),panti(pnew[1]),pgluon(pnew[2]); if(iemit==2) swap(pquark,panti); // ensure gluon can be put on shell Lorentz5Momentum ptest(pgluon); if(ptest.boost(-(pquark+panti).boostVector()).e() < - getParticleData(ParticleID::g)->constituentMass()) return; - // create the new gluon - PPtr newg= getParticleData(ParticleID::g)->produceParticle(pgluon); - PPtr newq,newa; - ColinePtr col; - // make the new particles - if(iemit==1) { - col=incoming[0]->colourLine(); - newq = getParticleData(incoming[0]->id())->produceParticle(pquark); - newa = new_ptr(Particle(*incoming[1])); - col->removeAntiColoured(newa); - newa->set5Momentum(panti); + getParticleData(ParticleID::g)->constituentMass()) return RealEmissionProcessPtr(); + // outgoing gluon + born->outgoing().push_back(getParticleData(ParticleID::g)->produceParticle(pgluon)); + // incoming particles + if(born->bornIncoming()[0]->id()>0) { + if(iemit==1) { + born->emitter(0); + born->spectator(1); + } + else { + born->emitter(1); + born->spectator(0); + } + born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->produceParticle(pquark)); + born->incoming().push_back(born->bornIncoming()[1]->dataPtr()->produceParticle(panti)); + born->outgoing().back()->incomingColour(born->incoming()[0]); + born->outgoing().back()->incomingAntiColour(born->incoming()[1]); } else { - col=incoming[1]->antiColourLine(); - newa = getParticleData(incoming[1]->id())->produceParticle(panti); - newq = new_ptr(Particle(*incoming[0])); - col->removeColoured(newq); - newq->set5Momentum(pquark); - } - // set the colour lines - ColinePtr newline=new_ptr(ColourLine()); - if(iemit==1) { - newline->addColoured(newq); - newline->addColoured(newg); - col->addAntiColoured(newg); - col->addAntiColoured(newa); - } - else { - newline->addAntiColoured(newa); - newline->addAntiColoured(newg); - col->addColoured(newg); - col->addColoured(newq); - } - // change the existing quark and antiquark - PPtr orig; - for(cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(cit->first->progenitor()->id()==newq->id()) { - // remove old particles from colour line - col->removeColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newq); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newq,1,false))); - sp->x(xnew.first); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(iemit!=1); - if(iemit==1) orig=cit->first->original(); + if(iemit==1) { + born->emitter(1); + born->spectator(0); } else { - // remove old particles from colour line - col->removeAntiColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newa); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newa,1,false))); - sp->x(xnew.second); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(iemit==1); - if(iemit==2) orig=cit->first->original(); + born->emitter(0); + born->spectator(1); } + born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->produceParticle(panti)); + born->incoming().push_back(born->bornIncoming()[1]->dataPtr()->produceParticle(pquark)); + born->outgoing().back()->incomingColour(born->incoming()[1]); + born->outgoing().back()->incomingAntiColour(born->incoming()[0]); } - // fix the momentum of the gauge boson - Boost boostv=pboson.findBoostToCM(); - trans *=LorentzRotation(boostv); - for( map::const_iterator - cjt= tree->outgoingLines().begin(); - cjt != tree->outgoingLines().end();++cjt ) { - cjt->first->progenitor()->transform(trans); - cjt->first->copy()->transform(trans); - } - tree->hardMatrixElementCorrection(true); - // add the gluon - ShowerParticlePtr sg=new_ptr(ShowerParticle(*newg,1,true)); - ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg)); - gluon->perturbative(false); - tree->outgoingLines().insert(make_pair(gluon,sg)); } else if(itype==1) { Lorentz5Momentum pin(pnew[0]),pout(pnew[1]),pgluon(pnew[2]); if(iemit==2) swap(pin,pout); // ensure outgoing quark can be put on-shell Lorentz5Momentum ptest(pout); if(ptest.boost(-(pin+pgluon).boostVector()).e() < - incoming[1]->dataPtr()->constituentMass()) return; + incoming[1]->dataPtr()->constituentMass()) return RealEmissionProcessPtr(); // create the new gluon PPtr newg = getParticleData(ParticleID::g)->produceParticle(pgluon); // create the new outgoing quark - PPtr newout= getParticleData(-incoming[1]->id())->produceParticle(pout); + PPtr newout= incoming[1]->dataPtr()->CC()->produceParticle(pout); // create the new incoming quark - PPtr newin = new_ptr(Particle(*incoming[0])); - newin->set5Momentum(pin); - // colour info - ColinePtr col=incoming[0]->colourLine(); - col->removeColoured(newin); - ColinePtr newline=new_ptr(ColourLine()); - newline->addColoured(newout); - newline->addColoured(newg); - col->addAntiColoured(newg); - col->addColoured(newin); - // change the existing incoming partons - PPtr orig; - for(cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(cit->first->progenitor()->id()==newin->id()) { - // remove old particles from colour line - col->removeColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newin); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newin,1,false))); - sp->x(xnew.first); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(true); - } - else { - // remove old particles from colour line - col->removeAntiColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newg); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newg,1,false))); - sp->x(xnew.second); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(false); - orig=cit->first->original(); - } + PPtr newin = incoming[0]->dataPtr()->produceParticle(pin); + // colours + newout->incomingColour(newg); + newin->antiColourNeighbour(newg); + if(born->bornIncoming()[0]->id()>0) { + born->emitter (1); + born->spectator(0); + born->incoming().push_back(newin); + born->incoming().push_back(newg ); } - // fix the momentum of the gauge boson - Boost boostv=pboson.findBoostToCM(); - trans *=LorentzRotation(boostv); - for( map::const_iterator - cjt= tree->outgoingLines().begin(); - cjt != tree->outgoingLines().end();++cjt ) { - cjt->first->progenitor()->transform(trans); - cjt->first->copy()->transform(trans); + else { + born->emitter (0); + born->spectator(1); + born->incoming().push_back(newg ); + born->incoming().push_back(newin); } - tree->hardMatrixElementCorrection(true); - // add the outgoing quark - ShowerParticlePtr sout=new_ptr(ShowerParticle(*newout,1,true)); - ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(orig,newout,sout)); - out->perturbative(false); - tree->outgoingLines().insert(make_pair(out,sout)); + born->outgoing().push_back(newout); } else if(itype==2) { Lorentz5Momentum pin(pnew[0]),pout(pnew[1]),pgluon(pnew[2]); if(iemit==2) swap(pin,pout); // ensure outgoing antiquark can be put on-shell - Lorentz5Momentum ptest(pout); - if(ptest.boost(-(pin+pgluon).boostVector()).e() < - incoming[0]->dataPtr()->constituentMass()) return; - // create the new gluon - PPtr newg = getParticleData(ParticleID::g)->produceParticle(pgluon); - // create the new outgoing antiquark - PPtr newout= getParticleData(-incoming[0]->id())->produceParticle(pout); - // create the new incoming antiquark - PPtr newin = new_ptr(Particle(*incoming[1])); - newin->set5Momentum(pin); - // colour info - ColinePtr col=incoming[0]->colourLine(); - col->removeAntiColoured(newin); - ColinePtr newline=new_ptr(ColourLine()); - newline->addAntiColoured(newout); - newline->addAntiColoured(newg); - col->addColoured(newg); - col->addAntiColoured(newin); - // change the existing incoming partons - PPtr orig; - for(cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(cit->first->progenitor()->id()==newin->id()) { - // remove old particles from colour line - col->removeAntiColoured(cit->first->copy()); - col->removeAntiColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newin); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newin,1,false))); - sp->x(xnew.second); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(true); - } - else { - // remove old particles from colour line - col->removeColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newg); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newg,1,false))); - sp->x(xnew.first); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(false); - orig=cit->first->original(); - } + Lorentz5Momentum ptest(pout); + if(ptest.boost(-(pin+pgluon).boostVector()).e() < + incoming[0]->dataPtr()->constituentMass()) return RealEmissionProcessPtr(); + // create the new gluon + PPtr newg = getParticleData(ParticleID::g)->produceParticle(pgluon); + // create the new outgoing antiquark + PPtr newout= incoming[0]->dataPtr()->CC()->produceParticle(pout); + // create the new incoming antiquark + PPtr newin = incoming[1]->dataPtr()->produceParticle(pin); + // colours + newout->incomingAntiColour(newg); + newin->colourNeighbour(newg); + if(born->bornIncoming()[0]->id()>0) { + born->emitter (0); + born->spectator(1); + born->incoming().push_back(newg ); + born->incoming().push_back(newin); } - // fix the momentum of the gauge boson - Boost boostv=pboson.findBoostToCM(); - trans *=LorentzRotation(boostv); - for( map::const_iterator - cjt= tree->outgoingLines().begin(); - cjt != tree->outgoingLines().end();++cjt ) { - cjt->first->progenitor()->transform(trans); - cjt->first->copy()->transform(trans); + else { + born->emitter (1); + born->spectator(0); + born->incoming().push_back(newin); + born->incoming().push_back(newg ); } - tree->hardMatrixElementCorrection(true); - // add the outgoing antiquark - ShowerParticlePtr sout=new_ptr(ShowerParticle(*newout,1,true)); - ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(orig,newout,sout)); - out->perturbative(false); - tree->outgoingLines().insert(make_pair(out,sout)); + born->outgoing().push_back(newout); } + else + assert(false); + born->emitted(born->outgoing().size()+1); + if(born->bornIncoming()[0]->id()<0) { + swap(xnew.first,xnew.second); + } + born->x(xnew); + born->interaction(ShowerInteraction::QCD); + return born; } -bool DrellYanBase::applyHard(ShowerParticleVector quarks, +bool DrellYanBase::applyHard(ParticleVector & quarks, vector beams, Lorentz5Momentum boson, unsigned int & iemit,unsigned int & itype, vector & pnew, LorentzRotation & trans, pair & xout) { // check that quark along +z and qbar along -z bool quarkplus=quarks[0]->momentum().z()>quarks[1]->momentum().z(); // calculate the limits on s Energy mb = sqrt(mb2_); Energy2 smin=mb2_; Energy2 s= (generator()->currentEvent()->incoming().first ->momentum()+ generator()->currentEvent()->incoming().second->momentum()).m2(); Energy2 smax(s); // calculate the rapidity of the boson double yB=0.5*log((boson.e()+boson.z())/ (boson.e()-boson.z())); if(!quarkplus) yB=-yB; // if no phase-space return if(smaxx(); assert(beams[ix]); pdf[ix]=beams[ix]->pdf(); assert(pdf[ix]); fx[ix]=pdf[ix]->xfx(beams[ix],quarks[ix]->dataPtr(),mb2_,x[ix]); } // select the type of process and generate the kinematics double rn(UseRandom::rnd()); Energy2 shat(ZERO),uhat(ZERO),that(ZERO); double weight(0.),xnew[2]={1.,1.}; // generate the value of s according to 1/s^2 shat = smax*smin/(smin+UseRandom::rnd()*(smax-smin)); Energy2 jacobian = sqr(shat)*(1./smin-1./smax); double sbar=shat/mb2_; // calculate limits on that Energy2 tmax=mb2_*kappa[0]*(1.-sbar)/(kappa[0]+sbar); Energy2 tmin=shat*(1.-sbar)/(kappa[1]+sbar); // calculate the limits on uhat Energy2 umax(mb2_-shat-tmin),umin(mb2_-shat-tmax); // check inside phase space if(tmax g V if(rn<_channelweights[0]) { // generate t and u according to 1/t+1/u // generate in 1/t if(UseRandom::rndbool(0.5)) { that=tmax*pow(tmin/tmax,UseRandom::rnd()); uhat=mb2_-shat-that; jacobian *=log(tmin/tmax); } // generate in 1/u else { uhat=umax*pow(umin/umax,UseRandom::rnd()); that=mb2_-shat-uhat; jacobian *=log(umin/umax); } Energy4 jacobian2 = jacobian * 2.*uhat*that/(shat-mb2_); // new scale (this is mt^2=pt^2+mb^2) Energy2 scale(uhat*that/shat+mb2_); // the PDF's with the emitted gluon double fxnew[2]; xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-uhat)/(mb2_-that)); xnew[1]=shat/(s*xnew[0]); for(unsigned int ix=0;ix<2;++ix) {fxnew[ix]=pdf[ix]->xfx(beams[ix],quarks[ix]->dataPtr(),scale,xnew[ix]);} // jacobian and me parts of the weight weight=jacobian2*(sqr(mb2_-that)+sqr(mb2_-uhat))/(sqr(shat)*that*uhat); // pdf part of the weight weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]); // finally coupling, colour factor and different channel pieces weight *= 2./3./Constants::pi/_channelweights[0]*_alpha->value(scale); // select the emiting particle iemit=1; if(UseRandom::rnd()_channelweights[1]) { swap(tmax,tmin); tmax=mb2_-shat-tmax; tmin=mb2_-shat-tmin; } that=tmax*pow(tmin/tmax,UseRandom::rnd()); uhat=mb2_-shat-that; Energy4 jacobian2 = jacobian * that*log(tmax/tmin); // new scale (this is mt^2=pt^2+mb^2) Energy2 scale(uhat*that/shat+mb2_); // g qbar -> qbar V double fxnew[2]; if(rn<_channelweights[1]) { itype=2; xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-uhat)/(mb2_-that)); xnew[1]=shat/(s*xnew[0]); fxnew[0]=pdf[0]->xfx(beams[0],getParticleData(ParticleID::g),scale,xnew[0]); fxnew[1]=pdf[1]->xfx(beams[1],quarks[1]->dataPtr(),scale,xnew[1]); jacobian2/=(_channelweights[1]-_channelweights[0]); } // q g -> q V else { itype=1; xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-that)/(mb2_-uhat)); xnew[1]=shat/(s*xnew[0]); fxnew[0]=pdf[0]->xfx(beams[0],quarks[0]->dataPtr(),scale,xnew[0]); fxnew[1]=pdf[1]->xfx(beams[1],getParticleData(ParticleID::g),scale,xnew[1]); jacobian2/=(_channelweights[2]-_channelweights[1]); } // jacobian and me parts of the weight weight=-jacobian2*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat)*shat*that); // pdf part of the weight weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]); // finally coupling, colour factor and different channel pieces weight *= 0.25/Constants::pi*_alpha->value(scale); // select the emiting particle iemit=1; if(UseRandom::rnd()1.) { ++_nover; _maxwgt=max(_maxwgt,weight); weight=1.; } if(UseRandom::rnd()>weight) return false; // construct the momenta in the rest frame of the boson Lorentz5Momentum pb(ZERO,ZERO,ZERO,mb,mb),pspect,pg,pemit; double cos3 = 0.0; if(itype==0) { pg = Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(shat-mb2_)/mb,ZERO); Energy2 tp(that),up(uhat); double zsign(-1.); if(iemit==2) { tp=uhat; up=that; zsign=1.; } pspect = Lorentz5Momentum(ZERO,ZERO,zsign*0.5*(mb2_-tp)/mb, 0.5*(mb2_-tp)/mb,ZERO); Energy eemit=0.5*(mb2_-up)/mb; cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit)); } else { pg=Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(mb2_-uhat)/mb,ZERO); double zsign(1.); if(iemit==1) { if(itype==1) zsign=-1.; pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(shat-mb2_)/mb, 0.5*(shat-mb2_)/mb); Energy eemit=0.5*(mb2_-that)/mb; cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit)); } else { if(itype==2) zsign=-1.; pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(mb2_-that)/mb, 0.5*(mb2_-that)/mb); Energy eemit=0.5*(shat-mb2_)/mb; cos3 = 0.5/pspect.z()/pg.e()*(-sqr(pspect.e())-sqr(pg.e())+sqr(eemit)); } } // rotate the gluon double sin3(sqrt(1.-sqr(cos3))); double phi(Constants::twopi*UseRandom::rnd()); pg.setX(pg.e()*sin3*cos(phi)); pg.setY(pg.e()*sin3*sin(phi)); pg.setZ(pg.e()*cos3); if(itype==0) { pemit=pb+pg-pspect; } else { if(iemit==1) pemit=pb+pspect-pg; else pemit=pspect+pg-pb; } pemit.rescaleMass(); // find the new CMF Lorentz5Momentum pp[2]; if(itype==0) { if(iemit==1) { pp[0]=pemit; pp[1]=pspect; } else { pp[0]=pspect; pp[1]=pemit; } } else if(itype==1) { pp[1]=pg; if(iemit==1) pp[0]=pemit; else pp[0]=pspect; } else { pp[0]=pg; if(iemit==1) pp[1]=pemit; else pp[1]=pspect; } Lorentz5Momentum pz= quarkplus ? pp[0] : pp[1]; pp[0]/=xnew[0]; pp[1]/=xnew[1]; Lorentz5Momentum plab(pp[0]+pp[1]); plab.rescaleMass(); // construct the boost to rest frame of plab trans=LorentzRotation(plab.findBoostToCM()); pz.transform(trans); // rotate so emitting particle along z axis // rotate so in x-z plane trans.rotateZ(-atan2(pz.y(),pz.x())); // rotate so along trans.rotateY(-acos(pz.z()/pz.vect().mag())); // undo azimuthal rotation trans.rotateZ(atan2(pz.y(),pz.x())); // perform the transforms pb .transform(trans); pspect.transform(trans); pg .transform(trans); pemit .transform(trans); // momenta to be returned pnew.push_back(pemit); pnew.push_back(pspect); pnew.push_back(pg); pnew.push_back(pb); xout.first=xnew[0]; xout.second=xnew[1]; return true; } bool DrellYanBase::softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent,Branching br) { if(parent->isFinalState()) return false; // check if me correction should be applied long id[2]={initial->id(),parent->id()}; if(id[0]!=id[1]||id[1]==ParticleID::g) return false; // get the pT Energy pT=br.kinematics->pT(); // check if hardest so far if(pThighestpT()) return false; // compute the invariants double kappa(sqr(br.kinematics->scale())/mb2_),z(br.kinematics->z()); Energy2 shat(mb2_/z*(1.+(1.-z)*kappa)),that(-(1.-z)*kappa*mb2_),uhat(-(1.-z)*shat); // check which type of process // g qbar double wgt(1.); if(id[0]>0&&br.ids[0]->id()==ParticleID::g) wgt=mb2_/(shat+uhat)*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat+uhat)+sqr(uhat)); else if(id[0]>0&&br.ids[0]->id()==id[0]) wgt=mb2_/(shat+uhat)*(sqr(mb2_-uhat)+sqr(mb2_-that))/(sqr(shat)+sqr(shat+uhat)); else if(id[0]<0&&br.ids[0]->id()==ParticleID::g) wgt=mb2_/(shat+uhat)*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat+uhat)+sqr(uhat)); - else if(id[0]<0&&br.ids[0]->id()==-id[0]) + else if(id[0]<0&&br.ids[0]->id()==id[0]) wgt=mb2_/(shat+uhat)*(sqr(mb2_-uhat)+sqr(mb2_-that))/(sqr(shat)+sqr(shat+uhat)); - else return false; + else + return false; if(wgt<.0||wgt>1.) generator()->log() << "Soft ME correction weight too large or " << "negative in DrellYanBase::" << "softMatrixElementVeto()soft weight " << " sbar = " << shat/mb2_ << " tbar = " << that/mb2_ << "weight = " << wgt << "\n"; // if not vetoed if(UseRandom::rndbool(wgt)) return false; // otherwise parent->vetoEmission(br.type,br.kinematics->scale()); return true; } -HardTreePtr DrellYanBase::generateHardest(ShowerTreePtr tree, - ShowerInteraction::Type inter) { +RealEmissionProcessPtr DrellYanBase::generateHardest(RealEmissionProcessPtr born, + ShowerInteraction::Type inter) { // check if generating QCD radiation if(inter!=ShowerInteraction::QCD && inter!=ShowerInteraction::QEDQCD && inter!=ShowerInteraction::ALL) - return HardTreePtr(); + return RealEmissionProcessPtr(); useMe(); // get the particles to be showered _beams.clear(); _partons.clear(); // find the incoming particles - ShowerParticleVector incoming; - map::const_iterator cit; + ParticleVector incoming; _quarkplus = true; - vector particlesToShower; - //progenitor particles are produced in z direction. - for( cit = tree->incomingLines().begin(); cit != tree->incomingLines().end(); ++cit ) { - incoming.push_back( cit->first->progenitor() ); - _beams.push_back( cit->first->beam() ); - _partons.push_back( cit->first->progenitor()->dataPtr() ); + ParticleVector particlesToShower; + // progenitor particles are produced in z direction. + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + incoming.push_back(born->bornIncoming()[ix]); + tPPtr beam = born->hadrons()[ix]; + _beams.push_back(dynamic_ptr_cast(beam->dataPtr())); + _partons.push_back( born->bornIncoming()[ix]->dataPtr() ); // check that quark is along +ve z direction - if(cit->first->progenitor()->id() > 0 && - cit->first->progenitor()->momentum().z() < ZERO ) + if(born->bornIncoming()[ix]->id() > 0 && + born->bornIncoming()[ix]->momentum().z() < ZERO ) _quarkplus = false; - particlesToShower.push_back( cit->first ); + particlesToShower.push_back( born->bornIncoming()[ix] ); } Lorentz5Momentum pboson; - for( map::const_iterator - cjt= tree->outgoingLines().begin(); - cjt != tree->outgoingLines().end();++cjt ) { - pboson += cjt->first->original()->momentum(); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + pboson += born->bornOutgoing()[ix]->momentum(); } pboson.rescaleMass(); // calculate the rapidity of the boson _yb = 0.5 * log((pboson.e()+pboson.z())/(pboson.e()-pboson.z())); _yb *= _quarkplus ? 1. : -1.; _mass = pboson.mass(); // we are assuming quark first, swap order to ensure this // if antiquark first - if(_partons[0]->id()<_partons[1]->id()) { + bool order = _partons[0]->id()<_partons[1]->id(); + if(order) { swap(_partons[0],_partons[1]); swap(_beams[0],_beams[1]); } vector pnew; int emission_type(-1); // generate the hard emission and return if no emission if(!getEvent(pnew,emission_type)) { - for(unsigned int ix=0;ixmaximumpT(_min_pt,ShowerInteraction::QCD); - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = _min_pt; + return born; } // construct the HardTree object needed to perform the showers - ShowerParticleVector newparticles; + ParticleVector newparticles; // make the particles for the HardTree tcPDPtr gluon=getParticleData(ParticleID::g); // create the partons int iemit; // q qbar -> g V ColinePtr newline[2]={new_ptr(ColourLine()),new_ptr(ColourLine())}; if(emission_type==0) { - newparticles.push_back(new_ptr(ShowerParticle(_partons[0] ,false))); - newparticles.push_back(new_ptr(ShowerParticle(_partons[1] ,false))); - newparticles.push_back(new_ptr(ShowerParticle(gluon , true))); + newparticles.push_back(_partons[0]->produceParticle(pnew[0])); + newparticles.push_back(_partons[1]->produceParticle(pnew[1])); + newparticles.push_back(gluon ->produceParticle(pnew[2])); newline[1]->addColoured(newparticles[0]); newline[1]->addColoured(newparticles[2]); newline[0]->addAntiColoured(newparticles[1]); newline[0]->addAntiColoured(newparticles[2]); iemit = (pnew[0]-pnew[2]).m2()>(pnew[1]-pnew[2]).m2() ? 0 : 1; } // q g -> q V else if(emission_type==1) { - iemit=1; - newparticles.push_back(new_ptr(ShowerParticle(_partons[0] ,false))); - newparticles.push_back(new_ptr(ShowerParticle(gluon ,false))); - newparticles.push_back(new_ptr(ShowerParticle(_partons[1]->CC(), true))); + iemit =1; + newparticles.push_back(_partons[0]->produceParticle(pnew[0])); + newparticles.push_back(gluon ->produceParticle(pnew[1])); + newparticles.push_back(_partons[1]->CC()->produceParticle(pnew[2])); newline[1]->addColoured(newparticles[0]); newline[1]->addAntiColoured(newparticles[1]); newline[0]->addColoured(newparticles[1]); newline[0]->addColoured(newparticles[2]); } // g qbar -> qbar V else { - iemit=0; - newparticles.push_back(new_ptr(ShowerParticle(gluon ,false))); - newparticles.push_back(new_ptr(ShowerParticle(_partons[1] ,false))); - newparticles.push_back(new_ptr(ShowerParticle(_partons[0]->CC(), true))); + iemit =0; + newparticles.push_back(gluon ->produceParticle(pnew[0])); + newparticles.push_back(_partons[1]->produceParticle(pnew[1])); + newparticles.push_back(_partons[0]->CC()->produceParticle(pnew[2])); newline[0]->addAntiColoured(newparticles[1]); newline[0]->addColoured(newparticles[0]); newline[1]->addAntiColoured(newparticles[0]); newline[1]->addAntiColoured(newparticles[2]); } - // set the momenta - for(unsigned int ix=0;ix<3;++ix) newparticles[ix]->set5Momentum(pnew[ix]); - // create the off-shell particle - Lorentz5Momentum poff=pnew[iemit]-pnew[2]; - poff.rescaleMass(); - newparticles.push_back(new_ptr(ShowerParticle(_partons[iemit],false))); - newparticles.back()->set5Momentum(poff); - if(iemit==0) { - newline[0]->addColoured(newparticles.back()); - } - else { - newline[1]->addAntiColoured(newparticles.back()); - } + int ispect = iemit == 0 ? 1 : 0; + if(iemit==0) newline[0]->addColoured(newparticles.back()); + else newline[1]->addAntiColoured(newparticles.back()); // compute the boost for the bosons LorentzRotation boost(pboson.findBoostToCM()); boost.boost(pnew[3].boostVector()); - for( map::const_iterator - cjt= tree->outgoingLines().begin(); - cjt != tree->outgoingLines().end();++cjt ) { - newparticles.push_back(new_ptr(ShowerParticle(cjt->first->original()->dataPtr(), - true))); - newparticles.back()->set5Momentum(boost*cjt->first->original()->momentum()); + born->transformation(boost); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + born->outgoing().push_back(born->bornOutgoing()[ix]->dataPtr()-> + produceParticle(born->bornOutgoing()[ix]->momentum())); + born->outgoing().back()->transform(boost); } - vector inBranch,hardBranch; - // create the branchings for the incoming particles - inBranch.push_back(new_ptr(HardBranching(newparticles[0],SudakovPtr(), - HardBranchingPtr(),HardBranching::Incoming))); - inBranch.push_back(new_ptr(HardBranching(newparticles[1],SudakovPtr(), - HardBranchingPtr(),HardBranching::Incoming))); - // intermediate IS particle - hardBranch.push_back(new_ptr(HardBranching(newparticles[3],SudakovPtr(), - inBranch[iemit],HardBranching::Incoming))); - inBranch[iemit]->addChild(hardBranch.back()); - inBranch[iemit]->type(hardBranch.back()->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - // create the branching for the emitted jet - inBranch[iemit]->addChild(new_ptr(HardBranching(newparticles[2],SudakovPtr(), - inBranch[iemit],HardBranching::Outgoing))); - // set the colour partners - hardBranch.back()->colourPartner(inBranch[iemit==0 ? 1 : 0]); - inBranch[iemit==0 ? 1 : 0]->colourPartner(hardBranch.back()); - // add other particle - hardBranch.push_back(inBranch[iemit==0 ? 1 : 0]); - // outgoing particles - for(unsigned int ix=4;ixincoming().push_back(newparticles[0]); + born->incoming().push_back(newparticles[1]); } - // make the tree - HardTreePtr hardtree=new_ptr(HardTree(hardBranch,inBranch,ShowerInteraction::QCD)); - // connect the ShowerParticles with the branchings - // and set the maximum pt for the radiation - set hard=hardtree->branchings(); - for(unsigned int ix=0;ixmaximumpT(_min_pt,ShowerInteraction::QCD); - else particlesToShower[ix]->maximumpT(_pt,ShowerInteraction::QCD); - for(set::const_iterator mit=hard.begin(); - mit!=hard.end();++mit) { - if(particlesToShower[ix]->progenitor()->id()==(*mit)->branchingParticle()->id()&& - (( particlesToShower[ix]->progenitor()->isFinalState()&& - (**mit).status()==HardBranching::Outgoing)|| - (!particlesToShower[ix]->progenitor()->isFinalState()&& - (**mit).status()==HardBranching::Incoming))) { - hardtree->connect(particlesToShower[ix]->progenitor(),*mit); - if((**mit).status()==HardBranching::Incoming) { - (*mit)->beam(particlesToShower[ix]->original()->parents()[0]); - } - HardBranchingPtr parent=(*mit)->parent(); - while(parent) { - parent->beam(particlesToShower[ix]->original()->parents()[0]); - parent=parent->parent(); - }; - } - } + else { + born->incoming().push_back(newparticles[1]); + born->incoming().push_back(newparticles[0]); + swap(iemit,ispect); } - // return the tree - return hardtree; + born->outgoing().push_back(newparticles[2]); + born->emitter (iemit ); + born->spectator(ispect); + born->emitted(born->bornOutgoing().size()+2); + pair xnew; + for(unsigned int ix=0;ix<2;++ix) { + double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); + if(ix==0) xnew.first = x; + else xnew.second = x; + } + born->x(xnew); + born->pT()[ShowerInteraction::QCD] = _pt; + born->interaction(ShowerInteraction::QCD); + return born; } double DrellYanBase::getResult(int emis_type, Energy pt, double yj) { Energy2 s=sqr(generator()->maximumCMEnergy()); Energy2 m2(sqr(_mass)); Energy2 scale = m2+sqr(pt); Energy et=sqrt(scale); // longitudinal real correction fractions double x = pt*exp( yj)/sqrt(s)+et*exp( _yb)/sqrt(s); double y = pt*exp(-yj)/sqrt(s)+et*exp(-_yb)/sqrt(s); // reject if outside region if(x<0.||x>1.||y<0.||y>1.||x*ypdf()->xfx(_beams[0],_partons[0],m2,x1); pdf[1]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],m2,y1); //qqbar2Zg using Constants::pi; if(emis_type==0) { pdf[2]=_beams[0]->pdf()->xfx(_beams[0],_partons[0],scale,x); pdf[3]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],scale,y); res = 4./3./pi*(sqr(th-m2)+sqr(uh-m2))*pt/(sh*uh*th)*GeV; } //qg2Zq else if(emis_type==1) { pdf[2]=_beams[0]->pdf()->xfx(_beams[0],_partons[0],scale,x); pdf[3]=_beams[1]->pdf()->xfx(_beams[1],getParticleData(ParticleID::g),scale,y); res = -1./2./pi*(sqr(uh-m2)+sqr(sh-m2))*pt/(sh*sh*uh)*GeV; } //qbarg2Zqbar else { pdf[2]=_beams[0]->pdf()->xfx(_beams[0],getParticleData(ParticleID::g),scale,x); pdf[3]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],scale,y); res =- 1./2./pi*(sqr(th-m2)+sqr(sh-m2))*pt/(sh*sh*th)*GeV; } //deals with pdf zero issue at large x if(pdf[0]<=0.||pdf[1]<=0.||pdf[2]<=0.||pdf[3]<=0.) { res=0.; } else { res*=pdf[2]*pdf[3]/pdf[0]/pdf[1]*m2/sh; } res*=_alpha->ratio(sqr(pt)); return res; } bool DrellYanBase::getEvent(vector & pnew, int & emis_type){ // pt cut-off // Energy minp = 0.1*GeV; // maximum pt (half of centre-of-mass energy) Energy maxp = 0.5*generator()->maximumCMEnergy(); // set pt of emission to zero _pt=ZERO; //Working Variables Energy pt; double yj; // limits on the rapidity of the jet double minyj = -8.0,maxyj = 8.0; bool reject; double wgt; emis_type=-1; for(int j=0;j<3;j++) { pt=maxp; double a = _alpha->overestimateValue()*_prefactor[j]*(maxyj-minyj)/(_power-1.); do { // generate next pt pt=GeV/pow(pow(GeV/pt,_power-1)-log(UseRandom::rnd())/a,1./(_power-1.)); // generate rapidity of the jet yj=UseRandom::rnd()*(maxyj-minyj)+ minyj; // calculate rejection weight wgt=getResult(j,pt,yj); wgt/= _prefactor[j]*pow(GeV/pt,_power); reject = UseRandom::rnd()>wgt; //no emission event if p goes past p min - basically set to outside //of the histogram bounds (hopefully hist object just ignores it) if(pt<_min_pt){ pt=ZERO; reject = false; } if(wgt>1.0) { ostringstream s; s << "DrellYanBase::getEvent weight for channel " << j << "is " << wgt << " which is greater than 1"; generator()->logWarning( Exception(s.str(), Exception::warning) ); } } while(reject); // set pt of emission etc if(pt>_pt){ emis_type = j; _pt=pt; _yj=yj; } } //was this an (overall) no emission event? if(_pt<_min_pt){ _pt=ZERO; emis_type = 3; } if(emis_type==3) return false; // generate the momenta of the particles // hadron-hadron cmf Energy2 s=sqr(generator()->maximumCMEnergy()); // transverse energy Energy2 m2(sqr(_mass)); Energy et=sqrt(m2+sqr(_pt)); // first calculate all the kinematic variables // longitudinal real correction fractions double x = _pt*exp( _yj)/sqrt(s)+et*exp( _yb)/sqrt(s); double y = _pt*exp(-_yj)/sqrt(s)+et*exp(-_yb)/sqrt(s); // that and uhat Energy2 th = -sqrt(s)*x*_pt*exp(-_yj); Energy2 uh = -sqrt(s)*y*_pt*exp( _yj); Energy2 sh = x*y*s; if(emis_type==1) swap(th,uh); // decide which was the emitting particle unsigned int iemit=1; // from q qbar if(emis_type==0) { if(UseRandom::rnd() beams, Lorentz5Momentum boson,unsigned int & iemit, unsigned int & itype,vector & pnew, LorentzRotation & trans, pair & xnew); /** * Returns the matrix element for a given type of process, * rapidity of the jet \f$y_j\f$ and transverse momentum \f$p_T\f$ * @param emis_type the type of emission, * (0 is \f$q\bar{q}\to Vg\f$, 1 is \f$qg\to Vq\f$ and 2 is \f$g\bar{q}\to V\bar{q}\f$) * @param pt The transverse momentum of the jet * @param yj The rapidity of the jet */ double getResult(int emis_type, Energy pt, double yj); /** * generates the hardest emission (yj,p) * @param pnew The momenta of the new particles * @param emissiontype The type of emission, as for getResult * @return Whether not an emission was generated */ bool getEvent(vector & pnew,int & emissiontype); 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(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initDrellYanBase; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DrellYanBase & operator=(const DrellYanBase &); private: /** * Mass squared of the vector boson */ Energy2 mb2_; /** * Parameters for the old-style ME correction */ //@{ /** * Relative weight for the \f$q\bar{q}\f$ and \f$q/\bar{q}g\f$ channels */ double _channelwgtA; /** * Relative weight for the \f$qg\f$ and \f$\bar{q}g\f$ channels */ double _channelwgtB; /** * Weights for the channels as a vector */ vector _channelweights; /** * Number of weights greater than 1 */ unsigned int _nover; /** * Maximum weight */ double _maxwgt; //@} /** * Constants for the sampling. The distribution is assumed to have the * form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$ */ //@{ /** * The power, \f$n\f$, for the sampling */ double _power; /** * The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel */ double _preqqbar; /** * The prefactor, \f$c\f$ for the \f$qg\f$ channel */ double _preqg; /** * The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel */ double _pregqbar; /** * The prefactors as a vector for easy use */ vector _prefactor; //@} /** * Properties of the incoming particles */ //@{ /** * Pointers to the BeamParticleData objects */ vector _beams; /** * Pointers to the ParticleDataObjects for the partons */ vector _partons; //@} /** * Properties of the boson and jets */ //@{ /** * The rapidity of the gauge boson */ double _yb; /** * The mass of the gauge boson */ Energy _mass; /** * Whether the quark is in the + or - z direction */ bool _quarkplus; /** * the rapidity of the jet */ double _yj; /** * The transverse momentum of the jet */ Energy _pt; //@} /** * The transverse momentum of the jet */ Energy _min_pt; /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr _alpha; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DrellYanBase. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DrellYanBase. */ typedef Herwig::HwMEBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DrellYanBase 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::DrellYanBase"; } }; /** @endcond */ } #endif /* HERWIG_DrellYanBase_H */ diff --git a/MatrixElement/Hadron/MEPP2Higgs.cc b/MatrixElement/Hadron/MEPP2Higgs.cc --- a/MatrixElement/Hadron/MEPP2Higgs.cc +++ b/MatrixElement/Hadron/MEPP2Higgs.cc @@ -1,1627 +1,1444 @@ // -*- C++ -*- // // MEPP2Higgs.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 MEPP2Higgs class. // #include "MEPP2Higgs.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Cuts/Cuts.h" #include "Herwig/MatrixElement/HardVertex.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/Utilities/Maths.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/Branching.h" -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" using namespace Herwig; const complex MEPP2Higgs::epsi_ = complex(ZERO,-1.e-10*GeV2); MEPP2Higgs::MEPP2Higgs() : scaleopt_(1), mu_F_(100.*GeV), shapeOption_(2), processOption_(1), minFlavour_(4), maxFlavour_(5), mh_(ZERO), wh_(ZERO), minLoop_(6),maxLoop_(6),massOption_(0), mu_R_opt_(1),mu_F_opt_(1), channelwgtA_(0.45),channelwgtB_(0.15), ggPow_(1.6), qgPow_(1.6), enhance_(1.1), nover_(0), ntry_(0), ngen_(0), maxwgt_(0.), power_(2.0), pregg_(7.), preqg_(3.), pregqbar_(3.), minpT_(2.*GeV), spinCorrelations_(true) {} ClassDescription MEPP2Higgs::initMEPP2Higgs; // Definition of the static class description member. void MEPP2Higgs::persistentOutput(PersistentOStream & os) const { os << HGGVertex_ << HFFVertex_ << shapeOption_ << processOption_ << minFlavour_ << maxFlavour_ << hmass_ << ounit(mh_,GeV) << ounit(wh_,GeV) << minLoop_ << maxLoop_ << massOption_ << alpha_ << prefactor_ << power_ << pregg_ << preqg_ << pregqbar_ << ounit( minpT_, GeV ) << ggPow_ << qgPow_ << enhance_ << channelwgtA_ << channelwgtB_ << channelWeights_ << mu_R_opt_ << mu_F_opt_ << spinCorrelations_; } void MEPP2Higgs::persistentInput(PersistentIStream & is, int) { is >> HGGVertex_ >> HFFVertex_ >> shapeOption_ >> processOption_ >> minFlavour_ >> maxFlavour_ >> hmass_ >> iunit(mh_,GeV) >> iunit(wh_,GeV) >> minLoop_ >> maxLoop_ >> massOption_ >> alpha_ >> prefactor_ >> power_ >> pregg_ >> preqg_ >> pregqbar_ >> iunit( minpT_, GeV ) >> ggPow_ >> qgPow_ >> enhance_ >> channelwgtA_ >> channelwgtB_ >> channelWeights_ >> mu_R_opt_ >> mu_F_opt_ >> spinCorrelations_; } void MEPP2Higgs::Init() { static ClassDocumentation documentation ("The MEPP2Higgs class implements the matrix elements for" " Higgs production (with decay H->W-W+) in hadron-hadron collisions" " including the generation of additional hard QCD radiation in " "gg to h0 processes in the POWHEG scheme", "Hard QCD radiation for $gg\\to h^0$ processes in the" " POWHEG scheme \\cite{Hamilton:2009za}.", "%\\cite{Hamilton:2009za}\n" "\\bibitem{Hamilton:2009za}\n" " K.~Hamilton, P.~Richardson and J.~Tully,\n" " ``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation for Higgs\n" " Boson Production,''\n" " JHEP {\\bf 0904}, 116 (2009)\n" " [arXiv:0903.4345 [hep-ph]].\n" " %%CITATION = JHEPA,0904,116;%%\n"); static Switch interfaceFactorizationScaleOption ("FactorizationScaleOption", "Option for the choice of factorization scale", &MEPP2Higgs::scaleopt_, 1, false, false); static SwitchOption interfaceDynamic (interfaceFactorizationScaleOption, "Dynamic", "Dynamic factorization scale equal to the current sqrt(sHat())", 1); static SwitchOption interfaceFixed (interfaceFactorizationScaleOption, "Fixed", "Use a fixed factorization scale set with FactorizationScaleValue", 2); static Parameter interfaceFactorizationScaleValue ("FactorizationScaleValue", "Value to use in the event of a fixed factorization scale", &MEPP2Higgs::mu_F_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV, true, false, Interface::limited); static Reference interfaceCoupling ("Coupling", "Pointer to the object to calculate the coupling for the correction", &MEPP2Higgs::alpha_, false, false, true, false, false); static Switch interfaceShapeOption ("ShapeScheme", "Option for the treatment of the Higgs resonance shape", &MEPP2Higgs::shapeOption_, 1, false, false); static SwitchOption interfaceStandardShapeFixed (interfaceShapeOption, "FixedBreitWigner", "Breit-Wigner s-channel resonanse", 1); static SwitchOption interfaceStandardShapeRunning (interfaceShapeOption, "MassGenerator", "Use the mass generator to give the shape", 2); static Switch interfaceProcess ("Process", "Which subprocesses to include", &MEPP2Higgs::processOption_, 1, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all subprocesses", 1); static SwitchOption interfaceProcess1 (interfaceProcess, "qqbar", "Only include the incoming q qbar subprocess", 2); static SwitchOption interfaceProcessgg (interfaceProcess, "gg", "Only include the incoming gg subprocess", 3); static Parameter interfaceMinimumInLoop ("MinimumInLoop", "The minimum flavour of the quarks to include in the loops", &MEPP2Higgs::minLoop_, 6, 5, 6, false, false, Interface::limited); static Parameter interfaceMaximumInLoop ("MaximumInLoop", "The maximum flavour of the quarks to include in the loops", &MEPP2Higgs::maxLoop_, 6, 5, 6, false, false, Interface::limited); static Switch interfaceMassOption ("MassOption", "Option for the treatment of the masses in the loop diagrams", &MEPP2Higgs::massOption_, 0, false, false); static SwitchOption interfaceMassOptionFull (interfaceMassOption, "Full", "Include the full mass dependence", 0); static SwitchOption interfaceMassOptionLarge (interfaceMassOption, "Large", "Use the heavy mass limit", 1); static Parameter interfaceMinimumFlavour ("MinimumFlavour", "The minimum flavour of the incoming quarks in the hard process", &MEPP2Higgs::minFlavour_, 4, 3, 5, false, false, Interface::limited); static Parameter interfaceMaximumFlavour ("MaximumFlavour", "The maximum flavour of the incoming quarks in the hard process", &MEPP2Higgs::maxFlavour_, 5, 3, 5, false, false, Interface::limited); static Parameter interfaceQGChannelWeight ("QGChannelWeight", "The relative weights of the g g and q g channels for selection." " This is a technical parameter for the phase-space generation and " "should not affect the results only the efficiency and fraction" " of events with weight > 1.", &MEPP2Higgs::channelwgtA_, 0.45, 0., 1.e10, false, false, Interface::limited); static Parameter interfaceQbarGChannelWeight ("QbarGChannelWeight", "The relative weights of the g g abd qbar g channels for selection." " This is a technical parameter for the phase-space generation and " "should not affect the results only the efficiency and fraction", &MEPP2Higgs::channelwgtB_, 0.15, 0., 1.e10, false, false, Interface::limited); static Parameter interfaceGGPower ("GGPower", "Power for the phase-space sampling of the gg channel", &MEPP2Higgs::ggPow_, 1.6, 1.0, 3.0, false, false, Interface::limited); static Parameter interfaceQGPower ("QGPower", "Power for the phase-space sampling of the qg and qbarg channels", &MEPP2Higgs::qgPow_, 1.6, 1.0, 3.0, false, false, Interface::limited); static Parameter interfaceEnhancementFactor ("InitialEnhancementFactor", "The enhancement factor for initial-state radiation in the shower to ensure" " the weight for the matrix element correction is less than one.", &MEPP2Higgs::enhance_, 1.1, 1.0, 10.0, false, false, Interface::limited); static Parameter interfacePower ("Power", "The power for the sampling of the matrix elements", &MEPP2Higgs::power_, 2.0, 1.0, 10.0, false, false, Interface::limited); static Parameter interfacePrefactorgg ("Prefactorgg", "The prefactor for the sampling of the q qbar channel", &MEPP2Higgs::pregg_, 7.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorqg ("Prefactorqg", "The prefactor for the sampling of the q g channel", &MEPP2Higgs::preqg_, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorgqbar ("Prefactorgqbar", "The prefactor for the sampling of the g qbar channel", &MEPP2Higgs::pregqbar_, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePtMin ("minPt", "The pt cut on hardest emision generation" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &MEPP2Higgs::minpT_, GeV, 2.*GeV, ZERO, 100000.0*GeV, false, false, Interface::limited); static Switch interface_mu_R_Option ("mu_R_Option", "Option to use pT or mT as the scale in alphaS", &MEPP2Higgs::mu_R_opt_, 1, false, false); static SwitchOption interface_mu_R_Option_mT (interface_mu_R_Option, "mT", "Use mT as the scale in alpha_S", 0); static SwitchOption interface_mu_R_Option_pT (interface_mu_R_Option, "pT", "Use pT as the scale in alpha_S", 1); static Switch interface_mu_F_Option ("mu_F_Option", "Option to use pT or mT as the factorization scale in the PDFs", &MEPP2Higgs::mu_F_opt_, 1, false, false); static SwitchOption interface_mu_F_Option_mT (interface_mu_F_Option, "mT", "Use mT as the scale in the PDFs", 0); static SwitchOption interface_mu_F_Option_pT (interface_mu_F_Option, "pT", "Use pT as the scale in the PDFs", 1); static Switch interfaceSpinCorrelations ("SpinCorrelations", "Which on/off spin correlations in the hard process", &MEPP2Higgs::spinCorrelations_, true, false, false); static SwitchOption interfaceSpinCorrelationsYes (interfaceSpinCorrelations, "Yes", "Switch correlations on", true); static SwitchOption interfaceSpinCorrelationsNo (interfaceSpinCorrelations, "No", "Switch correlations off", false); } void MEPP2Higgs::doinit() { HwMEBase::doinit(); // get the vertex pointers from the SM object tcHwSMPtr theSM = dynamic_ptr_cast(standardModel()); // do the initialisation if(!theSM) { throw InitException() << "Wrong type of StandardModel object in MEPP2Higgs::doinit()," << " the Herwig version must be used" << Exception::runerror; } HGGVertex_ = theSM->vertexHGG(); HFFVertex_ = theSM->vertexFFH(); // get the mass generator for the higgs PDPtr h0 = getParticleData(ParticleID::h0); mh_ = h0->mass(); wh_ = h0->generateWidth(mh_); if(h0->massGenerator()) { hmass_=dynamic_ptr_cast(h0->massGenerator()); } if(shapeOption_==2&&!hmass_) throw InitException() << "If using the mass generator for the line shape in MEPP2Higgs::doinit()" << "the mass generator must be an instance of the GenericMassGenerator class" << Exception::runerror; // stuff for the ME correction double total = 1.+channelwgtA_+channelwgtB_; channelWeights_.push_back(1./total); channelWeights_.push_back(channelWeights_.back()+channelwgtA_/total); channelWeights_.push_back(channelWeights_.back()+channelwgtB_/total); // insert the different prefactors in the vector for easy look up prefactor_.push_back(pregg_); prefactor_.push_back(preqg_); prefactor_.push_back(preqg_); prefactor_.push_back(pregqbar_); prefactor_.push_back(pregqbar_); } void MEPP2Higgs::dofinish() { HwMEBase::dofinish(); if(ntry_==0) return; generator()->log() << "MEPP2Higgs when applying the hard correction " << "generated " << ntry_ << " trial emissions of which " << ngen_ << " were accepted\n"; if(nover_==0) return; generator()->log() << "MEPP2Higgs when applying the hard correction " << nover_ << " weights larger than one were generated of which" << " the largest was " << maxwgt_ << "\n"; } unsigned int MEPP2Higgs::orderInAlphaS() const { return 2; } unsigned int MEPP2Higgs::orderInAlphaEW() const { return 1; } Energy2 MEPP2Higgs::scale() const { return scaleopt_ == 1 ? sHat() : sqr(mu_F_); } int MEPP2Higgs::nDim() const { return 0; } bool MEPP2Higgs::generateKinematics(const double *) { Lorentz5Momentum pout = meMomenta()[0] + meMomenta()[1]; pout.rescaleMass(); meMomenta()[2].setMass(pout.mass()); meMomenta()[2] = LorentzMomentum(pout.x(),pout.y(),pout.z(),pout.t()); jacobian(1.0); // check whether it passes all the cuts: returns true if it does vector out(1,meMomenta()[2]); tcPDVector tout(1,mePartonData()[2]); return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]); } void MEPP2Higgs::getDiagrams() const { tcPDPtr h0=getParticleData(ParticleID::h0); // gg -> H process if(processOption_==1||processOption_==3) { tcPDPtr g=getParticleData(ParticleID::g); add(new_ptr((Tree2toNDiagram(2), g, g, 1, h0, -1))); } // q qbar -> H processes if(processOption_==1||processOption_==2) { for ( int i = minFlavour_; i <= maxFlavour_; ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); add(new_ptr((Tree2toNDiagram(2), q, qb, 1, h0, -2))); } } } CrossSection MEPP2Higgs::dSigHatDR() const { using Constants::pi; InvEnergy2 bwfact; if(shapeOption_==1) { bwfact = mePartonData()[2]->generateWidth(sqrt(sHat()))*sqrt(sHat())/pi/ (sqr(sHat()-sqr(mh_))+sqr(mh_*wh_)); } else { bwfact = hmass_->BreitWignerWeight(sqrt(sHat())); } double cs = me2() * jacobian() * pi * double(UnitRemoval::E4 * bwfact/sHat()); return UnitRemoval::InvE2 * sqr(hbarc) * cs; } double MEPP2Higgs::me2() const { double output(0.0); ScalarWaveFunction hout(meMomenta()[2],mePartonData()[2],outgoing); // Safety code to garantee the reliable behaviour of Higgs shape limits // (important for heavy and broad Higgs resonance). Energy hmass = meMomenta()[2].m(); tcPDPtr h0 = mePartonData()[2]; Energy mass = h0->mass(); Energy halfmass = .5*mass; if (.0*GeV > hmass) return 0.0; // stricly speaking the condition is applicable if // h0->widthUpCut() == h0->widthLoCut()... if (h0->widthLoCut() > halfmass) { if ( mass + h0->widthUpCut() < hmass || mass - h0->widthLoCut() > hmass ) return 0.0; } else { if (mass + halfmass < hmass || halfmass > hmass) return 0.0; } if (mePartonData()[0]->id() == ParticleID::g && mePartonData()[1]->id() == ParticleID::g) { VectorWaveFunction gin1(meMomenta()[0],mePartonData()[0],incoming); VectorWaveFunction gin2(meMomenta()[1],mePartonData()[1],incoming); vector g1,g2; for(unsigned int i = 0; i < 2; ++i) { gin1.reset(2*i); g1.push_back(gin1); gin2.reset(2*i); g2.push_back(gin2); } output = ggME(g1,g2,hout,false); } else { if (mePartonData()[0]->id() == -mePartonData()[1]->id()) { SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming); SpinorBarWaveFunction qbin(meMomenta()[1],mePartonData()[1],incoming); vector fin; vector ain; for (unsigned int i = 0; i < 2; ++i) { qin.reset(i); fin.push_back(qin); qbin.reset(i); ain.push_back(qbin); } output = qqME(fin,ain,hout,false); } else assert(false); } return output; } Selector MEPP2Higgs::diagrams(const DiagramVector & diags) const { Selector sel; for (DiagramIndex i = 0; i < diags.size(); ++i) sel.insert(1.0, i); return sel; } Selector MEPP2Higgs::colourGeometries(tcDiagPtr diag) const { // colour lines static const ColourLines line1("1 -2,2 -1"); static const ColourLines line2("1 -2"); // select the colour flow Selector sel; if (diag->id() == -1) { sel.insert(1.0, &line1); } else { sel.insert(1.0, &line2); } // return the answer return sel; } void MEPP2Higgs::constructVertex(tSubProPtr sub) { if(!spinCorrelations_) return; // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]); if(hard[0]->id() < hard[1]->id()) { swap(hard[0],hard[1]); } // identify the process and calculate the matrix element if(hard[0]->id() == ParticleID::g && hard[1]->id() == ParticleID::g) { vector g1,g2; vector q; vector qbar; VectorWaveFunction (g1,hard[0],incoming,false,true,true); VectorWaveFunction (g2,hard[1],incoming,false,true,true); ScalarWaveFunction hout(hard[2],outgoing,true); g1[1] = g1[2]; g2[1] = g2[2]; ggME(g1,g2,hout,true); } else { vector q1; vector q2; SpinorWaveFunction (q1,hard[0],incoming,false,true); SpinorBarWaveFunction (q2,hard[1],incoming,false,true); ScalarWaveFunction hout(hard[2],outgoing,true); qqME(q1,q2,hout,true); } // construct the vertex HardVertexPtr hardvertex = new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(me_); // set the pointers and to and from the vertex for(unsigned int i = 0; i < 3; ++i) hard[i]->spinInfo()->productionVertex(hardvertex); } double MEPP2Higgs::ggME(vector g1, vector g2, ScalarWaveFunction & in, bool calc) const { ProductionMatrixElement newme(PDT::Spin1,PDT::Spin1,PDT::Spin0); Energy2 s(sHat()); double me2(0.0); for(int i = 0; i < 2; ++i) { for(int j = 0; j < 2; ++j) { Complex diag = HGGVertex_->evaluate(s,g1[i],g2[j],in); me2 += norm(diag); if(calc) newme(2*i, 2*j, 0) = diag; } } if(calc) me_.reset(newme); // initial colour and spin factors: colour -> (8/64) and spin -> (1/4) return me2/32.; } double MEPP2Higgs::qqME(vector & fin, vector & ain, ScalarWaveFunction & in, bool calc) const { ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0); Energy2 s(scale()); double me2(0.0); for(int i = 0; i < 2; ++i) { for(int j = 0; j < 2; ++j) { Complex diag = HFFVertex_->evaluate(s,fin[i],ain[j],in); me2+=norm(diag); if(calc) newme(i, j, 0) = diag; } } if(calc) me_.reset(newme); // final colour/spin factors return me2/12.; } -void MEPP2Higgs::applyHardMatrixElementCorrection(ShowerTreePtr tree) { +RealEmissionProcessPtr MEPP2Higgs::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { useMe(); - assert(tree->outgoingLines().size()==1); - if(tree->incomingLines().begin()->second->id()!=ParticleID::g) return; + assert(born->bornOutgoing().size()==1); + if(born->bornIncoming()[0]->id()!=ParticleID::g) + return RealEmissionProcessPtr(); // get gluons and Higgs // get the gluons - map::const_iterator cit; - ShowerParticleVector incoming; + ParticleVector incoming; vector beams; - for(cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - incoming.push_back(cit->first->progenitor()); - beams.push_back(cit->first->beam()); + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + incoming.push_back(born->bornIncoming()[ix]); + beams.push_back(dynamic_ptr_cast(born->hadrons()[ix]->dataPtr())); } + pair xnew=born->x(); if(incoming[0]->momentum().z()outgoingLines().begin()->first->copy(); + higgs=born->bornOutgoing()[0]; // calculate the momenta unsigned int iemit,itype; vector pnew; - pair xnew; // if not accepted return tPDPtr out; - if(!applyHard(incoming,beams,higgs,iemit,itype,pnew,xnew,out)) return; + if(!applyHard(incoming,beams,higgs,iemit,itype,pnew,xnew,out)) return RealEmissionProcessPtr(); + // fix the momentum of the higgs + Boost boostv=born->bornOutgoing()[0]->momentum().findBoostToCM(); + LorentzRotation trans(pnew[3].boostVector()); + trans *=LorentzRotation(boostv); + born->transformation(trans); + born->outgoing().push_back(born->bornOutgoing()[0]->dataPtr()->produceParticle(pnew[3])); + born->emitted(3); // if applying ME correction create the new particles if(itype==0) { // ensure gluon can be put on shell Lorentz5Momentum ptest(pnew[2]); if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() < - getParticleData(ParticleID::g)->constituentMass()) return; + getParticleData(ParticleID::g)->constituentMass()) return RealEmissionProcessPtr(); // create the new gluon PPtr newg= getParticleData(ParticleID::g)->produceParticle(pnew[2]); - PPtr newg1,newg2; - ColinePtr col; - bool colour = UseRandom::rndbool(); - // make the new particles - if(iemit==0) { - newg1 = incoming[0]->dataPtr()->produceParticle(pnew[0]); - if(colour) { - col = incoming[0]->colourLine(); - incoming[0]->antiColourLine()->addAntiColoured(newg1); + PPtr newg1 = incoming[0]->dataPtr()->produceParticle(pnew[0]); + PPtr newg2 = incoming[1]->dataPtr()->produceParticle(pnew[1]); + // set emitter and spectator + if(born->bornIncoming()[0]->momentum().z()>ZERO) { + born->incoming().push_back(newg1); + born->incoming().push_back(newg2); + if(iemit==0) { + born->emitter(0); + born->spectator(1); } else { - col = incoming[0]->antiColourLine(); - incoming[0]->colourLine()->addColoured(newg1); + born->emitter(1); + born->spectator(0); } - newg2 = new_ptr(Particle(*incoming[1])); - col->removeColoured(newg2,colour); - newg2->set5Momentum(pnew[1]); } else { - newg2 = incoming[1]->dataPtr()->produceParticle(pnew[1]); - if(colour) { - col= incoming[1]->antiColourLine(); - incoming[1]->colourLine()->addColoured(newg2); + born->incoming().push_back(newg2); + born->incoming().push_back(newg1); + if(iemit==0) { + born->emitter(1); + born->spectator(0); } else { - col= incoming[1]->colourLine(); - incoming[1]->antiColourLine()->addAntiColoured(newg2); - } - newg1 = new_ptr(Particle(*incoming[0])); - col->removeColoured(newg1,!colour); - newg1->set5Momentum(pnew[0]); - } - // set the colour lines - ColinePtr newline=new_ptr(ColourLine()); - if(iemit==0) { - newline->addColoured(newg1,!colour); - newline->addColoured(newg ,!colour); - col ->addColoured(newg , colour); - col ->addColoured(newg2, colour); - } - else { - newline->addColoured(newg2, colour); - newline->addColoured(newg , colour); - col ->addColoured(newg ,!colour); - col ->addColoured(newg1,!colour); - } - // change the existing gluons - PPtr orig; - for(cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - // remove old particles from colour line - ColinePtr l1=cit->first->copy()-> colourLine(); - ColinePtr l2=cit->first->copy()->antiColourLine(); - l1->removeColoured (cit->first->copy() ); - l1->removeColoured (cit->first->progenitor()); - l2->removeAntiColoured(cit->first->copy() ); - l2->removeAntiColoured(cit->first->progenitor()); - if(cit->first->progenitor()->momentum().z()/newg1->momentum().z()>0) { - // insert new particles - cit->first->copy(newg1); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newg1,1,false))); - sp->x(xnew.first); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(iemit!=0); - if(iemit==0) orig=cit->first->original(); - } - else { - // insert new particles - cit->first->copy(newg2); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newg2,1,false))); - sp->x(xnew.second); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(iemit==0); - if(iemit==1) orig=cit->first->original(); + born->emitter(0); + born->spectator(1); } } - // fix the momentum of the higgs - map::const_iterator - cjt=tree->outgoingLines().begin(); - Boost boostv=cjt->first->progenitor()->momentum().findBoostToCM(); - LorentzRotation trans(pnew[3].boostVector()); - trans *=LorentzRotation(boostv); - cjt->first->progenitor()->transform(trans); - cjt->first->copy()->transform(trans); - tree->hardMatrixElementCorrection(true); - // add the gluon - ShowerParticlePtr sg=new_ptr(ShowerParticle(*newg,1,true)); - ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg)); - gluon->perturbative(false); - tree->outgoingLines().insert(make_pair(gluon,sg)); + bool colour = UseRandom::rndbool(); + newg ->incomingColour(newg1,!colour); + newg ->incomingColour(newg2, colour); + newg1->colourConnect(newg2,!colour); + born->outgoing().push_back(newg); } else if(itype==1) { // ensure outgoing quark can be put on-shell Lorentz5Momentum ptest(pnew[2]); if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() < - out->constituentMass()) return; + out->constituentMass()) return RealEmissionProcessPtr(); // create the new particles PPtr newqout = out->produceParticle(pnew[2]); PPtr newqin,newg; if(iemit==0) { newqin = out ->produceParticle(pnew[0]); - newg = new_ptr(Particle(*incoming[1])); - newg->set5Momentum(pnew[1]); - incoming[0]->colourLine() ->addColoured(newqin); - incoming[0]->antiColourLine()->addColoured(newqout); + newg = incoming[1]->dataPtr()->produceParticle(pnew[1]); } else { - newg = new_ptr(Particle(*incoming[0])); - newg->set5Momentum(pnew[0]); + newg = incoming[0]->dataPtr()->produceParticle(pnew[0]); newqin = out ->produceParticle(pnew[1]); - incoming[1]->colourLine() ->addColoured(newqin); - incoming[1]->antiColourLine()->addColoured(newqout); } - // change the existing incoming partons - PPtr orig; - for(cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - // remove old particles from colour line - ColinePtr l1=cit->first->copy()-> colourLine(); - ColinePtr l2=cit->first->copy()->antiColourLine(); - l1->removeColoured (cit->first->copy() ); - l1->removeColoured (cit->first->progenitor()); - l2->removeAntiColoured(cit->first->copy() ); - l2->removeAntiColoured(cit->first->progenitor()); - if(cit->first->progenitor()->momentum().z()/newqin->momentum().z()>0.) { - // insert new particles - cit->first->copy(newqin); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newqin,1,false))); - sp->x(iemit==0 ? xnew.first : xnew.second ); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(false); - orig=cit->first->original(); - } - else { - // insert new particles - cit->first->copy(newg); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newg,1,false))); - sp->x(iemit==1 ? xnew.first : xnew.second ); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(true); - } + newqout->incomingColour(newg); + newg->colourConnect(newqin); + if((born->bornIncoming()[0]->momentum().z()>ZERO && iemit==0) || + (born->bornIncoming()[0]->momentum().z()incoming().push_back(newqin); + born->incoming().push_back(newg ); + born->emitter(0); + born->spectator(1); } - // fix the momentum of the higgs - map::const_iterator - cjt=tree->outgoingLines().begin(); - Boost boostv=cjt->first->progenitor()->momentum().findBoostToCM(); - LorentzRotation trans(pnew[3].boostVector()); - trans *=LorentzRotation(boostv); - cjt->first->progenitor()->transform(trans); - cjt->first->copy()->transform(trans); - tree->hardMatrixElementCorrection(true); - // add the outgoing quark - ShowerParticlePtr sout=new_ptr(ShowerParticle(*newqout,1,true)); - ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(orig,newqout,sout)); - out->perturbative(false); - tree->outgoingLines().insert(make_pair(out,sout)); + else { + born->incoming().push_back(newg ); + born->incoming().push_back(newqin); + born->emitter(1); + born->spectator(0); + } + born->outgoing().push_back(newqout); } else if(itype==2) { // ensure outgoing antiquark can be put on-shell Lorentz5Momentum ptest(pnew[2]); if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() < - incoming[0]->dataPtr()->constituentMass()) return; + incoming[0]->dataPtr()->constituentMass()) return RealEmissionProcessPtr(); // create the new particles PPtr newqout = out->produceParticle(pnew[2]); PPtr newqin,newg; if(iemit==0) { newqin = out ->produceParticle(pnew[0]); - newg = new_ptr(Particle(*incoming[1])); - newg->set5Momentum(pnew[1]); - incoming[0]->colourLine() ->addAntiColoured(newqout); - incoming[0]->antiColourLine()->addAntiColoured(newqin); + newg = incoming[1]->dataPtr()->produceParticle(pnew[1]); } else { - newg = new_ptr(Particle(*incoming[0])); - newg->set5Momentum(pnew[0]); + newg = incoming[0]->dataPtr()->produceParticle(pnew[0]); newqin = out ->produceParticle(pnew[1]); - incoming[1]->colourLine() ->addAntiColoured(newqout); - incoming[1]->antiColourLine()->addAntiColoured(newqin); } - // change the existing incoming partons - PPtr orig; - for(cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - // remove old particles from colour line - ColinePtr l1=cit->first->copy()-> colourLine(); - ColinePtr l2=cit->first->copy()->antiColourLine(); - l1->removeColoured (cit->first->copy() ); - l1->removeColoured (cit->first->progenitor()); - l2->removeAntiColoured(cit->first->copy() ); - l2->removeAntiColoured(cit->first->progenitor()); - if(cit->first->progenitor()->momentum().z()/newqin->momentum().z()>0.) { - // insert new particles - cit->first->copy(newqin); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newqin,1,false))); - sp->x(iemit==0 ? xnew.first : xnew.second ); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(false); - orig=cit->first->original(); - } - else { - // insert new particles - cit->first->copy(newg); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newg,1,false))); - sp->x(iemit==1 ? xnew.first : xnew.second ); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - cit->first->perturbative(true); - } + newqout->incomingAntiColour(newg); + newg->colourConnect(newqin,true); + if((born->bornIncoming()[0]->momentum().z()>ZERO && iemit==0) || + (born->bornIncoming()[0]->momentum().z()incoming().push_back(newqin); + born->incoming().push_back(newg ); + born->emitter(0); + born->spectator(1); } - // fix the momentum of the higgs - map::const_iterator - cjt=tree->outgoingLines().begin(); - Boost boostv=cjt->first->progenitor()->momentum().findBoostToCM(); - LorentzRotation trans(pnew[3].boostVector()); - trans *=LorentzRotation(boostv); - cjt->first->progenitor()->transform(trans); - cjt->first->copy()->transform(trans); - tree->hardMatrixElementCorrection(true); - // add the outgoing antiquark - ShowerParticlePtr sout=new_ptr(ShowerParticle(*newqout,1,true)); - ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(orig,newqout,sout)); - out->perturbative(false); - tree->outgoingLines().insert(make_pair(out,sout)); + else { + born->incoming().push_back(newg ); + born->incoming().push_back(newqin); + born->emitter(1); + born->spectator(0); + } + born->outgoing().push_back(newqout); } + if(born->bornIncoming()[0]->momentum().z()x(xnew); + born->interaction(ShowerInteraction::QCD); + return born; } bool MEPP2Higgs::softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent,Branching br) { if(parent->isFinalState()) return false; // check if me correction should be applied long id[2]={initial->id(),parent->id()}; // must have started as a gluon if(id[0]!=ParticleID::g) return false; // must be a gluon going into the hard process if(br.ids[1]->id()!=ParticleID::g) return false; // get the pT Energy pT=br.kinematics->pT(); // check if hardest so far if(pThighestpT()) return false; // compute the invariants double kappa(sqr(br.kinematics->scale())/mh2_),z(br.kinematics->z()); Energy2 shat(mh2_/z*(1.+(1.-z)*kappa)),that(-(1.-z)*kappa*mh2_),uhat(-(1.-z)*shat); // check which type of process Energy2 me; // g g if(br.ids[0]->id()==ParticleID::g&&br.ids[2]->id()==ParticleID::g) { double split = 6.*(z/(1.-z)+(1.-z)/z+z*(1.-z)); me = ggME(shat,that,uhat)/split; } // q g else if(br.ids[0]->id() >= 1 && br.ids[0]->id() <= 5 && br.ids[2]->id()==br.ids[0]->id()) { double split = 4./3./z*(1.+sqr(1.-z)); me = qgME(shat,uhat,that)/split; } // qbar g else if(br.ids[0]->id() <= -1 && br.ids[0]->id() >= -5 && br.ids[2]->id()==br.ids[0]->id()) { double split = 4./3./z*(1.+sqr(1.-z)); me = qbargME(shat,uhat,that)/split; } else { return false; } InvEnergy2 pre = 0.125/Constants::pi/loME()*sqr(mh2_)*that/shat/(shat+uhat); double wgt = -pre*me/enhance_; if(wgt<.0||wgt>1.) generator()->log() << "Soft ME correction weight too large or " << "negative in MEPP2Higgs::" << "softMatrixElementVeto()\n soft weight " << " sbar = " << shat/mh2_ << " tbar = " << that/mh2_ << "weight = " << wgt << " for " << br.ids[0]->id() << " " << br.ids[1]->id() << " " << br.ids[2]->id() << "\n"; // if not vetoed if(UseRandom::rndbool(wgt)) return false; // otherwise parent->vetoEmission(br.type,br.kinematics->scale()); return true; } -HardTreePtr MEPP2Higgs::generateHardest(ShowerTreePtr tree, - ShowerInteraction::Type inter) { +RealEmissionProcessPtr MEPP2Higgs::generateHardest(RealEmissionProcessPtr born, + ShowerInteraction::Type inter) { // check if generating QCD radiation if(inter!=ShowerInteraction::QCD && inter!=ShowerInteraction::QEDQCD && inter!=ShowerInteraction::ALL) - return HardTreePtr(); - if(tree->incomingLines().begin()->second->id()!=ParticleID::g) - return HardTreePtr(); + return RealEmissionProcessPtr(); + if(born->bornIncoming()[0]->id()!=ParticleID::g) + return RealEmissionProcessPtr(); useMe(); // get the particles to be showered beams_.clear(); partons_.clear(); // find the incoming particles - ShowerParticleVector incoming; - map::const_iterator cit; - vector particlesToShower; - for( cit = tree->incomingLines().begin(); - cit != tree->incomingLines().end(); ++cit ) { - incoming.push_back( cit->first->progenitor() ); - beams_.push_back( cit->first->beam() ); - partons_.push_back( cit->first->progenitor()->dataPtr() ); - particlesToShower.push_back( cit->first ); + ParticleVector incoming; + ParticleVector particlesToShower; + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + incoming.push_back( born->bornIncoming()[ix] ); + beams_.push_back( dynamic_ptr_cast(born->hadrons()[ix]->dataPtr())); + partons_.push_back( born->bornIncoming()[ix]->dataPtr() ); + particlesToShower.push_back( born->bornIncoming()[ix] ); } // find the higgs boson - PPtr higgs; - if(tree->outgoingLines().size() == 1) { - higgs = tree->outgoingLines().begin()->first->copy(); - } - else { - higgs = tree->outgoingLines().begin()->first->copy()->parents()[0]; - } + assert(born->bornOutgoing().size()==1); + PPtr higgs = born->bornOutgoing()[0]; // calculate the rapidity of the higgs yh_ = 0.5 * log((higgs->momentum().e()+higgs->momentum().z())/ (higgs->momentum().e()-higgs->momentum().z())); mass_=higgs->mass(); mh2_ = sqr(mass_); vector pnew; int emission_type(-1); // generate the hard emission and return if no emission if(!getEvent(pnew,emission_type)) { - for(unsigned int ix=0;ixmaximumpT(minpT_,ShowerInteraction::QCD); - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = minpT_; + return born; } // construct the HardTree object needed to perform the showers - ShowerParticleVector newparticles(4); + ParticleVector newparticles(4); // create the partons int iemit=-1; + // create the jet + newparticles[3] = out_->produceParticle(pnew[3]); // g g -> h g if(emission_type==0) { - newparticles[0] = new_ptr(ShowerParticle(partons_[0] ,false)); - newparticles[1] = new_ptr(ShowerParticle(partons_[1] ,false)); + newparticles[0] = partons_[0]->produceParticle(pnew[0]); + newparticles[1] = partons_[1]->produceParticle(pnew[1]); iemit = pnew[0].z()/pnew[3].z()>0. ? 0 : 1; + bool colour = UseRandom::rndbool(); + newparticles[3]->incomingColour(newparticles[0],!colour); + newparticles[3]->incomingColour(newparticles[1], colour); + newparticles[0]-> colourConnect(newparticles[1],!colour); } // g q -> H q else if(emission_type==1) { - newparticles[0] = new_ptr(ShowerParticle(partons_[0] ,false)); - newparticles[1] = new_ptr(ShowerParticle(out_ ,false)); + newparticles[0] = partons_[0]->produceParticle(pnew[0]); + newparticles[1] = out_ ->produceParticle(pnew[1]); iemit = 1; + newparticles[3]->incomingColour(newparticles[0]); + newparticles[0]->colourConnect (newparticles[1]); } // q g -> H q else if(emission_type==2) { - newparticles[0] = new_ptr(ShowerParticle(out_ ,false)); - newparticles[1] = new_ptr(ShowerParticle(partons_[1] ,false)); + newparticles[0] = out_ ->produceParticle(pnew[0]); + newparticles[1] = partons_[1]->produceParticle(pnew[1]); iemit = 0; + newparticles[3]->incomingColour(newparticles[1]); + newparticles[1]->colourConnect (newparticles[0]); } // g qbar -> H qbar else if(emission_type==3) { - newparticles[0] = new_ptr(ShowerParticle(partons_[0] ,false)); - newparticles[1] = new_ptr(ShowerParticle(out_ ,false)); + newparticles[0] = partons_[0]->produceParticle(pnew[0]); + newparticles[1] = out_ ->produceParticle(pnew[1]); iemit = 1; + newparticles[3]->incomingAntiColour(newparticles[0]); + newparticles[0]->colourConnect(newparticles[1],true); } // qbar g -> H qbar else if(emission_type==4) { - newparticles[0] = new_ptr(ShowerParticle(out_ ,false)); - newparticles[1] = new_ptr(ShowerParticle(partons_[1] ,false)); + newparticles[0] = out_ ->produceParticle(pnew[0]); + newparticles[1] = partons_[1]->produceParticle(pnew[1]); iemit = 0; + newparticles[3]->incomingAntiColour(newparticles[1]); + newparticles[1]->colourConnect(newparticles[0],true); } unsigned int ispect = iemit==0 ? 1 : 0; - // create the jet - newparticles[3] = new_ptr(ShowerParticle(out_ , true)); // create the boson - newparticles[2] = new_ptr(ShowerParticle(higgs->dataPtr(),true)); - // set the momenta - for(unsigned int ix=0;ix<4;++ix) newparticles[ix]->set5Momentum(pnew[ix]); - // create the off-shell particle - Lorentz5Momentum poff=pnew[iemit]-pnew[3]; - poff.rescaleMass(); - newparticles.push_back(new_ptr(ShowerParticle(partons_[iemit],false))); - newparticles.back()->set5Momentum(poff); - vector inBranch,hardBranch; // create the branchings for the incoming particles - inBranch.push_back(new_ptr(HardBranching(newparticles[0],SudakovPtr(), - HardBranchingPtr(),HardBranching::Incoming))); - inBranch.push_back(new_ptr(HardBranching(newparticles[1],SudakovPtr(), - HardBranchingPtr(),HardBranching::Incoming))); - // intermediate IS particle - hardBranch.push_back(new_ptr(HardBranching(newparticles[4],SudakovPtr(), - inBranch[iemit],HardBranching::Incoming))); - inBranch[iemit]->addChild(hardBranch.back()); - // create the branching for the emitted jet - inBranch[iemit]->addChild(new_ptr(HardBranching(newparticles[3],SudakovPtr(), - inBranch[iemit],HardBranching::Outgoing))); - ColinePtr cline1 = new_ptr(ColourLine()); - ColinePtr cline2 = new_ptr(ColourLine()); - ColinePtr cline3 = new_ptr(ColourLine()); - if(newparticles[3]->id()<0|| - (newparticles[3]->id()==ParticleID::g&&UseRandom::rndbool())) { - inBranch[iemit]->type(ShowerPartnerType::QCDColourLine); - cline1->addAntiColoured(newparticles[3]); - cline1->addColoured (newparticles[4]); - cline1->addAntiColoured(newparticles[ispect]); - cline2->addColoured (newparticles[ispect]); - cline2->addAntiColoured(newparticles[4]); - cline2->addAntiColoured(newparticles[iemit]); - if(newparticles[3]->id()==ParticleID::g) { - cline3->addColoured(newparticles[iemit]); - cline3->addColoured(newparticles[3]); - } + newparticles[2] = higgs->dataPtr()->produceParticle(pnew[2]); + born->emitter (iemit); + born->spectator(ispect); + born->emitted(3); + born->pT()[ShowerInteraction::QCD] = pt_; + pair xnew; + for(unsigned int ix=0;ix<2;++ix) { + born->incoming().push_back(newparticles[ix]); + if(ix==0) xnew.first = newparticles[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); + else xnew.second = newparticles[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); } - else { - inBranch[iemit]->type(ShowerPartnerType::QCDAntiColourLine); - cline1->addColoured (newparticles[3]); - cline1->addAntiColoured(newparticles[4]); - cline1->addColoured (newparticles[ispect]); - cline2->addAntiColoured(newparticles[ispect]); - cline2->addColoured (newparticles[4]); - cline2->addColoured (newparticles[iemit]); - if(newparticles[3]->id()==ParticleID::g) { - cline3->addAntiColoured(newparticles[iemit]); - cline3->addAntiColoured(newparticles[3]); - } - } - // set the colour partners - hardBranch.back()->colourPartner(inBranch[iemit==0 ? 1 : 0]); - inBranch[iemit==0 ? 1 : 0]->colourPartner(hardBranch.back()); - // add other particle - hardBranch.push_back(inBranch[iemit==0 ? 1 : 0]); - // outgoing Higgs boson - hardBranch.push_back(new_ptr(HardBranching(newparticles[2],SudakovPtr(), - HardBranchingPtr(),HardBranching::Outgoing))); - // make the tree - HardTreePtr hardtree=new_ptr(HardTree(hardBranch,inBranch,ShowerInteraction::QCD)); - // connect the ShowerParticles with the branchings - // and set the maximum pt for the radiation - set hard=hardtree->branchings(); - for(unsigned int ix=0;ixmaximumpT(minpT_,ShowerInteraction::QCD); - else particlesToShower[ix]->maximumpT(pt_,ShowerInteraction::QCD); - for(set::const_iterator mit=hard.begin(); - mit!=hard.end();++mit) { - if(particlesToShower[ix]->progenitor()->id()==(*mit)->branchingParticle()->id()&& - (( particlesToShower[ix]->progenitor()->isFinalState()&& - (**mit).status()==HardBranching::Outgoing)|| - (!particlesToShower[ix]->progenitor()->isFinalState()&& - (**mit).status()==HardBranching::Incoming))) { - if(particlesToShower[ix]->progenitor()->momentum().z()/ - (*mit)->branchingParticle()->momentum().z()<0.) continue; - hardtree->connect(particlesToShower[ix]->progenitor(),*mit); - if((**mit).status()==HardBranching::Incoming) { - (*mit)->beam(particlesToShower[ix]->original()->parents()[0]); - } - HardBranchingPtr parent=(*mit)->parent(); - while(parent) { - parent->beam(particlesToShower[ix]->original()->parents()[0]); - parent=parent->parent(); - }; - } - } - } + born->x(xnew); + for(unsigned int ix=0;ix<2;++ix) + born->outgoing().push_back(newparticles[ix+2]); // return the answer - return hardtree; + born->interaction(ShowerInteraction::QCD); + return born; } -bool MEPP2Higgs::applyHard(ShowerParticleVector gluons, +bool MEPP2Higgs::applyHard(ParticleVector gluons, vector beams,PPtr higgs, unsigned int & iemit, unsigned int & itype, vector & pnew, pair & xout, tPDPtr & out) { ++ntry_; // calculate the limits on s Energy mh(higgs->mass()); mh2_=sqr(mh); Energy2 smin=mh2_; Energy2 s= (generator()->currentEvent()->incoming().first->momentum()+ generator()->currentEvent()->incoming().second->momentum()).m2(); Energy2 smax(s); // calculate the rapidity of the higgs double yH = 0.5*log((higgs->momentum().e()+higgs->momentum().z())/ (higgs->momentum().e()-higgs->momentum().z())); // if no phase-space return if(smaxx(); assert(beams[ix]); pdf[ix]=beams[ix]->pdf(); assert(pdf[ix]); fx[ix]=pdf[ix]->xfx(beams[ix],gluons[ix]->dataPtr(),mh2_,x[ix]); } // leading order ME Energy4 lome = loME(); // select the type of process and generate the kinematics double rn(UseRandom::rnd()); Energy2 shat(ZERO),uhat(ZERO),that(ZERO); double weight(0.),xnew[2]={1.,1.}; // gg -> H g if(rn=1.||xnew[1]<=0.||xnew[1]>=1.) return false; for(unsigned int ix=0;ix<2;++ix) fxnew[ix]=pdf[ix]->xfx(beams[ix],gluons[ix]->dataPtr(),scale,xnew[ix]); // jacobian and me parts of the weight weight = jacobian2*ggME(shat,uhat,that)/lome*mh2_/sqr(shat); // pdf part of the weight weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]); // finally coupling and different channel pieces weight *= 1./16./sqr(Constants::pi)*alpha_->value(scale)/channelWeights_[0]; itype=0; iemit = that>uhat ? 0 : 1; out = getParticleData(ParticleID::g); } // incoming quark or antiquark else { // generate the value of s according to 1/s^n double rhomax(pow(smin/mh2_,1.-qgPow_)),rhomin(pow(smax/mh2_,1.-qgPow_)); double rho = rhomin+UseRandom::rnd()*(rhomax-rhomin); shat = mh2_*pow(rho,1./(1.-qgPow_)); Energy2 jacobian = mh2_/(qgPow_-1.)*(rhomax-rhomin)*pow(shat/mh2_,qgPow_); double sbar=shat/mh2_; // calculate limits on that Energy2 tmax=mh2_*kappa[0]*(1.-sbar)/(kappa[0]+sbar); Energy2 tmin=shat*(1.-sbar)/(kappa[1]+sbar); // calculate the limits on uhat Energy2 umax(mh2_-shat-tmin),umin(mh2_-shat-tmax); // check inside phase space if(tmax=1.||xnew[1]<=0.||xnew[1]>=1.) return false; if(rn H q if(!order) { out = quarkFlavour(pdf[0],scale,xnew[0],beams[0],fxnew[0],false); fxnew[1]=pdf[1]->xfx(beams[1],gluons[1]->dataPtr(),scale,xnew[1]); iemit = 0; mewgt = out ? qgME(shat,uhat,that)/lome*mh2_/sqr(shat) : ZERO; } // g q -> H q else { fxnew[0]=pdf[0]->xfx(beams[0],gluons[0]->dataPtr(),scale,xnew[0]); out = quarkFlavour(pdf[1],scale,xnew[1],beams[1],fxnew[1],false); iemit = 1; mewgt = out ? qgME(shat,that,uhat)/lome*mh2_/sqr(shat) : ZERO; } jacobian2 /= (channelWeights_[1]-channelWeights_[0]); } else { itype=2; // qbar g -> H qbar if(!order) { out = quarkFlavour(pdf[0],scale,xnew[0],beams[0],fxnew[0],true); fxnew[1]=pdf[1]->xfx(beams[1],gluons[1]->dataPtr(),scale,xnew[1]); iemit = 0; mewgt = out ? qbargME(shat,uhat,that)/lome*mh2_/sqr(shat) : ZERO; } // g qbar -> H qbar else { fxnew[0]=pdf[0]->xfx(beams[0],gluons[0]->dataPtr(),scale,xnew[0]); out = quarkFlavour(pdf[1],scale,xnew[1],beams[1],fxnew[1],true); iemit = 1; mewgt = out ? qbargME(shat,that,uhat)/lome*mh2_/sqr(shat) : ZERO; } jacobian2/=(channelWeights_[2]-channelWeights_[1]); } // weight (factor of 2 as pick q(bar)g or gq(bar) weight = 2.*jacobian2*mewgt; // pdf part of the weight weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]); // finally coupling and different channel pieces weight *= 1./16./sqr(Constants::pi)*alpha_->value(scale); } // if me correction should be applied if(weight>1.) { ++nover_; maxwgt_ = max( maxwgt_ , weight); weight=1.; } if(UseRandom::rnd()>weight) return false; ++ngen_; // construct the momenta Energy roots = 0.5*sqrt(s); Energy pt = sqrt(uhat*that/shat); Energy mt = sqrt(uhat*that/shat+mh2_); Lorentz5Momentum pin[2]={Lorentz5Momentum(ZERO,ZERO, xnew[0]*roots,xnew[0]*roots), Lorentz5Momentum(ZERO,ZERO,-xnew[1]*roots,xnew[1]*roots)}; double phi = Constants::twopi*UseRandom::rnd(); Lorentz5Momentum pH(pt*cos(phi),pt*sin(phi),mt*sinh(yH),mt*cosh(yH)); Lorentz5Momentum pJ(pin[0]+pin[1]-pH); // momenta to be returned pnew.push_back(pin[0]); pnew.push_back(pin[1]); pnew.push_back(pJ); pnew.push_back(pH); xout.first = xnew[0]; xout.second = xnew[1]; return true; } Energy2 MEPP2Higgs::ggME(Energy2 s, Energy2 t, Energy2 u) { Energy2 output; if(massOption_==0) { complex me[2][2][2]; me[1][1][1] = ZERO; me[1][1][0] = ZERO; me[0][1][0] = ZERO; me[0][1][1] = ZERO; for(unsigned int ix=minLoop_; ix<=maxLoop_; ++ix ) { Energy2 mf2=sqr(getParticleData(long(ix))->mass()); bi_[1]=B(s,mf2); bi_[2]=B(u,mf2); bi_[3]=B(t,mf2); bi_[4]=B(mh2_,mf2); bi_[1]=bi_[1]-bi_[4]; bi_[2]=bi_[2]-bi_[4]; bi_[3]=bi_[3]-bi_[4]; ci_[1]=C(s,mf2); ci_[2]=C(u,mf2); ci_[3]=C(t,mf2); ci_[7]=C(mh2_,mf2); ci_[4]=(s*ci_[1]-mh2_*ci_[7])/(s-mh2_); ci_[5]=(u*ci_[2]-mh2_*ci_[7])/(u-mh2_); ci_[6]=(t*ci_[3]-mh2_*ci_[7])/(t-mh2_); di_[1]=D(t,u,s,mf2); di_[2]=D(s,t,u,mf2); di_[3]=D(s,u,t,mf2); me[1][1][1]+=me1(s,u,t,mf2,1,2,3,4,5,6); me[1][1][0]+=me2(s,u,t,mf2); me[0][1][0]+=me1(u,s,t,mf2,2,1,3,5,4,6); me[0][1][1]+=me1(t,u,s,mf2,3,2,1,6,5,4); } me[0][0][0]=-me[1][1][1]; me[0][0][1]=-me[1][1][0]; me[1][0][1]=-me[0][1][0]; me[1][0][0]=-me[0][1][1]; output = real(me[0][0][0]*conj(me[0][0][0])+ me[0][0][1]*conj(me[0][0][1])+ me[0][1][0]*conj(me[0][1][0])+ me[0][1][1]*conj(me[0][1][1])+ me[1][0][0]*conj(me[1][0][0])+ me[1][0][1]*conj(me[1][0][1])+ me[1][1][0]*conj(me[1][1][0])+ me[1][1][1]*conj(me[1][1][1])); output *= 3./8.; } else { output=32./3.* (pow<4,1>(s)+pow<4,1>(t)+pow<4,1>(u)+pow<4,1>(mh2_))/s/t/u; } // spin and colour factors return output/4./64.; } Energy2 MEPP2Higgs::qgME(Energy2 s, Energy2 t, Energy2 u) { Energy2 output; if(massOption_==0) { complex A(ZERO); Energy2 si(u-mh2_); for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) { Energy2 mf2=sqr(getParticleData(long(ix))->mass()); A += mf2*(2.+2.*double(u/si)*(B(u,mf2)-B(mh2_,mf2)) +double((4.*mf2-s-t)/si)*Complex(u*C(u,mf2)-mh2_*C(mh2_,mf2))); } output =-4.*(sqr(s)+sqr(t))/sqr(si)/u*real(A*conj(A)); } else{ output =-4.*(sqr(s)+sqr(t))/u/9.; } // final colour/spin factors return output/24.; } Energy2 MEPP2Higgs::qbargME(Energy2 s, Energy2 t, Energy2 u) { Energy2 output; if(massOption_==0) { complex A(ZERO); Energy2 si(u-mh2_); for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) { Energy2 mf2=sqr(getParticleData(long(ix))->mass()); A+=mf2*(2.+2.*double(u/si)*(B(u,mf2)-B(mh2_,mf2)) +double((4.*mf2-s-t)/si)*Complex(u*C(u,mf2)-mh2_*C(mh2_,mf2))); } output =-4.*(sqr(s)+sqr(t))/sqr(si)/u*real(A*conj(A)); } else { output =-4.*(sqr(s)+sqr(t))/u/9.; } // final colour/spin factors return output/24.; } Energy4 MEPP2Higgs::loME() const { Complex I(0); if(massOption_==0) { for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) { double x = sqr(getParticleData(long(ix))->mass())/mh2_; I += 3.*x*(2.+(4.*x-1.)*F(x)); } } else { I = 1.; } return sqr(mh2_)/576./Constants::pi*norm(I); } tPDPtr MEPP2Higgs::quarkFlavour(tcPDFPtr pdf, Energy2 scale, double x, tcBeamPtr beam, double & pdfweight, bool anti) { vector weights; vector partons; pdfweight = 0.; if(!anti) { for(unsigned int ix=1;ix<=5;++ix) { partons.push_back(getParticleData(long(ix))); weights.push_back(max(0.,pdf->xfx(beam,partons.back(),scale,x))); pdfweight += weights.back(); } } else { for(unsigned int ix=1;ix<=5;++ix) { partons.push_back(getParticleData(-long(ix))); weights.push_back(max(0.,pdf->xfx(beam,partons.back(),scale,x))); pdfweight += weights.back(); } } if(pdfweight==0.) return tPDPtr(); double wgt=UseRandom::rnd()*pdfweight; for(unsigned int ix=0;ix=ZERO&&rat<1.) output=2.-2.*sqrt(1./rat-1.)*asin(sqrt(rat)); else output=2.-sqrt(1.-1./rat)*(2.*log(sqrt(rat)+sqrt(rat-1.))-pii); return output; } complex MEPP2Higgs::C(Energy2 s,Energy2 mf2) const { complex output; Complex pii(0.,Constants::pi); double rat=s/(4.*mf2); if(s=ZERO&&rat<1.) output=-2.*sqr(asin(sqrt(rat)))/s; else { double cosh=log(sqrt(rat)+sqrt(rat-1.)); output=2.*(sqr(cosh)-sqr(Constants::pi)/4.-pii*cosh)/s; } return output; } Complex MEPP2Higgs::dIntegral(Energy2 a, Energy2 b, double y0) const { Complex output; if(b==ZERO) output=0.; else { Complex y1=0.5*(1.+sqrt(1.-4.*(a+epsi_)/b)); Complex y2=1.-y1; Complex z1=y0/(y0-y1); Complex z2=(y0-1.)/(y0-y1); Complex z3=y0/(y0-y2); Complex z4=(y0-1.)/(y0-y2); output=Math::Li2(z1)-Math::Li2(z2)+Math::Li2(z3)-Math::Li2(z4); } return output; } complex MEPP2Higgs::D(Energy2 s,Energy2 t, Energy2, Energy2 mf2) const { Complex output,pii(0.,Constants::pi); Energy4 st=s*t; Energy4 root=sqrt(sqr(st)-4.*st*mf2*(s+t-mh2_)); double xp=0.5*(st+root)/st,xm=1-xp; output = 2.*(-dIntegral(mf2,s,xp)-dIntegral(mf2,t,xp) +dIntegral(mf2,mh2_,xp)+log(-xm/xp) *(log((mf2+epsi_)/GeV2)-log((mf2+epsi_-s*xp*xm)/GeV2) +log((mf2+epsi_-mh2_*xp*xm)/GeV2)-log((mf2+epsi_-t*xp*xm)/GeV2))); return output/root; } complex MEPP2Higgs::me1(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2, unsigned int i ,unsigned int j ,unsigned int k , unsigned int i1,unsigned int j1,unsigned int k1) const { Energy2 s1(s-mh2_),t1(t-mh2_),u1(u-mh2_); return mf2*4.*sqrt(2.*s*t*u)* (-4.*(1./(u*t)+1./(u*u1)+1./(t*t1)) -4.*((2.*s+t)*bi_[k]/sqr(u1)+(2.*s+u)*bi_[j]/sqr(t1))/s -(s-4.*mf2)*(s1*ci_[i1]+(u-s)*ci_[j1]+(t-s)*ci_[k1])/(s*t*u) -8.*mf2*(ci_[j1]/(t*t1)+ci_[k1]/(u*u1)) +0.5*(s-4.*mf2)*(s*t*di_[k]+u*s*di_[j]-u*t*di_[i])/(s*t*u) +4.*mf2*di_[i]/s -2.*(u*ci_[k]+t*ci_[j]+u1*ci_[k1]+t1*ci_[j1]-u*t*di_[i])/sqr(s)); } complex MEPP2Higgs::me2(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2) const { Energy2 s1(s-mh2_),t1(t-mh2_),u1(u-mh2_); return mf2*4.*sqrt(2.*s*t*u)*(4.*mh2_+(mh2_-4.*mf2)*(s1*ci_[4]+t1*ci_[5]+u1*ci_[6]) -0.5*(mh2_-4.*mf2)*(s*t*di_[3]+u*s*di_[2]+u*t*di_[1]) )/ (s*t*u); } Complex MEPP2Higgs::F(double x) const { if(x<.25) { double root = sqrt(1.-4.*x); Complex pii(0.,Constants::pi); return 0.5*sqr(log((1.+root)/(1.-root))-pii); } else { return -2.*sqr(asin(0.5/sqrt(x))); } } bool MEPP2Higgs::getEvent(vector & pnew, int & emis_type){ // maximum pt (half of centre-of-mass energy) Energy maxp = 0.5*generator()->maximumCMEnergy(); // set pt of emission to zero pt_=ZERO; //Working Variables Energy pt; double yj; // limits on the rapidity of the jet double minyj = -8.0,maxyj = 8.0; bool reject; double wgt; emis_type=-1; tcPDPtr outParton; for(int j=0;j<5;++j) { pt = maxp; do { double a = alpha_->overestimateValue()*prefactor_[j]*(maxyj-minyj)/(power_-1.); // generate next pt pt=GeV/pow(pow(GeV/pt,power_-1)-log(UseRandom::rnd())/a,1./(power_-1.)); // generate rapidity of the jet yj=UseRandom::rnd()*(maxyj-minyj)+ minyj; // calculate rejection weight wgt=getResult(j,pt,yj,outParton); wgt/= prefactor_[j]*pow(GeV/pt,power_); reject = UseRandom::rnd()>wgt; //no emission event if p goes past p min - basically set to outside //of the histogram bounds (hopefully hist object just ignores it) if(pt1.0) { ostringstream s; s << "MEPP2Higgs::getEvent weight for channel " << j << "is " << wgt << " which is greater than 1"; generator()->logWarning( Exception(s.str(), Exception::warning) ); } } while(reject); // set pt of emission etc if(pt>pt_){ emis_type = j; pt_=pt; yj_=yj; out_ = outParton; } } //was this an (overall) no emission event? if(pt_maximumCMEnergy()); // transverse energy Energy et=sqrt(mh2_+sqr(pt_)); // first calculate all the kinematic variables // longitudinal real correction fractions double x = pt_*exp( yj_)/sqrt(s)+et*exp( yh_)/sqrt(s); double y = pt_*exp(-yj_)/sqrt(s)+et*exp(-yh_)/sqrt(s); // that and uhat // Energy2 th = -sqrt(s)*x*pt_*exp(-yj_); // Energy2 uh = -sqrt(s)*y*pt_*exp( yj_); // Energy2 sh = x*y*s; // reconstruct the momenta // incoming momenta pnew.push_back(Lorentz5Momentum(ZERO,ZERO, x*0.5*sqrt(s), x*0.5*sqrt(s),ZERO)); pnew.push_back(Lorentz5Momentum(ZERO,ZERO, -y*0.5*sqrt(s), y*0.5*sqrt(s),ZERO)); // outgoing momenta double phi(Constants::twopi*UseRandom::rnd()); double sphi(sin(phi)),cphi(cos(phi)); pnew.push_back(Lorentz5Momentum( cphi*pt_, sphi*pt_, et*sinh(yh_), et*cosh(yh_), mass_)); pnew.push_back(Lorentz5Momentum(-cphi*pt_,-sphi*pt_,pt_*sinh(yj_), pt_*cosh(yj_),ZERO)); return true; } double MEPP2Higgs::getResult(int emis_type, Energy pt, double yj, tcPDPtr & outParton) { Energy2 s=sqr(generator()->maximumCMEnergy()); Energy2 scale = mh2_+sqr(pt); Energy et=sqrt(scale); scale = mu_F_opt_==0 ? mh2_+sqr(pt) : sqr(pt) ; // longitudinal real correction fractions double x = pt*exp( yj)/sqrt(s)+et*exp( yh_)/sqrt(s); double y = pt*exp(-yj)/sqrt(s)+et*exp(-yh_)/sqrt(s); // reject if outside region if(x<0.||x>1.||y<0.||y>1.||x*ypdf()->xfx(beams_[0],partons_[0],mh2_,x1); pdf[1]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],mh2_,y1); } else { // As in Nason and Ridolfi paper ... pdf[0]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x1); pdf[1]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y1); } // g g -> H g if(emis_type==0) { outParton = partons_[1]; pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x); pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y); res = ggME(sh,uh,th)/loME(); } // q g -> H q else if(emis_type==1) { outParton = quarkFlavour(beams_[0]->pdf(),scale,x,beams_[0],pdf[2],false); pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y); res = outParton ? qgME(sh,uh,th)/loME() : ZERO; } // g q -> H q else if(emis_type==2) { pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x); outParton = quarkFlavour(beams_[1]->pdf(),scale,y,beams_[1],pdf[3],false); res = outParton ? qgME(sh,th,uh)/loME() : ZERO; } // qbar g -> H qbar else if(emis_type==3) { outParton = quarkFlavour(beams_[0]->pdf(),scale,x,beams_[0],pdf[2],true); pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y); res = outParton ? qbargME(sh,uh,th)/loME() : ZERO; } // g qbar -> H qbar else if(emis_type==4) { pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x); outParton = quarkFlavour(beams_[1]->pdf(),scale,y,beams_[1],pdf[3],true); res = outParton ? qbargME(sh,th,uh)/loME() : ZERO; } //deals with pdf zero issue at large x if(pdf[0]<=0.||pdf[1]<=0.||pdf[2]<=0.||pdf[3]<=0.) { res = ZERO; } else { res *= pdf[2]*pdf[3]/pdf[0]/pdf[1]*mh2_/sh; } scale = mu_R_opt_==0 ? mh2_+sqr(pt) : sqr(pt) ; return alpha_->ratio(scale)/8./sqr(Constants::pi)*mh2_/sh*GeV*pt*res; } -void MEPP2Higgs::initializeMECorrection(ShowerTreePtr tree, double & initial, +void MEPP2Higgs::initializeMECorrection(RealEmissionProcessPtr born, double & initial, double & final) { final = 1.; - initial = tree->incomingLines().begin()->second->id()==ParticleID::g ? + initial = born->bornIncoming()[0]->id()==ParticleID::g ? enhance_ : 1.; } diff --git a/MatrixElement/Hadron/MEPP2Higgs.h b/MatrixElement/Hadron/MEPP2Higgs.h --- a/MatrixElement/Hadron/MEPP2Higgs.h +++ b/MatrixElement/Hadron/MEPP2Higgs.h @@ -1,741 +1,742 @@ // -*- C++ -*- // // MEPP2Higgs.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_MEPP2Higgs_H #define HERWIG_MEPP2Higgs_H // // This is the declaration of the MEPP2Higgs class. // #include "Herwig/MatrixElement/HwMEBase.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "Herwig/PDT/GenericMassGenerator.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; using namespace ThePEG::Helicity; /** * The MEPP2Higgs class implements the matrix element for the process * pp->Higgs with different Higgs shape prescriptions (see details in hep-ph/9505211) * and the NLL corrected Higgs width (see details in the FORTRAN HERWIG manual). * * @see \ref MEPP2HiggsInterfaces "The interfaces" * defined for MEPP2Higgs. */ class MEPP2Higgs: public HwMEBase { public: /** * The default constructor. */ MEPP2Higgs(); /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(). Uses * me(). */ virtual CrossSection dSigHatDR() const; /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries() * according to the associated XComb object. */ virtual void setKinematics() { HwMEBase::setKinematics(); mh2_ = sHat(); } public: /** @name Member functions for the generation of hard QCD radiation */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return ISR;} /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return true;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr tree, double & initial, - double & final); + virtual void initializeMECorrection(RealEmissionProcessPtr, double &, + double & ); /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr); + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent, Branching br); /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr,ShowerInteraction::Type); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, + ShowerInteraction::Type); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EW}\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Generate internal degrees of freedom given nDim() uniform * random numbers in the interval \f$ ]0,1[ \f$. To help the phase space * generator, the dSigHatDR should be a smooth function of these * numbers, although this is not strictly necessary. * @param r a pointer to the first of nDim() consecutive random numbers. * @return true if the generation succeeded, otherwise false. */ virtual bool generateKinematics(const double * r); /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * The number of internal degrees of freedom used in the matrix * element. */ virtual int nDim() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; /** * Construct the vertex of spin correlations. */ virtual void constructVertex(tSubProPtr); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const { return new_ptr(*this); } /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const { return new_ptr(*this); } //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} protected: /** * Members to calculate the real emission matrix elements */ //@{ /** * The leading-order matrix element for \f$gg\to H\f$ */ Energy4 loME() const; /** * The matrix element for \f$gg\to H g\f$ */ Energy2 ggME(Energy2 s, Energy2 t, Energy2 u); /** * The matrix element for \f$qg\to H q\f$ */ Energy2 qgME(Energy2 s, Energy2 t, Energy2 u); /** * The matrix element for \f$qbarg\to H qbar\f$ */ Energy2 qbargME(Energy2 s, Energy2 t, Energy2 u); //@} /** * Members to calculate the functions for the loop diagrams */ //@{ /** * The \f$B(s)\f$ function of NBP339 (1990) 38-66 * @param s The scale * @param mf2 The fermion mass squared. */ Complex B(Energy2 s,Energy2 mf2) const; /** * The \f$C(s)\f$ function of NBP339 (1990) 38-66 * @param s The scale * @param mf2 The fermion mass squared. */ complex C(Energy2 s,Energy2 mf2) const; /** * The \f$C(s)\f$ function of NBP339 (1990) 38-66 * @param s The \f$s\f$ invariant * @param t The \f$t\f$ invariant * @param u The \f$u\f$ invariant * @param mf2 The fermion mass squared */ complex D(Energy2 s,Energy2 t, Energy2 u,Energy2 mf2) const; /** * The integral \f$\int\frac{dy}{y-y_0}\log(a-i\epsilon-b y(1-y))\f$ * from NBP339 (1990) 38-66. * @param a The parameter \f$a\f$. * @param b The parameter \f$b\f$. * @param y0 The parameter \f$y_0\f$. */ Complex dIntegral(Energy2 a, Energy2 b, double y0) const; /** * The \f$M_{+++}\f$ matrix element of NBP339 (1990) 38-66. * @param s The \f$s\f$ invariant * @param t The \f$t\f$ invariant * @param u The \f$u\f$ invariant * @param mf2 The fermion mass squared. * @param i Which of the stored values to use for \f$D(u,t)\f$. * @param j Which of the stored values to use for \f$D(u,s)\f$. * @param k Which of the stored values to use for \f$D(s,t)\f$. * @param i1 Which of the stored values to use for \f$C_1(s)\f$. * @param j1 Which of the stored values to use for \f$C_1(t)\f$. * @param k1 Which of the stored values to use for \f$C_1(u)\f$. */ complex me1(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2, unsigned int i,unsigned int j, unsigned int k, unsigned int i1,unsigned int j1, unsigned int k1) const; /** * The \f$M_{++-}\f$ matrix element of NBP339 (1990) 38-66. * @param s The \f$s\f$ invariant * @param t The \f$t\f$ invariant * @param u The \f$u\f$ invariant * @param mf2 The fermion mass squared. */ complex me2(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2) const; /** * The \f$F(x)\f$ function for the leading-order result */ Complex F(double x) const; //@} /** * Method to extract the PDF weight for quark/antiquark * initiated processes and select the quark flavour */ tPDPtr quarkFlavour(tcPDFPtr pdf, Energy2 scale, double x, tcBeamPtr beam, double & pdfweight, bool anti); /** * Return the momenta and type of hard matrix element correction * @param gluons The original incoming particles. * @param beams The BeamParticleData objects * @param higgs The original outgoing higgs * @param iemit Whether the first (0) or second (1) particle emitted * the radiation * @param itype The type of radiated particle (0 is gluon, 1 is quark * and 2 is antiquark) * @param pnew The momenta of the new particles * @param xnew The new values of the momentuym fractions * @param out The ParticleData object for the outgoing parton * @return Whether or not the matrix element correction needs to be applied */ - bool applyHard(ShowerParticleVector gluons, + bool applyHard(ParticleVector gluons, vector beams, PPtr higgs,unsigned int & iemit, unsigned int & itype,vector & pnew, pair & xnew, tPDPtr & out); /** * generates the hardest emission (yj,p) * @param pnew The momenta of the new particles * @param emissiontype The type of emission, as for getResult * @return Whether not an emission was generated */ bool getEvent(vector & pnew,int & emissiontype); /** * Returns the matrix element for a given type of process, * rapidity of the jet \f$y_j\f$ and transverse momentum \f$p_T\f$ * @param emis_type the type of emission, * (0 is \f$gg\to h^0g\f$, 1 is \f$qg\to h^0q\f$ and 2 is \f$g\bar{q}\to h^0\bar{q}\f$) * @param pt The transverse momentum of the jet * @param yj The rapidity of the jet * @param outParton the outgoing parton */ double getResult(int emis_type, Energy pt, double yj,tcPDPtr & outParton); private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initMEPP2Higgs; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEPP2Higgs & operator=(const MEPP2Higgs &); //@} /** * Members to return the matrix elements for the different subprocesses */ //@{ /** * Calculates the matrix element for the process g,g->h (via quark loops) * @param g1 a vector of wave functions of the first incoming gluon * @param g2 a vector of wave functions of the second incoming gluon * @param calc Whether or not to calculate the matrix element for spin correlations * @return the amlitude value. */ double ggME(vector g1, vector g2, ScalarWaveFunction &, bool calc) const; /** * Calculates the matrix element for the process q,qbar->h * @param fin a vector of quark spinors * @param ain a vector of anti-quark spinors * @param calc Whether or not to calculate the matrix element for spin correlations * @return the amlitude value. */ double qqME(vector & fin, vector & ain, ScalarWaveFunction &, bool calc) const; //@} private: /** * Selects a dynamic (sHat) or fixed factorization scale */ unsigned int scaleopt_; /** * The value associated to the fixed factorization scale option */ Energy mu_F_; /** * Defines the Higgs resonance shape */ unsigned int shapeOption_; /** * The processes to be included (GG->H and/or qq->H) */ unsigned int processOption_; /** * Minimum flavour of incoming quarks */ int minFlavour_; /** * Maximum flavour of incoming quarks */ int maxFlavour_; /** * Matrix element for spin correlations */ ProductionMatrixElement me_; /** * Pointer to the H-> 2 gluon vertex (used in gg->H) */ AbstractVVSVertexPtr HGGVertex_; /** * Pointer to the fermion-fermion Higgs vertex (used in qq->H) */ AbstractFFSVertexPtr HFFVertex_; /** * The mass generator for the Higgs */ GenericMassGeneratorPtr hmass_; /** * On-shell mass for the higgs */ Energy mh_; /** * On-shell width for the higgs */ Energy wh_; /** * Stuff for the ME correction */ //@{ /** * Parameters for the evaluation of the loops for the * matrix elements */ //@{ /** * Minimum flavour of quarks to include in the loops */ unsigned int minLoop_; /** * Maximum flavour of quarks to include in the loops */ unsigned int maxLoop_; /** * Option for treatment of the fermion loops */ unsigned int massOption_; /** * Option for dynamic scale choice in alpha_S (0=mT,>0=pT) */ unsigned int mu_R_opt_; /** * Option for dynamic scale choice in PDFs (0=mT,>0=pT) */ unsigned int mu_F_opt_; //@} //@} /** * Small complex number to regularize some integrals */ static const complex epsi_; /** * Storage of the loop functions */ //@{ /** * B functions */ mutable Complex bi_[5]; /** * C functions */ mutable complex ci_[8]; /** * D functions */ mutable complex di_[4]; //@} /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alpha_; /** * Mass squared of Higgs */ Energy2 mh2_; /** * Relative weight of the \f$qg\f$ to the \f$gg\f$ channel */ double channelwgtA_; /** * Relative weight for the \f$\bar{q}g\f$ to the \f$gg\f$ channel */ double channelwgtB_; /** * Weights for the channels as a vector */ vector channelWeights_; /** * Power for the \f$\frac{{\rm d}\hat{s}}{\hat{s}^n}\f$ importance sampling * of the \f$gg\f$ component */ double ggPow_; /** * Power for the \f$\frac{{\rm d}\hat{s}}{\hat{s}^n}\f$ importance sampling * of the \f$qg\f$ and \f$\bar{q}g\f$ components */ double qgPow_; /** * The enhancement factor for initial-state radiation */ double enhance_; /** * Number of weights greater than 1 */ unsigned int nover_; /** * Number of attempts */ unsigned int ntry_; /** * Number which suceed */ unsigned int ngen_; /** * Maximum weight */ double maxwgt_; //@} /** * Constants for the sampling. The distribution is assumed to have the * form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$ */ //@{ /** * The power, \f$n\f$, for the sampling */ double power_; /** * The prefactor, \f$c\f$ for the \f$gg\f$ channel */ double pregg_; /** * The prefactor, \f$c\f$ for the \f$qg\f$ channel */ double preqg_; /** * The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel */ double pregqbar_; /** * The prefactors as a vector for easy use */ vector prefactor_; //@} /** * The transverse momentum of the jet */ Energy minpT_; /** * Properties of the incoming particles */ //@{ /** * Pointers to the BeamParticleData objects */ vector beams_; /** * Pointers to the ParticleDataObjects for the partons */ vector partons_; //@} /** * Properties of the boson and jets */ //@{ /** * The rapidity of the Higgs boson */ double yh_; /** * The mass of the Higgs boson */ Energy mass_; /** * the rapidity of the jet */ double yj_; /** * The transverse momentum of the jet */ Energy pt_; /** * The outgoing parton */ tcPDPtr out_; //@} /** * Whether of not to construct the vertex for spin correlations */ bool spinCorrelations_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes of MEPP2Higgs. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MEPP2Higgs. */ typedef Herwig::HwMEBase NthBase; }; /** This template specialization informs ThePEG about the name of * the MEPP2Higgs 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::MEPP2Higgs"; } /** * The name of a file containing the dynamic library where the class * MEPP2Higgs is implemented. It may also include several, space-separated, * libraries if the class MEPP2Higgs 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 "HwMEHadron.so"; } }; /** @endcond */ } #endif /* HERWIG_MEPP2Higgs_H */ diff --git a/MatrixElement/Hadron/MEPP2HiggsVBF.cc b/MatrixElement/Hadron/MEPP2HiggsVBF.cc --- a/MatrixElement/Hadron/MEPP2HiggsVBF.cc +++ b/MatrixElement/Hadron/MEPP2HiggsVBF.cc @@ -1,1632 +1,1456 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2HiggsVBF class. // #include "MEPP2HiggsVBF.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/PDT/StandardMatchers.h" #include #include "Herwig/Utilities/Maths.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/Repository/CurrentGenerator.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/Branching.h" -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; // namespace { // using namespace Herwig; // using namespace ThePEG; // using namespace ThePEG::Helicity; // void debuggingMatrixElement(bool BGF, // tcPDPtr partons1, tcPDPtr partons2, // tcPDPtr partons3, tcPDPtr partons4, // const Lorentz5Momentum & psystem0, // const Lorentz5Momentum & psystem1, // const Lorentz5Momentum & pother0, // const Lorentz5Momentum & pother1, // const Lorentz5Momentum & p0, // const Lorentz5Momentum & p1, // const Lorentz5Momentum & p2, // const Lorentz5Momentum & phiggs, // Energy2 Q12, Energy2 scale, // double old) { // // get the vertex and the boson // tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast // (CurrentGenerator::current().standardModel()); // assert(hwsm); // tcPDPtr boson; // AbstractFFVVertexPtr weakVertex; // AbstractFFVVertexPtr strongVertex = hwsm->vertexFFG(); // AbstractVVSVertexPtr higgsVertex = hwsm->vertexWWH(); // if(partons1->id()==partons2->id()) { // weakVertex = hwsm->vertexFFZ(); // boson = hwsm->getParticleData(ParticleID::Z0); // } // else { // weakVertex = hwsm->vertexFFW(); // boson = hwsm->getParticleData(ParticleID::Wplus); // } // tcPDPtr hdata = hwsm->getParticleData(ParticleID::h0); // tcPDPtr gluon = hwsm->getParticleData(ParticleID::g); // SpinorWaveFunction q1,q2; // SpinorBarWaveFunction qbar1,qbar2; // if(partons1->id()>0) { // q1 = SpinorWaveFunction (psystem0,partons1,incoming); // qbar1 = SpinorBarWaveFunction(psystem1,partons2,outgoing); // } // else { // q1 = SpinorWaveFunction (psystem1,partons2,outgoing); // qbar1 = SpinorBarWaveFunction(psystem0,partons1,incoming); // } // if(partons3->id()>0) { // q2 = SpinorWaveFunction (pother0,partons3,incoming); // qbar2 = SpinorBarWaveFunction(pother1,partons4,outgoing); // } // else { // q2 = SpinorWaveFunction (pother1,partons4,outgoing); // qbar2 = SpinorBarWaveFunction(pother0,partons3,incoming); // } // ScalarWaveFunction higgs(phiggs,hdata,outgoing); // if(!BGF) { // SpinorWaveFunction q1p; // SpinorBarWaveFunction qbar1p; // if(partons1->id()>0) { // q1p = SpinorWaveFunction (p0 ,partons1,incoming); // qbar1p = SpinorBarWaveFunction(p1 ,partons2,outgoing); // } // else { // q1p = SpinorWaveFunction (p1 ,partons2,outgoing); // qbar1p = SpinorBarWaveFunction(p0 ,partons1,incoming); // } // VectorWaveFunction gl(p2,gluon,outgoing); // double lome(0.),realme(0.); // for(unsigned int lhel1=0;lhel1<2;++lhel1) { // q2.reset(lhel1); // for(unsigned int lhel2=0;lhel2<2;++lhel2) { // qbar2.reset(lhel2); // VectorWaveFunction off1 // = weakVertex->evaluate(scale,3,boson,q2,qbar2); // VectorWaveFunction off2 // = higgsVertex->evaluate(scale,3,boson,off1,higgs); // for(unsigned int qhel1=0;qhel1<2;++qhel1) { // q1.reset(qhel1); // q1p.reset(qhel1); // for(unsigned int qhel2=0;qhel2<2;++qhel2) { // qbar1.reset(qhel2); // qbar1p.reset(qhel2); // Complex diag = weakVertex->evaluate(scale,q1,qbar1,off2); // lome += norm(diag); // for(unsigned int ghel=0;ghel<2;++ghel) { // gl.reset(2*ghel); // SpinorWaveFunction inter1 = // strongVertex->evaluate(Q12,5,q1p.particle(),q1p,gl); // Complex diag1 = weakVertex->evaluate(scale,inter1,qbar1p,off2); // SpinorBarWaveFunction inter2 = // strongVertex->evaluate(Q12,5,qbar1p.particle(),qbar1p,gl); // Complex diag2 = weakVertex->evaluate(scale,q1p,inter2,off2); // realme += norm(diag1+diag2); // } // } // } // } // } // double test1 = realme/lome/hwsm->alphaS(Q12)*Q12*UnitRemoval::InvE2; // cerr << "testing ratio A " << old/test1 << "\n"; // } // else { // SpinorWaveFunction q1p; // SpinorBarWaveFunction qbar1p; // if(partons1->id()>0) { // q1p = SpinorWaveFunction (p2,partons1->CC(),outgoing); // qbar1p = SpinorBarWaveFunction(p1,partons2 ,outgoing); // } // else { // q1p = SpinorWaveFunction (p1,partons2 ,outgoing); // qbar1p = SpinorBarWaveFunction(p2,partons1->CC(),outgoing); // } // VectorWaveFunction gl(p0,gluon,incoming); // double lome(0.),realme(0.); // for(unsigned int lhel1=0;lhel1<2;++lhel1) { // q2.reset(lhel1); // for(unsigned int lhel2=0;lhel2<2;++lhel2) { // qbar2.reset(lhel2); // VectorWaveFunction off1 // = weakVertex->evaluate(scale,3,boson,q2,qbar2); // VectorWaveFunction off2 // = higgsVertex->evaluate(scale,3,boson,off1,higgs); // for(unsigned int qhel1=0;qhel1<2;++qhel1) { // q1.reset(qhel1); // q1p.reset(qhel1); // for(unsigned int qhel2=0;qhel2<2;++qhel2) { // qbar1.reset(qhel2); // qbar1p.reset(qhel2); // Complex diag = weakVertex->evaluate(scale,q1,qbar1,off2); // lome += norm(diag); // for(unsigned int ghel=0;ghel<2;++ghel) { // gl.reset(2*ghel); // SpinorWaveFunction inter1 = // strongVertex->evaluate(Q12,5,q1p.particle(),q1p,gl); // Complex diag1 = weakVertex->evaluate(scale,inter1,qbar1p,off2); // SpinorBarWaveFunction inter2 = // strongVertex->evaluate(Q12,5,qbar1p.particle(),qbar1p,gl); // Complex diag2 = weakVertex->evaluate(scale,q1p,inter2,off2); // realme += norm(diag1+diag2); // } // } // } // } // } // double test1 = realme/lome/hwsm->alphaS(Q12)*Q12*UnitRemoval::InvE2; // cerr << "testing ratio B " << old/test1 << "\n"; // } // } // } MEPP2HiggsVBF::MEPP2HiggsVBF() : comptonWeight_(8.), BGFWeight_(30.), pTmin_(1.*GeV),initial_(10.),final_(8.), procProb_(0.5), comptonInt_(0.), bgfInt_(0.), nover_(0),maxwgt_(make_pair(0.,0.)) {} void MEPP2HiggsVBF::doinit() { gluon_ = getParticleData(ParticleID::g); // integrals of me over phase space double r5=sqrt(5.),darg((r5-1.)/(r5+1.)),ath(0.5*log((1.+1./r5)/(1.-1./r5))); comptonInt_ = 2.*(-21./20.-6./(5.*r5)*ath+sqr(Constants::pi)/3. -2.*Math::ReLi2(1.-darg)-2.*Math::ReLi2(1.-1./darg)); bgfInt_ = 121./9.-56./r5*ath; // get the vertex pointers from the SM object tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "MEPP2HiggsVBF::doinit() the Herwig" << " version must be used" << Exception::runerror; // set the vertex setWWHVertex(hwsm->vertexWWH()); higgs(getParticleData(ParticleID::h0)); MEfftoffH::doinit(); } void MEPP2HiggsVBF::dofinish() { MEfftoffH::dofinish(); if(nover_==0) return; generator()->log() << "VBFMECorrection when applying the hard correction " << nover_ << " weights larger than one were generated of which" << " the largest was " << maxwgt_.first << " for the QCD compton" << " processes and " << maxwgt_.second << " for the BGF process\n"; } void MEPP2HiggsVBF::getDiagrams() const { // get the quark particle data objects as we'll be using them tcPDPtr q[6],qbar[6]; for ( int ix=0; ix<5; ++ix ) { q [ix] = getParticleData(ix+1); qbar[ix] = q[ix]->CC(); } // WW processes if(process()==0||process()==1) { std::vector > parentpair; parentpair.reserve(6); // don't even think of putting 'break' in here! switch(maxFlavour()) { case 5: if (minFlavour()<=4) parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::c))); if (minFlavour()<=2) parentpair.push_back(make_pair(getParticleData(ParticleID::b), getParticleData(ParticleID::u))); case 4: if (minFlavour()<=3) parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::c))); if (minFlavour()<=1) parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::c))); case 3: if (minFlavour()<=2) parentpair.push_back(make_pair(getParticleData(ParticleID::s), getParticleData(ParticleID::u))); case 2: if (minFlavour()<=1) parentpair.push_back(make_pair(getParticleData(ParticleID::d), getParticleData(ParticleID::u))); default: ; } for(unsigned int ix=0;ix q1' q2' h if(parentpair[ix].first->id()id()) { add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first, WMinus(), WPlus(), parentpair[iy].second, 1, parentpair[ix].second, 3, parentpair[iy].first, 2, higgs(),-1))); } else { add(new_ptr((Tree2toNDiagram(4), parentpair[iy].second, WPlus(), WMinus(), parentpair[ix].first, 1, parentpair[iy].first, 3, parentpair[ix].second, 2, higgs(),-1))); } // q1 qbar2 -> q1' qbar2' h add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first, WMinus(), WPlus(), parentpair[iy].first->CC(), 1, parentpair[ix].second, 3, parentpair[iy].second->CC(), 2, higgs(),-1))); add(new_ptr((Tree2toNDiagram(4),parentpair[iy].second, WPlus(), WMinus(), parentpair[ix].second->CC(), 1, parentpair[iy].first, 3, parentpair[ix].first->CC(), 2, higgs(),-1))); // qbar1 qbar2 -> qbar1' qbar2' h if(parentpair[ix].first->id()id()) { add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first->CC(), WPlus(), WMinus(), parentpair[iy].second->CC(), 1, parentpair[ix].second->CC(), 3, parentpair[iy].first->CC(), 2, higgs(),-1))); } else { add(new_ptr((Tree2toNDiagram(4), parentpair[iy].second->CC(), WMinus(), WPlus(), parentpair[ix].first->CC(), 1, parentpair[iy].first->CC(), 3, parentpair[ix].second->CC(), 2, higgs(),-1))); } } } } // ZZ processes if(process()==0||process()==2) { for(unsigned int ix=minFlavour()-1;ix q q H add(new_ptr((Tree2toNDiagram(4), q[ix], Z0(), Z0(), q[iy], 1, q[ix], 3, q[iy], 2, higgs(),-2))); // qbar qbar -> qbar qbar H add(new_ptr((Tree2toNDiagram(4), qbar[ix], Z0(), Z0(), qbar[iy], 1, qbar[ix], 3, qbar[iy], 2, higgs(),-2))); } // q qbar -> q qbar H for(unsigned int iy=minFlavour()-1;iy> initial_ >> final_ >> alpha_ >> iunit(pTmin_,GeV) >> comptonWeight_ >> BGFWeight_ >> gluon_ >> comptonInt_ >> bgfInt_ >> procProb_; } ClassDescription MEPP2HiggsVBF::initMEPP2HiggsVBF; // Definition of the static class description member. void MEPP2HiggsVBF::Init() { static ClassDocumentation documentation ("The MEPP2HiggsVBF class implements Higgs production via vector-boson fusion"); static Reference interfaceShowerAlphaQCD ("ShowerAlphaQCD", "The object calculating the strong coupling constant", &MEPP2HiggsVBF::alpha_, false, false, true, false, false); static Parameter interfacepTMin ("pTMin", "The minimum pT", &MEPP2HiggsVBF::pTmin_, GeV, 1.*GeV, 0.0*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceComptonWeight ("ComptonWeight", "Weight for the overestimate ofthe compton channel", &MEPP2HiggsVBF::comptonWeight_, 50.0, 0.0, 100.0, false, false, Interface::limited); static Parameter interfaceBGFWeight ("BGFWeight", "Weight for the overestimate of the BGF channel", &MEPP2HiggsVBF::BGFWeight_, 100.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfaceProcessProbability ("ProcessProbability", "The probabilty of the QCD compton process for the process selection", &MEPP2HiggsVBF::procProb_, 0.3, 0.0, 1., false, false, Interface::limited); } -HardTreePtr MEPP2HiggsVBF::generateHardest(ShowerTreePtr tree, - ShowerInteraction::Type inter) { +RealEmissionProcessPtr MEPP2HiggsVBF::generateHardest(RealEmissionProcessPtr born, + ShowerInteraction::Type inter) { // check if generating QCD radiation if(inter!=ShowerInteraction::QCD && inter!=ShowerInteraction::QEDQCD && inter!=ShowerInteraction::ALL) - return HardTreePtr(); - pair< tShowerParticlePtr, tShowerParticlePtr> first,second; + return RealEmissionProcessPtr(); + pair first,second; pair beams; pair hadrons; // get the incoming particles - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { + for(unsigned int ix=0;ixbornIncoming().size();++ix) { if(!first.first) { - first.first = cit->first->progenitor(); - beams.first = cit->first->beam(); - hadrons.first = cit->first->original()->parents()[0]; + first.first = born->bornIncoming()[ix]; + hadrons.first = born->hadrons()[ix]; + beams.first = dynamic_ptr_cast(born->hadrons()[ix]->dataPtr()); } else { - second.first = cit->first->progenitor(); - beams.second = cit->first->beam(); - hadrons.second = cit->first->original()->parents()[0]; + second.first = born->bornIncoming()[ix]; + hadrons.second = born->hadrons()[ix]; + beams.second = dynamic_ptr_cast(born->hadrons()[ix]->dataPtr()); } } // and the outgoing - for(map::const_iterator - cjt=tree->outgoingLines().begin();cjt!=tree->outgoingLines().end();++cjt) { - if(cjt->first->progenitor()->id()==ParticleID::h0) { - higgs_ = cjt->first->progenitor(); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(born->bornOutgoing()[ix]->id()==ParticleID::h0) { + higgs_ = born->bornOutgoing()[ix]; } else { - if(abs(cjt->first->progenitor()->id())>5) continue; - if(cjt->first->progenitor()->colourLine()&& - cjt->first->progenitor()->colourLine()==first.first->colourLine()) { - first.second = cjt->first->progenitor(); - continue; + if(abs(born->bornOutgoing()[ix]->id())>5) continue; + if(born->bornOutgoing()[ix]->colourLine()&& + born->bornOutgoing()[ix]->colourLine()==first.first->colourLine()) { + first.second = born->bornOutgoing()[ix]; + continue; } - if(cjt->first->progenitor()->antiColourLine()&& - cjt->first->progenitor()->antiColourLine()==first.first->antiColourLine()) { - first.second = cjt->first->progenitor(); - continue; + if(born->bornOutgoing()[ix]->antiColourLine()&& + born->bornOutgoing()[ix]->antiColourLine()==first.first->antiColourLine()) { + first.second = born->bornOutgoing()[ix]; + continue; } - if(cjt->first->progenitor()->colourLine()&& - cjt->first->progenitor()->colourLine()==second.first->colourLine()) { - second.second = cjt->first->progenitor(); - continue; + if(born->bornOutgoing()[ix]->colourLine()&& + born->bornOutgoing()[ix]->colourLine()==second.first->colourLine()) { + second.second = born->bornOutgoing()[ix]; + continue; } - if(cjt->first->progenitor()->antiColourLine()&& - cjt->first->progenitor()->antiColourLine()==second.first->antiColourLine()) { - second.second = cjt->first->progenitor(); - continue; + if(born->bornOutgoing()[ix]->antiColourLine()&& + born->bornOutgoing()[ix]->antiColourLine()==second.first->antiColourLine()) { + second.second = born->bornOutgoing()[ix]; + continue; } } } // loop over the two possible emitting systems q_ [0] = first .second->momentum()-first .first->momentum(); q2_[0] = -q_[0].m2(); q_ [1] = second.second->momentum()-second.first->momentum(); q2_[1] = -q_[1].m2(); for(unsigned int ix=0;ix<2;++ix) { if(ix==1) { swap(first,second); swap(beams.first,beams.second); + swap(hadrons.first,hadrons.second); } // check beam, all particles assert(beams.first && higgs_ && - first .first && first.second && - second.first && second.second); + first .first && first.second && + second.first && second.second); // beam and pdf beam_[ix] = beams.first; pdf_ [ix] = beam_[ix]->pdf(); assert(beam_[ix] && pdf_[ix] ); // Particle data objects partons_[ix][0] = first. first->dataPtr(); partons_[ix][1] = first.second->dataPtr(); partons_[ix][2] = second. first->dataPtr(); partons_[ix][3] = second.second->dataPtr(); // extract the born variables - xB_[ix] = first.first->x(); + xB_[ix] = first.first->momentum().rho()/hadrons.first->momentum().rho(); Lorentz5Momentum pb = first.first->momentum(); Axis axis(q_[ix].vect().unit()); double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot_[ix] = LorentzRotation(); if(axis.perp2()>1e-20) { rot_[ix].setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot_[ix].rotateX(Constants::pi); } if(abs(1.-q_[ix].e()/q_[ix].vect().mag())>1e-6) rot_[ix].boostZ( q_[ix].e()/q_[ix].vect().mag()); pb *= rot_[ix]; if(pb.perp2()/GeV2>1e-20) { Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot_[ix].boost(trans); } // momenta of the particles phiggs_ [ix] = rot_[ix]*higgs_->momentum(); pother_ [ix][0] = rot_[ix]*second. first->momentum(); pother_ [ix][1] = rot_[ix]*second.second->momentum(); psystem_[ix][0] = rot_[ix]* first. first->momentum(); psystem_[ix][1] = rot_[ix]* first.second->momentum(); q_[ix] *= rot_[ix]; pTCompton_[ix] = pTBGF_[ix] = ZERO; // generate a compton point generateCompton(ix); // generate a BGF point generateBGF(ix); } // no valid emissions, return if(pTCompton_[0]::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) - cit->first->maximumpT(pTmin_,ShowerInteraction::QCD); - } - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) - cit->first->maximumpT(pTmin_,ShowerInteraction::QCD); - } - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = pTmin_; + return born; } // find the maximum pT emission unsigned int system = 0; bool isCompton = false; Energy pTmax = -GeV; for(unsigned int ix=0;ix<2;++ix) { if(pTCompton_[ix]>pTmax) { pTmax = pTCompton_[ix]; isCompton = true; system = ix; } if(pTBGF_[ix]>pTmax) { pTmax = pTBGF_[ix]; isCompton = false; system = ix; } } if(system==0) { swap(first,second); swap(beams.first,beams.second); + swap(hadrons.first,hadrons.second); } - // add the non emitting particles - vector spaceBranchings,allBranchings; - spaceBranchings.push_back(new_ptr(HardBranching(second.first,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - allBranchings.push_back(spaceBranchings.back()); - allBranchings.push_back(new_ptr(HardBranching(second.second,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - allBranchings.push_back(new_ptr(HardBranching(higgs_,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - allBranchings[0]->colourPartner(allBranchings[1]); - allBranchings[1]->colourPartner(allBranchings[0]); + // the non emitting particles + PPtr spectin =second.first ->dataPtr()->produceParticle(second.first ->momentum()); + PPtr spectout=second.second->dataPtr()->produceParticle(second.second->momentum()); + spectout->incomingColour(spectin,spectout->id()<0); + PPtr higgs = higgs_->dataPtr()->produceParticle(higgs_->momentum()); rot_[system].invert(); + PPtr newout,newin,emitted; + bool FSR = false; + bool isQuark = first.first->colourLine(); // compton hardest if(isCompton) { for(unsigned int ix=0;ixset5Momentum(ComptonMomenta_[system][1]); - ShowerParticlePtr newg(new_ptr(ShowerParticle(gluon_,true))); - newg->set5Momentum(ComptonMomenta_[system][2]); - ShowerParticlePtr newqin (new_ptr(ShowerParticle(partons_[system][0],false ))); - newqin->set5Momentum(ComptonMomenta_[system][0]); - if(ComptonISFS_[system]) { - ShowerParticlePtr newspace(new_ptr(ShowerParticle(partons_[system][0],false))); - newspace->set5Momentum(ComptonMomenta_[system][0]-ComptonMomenta_[system][2]); - HardBranchingPtr spaceBranch(new_ptr(HardBranching(newqin,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - HardBranchingPtr offBranch(new_ptr(HardBranching(newspace,SudakovPtr(), - spaceBranch, - HardBranching::Incoming))); - spaceBranch->addChild(offBranch); - HardBranchingPtr g(new_ptr(HardBranching(newg,SudakovPtr(),spaceBranch, - HardBranching::Outgoing))); - spaceBranch->addChild(g); - spaceBranch->type(offBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - HardBranchingPtr outBranch(new_ptr(HardBranching(newqout,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - spaceBranchings.push_back(spaceBranch); - allBranchings.push_back(offBranch); - allBranchings.push_back(outBranch); - ColinePtr newin(new_ptr(ColourLine())),newout(new_ptr(ColourLine())); - newin ->addColoured(newqin ,newspace->dataPtr()->iColour()!=PDT::Colour3); - newin ->addColoured(newg ,newspace->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newspace,newspace->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newqout ,newspace->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newg ,newspace->dataPtr()->iColour()==PDT::Colour3); - } - else { - ShowerParticlePtr newtime(new_ptr(ShowerParticle(partons_[system][1],true))); - newtime->set5Momentum(ComptonMomenta_[system][1]+ComptonMomenta_[system][2]); - HardBranchingPtr spaceBranch(new_ptr(HardBranching(newqin,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - HardBranchingPtr offBranch(new_ptr(HardBranching(newtime,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr g(new_ptr(HardBranching(newg,SudakovPtr(),offBranch, - HardBranching::Outgoing))); - HardBranchingPtr outBranch(new_ptr(HardBranching(newqout,SudakovPtr(),offBranch, - HardBranching::Outgoing))); - offBranch->addChild(outBranch); - offBranch->addChild(g); - offBranch->type(offBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - spaceBranchings.push_back(spaceBranch); - allBranchings.push_back(spaceBranch); - allBranchings.push_back(offBranch); - - ColinePtr newin(new_ptr(ColourLine())),newout(new_ptr(ColourLine())); - newin ->addColoured(newqin ,newqin->dataPtr()->iColour()!=PDT::Colour3); - newin ->addColoured(newtime ,newqin->dataPtr()->iColour()!=PDT::Colour3); - newin ->addColoured(newg ,newqin->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newg ,newqin->dataPtr()->iColour()==PDT::Colour3); - newout->addColoured(newqout ,newqin->dataPtr()->iColour()!=PDT::Colour3); - } + newout = partons_[system][1]->produceParticle(ComptonMomenta_[system][1]); + emitted = gluon_ ->produceParticle(ComptonMomenta_[system][2]); + newin = partons_[system][0]->produceParticle(ComptonMomenta_[system][0]); + FSR = !ComptonISFS_[system]; + emitted->incomingColour(newin,!isQuark); + emitted->colourConnect(newout,!isQuark); } // BGF hardest else { for(unsigned int ix=0;ixset5Momentum(BGFMomenta_[system][1]); - ShowerParticlePtr newqbar(new_ptr(ShowerParticle(partons_[system][0]->CC(),true))); - newqbar->set5Momentum(BGFMomenta_[system][2]); - ShowerParticlePtr newg (new_ptr(ShowerParticle(gluon_,false))); - newg->set5Momentum(BGFMomenta_[system][0]); - ShowerParticlePtr newspace(new_ptr(ShowerParticle(partons_[system][0],false))); - newspace->set5Momentum(BGFMomenta_[system][0]-BGFMomenta_[system][2]); - HardBranchingPtr spaceBranch(new_ptr(HardBranching(newg,SudakovPtr(),HardBranchingPtr(), - HardBranching::Incoming))); - HardBranchingPtr offBranch(new_ptr(HardBranching(newspace,SudakovPtr(),spaceBranch, - HardBranching::Incoming))); - HardBranchingPtr qbar(new_ptr(HardBranching(newqbar,SudakovPtr(),spaceBranch, - HardBranching::Outgoing))); - spaceBranch->addChild(offBranch); - spaceBranch->addChild(qbar); - spaceBranch->type(offBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - HardBranchingPtr outBranch(new_ptr(HardBranching(newq,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - spaceBranchings.push_back(spaceBranch); - allBranchings.push_back(offBranch); - allBranchings.push_back(outBranch); - - ColinePtr newin(new_ptr(ColourLine())),newout(new_ptr(ColourLine())); - newout->addColoured(newspace,newspace->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newq ,newspace->dataPtr()->iColour()!=PDT::Colour3); - newout->addColoured(newg ,newspace->dataPtr()->iColour()!=PDT::Colour3); - newin ->addColoured(newg ,newspace->dataPtr()->iColour()==PDT::Colour3); - newin ->addColoured(newqbar ,newspace->dataPtr()->iColour()==PDT::Colour3); + FSR = false; + newin = gluon_ ->produceParticle(BGFMomenta_[system][0]); + emitted = partons_[system][0]->CC()->produceParticle(BGFMomenta_[system][2]); + newout = partons_[system][1] ->produceParticle(BGFMomenta_[system][1]); + emitted->incomingColour(newin, isQuark); + newout ->incomingColour(newin,!isQuark); } - allBranchings[3]->colourPartner(allBranchings[4]); - allBranchings[4]->colourPartner(allBranchings[3]); - HardTreePtr newTree(new_ptr(HardTree(allBranchings,spaceBranchings, - ShowerInteraction::QCD))); - // Set the maximum pt for all other emissions and connect hard and shower tree - Energy pT = isCompton ? pTCompton_[system] : pTBGF_[system]; - // incoming particles - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - // set maximum pT - if(QuarkMatcher::Check(cit->first->progenitor()->data())) - cit->first->maximumpT(pT,ShowerInteraction::QCD); - set::iterator cjt=newTree->branchings().begin(); - if(cit->first->progenitor()==first.first) { - ++cjt;++cjt;++cjt; + pair x; + pair radiators; + if(born->bornIncoming()[0]!=first.first) { + born->incoming().push_back(spectin); + born->incoming().push_back(newin); + x.first = born->bornIncoming()[0]->momentum().rho()/born->hadrons()[0]->momentum().rho(); + x.second = newin ->momentum().rho()/born->hadrons()[1]->momentum().rho(); + radiators.first = 1; + } + else { + born->incoming().push_back(newin); + born->incoming().push_back(spectin); + x.first = newin ->momentum().rho()/born->hadrons()[0]->momentum().rho(); + x.second = born->bornIncoming()[1]->momentum().rho()/born->hadrons()[1]->momentum().rho(); + radiators.first = 0; + } + born->x(x); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(born->bornOutgoing()[ix]==second.second) { + born->outgoing().push_back(spectout); } - newTree->connect(cit->first->progenitor(),*cjt); - tPPtr beam =cit->first->original(); - if(!beam->parents().empty()) beam=beam->parents()[0]; - (*cjt)->beam(beam); - HardBranchingPtr parent=(*cjt)->parent(); - while(parent) { - parent->beam(beam); - parent=parent->parent(); - }; + else if(born->bornOutgoing()[ix]==first.second) { + radiators.second = born->outgoing().size()+2; + born->outgoing().push_back(newout); + } + else + born->outgoing().push_back(higgs); } - // outgoing particles - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - // set maximum pT - if(QuarkMatcher::Check(cit->first->progenitor()->data())) - cit->first->maximumpT(pT,ShowerInteraction::QCD); - for(set::iterator cjt=newTree->branchings().begin(); - cjt!=newTree->branchings().end();++cjt) { - if((*cjt)->branchingParticle()->isFinalState()&& - (*cjt)->branchingParticle()->id()==cit->first->progenitor()->id()) { - newTree->connect(cit->first->progenitor(),*cjt); - } - } - } - // set the evolution partners and scales - ShowerParticleVector particles; - for(set::iterator cit=newTree->branchings().begin(); - cit!=newTree->branchings().end();++cit) { - particles.push_back((*cit)->branchingParticle()); - } - for(set::iterator cjt=newTree->branchings().begin(); - cjt!=newTree->branchings().end();++cjt) { - if(cjt==newTree->branchings().begin()) { - (**cjt).showerMomentum((**cjt).branchingParticle()->momentum()); - ++cjt; - (**cjt).showerMomentum((**cjt).branchingParticle()->momentum()); - ++cjt; - (**cjt).showerMomentum((**cjt).branchingParticle()->momentum()); - ++cjt; - } - } - return newTree; + if(FSR) swap(radiators.first,radiators.second); + born->emitter (radiators.first ); + born->spectator(radiators.second); + born->emitted(born->outgoing().size()+2); + // radiated particle + born->outgoing().push_back(emitted); + born->pT()[ShowerInteraction::QCD] = isCompton ? pTCompton_[system] : pTBGF_[system]; + born->interaction(ShowerInteraction::QCD); + return born; } void MEPP2HiggsVBF::generateCompton(unsigned int system) { // calculate the A coefficient for the correlations acoeff_ = A(partons_[system][0],partons_[system][1], partons_[system][2],partons_[system][3]); // maximum value of the xT double xT = sqrt((1.-xB_[system])/xB_[system]); double xTMin = 2.*pTmin_/sqrt(q2_[system]); double zp; // prefactor double a = alpha_->overestimateValue()*comptonWeight_/Constants::twopi; // loop to generate kinematics double wgt(0.),xp(0.); l_ = 2.*pother_[system][0]/sqrt(q2_[system]); m_ = 2.*pother_[system][1]/sqrt(q2_[system]); vector azicoeff; do { wgt = 0.; // intergration variables dxT/xT^3 xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT)); // dz zp = UseRandom::rnd(); xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp)); // check allowed if(xp1.) continue; // phase-space piece of the weight wgt = 8.*(1.-xp)*zp/comptonWeight_; // PDF piece of the weight Energy2 mu2 = q2_[system]*((1.-xp)*(1-zp)*zp/xp+1.); double pdf = pdf_[system]->xfx(beam_[system],partons_[system][0], mu2 ,xB_[system]/xp)/ pdf_[system]->xfx(beam_[system],partons_[system][0], scale(),xB_[system] ); wgt *= max(pdf,0.); // me piece of the weight // double me = comptonME(system,xT,xp,zp,phi); double x2 = 1.-(1.-zp)/xp; azicoeff = ComptonME(xp,x2,xT,l_,m_); double me = 4./3.*alpha_->ratio(0.25*q2_[system]*sqr(xT))* (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4]); wgt *= me; - if(wgt>1.||wgt<0.) { + if(wgt>1.||wgt<-1e-8) { ostringstream wstring; wstring << "MEPP2HiggsVBF::generateCompton() " << "Weight greater than one or less than zero" << "wgt = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(xT>xTMin&&UseRandom::rnd()>wgt); if(xT<=xTMin) { pTCompton_[system]=-GeV; return; } // generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)),sphi(sin(phi)); phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi) +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in MEPP2HiggsVBF" << "::generateCompton() to" << " generate phi" << Exception::eventerror; // momenta for the configuration Energy Q(sqrt(q2_[system])); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); pTCompton_[system] = 0.5*Q*xT; ComptonMomenta_[system].resize(3); ComptonMomenta_[system][0] = p0; ComptonMomenta_[system][1] = p1; ComptonMomenta_[system][2] = p2; ComptonISFS_[system] = zp>xp; } double MEPP2HiggsVBF::comptonME(unsigned int system, double xT, double xp, double zp, double phi) { // scale and prefactors double CFfact = 4./3.*alpha_->ratio(0.25*q2_[system]*sqr(xT)); Energy Q(sqrt(q2_[system])); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; //set NLO momenta Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); Lorentz5Momentum qnlo = p2+p1-p0; // Breit frame variables Lorentz5Momentum r1 = -p0/x1; Lorentz5Momentum r2 = p1/x2; // electroweak parameters double c0L,c1L,c0R,c1R; // W if(partons_[system][0]->id()!=partons_[system][1]->id()) { c0L = sqrt(0.5); c0R = 0; c1L = sqrt(0.5); c1R = 0; } // Z else { if(abs(partons_[system][0]->id())%2==0) { c0L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c0R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c0L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c0R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } if(abs(partons_[system][2]->id())%2==0) { c1L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c1R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c1L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c1R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } c0L *= 0.25; c0R *= 0.25; c1L *= 0.25; c1R *= 0.25; } // Matrix element variables double G1 = sqr(c0L*c1L)+sqr(c0R*c1R); double G2 = sqr(c0L*c1R)+sqr(c0R*c1L); Energy4 term1,term2,loME; if(partons_[system][0]->id()>0) { if(partons_[system][2]->id()>0) { term1 = loMatrixElement(r1 ,pother_[system][0], qnlo+r1 ,pother_[system][1],G1,G2); term2 = loMatrixElement(r2-qnlo ,pother_[system][0], r2 ,pother_[system][1],G1,G2); loME = loMatrixElement(psystem_[system][0],pother_[system][0], psystem_[system][1],pother_[system][1],G1,G2); } else { term1 = loMatrixElement(r1 ,pother_[system][1], qnlo+r1 ,pother_[system][0],G1,G2); term2 = loMatrixElement(r2-qnlo ,pother_[system][1], r2 ,pother_[system][0],G1,G2); loME = loMatrixElement(psystem_[system][0],pother_[system][1], psystem_[system][1],pother_[system][0],G1,G2); } } else { if(partons_[system][2]->id()>0) { term1 = loMatrixElement(qnlo+r1 ,pother_[system][0], r1 ,pother_[system][1],G1,G2); term2 = loMatrixElement(r2 ,pother_[system][0], r2-qnlo ,pother_[system][1],G1,G2); loME = loMatrixElement(psystem_[system][1],pother_[system][0], psystem_[system][0],pother_[system][1],G1,G2); } else { term1 = loMatrixElement(qnlo+r1,pother_[system][1],r1 , pother_[system][0],G1,G2); term2 = loMatrixElement(r2 ,pother_[system][1],r2-qnlo, pother_[system][0],G1,G2); loME = loMatrixElement(psystem_[system][1],pother_[system][1], psystem_[system][0],pother_[system][0],G1,G2); } } double R1 = term1/loME; double R2 = sqr(x2)/(sqr(x2)+sqr(xT))*(term2/loME); // debuggingMatrixElement(false, // partons_[system][0],partons_[system][1], // partons_[system][2],partons_[system][3], // psystem_[system][0],psystem_[system][1], // pother_ [system][0],pother_ [system][1], // p0,p1,p2,phiggs_[system],q2_[system],scale(), // 8.*Constants::pi/(1.-xp)/(1.-zp)*(R1+sqr(xp)*(sqr(x2)+sqr(xT))*R2)); // cerr << "testing pieces A " << R1 << " " << sqr(xp)*(sqr(x2)+sqr(xT)) << " " << R2 << "\n"; return CFfact*(R1+sqr(xp)*(sqr(x2)+sqr(xT))*R2); } void MEPP2HiggsVBF::generateBGF(unsigned int system) { // maximum value of the xT double xT = (1.-xB_[system])/xB_[system]; double xTMin = 2.*pTmin_/sqrt(q2_[system]); double zp; // prefactor double a = alpha_->overestimateValue()*BGFWeight_/Constants::twopi; // loop to generate kinematics double wgt(0.),xp(0.); l_ = 2.*pother_[system][0]/sqrt(q2_[system]); m_ = 2.*pother_[system][1]/sqrt(q2_[system]); vector azicoeff; do { wgt = 0.; // intergration variables dxT/xT^3 xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT)); // dzp zp = UseRandom::rnd(); xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp)); // check allowed if(xp1.) continue; // phase-space piece of the weight wgt = 8.*sqr(1.-xp)*zp/BGFWeight_; // PDF piece of the weight Energy2 mu2 = q2_[system]*((1.-xp)*(1-zp)*zp/xp+1.); wgt *= pdf_[system]->xfx(beam_[system],gluon_ , mu2 ,xB_[system]/xp)/ pdf_[system]->xfx(beam_[system],partons_[system][0], scale(),xB_[system]); // me piece of the weight //double me = BGFME(system,xT,xp,zp,phi); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; azicoeff = BGFME(xp,x2,x3,xT,l_,m_); double me = 0.5*alpha_->ratio(0.25*q2_[system]*sqr(xT))* (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4]); wgt *= me; - if(wgt>1.||wgt<0.) { + if(wgt>1.||wgt<-1e-8) { ostringstream wstring; wstring << "MEPP2HiggsVBF::generateBGF() " << "Weight greater than one or less than zero" << "wgt = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(xT>xTMin&&UseRandom::rnd()>wgt); if(xT<=xTMin) { pTBGF_[system] = -GeV; return; } // generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)),sphi(sin(phi)); phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi) +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in MEPP2HiggsVBF" << "::generateBGF() to" << " generate phi" << Exception::eventerror; // momenta for the configuration Energy Q(sqrt(q2_[system])); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); pTBGF_[system] = 0.5*Q*xT; BGFMomenta_[system].resize(3); BGFMomenta_[system][0] = p0; BGFMomenta_[system][1] = p1; BGFMomenta_[system][2] = p2; } double MEPP2HiggsVBF::BGFME(unsigned int system, double xT, double xp, double zp, double phi) { // scale and prefactors double TRfact = 0.5*alpha_->ratio(0.25*q2_[system]*sqr(xT)); Energy Q(sqrt(q2_[system])); double x1 = -1./xp; double x2 = 1.-(1.-zp)/xp; double x3 = 2.+x1-x2; // Set NLO momenta Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); Lorentz5Momentum qnlo = p2+p1-p0; // Breit frame variables Lorentz5Momentum r2 = p1/x2; Lorentz5Momentum r3 = -p2/x3; // electroweak parameters double c0L,c1L,c0R,c1R; // W if(partons_[system][0]->id()!=partons_[system][1]->id()) { c0L = sqrt(0.5); c0R = 0; c1L = sqrt(0.5); c1R = 0; } // Z else { if(abs(partons_[system][0]->id())%2==0) { c0L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c0R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c0L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c0R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } if(abs(partons_[system][2]->id())%2==0) { c1L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c1R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c1L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c1R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } c0L *= 0.25; c0R *= 0.25; c1L *= 0.25; c1R *= 0.25; } // Matrix element variables double G1 = sqr(c0L*c1L)+sqr(c0R*c1R); double G2 = sqr(c0L*c1R)+sqr(c0R*c1L); Energy4 term2,term3,loME; if(partons_[system][0]->id()>0) { if(partons_[system][2]->id()>0) { term2 = loMatrixElement(r2-qnlo,pother_[system][0], r2 ,pother_[system][1],G1,G2); term3 = loMatrixElement(r3 ,pother_[system][0], qnlo+r3,pother_[system][1],G1,G2); loME = loMatrixElement(psystem_[system][0],pother_[system][0], psystem_[system][1],pother_[system][1],G1,G2); } else { term2 = loMatrixElement(r2-qnlo,pother_[system][1], r2 ,pother_[system][0],G1,G2); term3 = loMatrixElement(r3 ,pother_[system][1], qnlo+r3,pother_[system][0],G1,G2); loME = loMatrixElement(psystem_[system][0],pother_[system][1], psystem_[system][1],pother_[system][0],G1,G2); } } else { if(partons_[system][2]->id()>0) { term2 = loMatrixElement(r2 ,pother_[system][0], r2-qnlo,pother_[system][1],G1,G2); term3 = loMatrixElement(qnlo+r3,pother_[system][0], r3 ,pother_[system][1],G1,G2); loME = loMatrixElement(psystem_[system][1],pother_[system][0], psystem_[system][0],pother_[system][1],G1,G2); } else { term2 = loMatrixElement(r2 ,pother_[system][1], r2-qnlo,pother_[system][0],G1,G2); term3 = loMatrixElement(qnlo+r3,pother_[system][1], r3 ,pother_[system][0],G1,G2); loME = loMatrixElement(psystem_[system][1],pother_[system][1], psystem_[system][0],pother_[system][0],G1,G2); } } double R3 = sqr(x3)/(sqr(x3)+sqr(xT))*(term3/loME); double R2 = sqr(x2)/(sqr(x2)+sqr(xT))*(term2/loME); // debuggingMatrixElement(true, // partons_[system][0],partons_[system][1], // partons_[system][2],partons_[system][3], // psystem_[system][0],psystem_[system][1], // pother_ [system][0],pother_ [system][1], // p0,p1,p2,phiggs_[system],q2_[system], // 8.*Constants::pi/zp/(1.-zp)*(sqr(xp)*(sqr(x3)+sqr(xT))*R3+ // sqr(xp)*(sqr(x2)+sqr(xT))*R2)); return TRfact* (sqr(xp)*(sqr(x3)+sqr(xT))*R3+ sqr(xp)*(sqr(x2)+sqr(xT))*R2); } Energy4 MEPP2HiggsVBF::loMatrixElement(const Lorentz5Momentum &p1, const Lorentz5Momentum &p2, const Lorentz5Momentum &q1, const Lorentz5Momentum &q2, double G1, double G2) const { return G1*(p1*p2)*(q1*q2) + G2*(p1*q2)*(q1*p2); } -void MEPP2HiggsVBF::initializeMECorrection(ShowerTreePtr tree, double & initial, +void MEPP2HiggsVBF::initializeMECorrection(RealEmissionProcessPtr born, + double & initial, double & final) { systems_.clear(); - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(QuarkMatcher::Check(cit->first->progenitor()->data())) { + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) { systems_.push_back(tChannelPair()); - systems_.back().hadron = cit->first->original()->parents()[0]; - systems_.back().beam = cit->first->beam(); - systems_.back().incoming = cit->first->progenitor(); + systems_.back().hadron = born->hadrons()[ix]; + systems_.back().beam = dynamic_ptr_cast(systems_.back().hadron->dataPtr()); + systems_.back().incoming = born->bornIncoming()[ix]; systems_.back().pdf = systems_.back().beam->pdf(); } } - vector outgoing; - for(map::const_iterator - cjt=tree->outgoingLines().begin();cjt!=tree->outgoingLines().end();++cjt) { - if(cjt->first->progenitor()->id()==ParticleID::h0) - higgs_ = cjt->first->progenitor(); - else if(QuarkMatcher::Check(cjt->first->progenitor()->data())) - outgoing.push_back(cjt->first->progenitor()); + vector outgoing; + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(born->bornOutgoing()[ix]->id()==ParticleID::h0) + higgs_ = born->bornOutgoing()[ix]; + else if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data())) + outgoing.push_back(born->bornOutgoing()[ix]); } assert(outgoing.size()==2&&higgs_); // match up the quarks for(unsigned int ix=0;ixcolourLine()) { for(unsigned int iy=0;iycolourLine()==systems_[ix].incoming->colourLine()) { - systems_[ix].outgoing=outgoing[iy]; - break; - } + if(outgoing[iy]->colourLine()==systems_[ix].incoming->colourLine()) { + systems_[ix].outgoing=outgoing[iy]; + break; + } } } else { for(unsigned int iy=0;iyantiColourLine()==systems_[ix].incoming->antiColourLine()) { - systems_[ix].outgoing=outgoing[iy]; - break; - } + if(outgoing[iy]->antiColourLine()==systems_[ix].incoming->antiColourLine()) { + systems_[ix].outgoing=outgoing[iy]; + break; + } } } } assert(systems_[0].outgoing&&systems_[1].outgoing); assert(systems_.size()==2); initial = initial_; final = final_; } -void MEPP2HiggsVBF::applyHardMatrixElementCorrection(ShowerTreePtr tree) { +RealEmissionProcessPtr MEPP2HiggsVBF::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { static const double eps = 1e-6; // select emitting line if(UseRandom::rndbool()) swap(systems_[0],systems_[1]); // extract the born variables q_[0] = systems_[0].outgoing->momentum()-systems_[0].incoming->momentum(); q2_[0] = -q_[0].m2(); Energy Q = sqrt(q2_[0]); - xB_[0] = systems_[0].incoming->x(); + xB_[0] = systems_[0].incoming->momentum().rho()/systems_[0].hadron->momentum().rho(); // construct lorentz transform from lab to breit frame Lorentz5Momentum phadron = systems_[0].hadron->momentum(); phadron.setMass(0.*GeV); phadron.rescaleEnergy(); Lorentz5Momentum pcmf = phadron+0.5/xB_[0]*q_[0]; pcmf.rescaleMass(); LorentzRotation rot(-pcmf.boostVector()); Lorentz5Momentum pbeam = rot*phadron; Axis axis(pbeam.vect().unit()); double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); Lorentz5Momentum pout = rot*(systems_[1].outgoing->momentum()+higgs_->momentum()); rot.rotateZ(-atan2(pout.y(),pout.x())); // calculate the A coefficient for the correlations acoeff_ = A(systems_[0].incoming->dataPtr(),systems_[0].outgoing->dataPtr(), systems_[1].incoming->dataPtr(),systems_[1].outgoing->dataPtr()); vector azicoeff; // select the type of process bool BGF = UseRandom::rnd()>procProb_; double wgt,xp,zp,x1,x2,x3,xperp; l_ = 2.*(rot*systems_[1].incoming->momentum())/Q; m_ = 2.*(rot*systems_[1].outgoing->momentum())/Q; // compton process if(!BGF) { wgt = generateComptonPoint(xp,zp); - if(xpvalue(mu2)/procProb_; // PDF piece wgt *= systems_[0].pdf->xfx(systems_[0].beam, systems_[0].incoming->dataPtr(),mu2 ,xB_[0]/xp)/ systems_[0].pdf->xfx(systems_[0].beam, systems_[0].incoming->dataPtr(),scale(),xB_[0] ); // numerator factors wgt /= (1.-xp)*(1.-zp); // other bits xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); x1 = -1./xp; x2 = 1.-(1.-zp)/xp; x3 = 2.+x1-x2; // matrix element pieces azicoeff = ComptonME(xp,x2,xperp,l_,m_); } else { wgt = generateBGFPoint(xp,zp); - if(xp<1e-6) return; + if(xp<1e-6) return RealEmissionProcessPtr(); // common pieces Energy2 mu2 = q2_[0]*((1.-xp)*(1-zp)*zp/xp+1); wgt *= 0.25/Constants::pi*alpha_->value(mu2)/(1.-procProb_); // PDF piece wgt *= systems_[0].pdf->xfx(systems_[0].beam, gluon_ ,mu2 ,xB_[0]/xp)/ systems_[0].pdf->xfx(systems_[0].beam, systems_[0].incoming->dataPtr(),scale(),xB_[0] ); // numerator factors wgt /= (1.-zp); // other bits xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); x1 = -1./xp; x2 = 1.-(1.-zp)/xp; x3 = 2.+x1-x2; // matrix element pieces azicoeff = BGFME(xp,x2,x3,xperp,l_,m_); } // compute the azimuthal average of the weight wgt *= azicoeff[0]+0.5*(azicoeff[2]+azicoeff[4]); // finally factor as picked one line wgt *= 2.; // decide whether or not to accept the weight - if(UseRandom::rnd()>wgt) return; + if(UseRandom::rnd()>wgt) return RealEmissionProcessPtr(); // if accepted generate generate phi unsigned int itry(0); double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.); double phiwgt,phi; do { phi = UseRandom::rnd()*Constants::twopi; double cphi(cos(phi)),sphi(sin(phi)); phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi) +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi); ++itry; } while (phimax*UseRandom::rnd() > phiwgt && itry<200); if(itry==200) throw Exception() << "Too many tries in VBFMECorrection" << "::applyHardMatrixElementCorrection() to" << " generate phi" << Exception::eventerror; // compute the new incoming and outgoing momenta Lorentz5Momentum p1 = Lorentz5Momentum( 0.5*Q*xperp*cos(phi), 0.5*Q*xperp*sin(phi), -0.5*Q*x2,0.*GeV,0.*GeV); p1.rescaleEnergy(); Lorentz5Momentum p2 = Lorentz5Momentum(-0.5*Q*xperp*cos(phi),-0.5*Q*xperp*sin(phi), -0.5*Q*x3,0.*GeV,0.*GeV); p2.rescaleEnergy(); Lorentz5Momentum pin(0.*GeV,0.*GeV,-0.5*x1*Q,-0.5*x1*Q,0.*GeV); // debugging code to test vs helicity amplitude expression for matrix elements // double cphi(cos(phi)),sphi(sin(phi)); // double old = (azicoeff[0]+azicoeff[5]*sphi*cphi // +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi) // +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi)); // if(!BGF) { // old *= 8.*Constants::pi/(1.-xp)/(1.-zp); // } // else { // old *= 8.*Constants::pi/zp/(1.-zp); // } // debuggingMatrixElement(BGF, // systems_[0].incoming->dataPtr(), // systems_[0].outgoing->dataPtr(), // systems_[1].incoming->dataPtr(), // systems_[1].outgoing->dataPtr(), // rot*systems_[0].incoming->momentum(), // rot*systems_[0].outgoing->momentum(), // rot*systems_[1].incoming->momentum(), // rot*systems_[1].outgoing->momentum(), // pin,p1,p2,rot*higgs_->momentum(), // q2_[0],scale(),old); // we need inverse of the rotation, i.e back to lab from breit rot.invert(); // transform the momenta to lab frame pin *= rot; p1 *= rot; p2 *= rot; // test to ensure outgoing particles can be put on-shell if(!BGF) { - if(p1.e()dataPtr()->constituentMass()) return; - if(p2.e()constituentMass()) return; + if(p1.e()dataPtr()->constituentMass()) return RealEmissionProcessPtr(); + if(p2.e()constituentMass()) return RealEmissionProcessPtr(); } else { - if(p1.e()dataPtr() ->constituentMass()) return; - if(p2.e()dataPtr()->CC()->constituentMass()) return; + if(p1.e()dataPtr() ->constituentMass()) return RealEmissionProcessPtr(); + if(p2.e()dataPtr()->CC()->constituentMass()) return RealEmissionProcessPtr(); } // stats for weights > 1 if(wgt>1.) { ++nover_; if(!BGF) maxwgt_.first = max(maxwgt_.first ,wgt); else maxwgt_.second = max(maxwgt_.second,wgt); } // create the new particles and add to ShowerTree - bool isquark = systems_[0].incoming->colourLine(); + bool isQuark = systems_[0].incoming->colourLine(); + bool FSR= false; + PPtr newin,newout,emitted; if(!BGF) { - PPtr newin = new_ptr(Particle(*systems_[0].incoming)); - newin->set5Momentum(pin); - PPtr newg = gluon_ ->produceParticle(p2 ); - PPtr newout = systems_[0].outgoing->dataPtr()->produceParticle(p1 ); - ColinePtr col=isquark ? - systems_[0].incoming->colourLine() : systems_[0].incoming->antiColourLine(); - ColinePtr newline=new_ptr(ColourLine()); - // final-state emission - if(xp>zp) { - col->removeColoured(newout,!isquark); - col->addColoured(newin,!isquark); - col->addColoured(newg,!isquark); - newline->addColoured(newg,isquark); - newline->addColoured(newout,!isquark); - } - // initial-state emission - else { - col->removeColoured(newin ,!isquark); - col->addColoured(newout,!isquark); - col->addColoured(newg,isquark); - newline->addColoured(newg,!isquark); - newline->addColoured(newin,!isquark); - } - PPtr orig; - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(cit->first->progenitor()!=systems_[0].incoming) continue; - // remove old particles from colour line - col->removeColoured(cit->first->copy(),!isquark); - col->removeColoured(cit->first->progenitor(),!isquark); - // insert new particles - cit->first->copy(newin); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newin,1,false))); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - sp->x(xB_[0]/xp); - cit->first->perturbative(xp>zp); - if(xp<=zp) orig=cit->first->original(); - } - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(cit->first->progenitor()!=systems_[0].outgoing) continue; - // remove old particles from colour line - col->removeColoured(cit->first->copy(),!isquark); - col->removeColoured(cit->first->progenitor(),!isquark); - // insert new particles - cit->first->copy(newout); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newout,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(xp<=zp); - if(xp>zp) orig=cit->first->original(); - } - assert(orig); - // add the gluon - ShowerParticlePtr sg=new_ptr(ShowerParticle(*newg,1,true)); - ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg)); - gluon->perturbative(false); - tree->outgoingLines().insert(make_pair(gluon,sg)); - tree->hardMatrixElementCorrection(true); + newin = systems_[0].incoming->dataPtr()->produceParticle(pin); + emitted = gluon_ ->produceParticle(p2 ); + newout = systems_[0].outgoing->dataPtr()->produceParticle(p1 ); + emitted->incomingColour(newin,!isQuark); + emitted->colourConnect(newout,!isQuark); + FSR = xp>zp; } else { - PPtr newin = gluon_ ->produceParticle(pin); - PPtr newqbar = systems_[0].incoming->dataPtr()->CC()->produceParticle(p2 ); - PPtr newout = systems_[0].outgoing->dataPtr() ->produceParticle(p1 ); - ColinePtr col=isquark ? systems_[0].incoming->colourLine() : systems_[0].incoming->antiColourLine(); - ColinePtr newline=new_ptr(ColourLine()); - col ->addColoured(newin ,!isquark); - newline->addColoured(newin , isquark); - col ->addColoured(newout ,!isquark); - newline->addColoured(newqbar, isquark); - PPtr orig; - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) { - if(cit->first->progenitor()!=systems_[0].incoming) continue; - // remove old particles from colour line - col->removeColoured(cit->first->copy(),!isquark); - col->removeColoured(cit->first->progenitor(),!isquark); - // insert new particles - cit->first->copy(newin); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newin,1,false))); - cit->first->progenitor(sp); - tree->incomingLines()[cit->first]=sp; - sp->x(xB_[0]/xp); - cit->first->perturbative(false); - orig=cit->first->original(); + newin = gluon_ ->produceParticle(pin); + emitted = systems_[0].incoming->dataPtr()->CC()->produceParticle(p2 ); + newout = systems_[0].outgoing->dataPtr() ->produceParticle(p1 ); + emitted->incomingColour(newin, isQuark); + newout ->incomingColour(newin,!isQuark); + FSR = false; + } + pair x; + pair radiators; + if(born->bornIncoming()[0]!=systems_[0].incoming) { + born->incoming().push_back(born->bornIncoming()[0]); + born->incoming().push_back(newin); + x.first = born->bornIncoming()[0]->momentum().rho()/born->hadrons()[0]->momentum().rho(); + x.second = x.first = xB_[0]/xp; + radiators.first = 1; + } + else { + born->incoming().push_back(newin); + born->incoming().push_back(born->bornIncoming()[1]); + x.first = xB_[0]/xp; + x.second = born->bornIncoming()[1]->momentum().rho()/born->hadrons()[1]->momentum().rho(); + radiators.first = 0; + } + born->x(x); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + if(born->bornOutgoing()[ix]!=systems_[0].outgoing) { + born->outgoing().push_back(born->bornOutgoing()[ix]); } - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - if(cit->first->progenitor()!=systems_[0].outgoing) continue; - // remove old particles from colour line - col->removeColoured(cit->first->copy(),!isquark); - col->removeColoured(cit->first->progenitor(),!isquark); - // insert new particles - cit->first->copy(newout); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newout,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(true); + else { + radiators.second = born->outgoing().size()+2; + born->outgoing().push_back(newout); } - assert(orig); - // add the (anti)quark - ShowerParticlePtr sqbar=new_ptr(ShowerParticle(*newqbar,1,true)); - ShowerProgenitorPtr qbar=new_ptr(ShowerProgenitor(orig,newqbar,sqbar)); - qbar->perturbative(false); - tree->outgoingLines().insert(make_pair(qbar,sqbar)); - tree->hardMatrixElementCorrection(true); } + if(FSR) swap(radiators.first,radiators.second); + born->emitter (radiators.first ); + born->spectator(radiators.second); + born->emitted(born->outgoing().size()+2); + // radiated particle + born->outgoing().push_back(emitted); + born->interaction(ShowerInteraction::QCD); + return born; } double MEPP2HiggsVBF::A(tcPDPtr qin1, tcPDPtr qout1, tcPDPtr qin2, tcPDPtr ) { double output; // charged current if(qin1->id()!=qout1->id()) { output = 2; } // neutral current else { double cvl,cal,cvq,caq; if(abs(qin2->id())%2==0) { cvl = generator()->standardModel()->vu(); cal = generator()->standardModel()->au(); } else { cvl = generator()->standardModel()->vd(); cal = generator()->standardModel()->ad(); } if(abs(qin1->id())%2==0) { cvq = generator()->standardModel()->vu(); caq = generator()->standardModel()->au(); } else { cvq = generator()->standardModel()->vd(); caq = generator()->standardModel()->ad(); } output = 8.*cvl*cal*cvq*caq/(sqr(cvl)+sqr(cal))/(sqr(cvq)+sqr(caq)); } if(qin1->id()<0) output *= -1.; if(qin2->id()<0) output *= -1; return output; } double MEPP2HiggsVBF::generateComptonPoint(double &xp, double & zp) { static const double maxwgt = 50.; double wgt,xperp2,x2; do { xp = UseRandom::rnd(); double zpmin = xp, zpmax = 1./(1.+xp*(1.-xp)); zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax); wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp); if(UseRandom::rndbool()) swap(xp,zp); xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp; x2 = 1.-(1.-zp)/xp; wgt *= 2.*(1.+sqr(xp)*(sqr(x2)+1.5*xperp2))/(1.-xp)/(1.-zp); if(wgt>maxwgt) if(wgt>maxwgt) { ostringstream wstring; wstring << "MEPP2HiggsVBF::generateComptonPoint() " << "Weight greater than maximum" << "wgt = " << wgt << " maxwgt = " << maxwgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(wgtmaxwgt) { ostringstream wstring; wstring << "DISBase::generateBGFPoint " << "Weight greater than maximum " << "wgt = " << wgt << " maxwgt = 1\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } while(wgtisFinalState() ? 1./final_ : 1./initial_); // check if me correction should be applied long id[2]={initial->id(),parent->id()}; if(id[0]!=id[1]||id[1]==ParticleID::g) return veto; // if not from the right side if(initial->progenitor()!=systems_[0].incoming && initial->progenitor()!=systems_[0].outgoing) return veto; // get the pT Energy pT=br.kinematics->pT(); // check if hardest so far if(pThighestpT()) return veto; double kappa(sqr(br.kinematics->scale())/q2_[0]),z(br.kinematics->z()); double zk((1.-z)*kappa); // final-state double wgt(0.); if(parent->isFinalState()) { double zp=z,xp=1./(1.+z*zk); double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); double x2 = 1.-(1.-zp)/xp; vector azicoeff = ComptonME(xp,x2,xperp,l_,m_); wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])* xp/(1.+sqr(z))/final_; if(wgt<.0||wgt>1.) { ostringstream wstring; wstring << "Soft ME correction weight too large or " << "negative for FSR in MEPP2HiggsVBF::" << "softMatrixElementVeto() soft weight " << " xp = " << xp << " zp = " << zp << " weight = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } else { double xp = 2.*z/(1.+zk+sqrt(sqr(1.+zk)-4.*z*zk)); double zp = 0.5* (1.-zk+sqrt(sqr(1.+zk)-4.*z*zk)); double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp); double x1 = -1./xp, x2 = 1.-(1.-zp)/xp, x3 = 2.+x1-x2; // compton if(br.ids[0]->id()!=ParticleID::g) { vector azicoeff = ComptonME(xp,x2,xperp,l_,m_); wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])* xp*(1.-z)/(1.-xp)/(1.+sqr(z))/(1.-zp+xp-2.*xp*(1.-zp)); } // BGF else { vector azicoeff = BGFME(xp,x2,x3,xperp,l_,m_); wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])* xp/(1.-zp+xp-2.*xp*(1.-zp))/(sqr(z)+sqr(1.-z)); } wgt /=initial_; if(wgt<.0||wgt>1.) { ostringstream wstring; wstring << "Soft ME correction weight too large or " << "negative for ISR in MEPP2HiggsVBF::" << "softMatrixElementVeto() soft weight " << " xp = " << xp << " zp = " << zp << " weight = " << wgt << "\n"; generator()->logWarning( Exception(wstring.str(), Exception::warning) ); } } // if not vetoed if(UseRandom::rndbool(wgt)) return false; // otherwise parent->vetoEmission(br.type,br.kinematics->scale()); return true; } vector MEPP2HiggsVBF::ComptonME(double xp, double x2, double xperp, LorentzVector l, LorentzVector m) { vector output(6,0.); double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp)); double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp)); // no phi dependence output[0] = l.t()*m.t()-l.z()*m.z()*sqr(cos2)+0.5*acoeff_*cos2*(l.t()*m.z()-l.z()*m.t()); // cos(phi) output[1] = sin2*(-l.x()*m.t()-l.t()*m.x() + 0.5*acoeff_*cos2*(l.z()*m.x()-m.z()*l.x())); // cos(phi)^2 output[2] = +sqr(sin2)*l.x()*m.x(); // sin(phi) output[3] = sin2*(-l.t()*m.y()-l.y()*m.t() + 0.5*acoeff_*cos2*(l.z()*m.y()-m.z()*l.y())); // sin(phi)^2 output[4] = +sqr(sin2)*l.y()*m.y(); // sin(phi)cos(phi) output[5] = +sqr(sin2)*(m.y()*l.x()+m.x()*l.y()); // additional factors double denom = -l.z()*m.z()+l.t()*m.t()+0.5*acoeff_*(l.t()*m.z()-l.z()*m.t()); double fact = sqr(xp)*(sqr(x2)+sqr(xperp))/denom; for(unsigned int ix=0;ix MEPP2HiggsVBF::BGFME(double xp, double x2, double x3, double xperp, LorentzVector l, LorentzVector m) { vector output(6,0.); double denom = -l.z()*m.z()+l.t()*m.t()+0.5*acoeff_*(l.t()*m.z()-l.z()*m.t()); double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp)); double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp)); double fact2 = sqr(xp)*(sqr(x2)+sqr(xperp))/denom; double cos3 = x3 /sqrt(sqr(x3)+sqr(xperp)); double sin3 = xperp/sqrt(sqr(x3)+sqr(xperp)); double fact3 = sqr(xp)*(sqr(x3)+sqr(xperp))/denom; // no phi dependence output[0] = fact2*(l.t()*m.t()-l.z()*m.z()*sqr(cos2) + 0.5*acoeff_*cos2*(l.t()*m.z()-l.z()*m.t())) + fact3*(l.t()*m.t()-l.z()*m.z()*sqr(cos3) - 0.5*acoeff_*cos3*(l.t()*m.z()-l.z()*m.t())); // cos(phi) output[1] = fact2*sin2*( - l.x()*m.t()-l.t()*m.x() + 0.5*acoeff_*cos2*(l.z()*m.x()-m.z()*l.x())) - fact3*sin3*( - l.x()*m.t()-l.t()*m.x() - 0.5*acoeff_*cos3*(l.z()*m.x()-m.z()*l.x())) ; // cos(phi)^2 output[2] = (fact2*sqr(sin2)+fact3*sqr(sin3))*l.x()*m.x(); // sin(phi) output[3] = fact2*sin2*( - l.t()*m.y()-l.y()*m.t() + 0.5*acoeff_*cos2*(l.z()*m.y()-m.z()*l.y())) - fact3*sin3*( - l.t()*m.y()-l.y()*m.t() - 0.5*acoeff_*cos3*(l.z()*m.y()-m.z()*l.y())); // sin(phi)^2 output[4] = (fact2*sqr(sin2)+fact3*sqr(sin3))*l.y()*m.y(); // sin(phi)cos(phi) output[5] = (fact2*sqr(sin2)+fact3*sqr(sin3))*(m.y()*l.x()+m.x()*l.y()); // return the answer return output; } diff --git a/MatrixElement/Hadron/MEPP2HiggsVBF.h b/MatrixElement/Hadron/MEPP2HiggsVBF.h --- a/MatrixElement/Hadron/MEPP2HiggsVBF.h +++ b/MatrixElement/Hadron/MEPP2HiggsVBF.h @@ -1,501 +1,502 @@ // -*- C++ -*- #ifndef HERWIG_MEPP2HiggsVBF_H #define HERWIG_MEPP2HiggsVBF_H // // This is the declaration of the MEPP2HiggsVBF class. // #include "Herwig/MatrixElement/MEfftoffH.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; /** * The MEPP2HiggsVBF class provides the matrix elements for the * production of the Higgs boson via the vector boson fusion mechanism * in hadron collisions * * @see \ref MEPP2HiggsVBFInterfaces "The interfaces" * defined for MEPP2HiggsVBF. */ class MEPP2HiggsVBF: public MEfftoffH { /** * Struct to contain the hadronic system */ struct tChannelPair{ /** * The hadron */ PPtr hadron; /** * The beam particle data object */ tcBeamPtr beam; /** * The incoming particle */ - ShowerParticlePtr incoming; + PPtr incoming; /** * The outgoing particle */ - ShowerParticlePtr outgoing; + PPtr outgoing; /** * The PDF */ tcPDFPtr pdf; }; public: /** * The default constructor. */ MEPP2HiggsVBF(); /** @name Virtual functions required by the MEBase class. */ //@{ /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; //@} /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return Both;} /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return true;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr , double & , + virtual void initializeMECorrection(RealEmissionProcessPtr, double &, double & ); /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr); + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr, ShowerParticlePtr,Branching); /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr, ShowerInteraction::Type); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, + ShowerInteraction::Type); //@} 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: /** * Generate the hardest emission in the POWHEG approach */ //@{ /** * Generate a Compton process */ void generateCompton(unsigned int system); /** * Generate a BGF process */ void generateBGF(unsigned int system); /** * Matrix element piece for the Compton process */ double comptonME(unsigned int system, double xT,double xp, double zp, double phi); /** * Matrix element piece for the Compton process */ double BGFME(unsigned int system, double xT,double xp, double zp, double phi); /** * Leading order matrix element */ Energy4 loMatrixElement(const Lorentz5Momentum &p1, const Lorentz5Momentum &p2, const Lorentz5Momentum &q1, const Lorentz5Momentum &q2, double G1, double G2) const; //@} /** * Generate the hard emission in the old-fashioned matrix element correction approach */ //@{ /** * Generate the values of \f$x_p\f$ and \f$z_p\f$ * @param xp The value of xp, output * @param zp The value of zp, output */ double generateComptonPoint(double &xp, double & zp); /** * Generate the values of \f$x_p\f$ and \f$z_p\f$ * @param xp The value of xp, output * @param zp The value of zp, output */ double generateBGFPoint(double &xp, double & zp); /** * Return the coefficients for the matrix element piece for * the QCD compton case. The output is the \f$a_i\f$ coefficients to * give the function as * \f$a_0+a_1\cos\phi+a_2\sin\phi+a_3\cos^2\phi+a_4\sin^2\phi\f$ * @param xp \f$x_p\f$ * @param x2 \f$x_2\f$ * @param xperp \f$x_\perp\f$ * @param l Scaled momentum of incoming spectator * @param m Scaled momentum of outgoing spectator * */ vector ComptonME(double xp, double x2, double xperp, LorentzVector l, LorentzVector m); /** * Return the coefficients for the matrix element piece for * the QCD compton case. The output is the \f$a_i\f$ coefficients to * give the function as * \f$a_0+a_1\cos\phi+a_2\sin\phi+a_3\cos^2\phi+a_4\sin^2\phi\f$ * @param xp \f$x_p\f$ * @param x2 \f$x_3\f$ * @param x3 \f$x_2\f$ * @param xperp \f$x_\perp\f$ * @param l Scaled momentum of incoming spectator * @param m Scaled momentum of outgoing spectator * */ vector BGFME(double xp, double x2, double x3, double xperp, LorentzVector l, LorentzVector m); /** * Calculate the coefficient A for the correlations */ double A(tcPDPtr qin1, tcPDPtr qout1, tcPDPtr qin2, tcPDPtr qout2); //@} 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(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} 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 initMEPP2HiggsVBF; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEPP2HiggsVBF & operator=(const MEPP2HiggsVBF &); private: /** * Parameters for the hard POWHEG emission */ //@{ /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alpha_; /** * Weight for the compton channel */ double comptonWeight_; /** * Weight for the BGF channel */ double BGFWeight_; /** * Minimum value of \f$p_T\f$ */ Energy pTmin_; /** * Gluon particle data object */ PDPtr gluon_; //@} /** * Properties of the emission */ //@{ /** * Beam particle */ tcBeamPtr beam_[2]; /** * PDF object */ tcPDFPtr pdf_[2]; /** * Partons */ tcPDPtr partons_[2][4]; /** * q */ Lorentz5Momentum q_[2]; /** * \f$Q^2\f$ */ Energy2 q2_[2]; /** * Coupling factor */ double acoeff_; /** * Lorentz vectors for the matrix element */ LorentzVector l_; /** * Lorentz vectors for the matrix element */ LorentzVector m_; /** * Born momentum fraction */ double xB_[2]; /** * Rotation to the Breit frame */ LorentzRotation rot_[2]; /** * Quark momenta for spectator system */ Lorentz5Momentum pother_[2][2]; /** * Quark momenta for emitting system */ Lorentz5Momentum psystem_[2][2]; /** * Higgs momenta */ Lorentz5Momentum phiggs_[2]; /** * Transverse momenta for the compton emissions */ Energy pTCompton_[2]; /** * Transverse momenta for the BGF emissions */ Energy pTBGF_[2]; /** * Whether the Compton radiation is ISR or FSR */ bool ComptonISFS_[2]; /** * Momenta of the particles for a compton emission */ vector ComptonMomenta_[2]; /** * Momenta of the particles for a BGF emission */ vector BGFMomenta_[2]; /** * the systems */ vector systems_; /** * Higgs boson */ - ShowerParticlePtr higgs_; + PPtr higgs_; //@} /** * Parameters for the matrix element correction */ //@{ /** * Enchancement factor for ISR */ double initial_; /** * Enchancement factor for FSR */ double final_; /** * Relative fraction of compton and BGF processes to generate */ double procProb_; /** * Integral for compton process */ double comptonInt_; /** * Integral for BGF process */ double bgfInt_; /** * Number of weights greater than 1 */ unsigned int nover_; /** * Maximum weight */ pair maxwgt_; //@} }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEPP2HiggsVBF. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MEPP2HiggsVBF. */ typedef Herwig::MEfftoffH NthBase; }; /** This template specialization informs ThePEG about the name of * the MEPP2HiggsVBF 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::MEPP2HiggsVBF"; } /** * The name of a file containing the dynamic library where the class * MEPP2HiggsVBF is implemented. It may also include several, space-separated, * libraries if the class MEPP2HiggsVBF 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 "HwMEHadron.so"; } }; /** @endcond */ } #endif /* HERWIG_MEPP2HiggsVBF_H */ diff --git a/MatrixElement/HwMEBase.cc b/MatrixElement/HwMEBase.cc --- a/MatrixElement/HwMEBase.cc +++ b/MatrixElement/HwMEBase.cc @@ -1,289 +1,301 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the HwMEBase class. // #include "HwMEBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/PDT/GenericMassGenerator.h" #include "ThePEG/Cuts/Cuts.h" -#include "Herwig/Shower/Base/HardTree.h" -#include "Herwig/Shower/Base/Branching.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; void HwMEBase::persistentOutput(PersistentOStream & os) const { os << massOption_ << rescaleOption_; } void HwMEBase::persistentInput(PersistentIStream & is, int) { is >> massOption_ >> rescaleOption_; } AbstractClassDescription HwMEBase::initHwMEBase; // Definition of the static class description member. void HwMEBase::Init() { static ClassDocumentation documentation ("The HwMEBase class is the base class for matrix elements in Herwig" " and provides the virtual members for hard radiation corrections in the" " shower."); } int HwMEBase::nDim() const { unsigned ndim = 1; for(unsigned int ix=0;ix & masses, double & mjac, const double *r) { assert(massOption_.size()+2==mePartonData().size()); mjac = 1.; masses.clear(); masses.resize(massOption_.size(),ZERO); Energy ecm = sqrt(sHat()); Energy emin(ZERO); int noff(0); for(unsigned int ix=0;ixhardProcessMass(); emin += masses[ix]; } else if (massOption_[ix]==2) { emin += mePartonData()[ix+2]->massMin(); ++noff; } } // check allowed if(emin>ecm) return false; // if nothing off-shell return if(noff==0) return true; int iloc = nDim()-noff; emin = ecm - emin; // generate the masses for(unsigned int ix=0;ixmassMin(); emin += mmin; Energy mmax = min(mePartonData()[ix+2]->massMax(),emin); if(mmin>mmax) return false; tGenericMassGeneratorPtr gen = mePartonData()[ix+2]->massGenerator() ? dynamic_ptr_cast(mePartonData()[ix+2]->massGenerator()) : tGenericMassGeneratorPtr(); if(gen) { double jtemp(0.); masses[ix] = gen->mass(jtemp,*mePartonData()[ix+2],mmin,mmax,r[iloc]); mjac *= jtemp; } else { Energy mon(mePartonData()[ix+2]->hardProcessMass()); Energy width(mePartonData()[ix+2]->width()); double rhomin = atan2((sqr(mmin)-sqr(mon)), mon*width); double rhomax = atan2((sqr(mmax)-sqr(mon)), mon*width); masses[ix] = sqrt(mon*width*tan(rhomin+r[iloc]*(rhomax-rhomin))+sqr(mon)); mjac *= (rhomax-rhomin)/Constants::pi; } emin -= masses[ix]; if(emin masses; double mjac(0.); if(!generateMasses(masses,mjac,r)) return false; // set up the momenta for ( int i = 2, N = meMomenta().size(); i < N; ++i ) { meMomenta()[i] = Lorentz5Momentum(masses[i-2]); } double ctmin = -1.0, ctmax = 1.0; Energy q = ZERO; try { q = SimplePhaseSpace:: getMagnitude(sHat(), meMomenta()[2].mass(), meMomenta()[3].mass()); } catch ( ImpossibleKinematics ) { return false; } Energy e = sqrt(sHat())/2.0; Energy2 m22 = meMomenta()[2].mass2(); Energy2 m32 = meMomenta()[3].mass2(); Energy2 e0e2 = 2.0*e*sqrt(sqr(q) + m22); Energy2 e1e2 = 2.0*e*sqrt(sqr(q) + m22); Energy2 e0e3 = 2.0*e*sqrt(sqr(q) + m32); Energy2 e1e3 = 2.0*e*sqrt(sqr(q) + m32); Energy2 pq = 2.0*e*q; Energy2 thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[2]); if ( thmin > ZERO ) ctmax = min(ctmax, (e0e2 - m22 - thmin)/pq); thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[2]); if ( thmin > ZERO ) ctmin = max(ctmin, (thmin + m22 - e1e2)/pq); thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[3]); if ( thmin > ZERO ) ctmax = min(ctmax, (e1e3 - m32 - thmin)/pq); thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[3]); if ( thmin > ZERO ) ctmin = max(ctmin, (thmin + m32 - e0e3)/pq); Energy ptmin = max(lastCuts().minKT(mePartonData()[2]), lastCuts().minKT(mePartonData()[3])); if ( ptmin > ZERO ) { double ctm = 1.0 - sqr(ptmin/q); if ( ctm <= 0.0 ) return false; ctmin = max(ctmin, -sqrt(ctm)); ctmax = min(ctmax, sqrt(ctm)); } double ymin2 = lastCuts().minYStar(mePartonData()[2]); double ymax2 = lastCuts().maxYStar(mePartonData()[2]); double ymin3 = lastCuts().minYStar(mePartonData()[3]); double ymax3 = lastCuts().maxYStar(mePartonData()[3]); double ytot = lastCuts().Y() + lastCuts().currentYHat(); if ( ymin2 + ytot > -0.9*Constants::MaxRapidity ) ctmin = max(ctmin, sqrt(sqr(q) + m22)*tanh(ymin2)/q); if ( ymax2 + ytot < 0.9*Constants::MaxRapidity ) ctmax = min(ctmax, sqrt(sqr(q) + m22)*tanh(ymax2)/q); if ( ymin3 + ytot > -0.9*Constants::MaxRapidity ) ctmax = min(ctmax, sqrt(sqr(q) + m32)*tanh(-ymin3)/q); if ( ymax3 + ytot < 0.9*Constants::MaxRapidity ) ctmin = max(ctmin, sqrt(sqr(q) + m32)*tanh(-ymax3)/q); if ( ctmin >= ctmax ) return false; double cth = getCosTheta(ctmin, ctmax, r[0]); Energy pt = q*sqrt(1.0-sqr(cth)); phi(rnd(2.0*Constants::pi)); meMomenta()[2].setVect(Momentum3( pt*sin(phi()), pt*cos(phi()), q*cth)); meMomenta()[3].setVect(Momentum3(-pt*sin(phi()), -pt*cos(phi()), -q*cth)); meMomenta()[2].rescaleEnergy(); meMomenta()[3].rescaleEnergy(); vector out(2); out[0] = meMomenta()[2]; out[1] = meMomenta()[3]; tcPDVector tout(2); tout[0] = mePartonData()[2]; tout[1] = mePartonData()[3]; if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) ) return false; tHat(pq*cth + m22 - e0e2); uHat(m22 + m32 - sHat() - tHat()); jacobian((pq/sHat())*Constants::pi*jacobian()*mjac); // compute the rescaled momenta return rescaleMomenta(meMomenta(),mePartonData()); } bool HwMEBase::rescaleMomenta(const vector & momenta, const cPDVector & data) { assert(momenta.size()==4&&data.size()==4); // default just use the ones we generated rescaledMomenta_=momenta; if(rescaleOption_==1) return true; Energy mnew[2] = {0*MeV, ZERO}; if(rescaleOption_==0) { mnew[0] = ZERO; mnew[1] = ZERO; } else if(rescaleOption_==2) { mnew[0] = data[2]->hardProcessMass(); mnew[1] = data[3]->hardProcessMass(); } else if(rescaleOption_==3) { if(abs(data[2]->id())!=abs(data[3]->id())) return true; mnew[0] = 0.5*(momenta[2].mass()+momenta[3].mass()); mnew[1] = mnew[0]; } else { assert(false); } Lorentz5Momentum pcm(momenta[2]+momenta[3]); Energy m0=pcm.m(); if(m01e-10*(rescaledMomenta_[2].t()+rescaledMomenta_[2].mass())) rescaledMomenta_[2].rescaleRho(); else { rescaledMomenta_[2].setX(ZERO); rescaledMomenta_[2].setY(ZERO); rescaledMomenta_[2].setZ(ZERO); } rescaledMomenta_[2].boost(-bv); rescaledMomenta_[3].boost(bv); rescaledMomenta_[3].setMass(mnew[1]); rescaledMomenta_[3].setE(0.5*(sqr(m0)-sqr(mnew[0])+sqr(mnew[1]))/m0); if(rescaledMomenta_[3].t()-rescaledMomenta_[3].mass()>1e-10*(rescaledMomenta_[3].t()+rescaledMomenta_[3].mass())) rescaledMomenta_[3].rescaleRho(); else { rescaledMomenta_[3].setX(ZERO); rescaledMomenta_[3].setY(ZERO); rescaledMomenta_[3].setZ(ZERO); } rescaledMomenta_[3].boost(-bv); return true; } double HwMEBase::getCosTheta(double ctmin, double ctmax, const double r) { double cth = 0.0; static const double eps = 1.0e-6; if ( 1.0 + ctmin <= eps && 1.0 - ctmax <= eps ) { jacobian(jacobian()*(ctmax - ctmin)); cth = ctmin + r*(ctmax - ctmin); } else if ( 1.0 + ctmin <= eps ) { cth = 1.0 - (1.0 - ctmax)*pow((1.0 - ctmin)/(1.0 - ctmax), r); jacobian(jacobian()*log((1.0 - ctmin)/(1.0 - ctmax))*(1.0 - cth)); } else if ( 1.0 - ctmax <= eps ) { cth = -1.0 + (1.0 + ctmin)*pow((1.0 + ctmax)/(1.0 + ctmin), r); jacobian(jacobian()*log((1.0 + ctmax)/(1.0 + ctmin))*(1.0 + cth)); } else { double zmin = 0.5*(1.0 - ctmax); double zmax = 0.5*(1.0 - ctmin); double A1 = -ctmin/(zmax*(1.0-zmax)); double A0 = -ctmax/(zmin*(1.0-zmin)); double A = r*(A1 - A0) + A0; double z = A < 2.0? 2.0/(sqrt(sqr(A) + 4.0) + 2 - A): 0.5*(A - 2.0 + sqrt(sqr(A) + 4.0))/A; cth = 1.0 - 2.0*z; jacobian(jacobian()*2.0*(A1 - A0)*sqr(z)*sqr(1.0 - z)/(sqr(z) + sqr(1.0 - z))); } return cth; } bool HwMEBase::softMatrixElementVeto(ShowerProgenitorPtr, ShowerParticlePtr,Branching) { + assert(false); return false; } -HardTreePtr HwMEBase::generateHardest(ShowerTreePtr,ShowerInteraction::Type) { - return HardTreePtr(); +RealEmissionProcessPtr HwMEBase::generateHardest(RealEmissionProcessPtr,ShowerInteraction::Type) { + assert(false); + return RealEmissionProcessPtr(); } + +RealEmissionProcessPtr HwMEBase::applyHardMatrixElementCorrection(RealEmissionProcessPtr) { + assert(false); + return RealEmissionProcessPtr(); +} + +void HwMEBase::initializeMECorrection(RealEmissionProcessPtr , double & , + double & ) { + assert(false); +} diff --git a/MatrixElement/HwMEBase.h b/MatrixElement/HwMEBase.h --- a/MatrixElement/HwMEBase.h +++ b/MatrixElement/HwMEBase.h @@ -1,319 +1,319 @@ // -*- C++ -*- #ifndef HERWIG_HwMEBase_H #define HERWIG_HwMEBase_H // // This is the declaration of the HwMEBase class. // #include "ThePEG/MatrixElement/MEBase.h" -#include "Herwig/Shower/Base/ShowerParticle.fh" -#include "Herwig/Shower/Base/ShowerProgenitor.fh" -#include "Herwig/Shower/Base/ShowerTree.fh" -#include "Herwig/Shower/Base/HardTree.fh" -#include "Herwig/Shower/ShowerConfig.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.fh" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh" +#include "Herwig/Shower/RealEmissionProcess.fh" +#include "Herwig/Shower/QTilde/ShowerInteraction.h" #include "ThePEG/PDF/BeamParticleData.h" #include "HwMEBase.fh" namespace Herwig { struct Branching; using namespace ThePEG; typedef Ptr::transient_const_pointer tcBeamPtr; /** * The HwMEBase class serves a number of purposes * - it implements the phase space for \f$2\to2\f$ scattering processes * - it provides virtual members for the implementation of hard radiation * - it gives us greater control over the masses of the outgoing * particles so that they can be * - set massless where required by gauge invariance * - have their off-shell masses generated using the sophisticated approaches * available in Herwig. * * @see \ref HwMEBaseInterfaces "The interfaces" * defined for HwMEBase. */ class HwMEBase: public MEBase { public: /** * Default constructor. */ HwMEBase() : lastTHat_(ZERO), lastUHat_(ZERO), lastPhi_(0.0), rescaleOption_(1) {} /** @name Virtual functions required by the MEBase class. */ //@{ /** * The number of internal degreed of freedom used in the matrix * element. */ virtual int nDim() const; /** * Generate internal degrees of freedom given 'nDim()' uniform * random numbers in the interval ]0,1[. To help the phase space * generator, the 'dSigHatDR()' should be a smooth function of these * numbers, although this is not strictly necessary. Return * false if the chosen points failed the kinematical cuts. */ virtual bool generateKinematics(const double * r); /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(). Uses * me(). */ virtual CrossSection dSigHatDR() const; /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries() * according to the associated XComb object. */ virtual void setKinematics(); //@} /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Type of POWHEG correction */ enum POWHEGType {No, ISR, FSR, Both}; /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return No;} /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return false;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr , double & , - double & ) {} + virtual void initializeMECorrection(RealEmissionProcessPtr , double & , + double & ); /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr) {} + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent, Branching br); /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr,ShowerInteraction::Type); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, + ShowerInteraction::Type); //@} 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 Access cached values in of the last set phase space point. */ //@{ /** * Return the \f$\hat{t}\f$ of the last set phase space point. */ Energy2 tHat() const { return lastTHat_; } /** * Return the \f$\hat{u}\f$ of the last set phase space point. */ Energy2 uHat() const { return lastUHat_; } /** * Return the azimuth angle of the last set phase space point. */ double phi() const { return lastPhi_; } //@} /** @name Set the cached values in of the last set phase space point. */ //@{ /** * Set the \f$\hat{t}\f$ of the last set phase space point. */ void tHat(Energy2 e2) { lastTHat_ = e2; } /** * Set the \f$\hat{u}\f$ of the last set phase space point. */ void uHat(Energy2 e2) { lastUHat_ = e2; } /** * Set the azimuth angle of the last set phase space point. */ void phi(double phi) { lastPhi_ = phi; } //@} /** * Set the treatment of the outgoing masses * @param iopt The option for the treatment of the mass */ void massOption(vector iopt) { massOption_ = iopt; } /** * Rescaled momenta for the helicity ME */ //@{ /** * Set the treatment of the rescaling of the momenta for * the matrix element calculation * @param iopt The rescaling option */ void rescalingOption(unsigned int iopt) { rescaleOption_=iopt; } /** * rescale the momenta for the computation of the helicity matrix element */ bool rescaleMomenta(const vector &, const cPDVector &); /** * Access to the rescaled momenta */ const vector & rescaledMomenta() const { return rescaledMomenta_; } //@} /** * Generate the masses of the particles */ bool generateMasses(vector & masses, double & mjac, const double *r); /** * Used internally by generateKinematics, after calculating the * limits on cos(theta). */ virtual double getCosTheta(double cthmin, double cthmax, const double r); private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class without persistent data. */ static AbstractClassDescription initHwMEBase; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HwMEBase & operator=(const HwMEBase &); private: /** * Option for the treatment of the particle masses */ vector massOption_; /** * The \f$\hat{t}\f$ of the last set phase space point. */ Energy2 lastTHat_; /** * The \f$\hat{u}\f$ of the last set phase space point. */ Energy2 lastUHat_; /** * The azimuth angle of the last set phase space point. */ double lastPhi_; /** * Produced to produce rescaled momenta */ unsigned int rescaleOption_; /** * Rescaled momenta for use in ME calculations */ vector rescaledMomenta_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of HwMEBase. */ template <> struct BaseClassTrait { /** Typedef of the first base class of HwMEBase. */ typedef MEBase NthBase; }; /** This template specialization informs ThePEG about the name of * the HwMEBase 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::HwMEBase"; } }; /** @endcond */ } #endif /* HERWIG_HwMEBase_H */ diff --git a/MatrixElement/Lepton/MEee2gZ2ll.cc b/MatrixElement/Lepton/MEee2gZ2ll.cc --- a/MatrixElement/Lepton/MEee2gZ2ll.cc +++ b/MatrixElement/Lepton/MEee2gZ2ll.cc @@ -1,758 +1,718 @@ // -*- C++ -*- // // MEee2gZ2ll.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 MEee2gZ2ll class. // #include "MEee2gZ2ll.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/HardVertex.h" #include "ThePEG/PDF/PolarizedBeamParticleData.h" #include "ThePEG/Utilities/DescribeClass.h" #include -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; void MEee2gZ2ll::getDiagrams() const { // specific the diagrams tcPDPtr ep = getParticleData(ParticleID::eplus); tcPDPtr em = getParticleData(ParticleID::eminus); // setup the processes for( int i =11;i<=16;++i) { if(allowed_==0 || (allowed_==1 && i%2==1) || (allowed_==2&&i==11) || (allowed_==3&&i==13) || (allowed_==4&&i==15)) { tcPDPtr lm = getParticleData(i); tcPDPtr lp = lm->CC(); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, gamma_, 3, lm, 3, lp, -1))); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, Z0_, 3, lm, 3, lp, -2))); } } } Energy2 MEee2gZ2ll::scale() const { return sHat(); } unsigned int MEee2gZ2ll::orderInAlphaS() const { return 0; } unsigned int MEee2gZ2ll::orderInAlphaEW() const { return 2; } Selector MEee2gZ2ll::diagrams(const DiagramVector & diags) const { double lastCont(0.5),lastBW(0.5); if ( lastXCombPtr() ) { lastCont = meInfo()[0]; lastBW = meInfo()[1]; } Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { if ( diags[i]->id() == -1 ) sel.insert(lastCont, i); else if ( diags[i]->id() == -2 ) sel.insert(lastBW, i); } return sel; } Selector MEee2gZ2ll::colourGeometries(tcDiagPtr) const { static ColourLines ctST(" "); Selector sel; sel.insert(1.0, &ctST); return sel; } void MEee2gZ2ll::persistentOutput(PersistentOStream & os) const { os << allowed_ << FFZVertex_ << FFPVertex_ << gamma_ << Z0_ << alphaQED_ << ounit(pTmin_,GeV) << preFactor_; } void MEee2gZ2ll::persistentInput(PersistentIStream & is, int) { is >> allowed_ >> FFZVertex_ >> FFPVertex_ >> gamma_ >> Z0_ >> alphaQED_ >> iunit(pTmin_,GeV) >> preFactor_; } // *** 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 describeMEee2gZ2ll("Herwig::MEee2gZ2ll", "HwMELepton.so"); void MEee2gZ2ll::Init() { static ClassDocumentation documentation ("The MEee2gZ2ll class implements the matrix element for" "e+e- to leptons via Z and photon exchange using helicity amplitude" "techniques"); static Switch interfaceallowed ("Allowed", "Allowed outgoing leptons", &MEee2gZ2ll::allowed_, 0, false, false); static SwitchOption interfaceallowedAll (interfaceallowed, "All", "Allow all leptons as outgoing particles", 0); static SwitchOption interfaceallowedCharged (interfaceallowed, "Charged", "Only charged leptons as outgoing particles", 1); static SwitchOption interfaceallowedElectron (interfaceallowed, "Electron", "Only the electron and positron as outgoing leptons", 2); static SwitchOption interfaceallowedMuon (interfaceallowed, "Muon", "Only muons as outgoing particles", 3); static SwitchOption interfaceallowedTau (interfaceallowed, "Tau", "Only taus as outgoing particles", 4); static Parameter interfacepTMin ("pTMin", "Minimum pT for hard radiation", &MEee2gZ2ll::pTmin_, GeV, 1.0*GeV, 0.001*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfacePrefactor ("Prefactor", "Prefactor for the overestimate of the emission probability", &MEee2gZ2ll::preFactor_, 6.0, 1.0, 100.0, false, false, Interface::limited); static Reference interfaceEMCoupling ("AlphaQED", "Pointer to the object to calculate the EM coupling for the correction", &MEee2gZ2ll::alphaQED_, false, false, true, false, false); } double MEee2gZ2ll::me2() const { return loME(mePartonData(),rescaledMomenta(),true); } double MEee2gZ2ll::loME(const vector & partons, const vector & momenta, bool first) const { vector fin,aout; vector ain,fout; SpinorWaveFunction ein (momenta[0],partons[0],incoming); SpinorBarWaveFunction pin (momenta[1],partons[1],incoming); SpinorBarWaveFunction ilmout(momenta[2],partons[2],outgoing); SpinorWaveFunction ilpout(momenta[3],partons[3],outgoing); for(unsigned int ix=0;ix<2;++ix) { ein.reset(ix) ;fin.push_back( ein ); pin.reset(ix) ;ain.push_back( pin ); ilmout.reset(ix);fout.push_back(ilmout); ilpout.reset(ix);aout.push_back(ilpout); } // compute the matrix element double me,lastCont,lastBW; HelicityME(fin,ain,fout,aout,me,lastCont,lastBW); // save the components if(first) { DVector save; save.push_back(lastCont); save.push_back(lastBW); meInfo(save); } // return the answer return me; } ProductionMatrixElement MEee2gZ2ll::HelicityME(vector & fin, vector & ain, vector & fout, vector & aout, double & me,double & cont, double & BW ) const { // the particles should be in the order // for the incoming // 0 incoming fermion (u spinor) // 1 incoming antifermion (vbar spinor) // for the outgoing // 0 outgoing fermion (ubar spinor) // 1 outgoing antifermion (v spinor) // me to be returned ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); ProductionMatrixElement gamma (PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); ProductionMatrixElement Zboson(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); // // wavefunctions for the intermediate particles VectorWaveFunction interZ,interG; // temporary storage of the different diagrams Complex diag1,diag2; // sum over helicities to get the matrix element unsigned int inhel1,inhel2,outhel1,outhel2; double total[3]={0.,0.,0.}; for(inhel1=0;inhel1<2;++inhel1) { for(inhel2=0;inhel2<2;++inhel2) { // intermediate Z interZ = FFZVertex_->evaluate(sHat(),1,Z0_,fin[inhel1],ain[inhel2]); // intermediate photon interG = FFPVertex_->evaluate(sHat(),1,gamma_,fin[inhel1],ain[inhel2]); for(outhel1=0;outhel1<2;++outhel1) { for(outhel2=0;outhel2<2;++outhel2) { // first the Z exchange diagram diag1 = FFZVertex_->evaluate(sHat(),aout[outhel2],fout[outhel1], interZ); // then the photon exchange diagram diag2 = FFPVertex_->evaluate(sHat(),aout[outhel2],fout[outhel1], interG); // add up squares of individual terms total[1] += norm(diag1); Zboson(inhel1,inhel2,outhel1,outhel2) = diag1; total[2] += norm(diag2); gamma (inhel1,inhel2,outhel1,outhel2) = diag2; // the full thing including interference diag1 += diag2; total[0] += norm(diag1); output(inhel1,inhel2,outhel1,outhel2) = diag1; } } } } // results for(int ix=0;ix<3;++ix) total[ix] *= 0.25; tcPolarizedBeamPDPtr beam[2] = {dynamic_ptr_cast(mePartonData()[0]), dynamic_ptr_cast(mePartonData()[1])}; if( beam[0] || beam[1] ) { RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()), beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())}; total[0] = output.average(rho[0],rho[1]); total[1] = Zboson.average(rho[0],rho[1]); total[2] = gamma .average(rho[0],rho[1]); } cont = total[2]; BW = total[1]; me = total[0]; return output; } void MEee2gZ2ll::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]); if(hard[0]->id()id()) swap(hard[0],hard[1]); if(hard[2]->id()id()) swap(hard[2],hard[3]); vector fin,aout; vector ain,fout; SpinorWaveFunction( fin ,hard[0],incoming,false,true); SpinorBarWaveFunction(ain ,hard[1],incoming,false,true); SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true); SpinorWaveFunction( aout,hard[3],outgoing,true ,true); // calculate the matrix element double me,cont,BW; ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me,cont,BW); // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(prodme); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) { tSpinPtr spin = hard[ix]->spinInfo(); if(ix<2) { tcPolarizedBeamPDPtr beam = dynamic_ptr_cast(hard[ix]->dataPtr()); if(beam) spin->rhoMatrix() = beam->rhoMatrix(); } spin->productionVertex(hardvertex); } } void MEee2gZ2ll::doinit() { HwMEBase::doinit(); // set the particle data objects Z0_=getParticleData(ThePEG::ParticleID::Z0); gamma_=getParticleData(ThePEG::ParticleID::gamma); // cast the SM pointer to the Herwig SM pointer tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); // do the initialisation if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "MEee2gZ2ll::doinit() the Herwig" << " version must be used" << Exception::runerror; FFZVertex_ = hwsm->vertexFFZ(); FFPVertex_ = hwsm->vertexFFP(); } void MEee2gZ2ll::rebind(const TranslationMap & trans) { FFZVertex_ = trans.translate(FFZVertex_); FFPVertex_ = trans.translate(FFPVertex_); Z0_ = trans.translate(Z0_); gamma_ = trans.translate(gamma_); HwMEBase::rebind(trans); } IVector MEee2gZ2ll::getReferences() { IVector ret = HwMEBase::getReferences(); ret.push_back(FFZVertex_); ret.push_back(FFPVertex_); ret.push_back(Z0_ ); ret.push_back(gamma_ ); return ret; } -HardTreePtr MEee2gZ2ll::generateHardest(ShowerTreePtr tree,ShowerInteraction::Type inter) { +RealEmissionProcessPtr MEee2gZ2ll::generateHardest(RealEmissionProcessPtr born, + ShowerInteraction::Type inter) { // check if generating QCD radiation if(inter!=ShowerInteraction::QED && inter!=ShowerInteraction::QEDQCD && inter!=ShowerInteraction::ALL) - return HardTreePtr(); + return RealEmissionProcessPtr(); // generate the momenta for the hard emission - vector emmision; + vector emission; unsigned int iemit,ispect; - Energy pTveto = generateHard(tree,emmision,iemit,ispect,false); - // outgoing progenitors - ShowerProgenitorPtr - qkProgenitor = tree->outgoingLines().begin() ->first, - qbProgenitor = tree->outgoingLines().rbegin()->first; - if(qkProgenitor->id()<0) swap(qkProgenitor,qbProgenitor); + Energy pTveto = generateHard(born,emission,iemit,ispect,false); // check if charged - if(!qkProgenitor->progenitor()->dataPtr()->charged()) - return HardTreePtr(); + if(!partons_[2]->charged()) return RealEmissionProcessPtr(); // maximum pT of emission if(pTveto<=ZERO) { - qkProgenitor->maximumpT(pTmin_,ShowerInteraction::QED); - qbProgenitor->maximumpT(pTmin_,ShowerInteraction::QED); - return HardTreePtr(); + born->pT()[ShowerInteraction::QED] = pTmin_; + return born; } else { - qkProgenitor->maximumpT(pTveto,ShowerInteraction::QED); - qbProgenitor->maximumpT(pTveto,ShowerInteraction::QED); + born->pT()[ShowerInteraction::QED] = pTveto; } - // Make the particles for the hard tree - ShowerParticleVector hardParticles; - for(unsigned int ix=0;ix=2))); - hardParticles.back()->set5Momentum(emmision[ix]); + born->interaction(ShowerInteraction::QED); + // get the quark and antiquark + ParticleVector qq; + for(unsigned int ix=0;ix<2;++ix) qq.push_back(born->bornOutgoing()[ix]); + bool order = qq[0]->id()>0; + if(!order) swap(qq[0],qq[1]); + // create the new quark, antiquark and gluon + PPtr newq = qq[0]->dataPtr()->produceParticle(emission[2]); + PPtr newa = qq[1]->dataPtr()->produceParticle(emission[3]); + PPtr newg = gamma_->produceParticle(emission[4]); + // create the output real emission process + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + born->incoming().push_back(born->bornIncoming()[ix]->dataPtr()-> + produceParticle(born->bornIncoming()[ix]->momentum())); } - ShowerParticlePtr parent(new_ptr(ShowerParticle(partons_[iemit],true))); - Lorentz5Momentum parentMomentum(emmision[iemit]+emmision[4]); - parentMomentum.setMass(partons_[iemit]->mass()); - parent->set5Momentum(parentMomentum); - // Create the vectors of HardBranchings to create the HardTree: - vector spaceBranchings,allBranchings; - // Incoming boson: - for(unsigned int ix=0;ix<2;++ix) { - spaceBranchings.push_back(new_ptr(HardBranching(hardParticles[ix],SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - allBranchings.push_back(spaceBranchings.back()); + if(order) { + born->outgoing().push_back(newq); + born->outgoing().push_back(newa); } - // Outgoing particles from hard emission: - HardBranchingPtr spectatorBranch(new_ptr(HardBranching(hardParticles[ispect], - SudakovPtr(),HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr emitterBranch(new_ptr(HardBranching(parent,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(hardParticles[iemit], - SudakovPtr(),HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(hardParticles[4], - SudakovPtr(),HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->type(ShowerPartnerType::QED); - if(iemit==0) { - allBranchings.push_back(emitterBranch); - allBranchings.push_back(spectatorBranch); - } else { - allBranchings.push_back( spectatorBranch ); - allBranchings.push_back( emitterBranch ); + born->outgoing().push_back(newa); + born->outgoing().push_back(newq); + swap(iemit,ispect); } - emitterBranch ->branchingParticle()->partner(spectatorBranch->branchingParticle()); - spectatorBranch->branchingParticle()->partner(emitterBranch ->branchingParticle()); - spaceBranchings[0]->branchingParticle()->partner(spaceBranchings[1]->branchingParticle()); - spaceBranchings[1]->branchingParticle()->partner(spaceBranchings[0]->branchingParticle()); - // Make the HardTree from the HardBranching vectors. - HardTreePtr hardtree = new_ptr(HardTree(allBranchings,spaceBranchings, - ShowerInteraction::QED)); - hardtree->partnersSet(true); - // Connect the particles with the branchings in the HardTree - hardtree->connect( qkProgenitor->progenitor(), allBranchings[2] ); - hardtree->connect( qbProgenitor->progenitor(), allBranchings[3] ); - // colour flow - ColinePtr newline=new_ptr(ColourLine()); - // Return the HardTree - return hardtree; + born->outgoing().push_back(newg); + // set emitter and spectator + born->emitter (iemit); + born->spectator(ispect); + born->emitted(4); + return born; } double MEee2gZ2ll::meRatio(vector partons, vector momenta, unsigned int iemitter, bool subtract) const { Lorentz5Momentum q = momenta[2]+momenta[3]+momenta[4]; Energy2 Q2=q.m2(); Energy2 lambda = sqrt((Q2-sqr(momenta[2].mass()+momenta[3].mass()))* (Q2-sqr(momenta[2].mass()-momenta[3].mass()))); InvEnergy2 D[2]; double lome[2]; for(unsigned int iemit=0;iemit<2;++iemit) { unsigned int ispect = iemit==0 ? 1 : 0; Energy2 pipj = momenta[4 ] * momenta[2+iemit ]; Energy2 pipk = momenta[4 ] * momenta[2+ispect]; Energy2 pjpk = momenta[2+iemit] * momenta[2+ispect]; double y = pipj/(pipj+pipk+pjpk); double z = pipk/( pipk+pjpk); Energy mij = sqrt(2.*pipj+sqr(momenta[2+iemit].mass())); Energy2 lamB = sqrt((Q2-sqr(mij+momenta[2+ispect].mass()))* (Q2-sqr(mij-momenta[2+ispect].mass()))); Energy2 Qpk = q*momenta[2+ispect]; Lorentz5Momentum pkt = lambda/lamB*(momenta[2+ispect]-Qpk/Q2*q) +0.5/Q2*(Q2+sqr(momenta[2+ispect].mass())-sqr(momenta[2+ispect].mass()))*q; Lorentz5Momentum pijt = q-pkt; double muj = momenta[2+iemit ].mass()/sqrt(Q2); double muk = momenta[2+ispect].mass()/sqrt(Q2); double vt = sqrt((1.-sqr(muj+muk))*(1.-sqr(muj-muk)))/(1.-sqr(muj)-sqr(muk)); double v = sqrt(sqr(2.*sqr(muk)+(1.-sqr(muj)-sqr(muk))*(1.-y))-4.*sqr(muk)) /(1.-y)/(1.-sqr(muj)-sqr(muk)); // dipole term D[iemit] = 0.5/pipj*(2./(1.-(1.-z)*(1.-y)) -vt/v*(2.-z+sqr(momenta[2+iemit].mass())/pipj)); // matrix element vector lomom(4); lomom[0] = momenta[0]; lomom[1] = momenta[1]; if(iemit==0) { lomom[2] = pijt; lomom[3] = pkt ; } else { lomom[3] = pijt; lomom[2] = pkt ; } lome[iemit] = loME(partons,lomom,false); } InvEnergy2 ratio = realME(partons,momenta) *abs(D[iemitter])/(abs(D[0]*lome[0])+abs(D[1]*lome[1])); double output = Q2*ratio; if(subtract) output -= 2.*Q2*D[iemitter]; return output; } InvEnergy2 MEee2gZ2ll::realME(const vector & partons, const vector & momenta) const { // compute the spinors vector fin,aout; vector ain,fout; vector gout; SpinorWaveFunction ein (momenta[0],partons[0],incoming); SpinorBarWaveFunction pin (momenta[1],partons[1],incoming); SpinorBarWaveFunction qkout(momenta[2],partons[2],outgoing); SpinorWaveFunction qbout(momenta[3],partons[3],outgoing); VectorWaveFunction photon(momenta[4],partons[4],outgoing); for(unsigned int ix=0;ix<2;++ix) { ein.reset(ix) ; fin.push_back( ein ); pin.reset(ix) ; ain.push_back( pin ); qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); photon.reset(2*ix); gout.push_back(photon); } vector diag(4,0.); ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1); double total(0.); for(unsigned int inhel1=0;inhel1<2;++inhel1) { for(unsigned int inhel2=0;inhel2<2;++inhel2) { // intermediate Z VectorWaveFunction interZ = FFZVertex_->evaluate(scale(),1,Z0_,fin[inhel1],ain[inhel2]); // intermediate photon VectorWaveFunction interG = FFPVertex_->evaluate(scale(),1,gamma_,fin[inhel1],ain[inhel2]); for(unsigned int outhel1=0;outhel1<2;++outhel1) { for(unsigned int outhel2=0;outhel2<2;++outhel2) { for(unsigned int outhel3=0;outhel3<2;++outhel3) { SpinorBarWaveFunction off1 = FFPVertex_->evaluate(scale(),3,partons[2],fout[outhel1],gout[outhel3]); diag[0] = FFZVertex_->evaluate(scale(),aout[outhel2],off1,interZ); diag[1] = FFPVertex_->evaluate(scale(),aout[outhel2],off1,interG); SpinorWaveFunction off2 = FFPVertex_->evaluate(scale(),3,partons[3],aout[outhel2],gout[outhel3]); diag[2] = FFZVertex_->evaluate(scale(),off2,fout[outhel1],interZ); diag[3] = FFPVertex_->evaluate(scale(),off2,fout[outhel1],interG); // sum of diagrams Complex sum = std::accumulate(diag.begin(),diag.end(),Complex(0.)); // matrix element output(inhel1,inhel2,outhel1,outhel2,outhel3)=sum; // me2 total += norm(sum); } } } } } // spin average total *= 0.25; tcPolarizedBeamPDPtr beam[2] = {dynamic_ptr_cast(partons[0]), dynamic_ptr_cast(partons[1])}; if( beam[0] || beam[1] ) { RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()), beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())}; total = output.average(rho[0],rho[1]); } // divide out the coupling and charge total /= norm(FFPVertex_->norm())* sqr(double(mePartonData()[2]->iCharge())/3.); // return the total return total*UnitRemoval::InvE2; } -Energy MEee2gZ2ll::generateHard(ShowerTreePtr tree, +Energy MEee2gZ2ll::generateHard(RealEmissionProcessPtr born, vector & emmision, unsigned int & iemit, unsigned int & ispect, bool applyVeto) { // get the momenta of the incoming and outgoing particles // incoming - ShowerProgenitorPtr - emProgenitor = tree->incomingLines().begin() ->first, - epProgenitor = tree->incomingLines().rbegin()->first; + tPPtr em = born->bornIncoming()[0]; + tPPtr ep = born->bornIncoming()[1]; + if(em->id()<0) swap(em,ep); // outgoing - ShowerProgenitorPtr - qkProgenitor = tree->outgoingLines().begin() ->first, - qbProgenitor = tree->outgoingLines().rbegin()->first; - // get the order right - if(emProgenitor->id()<0) swap(emProgenitor,epProgenitor); - if(qkProgenitor->id()<0) swap(qkProgenitor,qbProgenitor); - loMomenta_.resize(0); + tPPtr qk = born->bornOutgoing()[0]; + tPPtr qb = born->bornOutgoing()[1]; + if(qk->id()<0) swap(qk,qb); // extract the momenta - loMomenta_.push_back(emProgenitor->progenitor()->momentum()); - loMomenta_.push_back(epProgenitor->progenitor()->momentum()); - loMomenta_.push_back(qkProgenitor->progenitor()->momentum()); - loMomenta_.push_back(qbProgenitor->progenitor()->momentum()); + loMomenta_.clear(); + loMomenta_.push_back(em->momentum()); + loMomenta_.push_back(ep->momentum()); + loMomenta_.push_back(qk->momentum()); + loMomenta_.push_back(qb->momentum()); // and ParticleData objects partons_.resize(5); - partons_[0]=emProgenitor->progenitor()->dataPtr(); - partons_[1]=epProgenitor->progenitor()->dataPtr(); - partons_[2]=qkProgenitor->progenitor()->dataPtr(); - partons_[3]=qbProgenitor->progenitor()->dataPtr(); + partons_[0]=em->dataPtr(); + partons_[1]=ep->dataPtr(); + partons_[2]=qk->dataPtr(); + partons_[3]=qb->dataPtr(); partons_[4]=gamma_; // boost from lab to CMS frame with outgoing particles // along the z axis LorentzRotation eventFrame( ( loMomenta_[2] + loMomenta_[3] ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*loMomenta_[2]; eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() ); eventFrame.invert(); // mass of the final-state system Energy2 M2 = (loMomenta_[2]+loMomenta_[3]).m2(); Energy M = sqrt(M2); double mu1 = loMomenta_[2].mass()/M; double mu2 = loMomenta_[3].mass()/M; double mu12 = sqr(mu1), mu22 = sqr(mu2); double lambda = sqrt(1.+sqr(mu12)+sqr(mu22)-2.*mu12-2.*mu22-2.*mu12*mu22); // max pT Energy pTmax = 0.5*sqrt(M2)* (1.-sqr(loMomenta_[2].mass()+loMomenta_[3].mass())/M2); // max y double ymax = acosh(pTmax/pTmin_); double a = alphaQED_->overestimateValue()/Constants::twopi* 2.*ymax*preFactor_*sqr(double(mePartonData()[2]->iCharge())/3.); // variables for the emission Energy pT[2]; double y[2],phi[2],x3[2],x1[2][2],x2[2][2]; double contrib[2][2]; // storage of the real emission momenta vector realMomenta[2][2]= {{vector(5),vector(5)}, {vector(5),vector(5)}}; for(unsigned int ix=0;ix<2;++ix) for(unsigned int iy=0;iy<2;++iy) for(unsigned int iz=0;iz<2;++iz) realMomenta[ix][iy][iz] = loMomenta_[iz]; // generate the emission for(unsigned int ix=0;ix<2;++ix) { if(ix==1) { swap(mu1 ,mu2 ); swap(mu12,mu22); } pT[ix] = pTmax; y [ix] = 0.; bool reject = true; do { // generate pT pT[ix] *= pow(UseRandom::rnd(),1./a); if(pT[ix] 1. -sqr( mu1 + mu2 ) ) continue; // find the possible solutions for x1 double xT2 = sqr(2./M*pT[ix]); double root = (-sqr(x3[ix])+xT2)* (xT2*mu22+2.*x3[ix]-sqr(mu12)+2.*mu22+2.*mu12-sqr(x3[ix])-1. +2.*mu12*mu22-sqr(mu22)-2.*mu22*x3[ix]-2.*mu12*x3[ix]); double c1=2.*sqr(x3[ix])-4.*mu22-6.*x3[ix]+4.*mu12-xT2*x3[ix] +2.*xT2-2.*mu12*x3[ix]+2.*mu22*x3[ix]+4.; if(root<0.) continue; x1[ix][0] = 1./(4.-4.*x3[ix]+xT2)*(c1-2.*sqrt(root)); x1[ix][1] = 1./(4.-4.*x3[ix]+xT2)*(c1+2.*sqrt(root)); // change sign of y if 2nd particle emits if(ix==1) y[ix] *=-1.; // loop over the solutions for(unsigned int iy=0;iy<2;++iy) { contrib[ix][iy]=0.; // check x1 value allowed if(x1[ix][iy]<2.*mu1||x1[ix][iy]>1.+mu12-mu22) continue; // calculate x2 value and check allowed x2[ix][iy] = 2.-x3[ix]-x1[ix][iy]; double root = max(0.,sqr(x1[ix][iy])-4.*mu12); root = sqrt(root); double x2min = 1.+mu22-mu12 -0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12+root); double x2max = 1.+mu22-mu12 -0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12-root); if(x2[ix][iy]x2max) continue; // check the z components double z1 = sqrt(sqr(x1[ix][iy])-4.*mu12-xT2); double z2 = -sqrt(sqr(x2[ix][iy])-4.*mu22); double z3 = pT[ix]*sinh(y[ix])*2./M; if(ix==1) z3 *=-1.; if(abs(-z1+z2+z3)<1e-9) z1 *= -1.; if(abs(z1+z2+z3)>1e-5) continue; // if using as an ME correction the veto if(applyVeto) { // double xb = x1[ix][iy], xc = x2[ix][iy]; // double b = mu12, c = mu22; // double r = 0.5*(1.+b/(1.+c-xc)); // double z1 = r + (xb-(2.-xc)*r)/sqrt(sqr(xc)-4.*c); // double kt1 = (1.-b+c-xc)/z1/(1.-z1); // r = 0.5*(1.+c/(1.+b-xb)); // double z2 = r + (xc-(2.-xb)*r)/sqrt(sqr(xb)-4.*b); // double kt2 = (1.-c+b-xb)/z2/(1.-z2); // if(ix==1) { // swap(z1 ,z2); // swap(kt1,kt2); // } // // veto the shower region // if( kt1 < d_kt1_ || kt2 < d_kt2_ ) continue; } // construct the momenta realMomenta[ix][iy][4] = Lorentz5Momentum(pT[ix]*cos(phi[ix]),pT[ix]*sin(phi[ix]), pT[ix]*sinh(y[ix]) ,pT[ix]*cosh(y[ix]),ZERO); if(ix==0) { realMomenta[ix][iy][2] = Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]), z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1); realMomenta[ix][iy][3] = Lorentz5Momentum(ZERO,ZERO, z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2); } else { realMomenta[ix][iy][2] = Lorentz5Momentum(ZERO,ZERO,-z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2); realMomenta[ix][iy][3] = Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]), -z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1); } // boost the momenta back to the lab for(unsigned int iz=2;iz<5;++iz) realMomenta[ix][iy][iz] *= eventFrame; // jacobian and prefactors for the weight Energy J = M/sqrt(xT2)*abs(-x1[ix][iy]*x2[ix][iy]+2.*mu22*x1[ix][iy] +x2[ix][iy]+x2[ix][iy]*mu12+mu22*x2[ix][iy] -sqr(x2[ix][iy])) /pow(sqr(x2[ix][iy])-4.*mu22,1.5); // prefactors etc contrib[ix][iy] = 0.5*pT[ix]/J/preFactor_/lambda; // matrix element piece contrib[ix][iy] *= meRatio(partons_,realMomenta[ix][iy],ix,false); // coupling piece contrib[ix][iy] *= alphaQED_->ratio(sqr(pT[ix])); } if(contrib[ix][0]+contrib[ix][1]>1.) { ostringstream s; s << "MEee2gZ2qq::generateHardest weight for channel " << ix << "is " << contrib[ix][0]+contrib[ix][1] << " which is greater than 1"; generator()->logWarning( Exception(s.str(), Exception::warning) ); } reject = UseRandom::rnd() > contrib[ix][0] + contrib[ix][1]; } while (reject); if(pT[ix]pT[1]) { iemit = 2; ispect = 3; pTemit = pT[0]; if(UseRandom::rnd()(2,1)); } /** * Members for hard corrections to the emission of QCD radiation */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return false;} /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr,ShowerInteraction::Type); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, + ShowerInteraction::Type); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EW}\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; /** * Construct the vertex of spin correlations. */ virtual void constructVertex(tSubProPtr); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Rebind pointer to other Interfaced objects. Called in the setup phase * after all objects used in an EventGenerator has been cloned so that * the pointers will refer to the cloned objects afterwards. * @param trans a TranslationMap relating the original objects to * their respective clones. * @throws RebindException if no cloned object was found for a given * pointer. */ virtual void rebind(const TranslationMap & trans) ; /** * Return a vector of all pointers to Interfaced objects used in this * object. * @return a vector of pointers. */ virtual IVector getReferences(); //@} protected: /** * Calculate the matrix element for \f$e^+e^-\to \ell^+ \ell^-\f$. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles */ double loME(const vector & partons, const vector & momenta, bool first) const; /** * Member to calculate the matrix element * @param fin Spinors for incoming fermion * @param ain Spinors for incoming antifermion * @param fout Spinors for outgoing fermion * @param aout Spinors for outgong antifermion * @param me Spin summed Matrix element * @param cont The continuum piece of the matrix element * @param BW The Z piece of the matrix element */ ProductionMatrixElement HelicityME(vector & fin, vector & ain, vector & fout, vector & aout, double & me, double & cont, double & BW ) const; /** * The ratio of the matrix element for one additional jet over the * leading order result. In practice * \[\frac{\hat{s}|\overline{\mathcal{M}}|^2_2|D_{\rm emit}|}{4\pi C_F\alpha_S|\overline{\mathcal{M}}|^2_3\left(|D_{\rm emit}|+|D_{\rm spect}\right)}}\] * is returned where \f$\|\overline{\mathcal{M}}|^2\f$ is * the spin and colour summed/averaged matrix element. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles * @param iemitter Whether the quark or antiquark is regardede as the emitter * @param inter The type of interaction */ double meRatio(vector partons, vector momenta, unsigned int iemittor, bool subtract=false) const; /** * Calculate the matrix element for \f$e^-e^-\to q \bar q g$. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles * @param inter The type of interaction */ InvEnergy2 realME(const vector & partons, const vector & momenta) const; /** * Generate the momenta for a hard configuration */ - Energy generateHard(ShowerTreePtr tree, + Energy generateHard(RealEmissionProcessPtr tree, vector & emission, unsigned int & iemit, unsigned int & ispect, bool applyVeto); protected: /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFZVertex() const {return FFZVertex_;} /** * Pointer to the fermion-antifermion photon vertex */ AbstractFFVVertexPtr FFPVertex() const {return FFPVertex_;} /** * Pointer to the particle data object for the Z */ PDPtr Z0() const {return Z0_;} /** * Pointer to the particle data object for the photon */ PDPtr gamma() const {return gamma_;} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEee2gZ2ll & operator=(const MEee2gZ2ll &); private: /** * Pointers to the vertices */ //@{ /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFZVertex_; /** * Pointer to the fermion-antifermion photon vertex */ AbstractFFVVertexPtr FFPVertex_; //@} /** * Pointer to the particle data object for the Z */ PDPtr Z0_; /** * Pointer to the particle data object for the photon */ PDPtr gamma_; /** * The allowed outgoing */ int allowed_; /** * The initial kappa-tilde values for radiation from the quark */ double d_kt1_; /** * Pointer to the EM coupling */ ShowerAlphaPtr alphaQED_; /** * Variables for the POWHEG style corrections */ //@{ /** * The cut off on pt, assuming massless quarks. */ Energy pTmin_; /** * Overestimate for the prefactor */ double preFactor_; /** * ParticleData objects for the partons */ vector partons_; /** * Momenta of the leading-order partons */ vector loMomenta_; //@} }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEee2gZ2ll. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MEee2gZ2ll. */ typedef Herwig::HwMEBase NthBase; }; /** This template specialization informs ThePEG about the name of * the MEee2gZ2ll 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::MEee2gZ2ll"; } /** * The name of a file containing the dynamic library where the class * MEee2gZ2ll is implemented. It may also include several, space-separated, * libraries if the class MEee2gZ2ll 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 "HwMELepton.so"; } }; /** @endcond */ } #endif /* HERWIG_MEee2gZ2ll_H */ diff --git a/MatrixElement/Lepton/MEee2gZ2qq.cc b/MatrixElement/Lepton/MEee2gZ2qq.cc --- a/MatrixElement/Lepton/MEee2gZ2qq.cc +++ b/MatrixElement/Lepton/MEee2gZ2qq.cc @@ -1,1169 +1,990 @@ // -*- C++ -*- // // MEee2gZ2qq.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 MEee2gZ2qq class. // #include "MEee2gZ2qq.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/HardVertex.h" -#include "Herwig/Shower/Base/Evolver.h" -#include "Herwig/Shower/Base/KinematicsReconstructor.h" -#include "Herwig/Shower/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" #include "ThePEG/PDF/PolarizedBeamParticleData.h" #include #include "ThePEG/Utilities/DescribeClass.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" + using namespace Herwig; const double MEee2gZ2qq::EPS_=0.00000001; void MEee2gZ2qq::doinit() { HwMEBase::doinit(); massOption(vector(2,massopt_)); rescalingOption(3); if(minflav_>maxflav_) throw InitException() << "The minimum flavour " << minflav_ << "must be lower the than maximum flavour " << maxflav_ << " in MEee2gZ2qq::doinit() " << Exception::runerror; // set the particle data objects Z0_ = getParticleData(ParticleID::Z0); gamma_ = getParticleData(ParticleID::gamma); gluon_ = getParticleData(ParticleID::g); // cast the SM pointer to the Herwig SM pointer tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); // do the initialisation if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "MEee2gZ2qq::doinit() the Herwig version must be used" << Exception::runerror; FFZVertex_ = hwsm->vertexFFZ(); FFPVertex_ = hwsm->vertexFFP(); FFGVertex_ = hwsm->vertexFFG(); } void MEee2gZ2qq::getDiagrams() const { // specific the diagrams tcPDPtr ep = getParticleData(ParticleID::eplus); tcPDPtr em = getParticleData(ParticleID::eminus); tcPDPtr gamma = getParticleData(ParticleID::gamma); tcPDPtr Z0 = getParticleData(ParticleID::Z0); // setup the processes for ( int i =minflav_; i<=maxflav_; ++i ) { tcPDPtr qk = getParticleData(i); tcPDPtr qb = qk->CC(); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, gamma, 3, qk, 3, qb, -1))); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, Z0 , 3, qk, 3, qb, -2))); } } Energy2 MEee2gZ2qq::scale() const { return sqr(getParticleData(ParticleID::Z0)->mass()); // return sHat(); } unsigned int MEee2gZ2qq::orderInAlphaS() const { return 0; } unsigned int MEee2gZ2qq::orderInAlphaEW() const { return 2; } Selector MEee2gZ2qq::diagrams(const DiagramVector & diags) const { double lastCont(0.5),lastBW(0.5); if ( lastXCombPtr() ) { lastCont = meInfo()[0]; lastBW = meInfo()[1]; } Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { if ( diags[i]->id() == -1 ) sel.insert(lastCont, i); else if ( diags[i]->id() == -2 ) sel.insert(lastBW, i); } return sel; } Selector MEee2gZ2qq::colourGeometries(tcDiagPtr ) const { static const ColourLines c("-5 4"); Selector sel; sel.insert(1.0, &c); return sel; } void MEee2gZ2qq::persistentOutput(PersistentOStream & os) const { os << FFZVertex_ << FFPVertex_ << FFGVertex_ << Z0_ << gamma_ << gluon_ << minflav_ << maxflav_ << massopt_ << alphaQCD_ << alphaQED_ << ounit(pTminQED_,GeV) << ounit(pTminQCD_,GeV) << preFactor_ << spinCorrelations_; } void MEee2gZ2qq::persistentInput(PersistentIStream & is, int) { is >> FFZVertex_ >> FFPVertex_ >> FFGVertex_ >> Z0_ >> gamma_ >> gluon_ >> minflav_ >> maxflav_ >> massopt_ >> alphaQCD_ >> alphaQED_ >> iunit(pTminQED_,GeV) >> iunit(pTminQCD_,GeV) >> preFactor_ >> spinCorrelations_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeMEee2gZ2qq("Herwig::MEee2gZ2qq", "HwMELepton.so"); void MEee2gZ2qq::Init() { static ClassDocumentation documentation ("The MEee2gZ2qq class implements the matrix element for e+e- -> q qbar"); static Parameter interfaceMinimumFlavour ("MinimumFlavour", "The PDG code of the quark with the lowest PDG code to produce.", &MEee2gZ2qq::minflav_, 1, 1, 6, false, false, Interface::limited); static Parameter interfaceMaximumFlavour ("MaximumFlavour", "The PDG code of the quark with the highest PDG code to produce", &MEee2gZ2qq::maxflav_, 5, 1, 6, false, false, Interface::limited); static Switch interfaceTopMassOption ("TopMassOption", "Option for the treatment of the top quark mass", &MEee2gZ2qq::massopt_, 1, false, false); static SwitchOption interfaceTopMassOptionOnMassShell (interfaceTopMassOption, "OnMassShell", "The top is produced on its mass shell", 1); static SwitchOption interfaceTopMassOption2 (interfaceTopMassOption, "OffShell", "The top is generated off-shell using the mass and width generator.", 2); static Parameter interfacepTMinQED ("pTMinQED", "Minimum pT for hard QED radiation", &MEee2gZ2qq::pTminQED_, GeV, 1.0*GeV, 0.001*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfacepTMinQCD ("pTMinQCD", "Minimum pT for hard QCD radiation", &MEee2gZ2qq::pTminQCD_, GeV, 1.0*GeV, 0.001*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfacePrefactor ("Prefactor", "Prefactor for the overestimate of the emission probability", &MEee2gZ2qq::preFactor_, 6.0, 1.0, 100.0, false, false, Interface::limited); static Reference interfaceQCDCoupling ("AlphaQCD", "Pointer to the object to calculate the strong coupling for the correction", &MEee2gZ2qq::alphaQCD_, false, false, true, false, false); static Reference interfaceEMCoupling ("AlphaQED", "Pointer to the object to calculate the EM coupling for the correction", &MEee2gZ2qq::alphaQED_, false, false, true, false, false); static Switch interfaceSpinCorrelations ("SpinCorrelations", "Switch the construction of the veretx for spin correlations on/off", &MEee2gZ2qq::spinCorrelations_, true, false, false); static SwitchOption interfaceSpinCorrelationsYes (interfaceSpinCorrelations, "Yes", "Swtich On", true); static SwitchOption interfaceSpinCorrelationsNo (interfaceSpinCorrelations, "No", "Switch off", false); } double MEee2gZ2qq::me2() const { return loME(mePartonData(),rescaledMomenta(),true); } ProductionMatrixElement MEee2gZ2qq::HelicityME(vector & fin, vector & ain, vector & fout, vector & aout, double & me, double & cont, double & BW ) const { // the particles should be in the order // for the incoming // 0 incoming fermion (u spinor) // 1 incoming antifermion (vbar spinor) // for the outgoing // 0 outgoing fermion (ubar spinor) // 1 outgoing antifermion (v spinor) // me to be returned ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); ProductionMatrixElement gamma (PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); ProductionMatrixElement Zboson(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); // wavefunctions for the intermediate particles VectorWaveFunction interZ,interG; // temporary storage of the different diagrams Complex diag1,diag2; // sum over helicities to get the matrix element unsigned int inhel1,inhel2,outhel1,outhel2; double total[3]={0.,0.,0.}; for(inhel1=0;inhel1<2;++inhel1) { for(inhel2=0;inhel2<2;++inhel2) { // intermediate Z interZ = FFZVertex_->evaluate(scale(),1,Z0_,fin[inhel1],ain[inhel2]); // intermediate photon interG = FFPVertex_->evaluate(scale(),1,gamma_,fin[inhel1],ain[inhel2]); for(outhel1=0;outhel1<2;++outhel1) { for(outhel2=0;outhel2<2;++outhel2) { // first the Z exchange diagram diag1 = FFZVertex_->evaluate(scale(),aout[outhel2],fout[outhel1], interZ); // then the photon exchange diagram diag2 = FFPVertex_->evaluate(scale(),aout[outhel2],fout[outhel1], interG); // add up squares of individual terms total[1] += norm(diag1); Zboson(inhel1,inhel2,outhel1,outhel2) = diag1; total[2] += norm(diag2); gamma (inhel1,inhel2,outhel1,outhel2) = diag2; // the full thing including interference diag1 += diag2; total[0] += norm(diag1); output(inhel1,inhel2,outhel1,outhel2)=diag1; } } } } for(int ix=0;ix<3;++ix) total[ix] *= 0.25; tcPolarizedBeamPDPtr beam[2] = {dynamic_ptr_cast(mePartonData()[0]), dynamic_ptr_cast(mePartonData()[1])}; if( beam[0] || beam[1] ) { RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()), beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())}; total[0] = output.average(rho[0],rho[1]); total[1] = Zboson.average(rho[0],rho[1]); total[2] = gamma .average(rho[0],rho[1]); } // results for(int ix=0;ix<3;++ix) total[ix]*= 3.; cont = total[2]; BW = total[1]; me = total[0]; return output; } void MEee2gZ2qq::constructVertex(tSubProPtr sub) { if(!spinCorrelations_) return; // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first); hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]); hard.push_back(sub->outgoing()[1]); if(hard[0]->id()id()) swap(hard[0],hard[1]); if(hard[2]->id()id()) swap(hard[2],hard[3]); vector fin,aout; vector ain,fout; // get wave functions for off-shell momenta for later on SpinorWaveFunction( fin ,hard[0],incoming,false,true); SpinorBarWaveFunction(ain ,hard[1],incoming,false,true); SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true); SpinorWaveFunction( aout,hard[3],outgoing,true ,true); // now rescale the momenta and compute the matrix element with the // rescaled momenta for correlations vector momenta; cPDVector data; for(unsigned int ix=0;ix<4;++ix) { momenta.push_back(hard[ix]->momentum()); data .push_back(hard[ix]->dataPtr()); } rescaleMomenta(momenta,data); SpinorWaveFunction ein (rescaledMomenta()[0],data[0],incoming); SpinorBarWaveFunction pin (rescaledMomenta()[1],data[1],incoming); SpinorBarWaveFunction qkout(rescaledMomenta()[2],data[2],outgoing); SpinorWaveFunction qbout(rescaledMomenta()[3],data[3],outgoing); for(unsigned int ix=0;ix<2;++ix) { ein.reset(ix) ; fin [ix] = ein ; pin.reset(ix) ; ain [ix] = pin ; qkout.reset(ix); fout[ix] = qkout; qbout.reset(ix); aout[ix] = qbout; } // calculate the matrix element double me,cont,BW; ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me,cont,BW); // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(prodme); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) { tSpinPtr spin = hard[ix]->spinInfo(); if(ix<2) { tcPolarizedBeamPDPtr beam = dynamic_ptr_cast(hard[ix]->dataPtr()); if(beam) spin->rhoMatrix() = beam->rhoMatrix(); } spin->productionVertex(hardvertex); } } void MEee2gZ2qq::rebind(const TranslationMap & trans) { FFZVertex_ = trans.translate(FFZVertex_); FFPVertex_ = trans.translate(FFPVertex_); FFGVertex_ = trans.translate(FFGVertex_); Z0_ = trans.translate(Z0_); gamma_ = trans.translate(gamma_); gluon_ = trans.translate(gluon_); HwMEBase::rebind(trans); } IVector MEee2gZ2qq::getReferences() { IVector ret = HwMEBase::getReferences(); ret.push_back(FFZVertex_); ret.push_back(FFPVertex_); ret.push_back(FFGVertex_); ret.push_back(Z0_ ); ret.push_back(gamma_ ); ret.push_back(gluon_ ); return ret; } -void MEee2gZ2qq::initializeMECorrection(ShowerTreePtr , double & initial, +void MEee2gZ2qq::initializeMECorrection(RealEmissionProcessPtr, + double & initial, double & final) { d_Q_ = sqrt(sHat()); d_m_ = 0.5*(meMomenta()[2].mass()+meMomenta()[3].mass()); // set the other parameters d_rho_ = sqr(d_m_/d_Q_); d_v_ = sqrt(1.-4.*d_rho_); // maximum evolution scale d_kt1_ = (1. + sqrt(1. - 4.*d_rho_))/2.; double num = d_rho_ * d_kt1_ + 0.25 * d_v_ *(1.+d_v_)*(1.+d_v_); double den = d_kt1_ - d_rho_; d_kt2_ = num/den; // maximums for reweighting initial = 1.; final = 1.; } -void MEee2gZ2qq::applyHardMatrixElementCorrection(ShowerTreePtr tree) { +RealEmissionProcessPtr MEee2gZ2qq::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { + return calculateRealEmission(born,true,ShowerInteraction::QCD); +} + +RealEmissionProcessPtr MEee2gZ2qq::calculateRealEmission(RealEmissionProcessPtr born, bool veto, + ShowerInteraction::Type inter) { vector emission; unsigned int iemit,ispect; - generateHard(tree,emission,iemit,ispect,true,ShowerInteraction::QCD); - if(emission.empty()) return; + pair output = + generateHard(born,emission,iemit,ispect,veto,inter); + if(emission.empty()) { + if(inter!=ShowerInteraction::QCD) born->pT()[ShowerInteraction::QED] = pTminQED_; + if(inter!=ShowerInteraction::QED) born->pT()[ShowerInteraction::QCD] = pTminQCD_; + return born; + } + else { + Energy pTveto = output.first; + if(inter!=ShowerInteraction::QCD) born->pT()[ShowerInteraction::QED] = pTveto; + if(inter!=ShowerInteraction::QED) born->pT()[ShowerInteraction::QCD] = pTveto; + } + // generate the momenta for the hard emission + ShowerInteraction::Type force = output.second; + born->interaction(force); // get the quark and antiquark - ParticleVector qq; - map::const_iterator cit; - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) - qq.push_back(cit->first->copy()); - // ensure quark first - if(qq[0]->id()<0) swap(qq[0],qq[1]); + ParticleVector qq; + for(unsigned int ix=0;ix<2;++ix) qq.push_back(born->bornOutgoing()[ix]); + bool order = qq[0]->id()>0; + if(!order) swap(qq[0],qq[1]); // perform final check to ensure energy greater than constituent mass for (int i=0; i<2; i++) { - if (emission[i+2].e() < qq[i]->data().constituentMass()) return; + if (emission[i+2].e() < qq[i]->data().constituentMass()) + return RealEmissionProcessPtr(); } - if (emission[4].e() < gluon_->constituentMass()) return; + if(force!=ShowerInteraction::QED && + emission[4].e() < gluon_->constituentMass()) + return RealEmissionProcessPtr(); // set masses for (int i=0; i<2; i++) emission[i+2].setMass(qq[i]->mass()); emission[4].setMass(ZERO); - // decide which particle emits - bool firstEmits= - emission[4].vect().perp2(emission[2].vect())< - emission[4].vect().perp2(emission[3].vect()); // create the new quark, antiquark and gluon - PPtr newg = gluon_->produceParticle(emission[4]); - PPtr newq,newa; - if(firstEmits) { - newq = qq[0]->dataPtr()->produceParticle(emission[2]); - newa = new_ptr(Particle(*qq[1])); - qq[1]->antiColourLine()->removeAntiColoured(newa); - newa->set5Momentum(emission[3]); + PPtr newq = qq[0]->dataPtr()->produceParticle(emission[2]); + PPtr newa = qq[1]->dataPtr()->produceParticle(emission[3]); + PPtr newg; + if(force==ShowerInteraction::QCD) + newg = gluon_->produceParticle(emission[4]); + else + newg = gamma_->produceParticle(emission[4]); + // create the output real emission process + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + born->incoming().push_back(born->bornIncoming()[ix]->dataPtr()-> + produceParticle(born->bornIncoming()[ix]->momentum())); + } + if(order) { + born->outgoing().push_back(newq); + born->outgoing().push_back(newa); } else { - newq = new_ptr(Particle(*qq[0])); - qq[0]->colourLine()->removeColoured(newq); - newq->set5Momentum(emission[2]); - newa = qq[1]->dataPtr()->produceParticle(emission[3]); + born->outgoing().push_back(newa); + born->outgoing().push_back(newq); + swap(iemit,ispect); } - // get the original colour line - ColinePtr col; - if(qq[0]->id()>0) col=qq[0]->colourLine(); - else col=qq[0]->antiColourLine(); - // set the colour lines - if(firstEmits) { - col->addColoured(newq); - col->addAntiColoured(newg); + born->outgoing().push_back(newg); + // set emitter and spectator + born->emitter (iemit); + born->spectator(ispect); + born->emitted(4); + // make colour connections + if(force==ShowerInteraction::QCD) { + newg->colourNeighbour(newq); newa->colourNeighbour(newg); } else { - col->addAntiColoured(newa); - col->addColoured(newg); - newq->antiColourNeighbour(newg); + newa->colourNeighbour(newq); } - // change the existing quark and antiquark - PPtr orig; - for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) { - map >::const_iterator tit; - for(tit = tree->treelinks().begin(); - tit != tree->treelinks().end();++tit) { - if(tit->second.first && tit->second.second==cit->first->progenitor()) - break; - } - if(cit->first->progenitor()->id()==newq->id()) { - // remove old particles from colour line - col->removeColoured(cit->first->copy()); - col->removeColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newq); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newq,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(!firstEmits); - if(firstEmits) orig=cit->first->original(); - if(tit!=tree->treelinks().end()) - tree->updateLink(tit->first,make_pair(cit->first,sp)); - } - else { - // remove old particles from colour line - col->removeAntiColoured(cit->first->copy()); - col->removeAntiColoured(cit->first->progenitor()); - // insert new particles - cit->first->copy(newa); - ShowerParticlePtr sp(new_ptr(ShowerParticle(*newa,1,true))); - cit->first->progenitor(sp); - tree->outgoingLines()[cit->first]=sp; - cit->first->perturbative(firstEmits); - if(!firstEmits) orig=cit->first->original(); - if(tit!=tree->treelinks().end()) - tree->updateLink(tit->first,make_pair(cit->first,sp)); - } - } - // add the gluon - ShowerParticlePtr sg=new_ptr(ShowerParticle(*newg,1,true)); - ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg)); - gluon->perturbative(false); - tree->outgoingLines().insert(make_pair(gluon,sg)); - tree->hardMatrixElementCorrection(true); + return born; } bool MEee2gZ2qq::softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent,Branching br) { // check we should be applying the veto if(parent->id()!=initial->progenitor()->id()|| br.ids[0]->id()!=br.ids[1]->id()|| br.ids[2]->id()!=ParticleID::g) return false; // calculate pt double d_z = br.kinematics->z(); Energy d_qt = br.kinematics->scale(); Energy2 d_m2 = parent->momentum().m2(); Energy pPerp = (1.-d_z)*sqrt( sqr(d_z*d_qt) - d_m2); // if not hardest so far don't apply veto if(pPerphighestpT()) return false; // calculate x and xb double kti = sqr(d_qt/d_Q_); double w = sqr(d_v_) + kti*(-1. + d_z)*d_z*(2. + kti*(-1. + d_z)*d_z); if (w < 0) return false; double x = (1. + sqr(d_v_)*(-1. + d_z) + sqr(kti*(-1. + d_z))*d_z*d_z*d_z + d_z*sqrt(w) - kti*(-1. + d_z)*d_z*(2. + d_z*(-2 + sqrt(w))))/ (1. - kti*(-1. + d_z)*d_z + sqrt(w)); double xb = 1. + kti*(-1. + d_z)*d_z; // calculate the weight if(parent->id()<0) swap(x,xb); // if exceptionally out of phase space, leave this emission, as there // is no good interpretation for the soft ME correction. if( x<0 || xb<0) return false; double xg = 2. - xb - x; // always return one in the soft gluon region if(xg < EPS_) return false; // check it is in the phase space if((1.-x)*(1.-xb)*(1.-xg) < d_rho_*xg*xg) { parent->vetoEmission(parent->id()>0 ? ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDColourLine,br.kinematics->scale()); return true; } double k1 = getKfromX(x, xb); double k2 = getKfromX(xb, x); double weight = 1.; // quark emission if(parent->id() > 0 && k1 < d_kt1_) { weight = MEV(x, xb)/PS(x, xb); // is it also in the anti-quark emission zone? if(k2 < d_kt2_) weight *= 0.5; } // antiquark emission if(parent->id() < 0 && k2 < d_kt2_) { weight = MEV(x, xb)/PS(xb, x); // is it also in the quark emission zone? if(k1 < d_kt1_) weight *= 0.5; } // compute veto from weight bool veto = !UseRandom::rndbool(weight); // if not vetoed reset max // if vetoing reset the scale if(veto) { parent->vetoEmission(parent->id()>0 ? ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDColourLine,br.kinematics->scale()); } // return the veto return veto; } double MEee2gZ2qq::getKfromX(double x1, double x2) { double uval = 0.5*(1. + d_rho_/(1.-x2+d_rho_)); double num = x1 - (2. - x2)*uval; double den = sqrt(x2*x2 - 4.*d_rho_); double zval = uval + num/den; return (1.-x2)/(zval*(1.-zval)); } double MEee2gZ2qq::MEV(double x1, double x2) { // Vector part double num = (x1+2.*d_rho_)*(x1+2.*d_rho_) + (x2+2.*d_rho_)*(x2+2.*d_rho_) - 8.*d_rho_*(1.+2.*d_rho_); double den = (1.+2.*d_rho_)*(1.-x1)*(1.-x2); return (num/den - 2.*d_rho_/((1.-x1)*(1.-x1)) - 2*d_rho_/((1.-x2)*(1.-x2)))/d_v_; } double MEee2gZ2qq::PS(double x, double xbar) { double u = 0.5*(1. + d_rho_ / (1.-xbar+d_rho_)); double z = u + (x - (2.-xbar)*u)/sqrt(xbar*xbar - 4.*d_rho_); double brack = (1.+z*z)/(1.-z)- 2.*d_rho_/(1-xbar); // interesting: the splitting function without the subtraction // term. Actually gives a much worse approximation in the collinear // limit. double brack = (1.+z*z)/(1.-z); double den = (1.-xbar)*sqrt(xbar*xbar - 4.*d_rho_); return brack/den; } pair -MEee2gZ2qq::generateHard(ShowerTreePtr tree, +MEee2gZ2qq::generateHard(RealEmissionProcessPtr born, vector & emmision, unsigned int & iemit, unsigned int & ispect, bool applyVeto,ShowerInteraction::Type type) { - vector inter; + vector interactions; if(type==ShowerInteraction::QCD) - inter.push_back(ShowerInteraction::QCD); + interactions.push_back(ShowerInteraction::QCD); else if(type==ShowerInteraction::QED) - inter.push_back(ShowerInteraction::QED); + interactions.push_back(ShowerInteraction::QED); else if(type==ShowerInteraction::QEDQCD || type==ShowerInteraction::ALL) { - inter.push_back(ShowerInteraction::QCD); - inter.push_back(ShowerInteraction::QED); + interactions.push_back(ShowerInteraction::QCD); + interactions.push_back(ShowerInteraction::QED); } - // get the momenta of the incoming and outgoing partons - // incoming - ShowerProgenitorPtr - emProgenitor = tree->incomingLines().begin() ->first, - epProgenitor = tree->incomingLines().rbegin()->first; - // outgoing - ShowerProgenitorPtr - qkProgenitor = tree->outgoingLines().begin() ->first, - qbProgenitor = tree->outgoingLines().rbegin()->first; - // get the order right - if(emProgenitor->id()<0) swap(emProgenitor,epProgenitor); - if(qkProgenitor->id()<0) swap(qkProgenitor,qbProgenitor); + // incoming particles + tPPtr em = born->bornIncoming()[0]; + tPPtr ep = born->bornIncoming()[1]; + if(em->id()<0) swap(em,ep); + // outgoing particles + tPPtr qk = born->bornOutgoing()[0]; + tPPtr qb = born->bornOutgoing()[1]; + if(qk->id()<0) swap(qk,qb); + // extract the momenta loMomenta_.clear(); - // extract the momenta - loMomenta_.push_back(emProgenitor->progenitor()->momentum()); - loMomenta_.push_back(epProgenitor->progenitor()->momentum()); - loMomenta_.push_back(qkProgenitor->progenitor()->momentum()); - loMomenta_.push_back(qbProgenitor->progenitor()->momentum()); + loMomenta_.push_back(em->momentum()); + loMomenta_.push_back(ep->momentum()); + loMomenta_.push_back(qk->momentum()); + loMomenta_.push_back(qb->momentum()); // and ParticleData objects partons_.resize(5); - partons_[0]=emProgenitor->progenitor()->dataPtr(); - partons_[1]=epProgenitor->progenitor()->dataPtr(); - partons_[2]=qkProgenitor->progenitor()->dataPtr(); - partons_[3]=qbProgenitor->progenitor()->dataPtr(); + partons_[0]=em->dataPtr(); + partons_[1]=ep->dataPtr(); + partons_[2]=qk->dataPtr(); + partons_[3]=qb->dataPtr(); partons_[4]=cPDPtr(); // boost from lab to CMS frame with outgoing particles // along the z axis LorentzRotation eventFrame( ( loMomenta_[2] + loMomenta_[3] ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*loMomenta_[2]; eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() ); eventFrame.invert(); // mass of the final-state system Energy2 M2 = (loMomenta_[2]+loMomenta_[3]).m2(); Energy M = sqrt(M2); double mu1 = loMomenta_[2].mass()/M; double mu2 = loMomenta_[3].mass()/M; double mu12 = sqr(mu1), mu22 = sqr(mu2); double lambda = sqrt(1.+sqr(mu12)+sqr(mu22)-2.*mu12-2.*mu22-2.*mu12*mu22); // max pT Energy pTmax = 0.5*sqrt(M2)* (1.-sqr(loMomenta_[2].mass()+loMomenta_[3].mass())/M2); // max y if ( pTmax < pTminQED_ && pTmax < pTminQCD_ ) return make_pair(ZERO,ShowerInteraction::QCD); vector pTemit; vector > emittedMomenta;; - vector iemitter,ispectater; - for(unsigned int iinter=0;iinter iemitter,ispectator; + for(unsigned int iinter=0;iinteroverestimateValue()/Constants::twopi* - 2.*ymax*preFactor_; + 2.*ymax*preFactor_; } else { pTmin = pTminQED_; ymax = acosh(pTmax/pTmin); partons_[4] = gamma_; a = alphaQED_->overestimateValue()/Constants::twopi* - 2.*ymax*preFactor_*sqr(double(mePartonData()[2]->iCharge())/3.); + 2.*ymax*preFactor_*sqr(double(mePartonData()[2]->iCharge())/3.); } // variables for the emission Energy pT[2]; double y[2],phi[2],x3[2],x1[2][2],x2[2][2]; double contrib[2][2]; // storage of the real emission momenta vector realMomenta[2][2]= {{vector(5),vector(5)}, {vector(5),vector(5)}}; for(unsigned int ix=0;ix<2;++ix) for(unsigned int iy=0;iy<2;++iy) - for(unsigned int iz=0;iz<2;++iz) - realMomenta[ix][iy][iz] = loMomenta_[iz]; + for(unsigned int iz=0;iz<2;++iz) + realMomenta[ix][iy][iz] = loMomenta_[iz]; // generate the emission for(unsigned int ix=0;ix<2;++ix) { if(ix==1) { - swap(mu1 ,mu2 ); - swap(mu12,mu22); + swap(mu1 ,mu2 ); + swap(mu12,mu22); } pT[ix] = pTmax; y [ix] = 0.; bool reject = true; do { - // generate pT - pT[ix] *= pow(UseRandom::rnd(),1./a); - if(pT[ix] 1. -sqr( mu1 + mu2 ) ) continue; - // find the possible solutions for x1 - double xT2 = sqr(2./M*pT[ix]); - double root = (-sqr(x3[ix])+xT2)* - (xT2*mu22+2.*x3[ix]-sqr(mu12)+2.*mu22+2.*mu12-sqr(x3[ix])-1. - +2.*mu12*mu22-sqr(mu22)-2.*mu22*x3[ix]-2.*mu12*x3[ix]); - double c1=2.*sqr(x3[ix])-4.*mu22-6.*x3[ix]+4.*mu12-xT2*x3[ix] - +2.*xT2-2.*mu12*x3[ix]+2.*mu22*x3[ix]+4.; - if(root<0.) continue; - x1[ix][0] = 1./(4.-4.*x3[ix]+xT2)*(c1-2.*sqrt(root)); - x1[ix][1] = 1./(4.-4.*x3[ix]+xT2)*(c1+2.*sqrt(root)); - // change sign of y if 2nd particle emits - if(ix==1) y[ix] *=-1.; - // loop over the solutions - for(unsigned int iy=0;iy<2;++iy) { - contrib[ix][iy]=0.; - // check x1 value allowed - if(x1[ix][iy]<2.*mu1||x1[ix][iy]>1.+mu12-mu22) continue; - // calculate x2 value and check allowed - x2[ix][iy] = 2.-x3[ix]-x1[ix][iy]; - double root = max(0.,sqr(x1[ix][iy])-4.*mu12); - root = sqrt(root); - double x2min = 1.+mu22-mu12 - -0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12+root); - double x2max = 1.+mu22-mu12 - -0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12-root); - if(x2[ix][iy]x2max) continue; - // check the z components - double z1 = sqrt(sqr(x1[ix][iy])-4.*mu12-xT2); - double z2 = -sqrt(sqr(x2[ix][iy])-4.*mu22); - double z3 = pT[ix]*sinh(y[ix])*2./M; - if(ix==1) z3 *=-1.; - if(abs(-z1+z2+z3)<1e-9) z1 *= -1.; - if(abs(z1+z2+z3)>1e-5) continue; - // if using as an ME correction the veto - if(applyVeto) { - double xb = x1[ix][iy], xc = x2[ix][iy]; - double b = mu12, c = mu22; - double r = 0.5*(1.+b/(1.+c-xc)); - double z1 = r + (xb-(2.-xc)*r)/sqrt(sqr(xc)-4.*c); - double kt1 = (1.-b+c-xc)/z1/(1.-z1); - r = 0.5*(1.+c/(1.+b-xb)); - double z2 = r + (xc-(2.-xb)*r)/sqrt(sqr(xb)-4.*b); - double kt2 = (1.-c+b-xb)/z2/(1.-z2); - if(ix==1) { - swap(z1 ,z2); - swap(kt1,kt2); - } - // veto the shower region - if( kt1 < d_kt1_ || kt2 < d_kt2_ ) continue; - } - // construct the momenta - realMomenta[ix][iy][4] = - Lorentz5Momentum(pT[ix]*cos(phi[ix]),pT[ix]*sin(phi[ix]), - pT[ix]*sinh(y[ix]) ,pT[ix]*cosh(y[ix]),ZERO); - if(ix==0) { - realMomenta[ix][iy][2] = - Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]), - z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1); - realMomenta[ix][iy][3] = - Lorentz5Momentum(ZERO,ZERO, z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2); - } - else { - realMomenta[ix][iy][2] = - Lorentz5Momentum(ZERO,ZERO,-z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2); - realMomenta[ix][iy][3] = - Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]), - -z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1); - } - // boost the momenta back to the lab - for(unsigned int iz=2;iz<5;++iz) - realMomenta[ix][iy][iz] *= eventFrame; - // jacobian and prefactors for the weight - Energy J = M/sqrt(xT2)*abs(-x1[ix][iy]*x2[ix][iy]+2.*mu22*x1[ix][iy] - +x2[ix][iy]+x2[ix][iy]*mu12+mu22*x2[ix][iy] - -sqr(x2[ix][iy])) - /pow(sqr(x2[ix][iy])-4.*mu22,1.5); - // prefactors etc - contrib[ix][iy] = 0.5*pT[ix]/J/preFactor_/lambda; - // matrix element piece - contrib[ix][iy] *= meRatio(partons_,realMomenta[ix][iy], - ix,inter[iinter],false); - // coupling piece - if(inter[iinter]==ShowerInteraction::QCD) - contrib[ix][iy] *= alphaQCD_->ratio(sqr(pT[ix])); - else - contrib[ix][iy] *= alphaQED_->ratio(sqr(pT[ix])); - } - if(contrib[ix][0]+contrib[ix][1]>1.) { - ostringstream s; - s << "MEee2gZ2qq::generateHardest weight for channel " << ix - << "is " << contrib[ix][0]+contrib[ix][1] - << " which is greater than 1"; - generator()->logWarning( Exception(s.str(), Exception::warning) ); - } - reject = UseRandom::rnd() > contrib[ix][0] + contrib[ix][1]; + // generate pT + pT[ix] *= pow(UseRandom::rnd(),1./a); + if(pT[ix] 1. -sqr( mu1 + mu2 ) ) continue; + // find the possible solutions for x1 + double xT2 = sqr(2./M*pT[ix]); + double root = (-sqr(x3[ix])+xT2)* + (xT2*mu22+2.*x3[ix]-sqr(mu12)+2.*mu22+2.*mu12-sqr(x3[ix])-1. + +2.*mu12*mu22-sqr(mu22)-2.*mu22*x3[ix]-2.*mu12*x3[ix]); + double c1=2.*sqr(x3[ix])-4.*mu22-6.*x3[ix]+4.*mu12-xT2*x3[ix] + +2.*xT2-2.*mu12*x3[ix]+2.*mu22*x3[ix]+4.; + if(root<0.) continue; + x1[ix][0] = 1./(4.-4.*x3[ix]+xT2)*(c1-2.*sqrt(root)); + x1[ix][1] = 1./(4.-4.*x3[ix]+xT2)*(c1+2.*sqrt(root)); + // change sign of y if 2nd particle emits + if(ix==1) y[ix] *=-1.; + // loop over the solutions + for(unsigned int iy=0;iy<2;++iy) { + contrib[ix][iy]=0.; + // check x1 value allowed + if(x1[ix][iy]<2.*mu1||x1[ix][iy]>1.+mu12-mu22) continue; + // calculate x2 value and check allowed + x2[ix][iy] = 2.-x3[ix]-x1[ix][iy]; + double root = max(0.,sqr(x1[ix][iy])-4.*mu12); + root = sqrt(root); + double x2min = 1.+mu22-mu12 + -0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12+root); + double x2max = 1.+mu22-mu12 + -0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12-root); + if(x2[ix][iy]x2max) continue; + // check the z components + double z1 = sqrt(sqr(x1[ix][iy])-4.*mu12-xT2); + double z2 = -sqrt(sqr(x2[ix][iy])-4.*mu22); + double z3 = pT[ix]*sinh(y[ix])*2./M; + if(ix==1) z3 *=-1.; + if(abs(-z1+z2+z3)<1e-9) z1 *= -1.; + if(abs(z1+z2+z3)>1e-5) continue; + // if using as an ME correction the veto + if(applyVeto) { + double xb = x1[ix][iy], xc = x2[ix][iy]; + double b = mu12, c = mu22; + double r = 0.5*(1.+b/(1.+c-xc)); + double z1 = r + (xb-(2.-xc)*r)/sqrt(sqr(xc)-4.*c); + double kt1 = (1.-b+c-xc)/z1/(1.-z1); + r = 0.5*(1.+c/(1.+b-xb)); + double z2 = r + (xc-(2.-xb)*r)/sqrt(sqr(xb)-4.*b); + double kt2 = (1.-c+b-xb)/z2/(1.-z2); + if(ix==1) { + swap(z1 ,z2); + swap(kt1,kt2); + } + // veto the shower region + if( kt1 < d_kt1_ || kt2 < d_kt2_ ) continue; + } + // construct the momenta + realMomenta[ix][iy][4] = + Lorentz5Momentum(pT[ix]*cos(phi[ix]),pT[ix]*sin(phi[ix]), + pT[ix]*sinh(y[ix]) ,pT[ix]*cosh(y[ix]),ZERO); + if(ix==0) { + realMomenta[ix][iy][2] = + Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]), + z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1); + realMomenta[ix][iy][3] = + Lorentz5Momentum(ZERO,ZERO, z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2); + } + else { + realMomenta[ix][iy][2] = + Lorentz5Momentum(ZERO,ZERO,-z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2); + realMomenta[ix][iy][3] = + Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]), + -z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1); + } + // boost the momenta back to the lab + for(unsigned int iz=2;iz<5;++iz) + realMomenta[ix][iy][iz] *= eventFrame; + // jacobian and prefactors for the weight + Energy J = M/sqrt(xT2)*abs(-x1[ix][iy]*x2[ix][iy]+2.*mu22*x1[ix][iy] + +x2[ix][iy]+x2[ix][iy]*mu12+mu22*x2[ix][iy] + -sqr(x2[ix][iy])) + /pow(sqr(x2[ix][iy])-4.*mu22,1.5); + // prefactors etc + contrib[ix][iy] = 0.5*pT[ix]/J/preFactor_/lambda; + // matrix element piece + contrib[ix][iy] *= meRatio(partons_,realMomenta[ix][iy], + ix,interactions[iinter],false); + // coupling piece + if(interactions[iinter]==ShowerInteraction::QCD) + contrib[ix][iy] *= alphaQCD_->ratio(sqr(pT[ix])); + else + contrib[ix][iy] *= alphaQED_->ratio(sqr(pT[ix])); + } + if(contrib[ix][0]+contrib[ix][1]>1.) { + ostringstream s; + s << "MEee2gZ2qq::generateHardest weight for channel " << ix + << "is " << contrib[ix][0]+contrib[ix][1] + << " which is greater than 1"; + generator()->logWarning( Exception(s.str(), Exception::warning) ); + } + reject = UseRandom::rnd() > contrib[ix][0] + contrib[ix][1]; } while (reject); if(pT[ix]()); iemitter .push_back(0); - ispectater.push_back(0); + ispectator.push_back(0); continue; } // now pick the emission with highest pT vector emission; if(pT[0]>pT[1]) { iemitter .push_back(2); - ispectater.push_back(3); + ispectator.push_back(3); pTemit.push_back(pT[0]); if(UseRandom::rnd()pTmax) { iselect = ix; pTmax = pTemit[ix]; } } // no emission return if(iselect<0) { return make_pair(ZERO,ShowerInteraction::QCD); } - partons_[4] = inter[iselect]==ShowerInteraction::QCD ? gluon_ : gamma_; + partons_[4] = interactions[iselect]==ShowerInteraction::QCD ? gluon_ : gamma_; iemit = iemitter[iselect]; - ispect = ispectater[iselect]; + ispect = ispectator[iselect]; emmision = emittedMomenta[iselect]; // return pT of emission - return make_pair(pTmax,inter[iselect]); + return make_pair(pTmax,interactions[iselect]); } -HardTreePtr MEee2gZ2qq::generateHardest(ShowerTreePtr tree, - ShowerInteraction::Type inter) { - // generate the momenta for the hard emission - vector emmision; - unsigned int iemit,ispect; - pair output - = generateHard(tree,emmision,iemit,ispect,false,inter); - Energy pTveto = output.first; - ShowerInteraction::Type force = output.second; - // incoming progenitors - ShowerProgenitorPtr - ePProgenitor = tree->incomingLines().begin() ->first, - eMProgenitor = tree->incomingLines().rbegin()->first; - if(eMProgenitor->id()<0) swap(eMProgenitor,ePProgenitor); - // outgoing progenitors - ShowerProgenitorPtr - qkProgenitor = tree->outgoingLines().begin() ->first, - qbProgenitor = tree->outgoingLines().rbegin()->first; - if(qkProgenitor->id()<0) swap(qkProgenitor,qbProgenitor); - // maximum pT of emission - if(emmision.empty()) { - if(inter==ShowerInteraction::QCD || - inter==ShowerInteraction::QEDQCD || - inter==ShowerInteraction::ALL) { - qkProgenitor->maximumpT(pTminQCD_,ShowerInteraction::QCD); - qbProgenitor->maximumpT(pTminQCD_,ShowerInteraction::QCD); - } - if(inter==ShowerInteraction::QED || - inter==ShowerInteraction::QEDQCD || - inter==ShowerInteraction::ALL) { - qkProgenitor->maximumpT(pTminQED_,ShowerInteraction::QED); - qbProgenitor->maximumpT(pTminQED_,ShowerInteraction::QED); - } - return HardTreePtr(); - } - else { - if(inter==ShowerInteraction::QCD || - inter==ShowerInteraction::QEDQCD || - inter==ShowerInteraction::ALL) { - qkProgenitor->maximumpT(pTveto,ShowerInteraction::QCD); - qbProgenitor->maximumpT(pTveto,ShowerInteraction::QCD); - } - if(inter==ShowerInteraction::QED || - inter==ShowerInteraction::QEDQCD || - inter==ShowerInteraction::ALL) { - qkProgenitor->maximumpT(pTveto,ShowerInteraction::QED); - qbProgenitor->maximumpT(pTveto,ShowerInteraction::QED); - } - } - // perform final check to ensure energy greater than constituent mass - if (emmision[2].e() < qkProgenitor->progenitor()->data().constituentMass()) return HardTreePtr(); - if (emmision[3].e() < qbProgenitor->progenitor()->data().constituentMass()) return HardTreePtr(); - if(force!=ShowerInteraction::QED && - emmision[4].e() < gluon_->constituentMass()) return HardTreePtr(); - - // Make the particles for the hard tree - ShowerParticleVector hardParticles; - for(unsigned int ix=0;ix=2))); - hardParticles.back()->set5Momentum(emmision[ix]); - } - ShowerParticlePtr parent(new_ptr(ShowerParticle(partons_[iemit],true))); - Lorentz5Momentum parentMomentum(emmision[iemit]+emmision[4]); - parentMomentum.setMass(partons_[iemit]->mass()); - parent->set5Momentum(parentMomentum); - // Create the vectors of HardBranchings to create the HardTree: - vector spaceBranchings,allBranchings; - // Incoming boson: - for(unsigned int ix=0;ix<2;++ix) { - spaceBranchings.push_back(new_ptr(HardBranching(hardParticles[ix],SudakovPtr(), - HardBranchingPtr(), - HardBranching::Incoming))); - allBranchings.push_back(spaceBranchings.back()); - } - // Outgoing particles from hard emission: - HardBranchingPtr spectatorBranch(new_ptr(HardBranching(hardParticles[ispect], - SudakovPtr(),HardBranchingPtr(), - HardBranching::Outgoing))); - HardBranchingPtr emitterBranch(new_ptr(HardBranching(parent,SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - if(force==ShowerInteraction::QED) { - emitterBranch->type(ShowerPartnerType::QED); - } - else { - emitterBranch->type(emitterBranch->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - } - emitterBranch->addChild(new_ptr(HardBranching(hardParticles[iemit], - SudakovPtr(),HardBranchingPtr(), - HardBranching::Outgoing))); - emitterBranch->addChild(new_ptr(HardBranching(hardParticles[4], - SudakovPtr(),HardBranchingPtr(), - HardBranching::Outgoing))); - if(iemit==0) { - allBranchings.push_back(emitterBranch); - allBranchings.push_back(spectatorBranch); - } - else { - allBranchings.push_back( spectatorBranch ); - allBranchings.push_back( emitterBranch ); - } - emitterBranch ->branchingParticle()->partner(spectatorBranch->branchingParticle()); - spectatorBranch->branchingParticle()->partner(emitterBranch ->branchingParticle()); - if(force==ShowerInteraction::QED) { - spaceBranchings[0]->branchingParticle()->partner(spaceBranchings[1]->branchingParticle()); - spaceBranchings[1]->branchingParticle()->partner(spaceBranchings[0]->branchingParticle()); - } - // Make the HardTree from the HardBranching vectors. - HardTreePtr hardtree = new_ptr(HardTree(allBranchings,spaceBranchings, - force)); - hardtree->partnersSet(true); - // Connect the particles with the branchings in the HardTree - hardtree->connect( eMProgenitor->progenitor(), allBranchings[0] ); - tPPtr beam = eMProgenitor->original(); - if(!beam->parents().empty()) beam = beam->parents()[0]; - allBranchings[0]->beam(beam); - hardtree->connect( ePProgenitor->progenitor(), allBranchings[1] ); - beam = ePProgenitor->original(); - if(!beam->parents().empty()) beam = beam->parents()[0]; - allBranchings[1]->beam(beam); - hardtree->connect( qkProgenitor->progenitor(), allBranchings[2] ); - hardtree->connect( qbProgenitor->progenitor(), allBranchings[3] ); - // colour flow - ColinePtr newline=new_ptr(ColourLine()); - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) { - if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3) - newline->addColoured((**cit).branchingParticle()); - else if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3bar) - newline->addAntiColoured((**cit).branchingParticle()); - } - allBranchings[2]->colourPartner(allBranchings[3]); - allBranchings[3]->colourPartner(allBranchings[2]); - if(hardParticles[4]->dataPtr()->iColour()==PDT::Colour8) { - ColinePtr newLine2=new_ptr(ColourLine()); - if(emitterBranch->branchingParticle()->dataPtr()->iColour()==PDT::Colour3) { - emitterBranch->branchingParticle()->colourLine()->addColoured(hardParticles[4]); - newLine2->addColoured(hardParticles[iemit]); - newLine2->addAntiColoured(hardParticles[4]); - } - else { - emitterBranch->branchingParticle()->antiColourLine()->addAntiColoured(hardParticles[4]); - newLine2->addAntiColoured(hardParticles[iemit]); - newLine2->addColoured(hardParticles[4]); - } - } - else { - if(emitterBranch->branchingParticle()->dataPtr()->iColour()==PDT::Colour3) { - emitterBranch->branchingParticle()->colourLine()->addColoured(hardParticles[iemit]); - } - else { - emitterBranch->branchingParticle()->antiColourLine()->addAntiColoured(hardParticles[iemit]); - } - } - // Return the HardTree - return hardtree; +RealEmissionProcessPtr MEee2gZ2qq::generateHardest(RealEmissionProcessPtr born, + ShowerInteraction::Type inter) { + return calculateRealEmission(born,false,inter); } double MEee2gZ2qq::meRatio(vector partons, vector momenta, unsigned int iemitter, ShowerInteraction::Type inter, bool subtract) const { Lorentz5Momentum q = momenta[2]+momenta[3]+momenta[4]; Energy2 Q2=q.m2(); Energy2 lambda = sqrt((Q2-sqr(momenta[2].mass()+momenta[3].mass()))* (Q2-sqr(momenta[2].mass()-momenta[3].mass()))); InvEnergy2 D[2]; double lome[2]; for(unsigned int iemit=0;iemit<2;++iemit) { unsigned int ispect = iemit==0 ? 1 : 0; Energy2 pipj = momenta[4 ] * momenta[2+iemit ]; Energy2 pipk = momenta[4 ] * momenta[2+ispect]; Energy2 pjpk = momenta[2+iemit] * momenta[2+ispect]; double y = pipj/(pipj+pipk+pjpk); double z = pipk/( pipk+pjpk); Energy mij = sqrt(2.*pipj+sqr(momenta[2+iemit].mass())); Energy2 lamB = sqrt((Q2-sqr(mij+momenta[2+ispect].mass()))* (Q2-sqr(mij-momenta[2+ispect].mass()))); Energy2 Qpk = q*momenta[2+ispect]; Lorentz5Momentum pkt = lambda/lamB*(momenta[2+ispect]-Qpk/Q2*q) +0.5/Q2*(Q2+sqr(momenta[2+ispect].mass())-sqr(momenta[2+ispect].mass()))*q; Lorentz5Momentum pijt = q-pkt; double muj = momenta[2+iemit ].mass()/sqrt(Q2); double muk = momenta[2+ispect].mass()/sqrt(Q2); double vt = sqrt((1.-sqr(muj+muk))*(1.-sqr(muj-muk)))/(1.-sqr(muj)-sqr(muk)); double v = sqr(2.*sqr(muk)+(1.-sqr(muj)-sqr(muk))*(1.-y))-4.*sqr(muk); if(v<=0.) return 0.; v = sqrt(v)/(1.-y)/(1.-sqr(muj)-sqr(muk)); // dipole term D[iemit] = 0.5/pipj*(2./(1.-(1.-z)*(1.-y)) -vt/v*(2.-z+sqr(momenta[2+iemit].mass())/pipj)); // matrix element vector lomom(4); lomom[0] = momenta[0]; lomom[1] = momenta[1]; if(iemit==0) { lomom[2] = pijt; lomom[3] = pkt ; } else { lomom[3] = pijt; lomom[2] = pkt ; } lome[iemit] = loME(partons,lomom,false)/3.; } InvEnergy2 ratio = realME(partons,momenta,inter) *abs(D[iemitter])/(abs(D[0]*lome[0])+abs(D[1]*lome[1])); double output = Q2*ratio; if(subtract) output -= 2.*Q2*D[iemitter]; return output; } double MEee2gZ2qq::loME(const vector & partons, const vector & momenta, bool first) const { // compute the spinors vector fin,aout; vector ain,fout; SpinorWaveFunction ein (momenta[0],partons[0],incoming); SpinorBarWaveFunction pin (momenta[1],partons[1],incoming); SpinorBarWaveFunction qkout(momenta[2],partons[2],outgoing); SpinorWaveFunction qbout(momenta[3],partons[3],outgoing); for(unsigned int ix=0;ix<2;++ix) { ein.reset(ix) ; fin.push_back( ein ); pin.reset(ix) ; ain.push_back( pin ); qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); } // compute the matrix element double me,lastCont,lastBW; HelicityME(fin,ain,fout,aout,me,lastCont,lastBW); // save the components if(first) { DVector save; save.push_back(lastCont); save.push_back(lastBW); meInfo(save); } // return the answer return me; } InvEnergy2 MEee2gZ2qq::realME(const vector & partons, const vector & momenta, ShowerInteraction::Type inter) const { // compute the spinors vector fin,aout; vector ain,fout; vector gout; SpinorWaveFunction ein (momenta[0],partons[0],incoming); SpinorBarWaveFunction pin (momenta[1],partons[1],incoming); SpinorBarWaveFunction qkout(momenta[2],partons[2],outgoing); SpinorWaveFunction qbout(momenta[3],partons[3],outgoing); VectorWaveFunction gluon(momenta[4],partons[4],outgoing); for(unsigned int ix=0;ix<2;++ix) { ein.reset(ix) ; fin.push_back( ein ); pin.reset(ix) ; ain.push_back( pin ); qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); gluon.reset(2*ix); gout.push_back(gluon); } AbstractFFVVertexPtr vertex = inter == ShowerInteraction::QCD ? FFGVertex_ : FFPVertex_; vector diag(4,0.); ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1); double total(0.); for(unsigned int inhel1=0;inhel1<2;++inhel1) { for(unsigned int inhel2=0;inhel2<2;++inhel2) { // intermediate Z VectorWaveFunction interZ = FFZVertex_->evaluate(scale(),1,Z0_,fin[inhel1],ain[inhel2]); // intermediate photon VectorWaveFunction interG = FFPVertex_->evaluate(scale(),1,gamma_,fin[inhel1],ain[inhel2]); for(unsigned int outhel1=0;outhel1<2;++outhel1) { for(unsigned int outhel2=0;outhel2<2;++outhel2) { for(unsigned int outhel3=0;outhel3<2;++outhel3) { SpinorBarWaveFunction off1 = vertex->evaluate(scale(),3,partons[2],fout[outhel1],gout[outhel3]); diag[0] = FFZVertex_->evaluate(scale(),aout[outhel2],off1,interZ); diag[1] = FFPVertex_->evaluate(scale(),aout[outhel2],off1,interG); SpinorWaveFunction off2 = vertex->evaluate(scale(),3,partons[3],aout[outhel2],gout[outhel3]); diag[2] = FFZVertex_->evaluate(scale(),off2,fout[outhel1],interZ); diag[3] = FFPVertex_->evaluate(scale(),off2,fout[outhel1],interG); // sum of diagrams Complex sum = std::accumulate(diag.begin(),diag.end(),Complex(0.)); // matrix element output(inhel1,inhel2,outhel1,outhel2,outhel3)=sum; // me2 total += norm(sum); } } } } } // spin average total *= 0.25; tcPolarizedBeamPDPtr beam[2] = {dynamic_ptr_cast(partons[0]), dynamic_ptr_cast(partons[1])}; if( beam[0] || beam[1] ) { RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()), beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())}; total = output.average(rho[0],rho[1]); } // divide out the coupling total /= norm(vertex->norm()); // and charge (if needed) if(inter==ShowerInteraction::QED) total /= sqr(double(mePartonData()[2]->iCharge())/3.); // return the total return total*UnitRemoval::InvE2; } diff --git a/MatrixElement/Lepton/MEee2gZ2qq.h b/MatrixElement/Lepton/MEee2gZ2qq.h --- a/MatrixElement/Lepton/MEee2gZ2qq.h +++ b/MatrixElement/Lepton/MEee2gZ2qq.h @@ -1,501 +1,507 @@ // -*- C++ -*- // // MEee2gZ2qq.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_MEee2gZ2qq_H #define HERWIG_MEee2gZ2qq_H // // This is the declaration of the MEee2gZ2qq class. // #include "Herwig/MatrixElement/HwMEBase.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/Rebinder.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; /** * The MEee2gZ2qq class implements the matrix element * for \f$e^+e^-\to Z/\gamma \to q\bar{q}\f$ including spin correlations. * The class includes greater control over the type of quark produced than is available * in the corresponding matrix element from ThePEG, in addition to spin correlations. * * @see \ref MEee2gZ2qqInterfaces "The interfaces" * defined for MEee2gZ2qq. */ class MEee2gZ2qq: public HwMEBase { public: /** * The default constructor. */ MEee2gZ2qq() : minflav_(1), maxflav_(5), massopt_(1), spinCorrelations_(true), pTminQED_(GeV), pTminQCD_(GeV), preFactor_(6.) {} /** * Members for hard corrections to the emission of QCD radiation */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return true;} /** * Initialize the ME correction */ - virtual void initializeMECorrection(ShowerTreePtr, double &, + virtual void initializeMECorrection(RealEmissionProcessPtr, double &, double & ); /** * Apply the hard matrix element correction to a given hard process or decay */ - virtual void applyHardMatrixElementCorrection(ShowerTreePtr); + virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr); /** * Apply the soft matrix element correction * @param initial The particle from the hard process which started the * shower * @param parent The initial particle in the current branching * @param br The branching struct * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial, ShowerParticlePtr parent, Branching br); /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr,ShowerInteraction::Type); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,ShowerInteraction::Type); //@} /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EW}\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; /** * Construct the vertex of spin correlations. */ virtual void constructVertex(tSubProPtr); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Rebind pointer to other Interfaced objects. Called in the setup phase * after all objects used in an EventGenerator has been cloned so that * the pointers will refer to the cloned objects afterwards. * @param trans a TranslationMap relating the original objects to * their respective clones. * @throws RebindException if no cloned object was found for a given * pointer. */ virtual void rebind(const TranslationMap & trans) ; /** * Return a vector of all pointers to Interfaced objects used in this * object. * @return a vector of pointers. */ virtual IVector getReferences(); //@} protected: /** * Calculate the matrix element for \f$e^+e^-\to q \bar{q}\f$. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles * @param first Whether or not to calculate the spin correlations */ double loME(const vector & partons, const vector & momenta, bool first) const; /** * Member to calculate the matrix element * @param fin Spinors for incoming fermion * @param ain Spinors for incoming antifermion * @param fout Spinors for outgoing fermion * @param aout Spinors for outgong antifermion * @param me Spin summed Matrix element * @param cont The continuum piece of the matrix element * @param BW The Z piece of the matrix element */ ProductionMatrixElement HelicityME(vector & fin, vector & ain, vector & fout, vector & aout, double & me, double & cont, double & BW ) const; /** * The ratio of the matrix element for one additional jet over the * leading order result. In practice * \f[\frac{\hat{s}|\overline{\mathcal{M}}|^2_2|D_{\rm emit}|}{4\pi C_F\alpha_S|\overline{\mathcal{M}}|^2_3\left(|D_{\rm emit}|+|D_{\rm spect}|\right)}\f] * is returned where \f$\|\overline{\mathcal{M}}|^2\f$ is * the spin and colour summed/averaged matrix element. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles * @param iemitter Whether the quark or antiquark is regardede as the emitter * @param inter The type of interaction * @param subtract Whether or not to subtract the relevant dipole term */ double meRatio(vector partons, vector momenta, unsigned int iemitter, ShowerInteraction::Type inter, bool subtract =false) const; /** * Calculate the matrix element for \f$e^-e^-\to q \bar q g\f$. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles * @param inter The type of interaction */ InvEnergy2 realME(const vector & partons, const vector & momenta, ShowerInteraction::Type inter) const; private: /** * Generate the momenta for a hard configuration */ pair - generateHard(ShowerTreePtr tree, - vector & emission, - unsigned int & iemit, unsigned int & ispect, - bool applyVeto,ShowerInteraction::Type); + generateHard(RealEmissionProcessPtr, + vector & emission, + unsigned int & iemit, unsigned int & ispect, + bool applyVeto,ShowerInteraction::Type); + + /** + * Calculate the reall emission + */ + RealEmissionProcessPtr calculateRealEmission(RealEmissionProcessPtr born, bool veto, + ShowerInteraction::Type inter); /** * Calculate \f$\tilde{\kappa}\f$. */ double getKfromX(double, double); /** * Vector and axial vector parts of the matrix element */ //@{ /** * Vector part of the matrix element */ double MEV(double, double); /** * The matrix element, given \f$x_1\f$, \f$x_2\f$. * @param x1 \f$x_1\f$ * @param x2 \f$x_2\f$ */ double PS(double x1, double x2); //@} protected: /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFZVertex() const {return FFZVertex_;} /** * Pointer to the fermion-antifermion photon vertex */ AbstractFFVVertexPtr FFPVertex() const {return FFPVertex_;} /** * Pointer to the particle data object for the Z */ PDPtr Z0() const {return Z0_;} /** * Pointer to the particle data object for the photon */ PDPtr gamma() const {return gamma_;} /** * Pointer to the particle data object for the gluon */ PDPtr gluon() const {return gluon_;} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEee2gZ2qq & operator=(const MEee2gZ2qq &); private: /** * Parameters controlling the leading-order process */ //@{ /** * The minimum PDG of the quarks to be produced */ int minflav_; /** * The maximum PDG of the quarks to be produced */ int maxflav_; /** * Option for the treatment of the top quark mass */ unsigned int massopt_; //@} /** * Pointers to the vertices */ //@{ /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFZVertex_; /** * Pointer to the fermion-antifermion photon vertex */ AbstractFFVVertexPtr FFPVertex_; /** * Pointer to the fermion-antifermion photon vertex */ AbstractFFVVertexPtr FFGVertex_; //@} /** * Switch on/off the helivity vertex construction */ bool spinCorrelations_; /** * Pointer to the ParticleData objects */ //@{ /** * Pointer to the particle data object for the Z */ PDPtr Z0_; /** * Pointer to the particle data object for the photon */ PDPtr gamma_; /** * Pointer to the particle data object for the gluon */ PDPtr gluon_; //@} /** * CM energy */ Energy d_Q_; /** * Quark mass */ Energy d_m_; /** * The rho parameter */ double d_rho_; /** * The v parameter */ double d_v_; /** * The initial kappa-tilde values for radiation from the quark */ double d_kt1_; /** * The initial kappa-tilde values for radiation from the antiquark */ double d_kt2_; /** * Cut-off parameter */ static const double EPS_; /** * Pointer to the strong coupling */ ShowerAlphaPtr alphaQCD_; /** * Pointer to the EM coupling */ ShowerAlphaPtr alphaQED_; private: /** * Variables for the POWHEG style corrections */ //@{ /** * The cut off on pt for QED, assuming massless quarks. */ Energy pTminQED_; /** * The cut off on pt for QCD, assuming massless quarks. */ Energy pTminQCD_; /** * Overestimate for the prefactor */ double preFactor_; /** * ParticleData objects for the partons */ vector partons_; /** * Momenta of the leading-order partons */ vector loMomenta_; //@} }; } #endif /* HERWIG_MEee2gZ2qq_H */ diff --git a/MatrixElement/Matchbox/CVolver/ColourFlows.h b/MatrixElement/Matchbox/CVolver/ColourFlows.h --- a/MatrixElement/Matchbox/CVolver/ColourFlows.h +++ b/MatrixElement/Matchbox/CVolver/ColourFlows.h @@ -1,435 +1,435 @@ // -*- C++ -*- // // ColourFlowBasis.hpp is part of CVolver, (C) 2013 Simon Plätzer -- simon.plaetzer@desy.de // CVolver is licenced under version 2 of the GPL, see COPYING for details. // #ifndef CVOLVER_ColourFlowBasis_hpp_included #define CVOLVER_ColourFlowBasis_hpp_included #include #include #include #include #include namespace CVolver { /** * Generate the identical permutation. */ template void iota(ForwardIterator begin, ForwardIterator end, T value) { while ( begin != end ) { *begin = value; value += 1; ++begin; } } /** * Return the identical permutation */ inline std::vector identicalPermutation(const std::size_t n) { std::vector res(n); CVolver::iota(res.begin(),res.end(),0); return res; } /** * Return a random permutation */ template std::vector randomPermutation(const std::size_t n, Rnd& rnd) { std::vector pick = identicalPermutation(n); std::vector res(n); std::size_t count = 0; while ( !pick.empty() ) { std::size_t i = rnd.template uniform_int_distribution(0,pick.size()-1); res[count] = pick[i]; pick.erase(pick.begin()+i); ++count; } return res; } /** * A colour flow (basis tensor). */ class ColourFlow { public: /** * Default constructor */ ColourFlow() {} /** * Construct a colour flow given a permutation */ explicit ColourFlow(const std::vector& perm) : thePermutation(perm) {} /** * Generate a random colour flow */ template static ColourFlow randomFlow(const std::size_t& n, Rnd& rnd) { return ColourFlow(randomPermutation(n,rnd)); } /** * Generate all colour flows */ static std::set allFlows(const std::size_t& n); /** * Compare for equality */ bool operator==(const ColourFlow& other) const { return thePermutation == other.thePermutation; } /** * Compare for inequality */ bool operator!=(const ColourFlow& other) const { return thePermutation != other.thePermutation; } /** * Compare for ordering */ bool operator<(const ColourFlow& other) const { return thePermutation < other.thePermutation; } /** * Conjugate this basis tensor */ ColourFlow& conjugate() { std::vector tmp = thePermutation; for ( std::size_t k = 0; k < tmp.size(); ++k ) { thePermutation[tmp[k]] = k; } return *this; } /** * Return the scalar product with another basis tensor as the * resulting power of N */ std::size_t scalarProduct(const ColourFlow& other) const; /** * Return the permutation */ const std::vector& permutation() const { return thePermutation; } /** * Return the anti-colour index connected to the given colour index */ const std::size_t& antiColour(const std::size_t& i) const { assert(i < thePermutation.size()); return thePermutation[i]; } /** * Return the colour index connected to the given anti-colour index */ std::size_t colour(const std::size_t& i) const { std::vector::const_iterator k = std::find(thePermutation.begin(),thePermutation.end(),i); assert(k != thePermutation.end()); return std::distance(thePermutation.begin(),k); } /** * Return the swapped indices, if this corresponds to a * transposition of the given one, or (0,0) */ std::pair getTranspositionOf(const ColourFlow& other) const; /** * Act a transposition on this index */ ColourFlow& swap(const std::size_t& i, const std::size_t& j) { assert(i < thePermutation.size() && j < thePermutation.size()); std::swap(thePermutation[i],thePermutation[j]); return *this; } /** * Add another flow to this basis tensor; this correspons to * emitting a `singlet' gluon. */ ColourFlow& emitSinglet() { thePermutation.push_back(thePermutation.size()); return *this; } /** * Emit a gluon on a given colour line */ ColourFlow& emitFromColour(const std::size_t& i) { assert(i < thePermutation.size()); thePermutation.push_back(thePermutation[i]); thePermutation[i] = thePermutation.size()-1; return *this; } /** * Emit a gluon on a given anti-colour line */ ColourFlow& emitFromAntiColour(const std::size_t& i) { return emitFromColour(colour(i)); } /** * Return true, if this colour flow is non-vanishing for the given * colours and anticolours */ bool isNonZero(const std::vector& colours, const std::vector& antiColours) const; /** * Return the number of coloured legs */ size_t nLegs() const { return thePermutation.size(); } private: /** * The vector representing the permutation of anti-fundamental * w.r.t. fundamental indices. */ std::vector thePermutation; }; /** * ParticleData traits */ template struct ParticleDataTraits { /** * Return true, if singlet */ static bool isSinglet(const ParticleData&) { return true; } /** * Return true, if anti-fundamental */ static bool isAntiFundamental(const ParticleData&) { return false; } /** * Return true, if fundamental */ static bool isFundamental(const ParticleData&) { return false; } /** * Return true, if adjoint */ static bool isAdjoint(const ParticleData&) { return false; } }; /** * The crossing of a physical process to a colour flow basis */ class ColourFlowCrossing { private: /** * Add colour leg mapping */ void addColourCrossing(const std::size_t& leg, std::size_t& count, - const double& sign) { + double sign) { theColourMap[count] = leg; theColourCrossingSigns[count] = sign; theReverseColourMap[leg] = count; ++count; } /** * Add anti-colour leg mapping */ void addAntiColourCrossing(const std::size_t& leg, std::size_t& count, - const double& sign) { + double sign) { theAntiColourMap[count] = leg; theAntiColourCrossingSigns[count] = sign; theReverseAntiColourMap[leg] = count; ++count; } public: /** * Default constructor */ ColourFlowCrossing() : theNFlows(0) {} /** * Construct for the given process */ template explicit ColourFlowCrossing(const std::vector& proc, bool signs = true) : theNFlows(0) { typedef ParticleDataTraits Traits; std::size_t colourCounter = 0; std::size_t antiColourCounter = 0; for ( std::size_t k = 0; k < proc.size(); ++k ) { if ( Traits::isSinglet(proc[k]) ) continue; double sign = k > 1 ? 1. : -1.; if ( Traits::isAntiFundamental(proc[k]) ) { if ( k > 1 ) addAntiColourCrossing(k,antiColourCounter,signs ? sign : 1.0); else addColourCrossing(k,colourCounter,signs ? sign : 1.0); } if ( Traits::isFundamental(proc[k]) ) { if ( k > 1 ) addColourCrossing(k,colourCounter,signs ? sign : 1.0); else addAntiColourCrossing(k,antiColourCounter,signs ? sign : 1.0); } if ( Traits::isAdjoint(proc[k]) ) { addColourCrossing(k,colourCounter,1.0); addAntiColourCrossing(k,antiColourCounter,1.0); } } theNFlows = colourCounter; } /** * Return the number of colour flows */ const std::size_t& nFlows() const { return theNFlows; } /** * Return the external leg for the given colour */ std::size_t colourLeg(const std::size_t& i) const { std::map::const_iterator l = theColourMap.find(i); assert(l != theColourMap.end()); return l->second; } /** * Return the external leg for the given anti-colour */ std::size_t antiColourLeg(const std::size_t& i) const { std::map::const_iterator l = theAntiColourMap.find(i); assert(l != theAntiColourMap.end()); return l->second; } /** * Return the crossing sign for the given colour */ std::size_t colourCrossingSign(const std::size_t& i) const { std::map::const_iterator l = theColourCrossingSigns.find(i); assert(l != theColourCrossingSigns.end()); return l->second; } /** * Return the crossing sign for the given anti-colour */ double antiColourCrossingSign(const std::size_t& i) const { std::map::const_iterator l = theAntiColourCrossingSigns.find(i); assert(l != theAntiColourCrossingSigns.end()); return l->second; } /** * Return true, if the external line carries colour */ bool coloured(const std::size_t& i) const { return theReverseColourMap.find(i) != theReverseColourMap.end(); } /** * Return the colour line for the given external leg */ std::size_t colourLine(const std::size_t& i) const { std::map::const_iterator l = theReverseColourMap.find(i); assert(l != theReverseColourMap.end()); return l->second; } /** * Return true, if the external line carries anti-colour */ bool antiColoured(const std::size_t& i) const { return theReverseAntiColourMap.find(i) != theReverseAntiColourMap.end(); } /** * Return the anti-colour line for the given external leg */ std::size_t antiColourLine(const std::size_t& i) const { std::map::const_iterator l = theReverseAntiColourMap.find(i); assert(l != theReverseAntiColourMap.end()); return l->second; } private: /** * The number of colour flows */ std::size_t theNFlows; /** * Map colour legs to external legs */ std::map theColourMap; /** * Map anti-colour legs to external legs */ std::map theAntiColourMap; /** * Map external legs to colour legs */ std::map theReverseColourMap; /** * Map external legs to anti-colour legs */ std::map theReverseAntiColourMap; /** * Map colour legs to crossing signs */ std::map theColourCrossingSigns; /** * Map anti-colour legs to crossing signs */ std::map theAntiColourCrossingSigns; }; } #endif // CVOLVER_ColourFlowBasis_hpp_included diff --git a/MatrixElement/Matchbox/External/GoSam/Makefile.am b/MatrixElement/Matchbox/External/GoSam/Makefile.am --- a/MatrixElement/Matchbox/External/GoSam/Makefile.am +++ b/MatrixElement/Matchbox/External/GoSam/Makefile.am @@ -1,18 +1,18 @@ pkglib_LTLIBRARIES = HwMatchboxGoSam.la -HwMatchboxGoSam_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 12:0:0 +HwMatchboxGoSam_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 13:0:0 HwMatchboxGoSam_la_SOURCES = \ GoSamAmplitude.h GoSamAmplitude.cc HwMatchboxGoSam_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DHERWIG_BINDIR="\"$(bindir)\"" \ -DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \ -DGOSAM_PREFIX="\"$(GOSAMPREFIX)\"" EXTRA_DIST = gosam2herwig.py install-exec-local: $(install_sh_SCRIPT) $(srcdir)/gosam2herwig.py $(DESTDIR)$(bindir)/gosam2herwig uninstall-local: rm -f $(DESTDIR)$(bindir)/gosam2herwig diff --git a/MatrixElement/Matchbox/External/MadGraph/Makefile.am b/MatrixElement/Matchbox/External/MadGraph/Makefile.am --- a/MatrixElement/Matchbox/External/MadGraph/Makefile.am +++ b/MatrixElement/Matchbox/External/MadGraph/Makefile.am @@ -1,28 +1,28 @@ pkglib_LTLIBRARIES = HwMatchboxMadGraph.la -HwMatchboxMadGraph_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:1:0 +HwMatchboxMadGraph_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0 HwMatchboxMadGraph_la_SOURCES = \ MadGraphAmplitude.h MadGraphAmplitude.cc madgraphdir = ${pkgdatadir}/MadGraphInterface INPUTFILES = \ InterfaceMadGraph.f.in \ param_card.dat.in \ param_card_heft.dat.in dist_madgraph_DATA = $(INPUTFILES) HwMatchboxMadGraph_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DHERWIG_BINDIR="\"$(bindir)\"" \ -DHERWIG_INCLUDEDIR="\"$(includedir)\"" \ -DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \ -DMADGRAPH_PREFIX="\"$(MADGRAPHPREFIX)\"" EXTRA_DIST = mg2herwig.py install-exec-local: $(install_sh_SCRIPT) $(builddir)/mg2herwig.py $(DESTDIR)$(bindir)/mg2herwig uninstall-local: rm -f $(DESTDIR)$(bindir)/mg2herwig diff --git a/MatrixElement/Matchbox/External/VBFNLO/Makefile.am b/MatrixElement/Matchbox/External/VBFNLO/Makefile.am --- a/MatrixElement/Matchbox/External/VBFNLO/Makefile.am +++ b/MatrixElement/Matchbox/External/VBFNLO/Makefile.am @@ -1,16 +1,16 @@ pkglib_LTLIBRARIES = HwMatchboxVBFNLO.la -HwMatchboxVBFNLO_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0 +HwMatchboxVBFNLO_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:1:0 HwMatchboxVBFNLO_la_CPPFLAGS = $(AM_CPPFLAGS) HwMatchboxVBFNLO_la_CPPFLAGS += -I$(VBFNLOINCLUDE) HwMatchboxVBFNLO_la_CPPFLAGS += -DVBFNLOLIB=$(VBFNLOLIB) #HwMatchboxVBFNLO_la_LIBADD = \ #-L$(VBFNLOLIBS) \ #-lVBFNLO -lVBFNLOAmplitudes -lVBFNLOUtilities -lVBFNLOLoops \ #-lHELAS -lVBFNLOPDFsets -lVBFNLOPhasespace -lVBFspecific -lgfortran HwMatchboxVBFNLO_la_SOURCES = \ VBFNLOAmplitude.h VBFNLOAmplitude.cc \ VBFNLOPhasespace.h VBFNLOPhasespace.cc 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,521 +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; + const double z = vars.second; double Nc = SM().Nc(); // final state branching if ( dipole()->bornEmitter() > 1 ) { // final state quark quark branching if ( abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 7 ) { Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(z)-2.*sqr(m)/(z*qtilde2))/(1.-z); } // final state gluon branching if ( bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == ParticleID::g ) { if ( realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { // ATTENTION the factor 2 here is intentional as it cancels to the 1/2 // stemming from the large-N colour correlator return 2.*Nc*(z/(1.-z)+(1.-z)/z+z*(1.-z)); } if ( abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { Energy m = realCXComb()->mePartonData()[dipole()->realEmission()]->hardProcessMass(); return (1./2.)*(1.-2.*z*(1.-z)+2.*sqr(m)/(z*(1.-z)*qtilde2)); } } // final state squark branching if ((abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) > 1000000 && abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 1000007) || (abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) > 2000000 && abs(bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id()) < 2000007)){ Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return ((sqr(Nc)-1.)/Nc)*(z-sqr(m)/(z*qtilde2))/(1.-z); } // final state gluino branching if (bornCXComb()->mePartonData()[dipole()->bornEmitter()]->id() == 1000021){ Energy m = bornCXComb()->mePartonData()[dipole()->bornEmitter()]->hardProcessMass(); return Nc*(1.+sqr(z)-2.*sqr(m)/(z*qtilde2))/(1.-z); } } // initial state branching if ( dipole()->bornEmitter() < 2 ) { // g/g if ( realCXComb()->mePartonData()[dipole()->realEmitter()]->id() == ParticleID::g && realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { // see above for factor of 2 return 2.*Nc*(z/(1.-z)+(1.-z)/z+z*(1.-z)); } // q/q if ( abs(realCXComb()->mePartonData()[dipole()->realEmitter()]->id()) < 7 && realCXComb()->mePartonData()[dipole()->realEmission()]->id() == ParticleID::g ) { return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(z))/(1.-z); } // g/q if ( realCXComb()->mePartonData()[dipole()->realEmitter()]->id() == ParticleID::g && abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { return (1./2.)*(1.-2.*z*(1.-z)); } // q/g if ( abs(realCXComb()->mePartonData()[dipole()->realEmitter()]->id()) < 7 && abs(realCXComb()->mePartonData()[dipole()->realEmission()]->id()) < 7 ) { return ((sqr(Nc)-1.)/(2.*Nc))*(1+sqr(1.-z))/z; } } return 0.0; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void QTildeMatching::doinit() { assert(theShowerHandler && theQTildeFinder && theQTildeSudakov); theShowerHandler->init(); theQTildeFinder->init(); theQTildeSudakov->init(); hardScaleFactor(theShowerHandler->hardScaleFactor()); factorizationScaleFactor(theShowerHandler->factorizationScaleFactor()); renormalizationScaleFactor(theShowerHandler->renormalizationScaleFactor()); profileScales(theShowerHandler->profileScales()); restrictPhasespace(theShowerHandler->restrictPhasespace()); hardScaleIsMuF(theShowerHandler->hardScaleIsMuF()); ShowerApproximation::doinit(); } void QTildeMatching::doinitrun() { assert(theShowerHandler && theQTildeFinder && theQTildeSudakov); theShowerHandler->initrun(); theQTildeFinder->initrun(); theQTildeSudakov->initrun(); ShowerApproximation::doinitrun(); } void QTildeMatching::persistentOutput(PersistentOStream & os) const { os << theQTildeFinder << theQTildeSudakov << theShowerHandler << theCorrectForXZMismatch; } void QTildeMatching::persistentInput(PersistentIStream & is, int) { is >> theQTildeFinder >> theQTildeSudakov >> theShowerHandler >> theCorrectForXZMismatch; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeHerwigQTildeMatching("Herwig::QTildeMatching", "HwShower.so HwQTildeMatching.so"); void QTildeMatching::Init() { static ClassDocumentation documentation ("QTildeMatching implements NLO matching with the default shower."); static Reference interfaceQTildeFinder ("QTildeFinder", "Set the partner finder to calculate hard scales.", &QTildeMatching::theQTildeFinder, false, false, true, false, false); 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/QTildeMatching.h b/MatrixElement/Matchbox/Matching/QTildeMatching.h --- a/MatrixElement/Matchbox/Matching/QTildeMatching.h +++ b/MatrixElement/Matchbox/Matching/QTildeMatching.h @@ -1,201 +1,201 @@ // -*- C++ -*- // // QTildeMatching.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_QTildeMatching_H #define Herwig_QTildeMatching_H // // This is the declaration of the QTildeMatching class. // #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" #include "Herwig/Shower/ShowerHandler.h" -#include "Herwig/Shower/Default/QTildeFinder.h" -#include "Herwig/Shower/Default/QTildeSudakov.h" +#include "Herwig/Shower/QTilde/Default/QTildeFinder.h" +#include "Herwig/Shower/QTilde/Default/QTildeSudakov.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer * * \brief QTildeMatching implements NLO matching with the default shower. * */ class QTildeMatching: public Herwig::ShowerApproximation { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ QTildeMatching(); /** * The destructor. */ virtual ~QTildeMatching(); //@} public: /** * Return the shower approximation to the real emission cross * section for the given pair of Born and real emission * configurations. */ virtual CrossSection dSigHatDR() const; /** * Return the shower approximation splitting kernel for the given * pair of Born and real emission configurations in units of the * Born center of mass energy squared, and including a weight to * project onto the splitting given by the dipole used. */ virtual double me2() const; /** * Determine if the configuration is below or above the cutoff. */ virtual void checkCutoff(); /** * Determine all kinematic variables which are not provided by the * dipole kinematics; store all shower variables in the respective * dipole object for later use. */ virtual void getShowerVariables(); protected: /** * Return true, if the shower was able to generate an emission * leading from the given Born to the given real emission process. */ virtual bool isInShowerPhasespace() const; /** * Return true, if the shower emission leading from the given Born * to the given real emission process would have been generated * above the shower's infrared cutoff. */ virtual bool isAboveCutoff() const; /** * Calculate qtilde^2 and z for the splitting considered */ void calculateShowerVariables() const; /** * Return the splitting function as a function of the kinematic * variables */ double splitFn(const pair&) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeMatching & operator=(const QTildeMatching &); /** * The shower handler to be used */ Ptr::ptr theShowerHandler; /** * The qtilde partner finder for calculating the hard scales */ Ptr::ptr theQTildeFinder; /** * The qtilde Sudakov to access the cutoff */ Ptr::ptr theQTildeSudakov; /** * True, if PDF weight should be corrected for z/x mismatch at the * hard phase space boundary */ bool theCorrectForXZMismatch; }; } #endif /* Herwig_QTildeMatching_H */ diff --git a/MatrixElement/Powheg/MEPP2GammaGammaPowheg.cc b/MatrixElement/Powheg/MEPP2GammaGammaPowheg.cc --- a/MatrixElement/Powheg/MEPP2GammaGammaPowheg.cc +++ b/MatrixElement/Powheg/MEPP2GammaGammaPowheg.cc @@ -1,2198 +1,2055 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2GammaGammaPowheg class. // #include "MEPP2GammaGammaPowheg.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/Utilities/Maths.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/Branching.h" -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/RealEmissionProcess.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeMEPP2GammaGammaPowheg("Herwig::MEPP2GammaGammaPowheg", "HwMEHadron.so HwPowhegMEHadron.so"); unsigned int MEPP2GammaGammaPowheg::orderInAlphaS() const { return 0; } unsigned int MEPP2GammaGammaPowheg::orderInAlphaEW() const { return 2; } IBPtr MEPP2GammaGammaPowheg::clone() const { return new_ptr(*this); } IBPtr MEPP2GammaGammaPowheg::fullclone() const { return new_ptr(*this); } MEPP2GammaGammaPowheg::MEPP2GammaGammaPowheg() : contrib_(1), power_(0.1), process_(0), threeBodyProcess_(0), maxflavour_(5), alphaS_(0.), fixedAlphaS_(false), supressionFunction_(0), supressionScale_(0), lambda_(20.*GeV), preQCDqqbarq_(5.), preQCDqqbarqbar_(0.5), preQCDqg_(50.), preQCDgqbar_(50.), preQEDqqbarq_(40.), preQEDqqbarqbar_(0.5), preQEDqgq_(1.), preQEDgqbarqbar_(1.), minpT_(2.*GeV), scaleChoice_(0), scalePreFactor_(1.) {} void MEPP2GammaGammaPowheg::getDiagrams() const { tcPDPtr gamma = getParticleData(ParticleID::gamma); tcPDPtr g = getParticleData(ParticleID::g); for(int ix=1;ix<=maxflavour_;++ix) { tcPDPtr qk = getParticleData(ix); tcPDPtr qb = qk->CC(); // gamma gamma if(process_==0 || process_ == 1) { add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 1, gamma, 2, gamma, -1))); add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 2, gamma, 1, gamma, -2))); } // gamma +jet if(process_==0 || process_ == 2) { add(new_ptr((Tree2toNDiagram(3), qk, qb, qb, 1, gamma, 2, g, -4))); add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 2, gamma, 1, g, -5))); add(new_ptr((Tree2toNDiagram(3), qk, qk, g, 1, gamma, 2, qk, -6))); add(new_ptr((Tree2toNDiagram(2), qk, g, 1, qk, 3, gamma, 3, qk, -7))); add(new_ptr((Tree2toNDiagram(3), g, qb, qb, 2, gamma, 1, qb, -8))); add(new_ptr((Tree2toNDiagram(2), g, qb, 1, qb, 3, gamma, 3, qb, -9))); } // gamma + jet + gamma if((process_==0 && contrib_==1) || process_ == 3) { // gamma + g + gamma if(threeBodyProcess_==0 || threeBodyProcess_==1) { add(new_ptr((Tree2toNDiagram(4), qk, qk, qk, qb, 1, gamma, 2, gamma, 3, g, -10))); add(new_ptr((Tree2toNDiagram(4), qk, qk, qk, qb, 3, gamma, 2, gamma, 1, g, -12))); } // Z + q + gamma if(threeBodyProcess_==0 || threeBodyProcess_==2) { add(new_ptr((Tree2toNDiagram(4),qk,qk,qk,g,1,gamma,2,gamma,3,qk, -20))); add(new_ptr((Tree2toNDiagram(4),qk,qk,qk,g,2,gamma,1,gamma,3,qk, -21))); add(new_ptr((Tree2toNDiagram(3),qk,qk,g,1,gamma,2,qk,5,gamma,5,qk,-22))); } // Z + qbar + gamma if(threeBodyProcess_==0 || threeBodyProcess_==3) { add(new_ptr((Tree2toNDiagram(4),g,qb,qb,qb,3,gamma,2,gamma,1,qb ,-30))); add(new_ptr((Tree2toNDiagram(4),g,qb,qb,qb,2,gamma,3,gamma,1,qb ,-31))); add(new_ptr((Tree2toNDiagram(3),g,qb,qb ,2,gamma,1,qb,5,gamma,5,qb,-32))); } } } } Energy2 MEPP2GammaGammaPowheg::scale() const { Energy2 scale; if(scaleChoice_==0) { Energy pt; if(meMomenta()[2].perp(meMomenta()[0].vect())>= meMomenta()[3].perp(meMomenta()[0].vect())){ pt = meMomenta()[2].perp(meMomenta()[0].vect()); } else { pt = meMomenta()[3].perp(meMomenta()[0].vect()); } scale = sqr(pt); } else if(scaleChoice_==1) { scale = sHat(); } return scalePreFactor_*scale; } int MEPP2GammaGammaPowheg::nDim() const { return HwMEBase::nDim() + ( contrib_>=1 ? 3 : 0 ); } bool MEPP2GammaGammaPowheg::generateKinematics(const double * r) { // radiative variables if(contrib_>=1) { zTilde_ = r[nDim()-1]; vTilde_ = r[nDim()-2]; phi_ = Constants::twopi*r[nDim()-3]; } // set the jacobian jacobian(1.0); // set up the momenta for ( int i = 2, N = meMomenta().size(); i < N; ++i ) meMomenta()[i] = Lorentz5Momentum(ZERO); // generate sHat Energy2 shat(sHat()); if(mePartonData().size()==5) { double eps = sqr(meMomenta()[2].mass())/shat; jacobian(jacobian()*(1.-eps)); shat *= eps+zTilde_*(1.-eps); } // momenta of the core process double ctmin = -1.0, ctmax = 1.0; Energy q = ZERO; try { q = SimplePhaseSpace:: getMagnitude(shat, meMomenta()[2].mass(), ZERO); } catch ( ImpossibleKinematics ) { return false; } Energy e = 0.5*sqrt(shat); Energy2 m22 = meMomenta()[2].mass2(); Energy2 e0e2 = 2.0*e*sqrt(sqr(q) + m22); Energy2 e1e2 = 2.0*e*sqrt(sqr(q) + m22); Energy2 e0e3 = 2.0*e*sqrt(sqr(q)); Energy2 e1e3 = 2.0*e*sqrt(sqr(q)); Energy2 pq = 2.0*e*q; if(mePartonData().size()==4) { Energy2 thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[2]); if ( thmin > ZERO ) ctmax = min(ctmax, (e0e2 - m22 - thmin)/pq); thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[2]); if ( thmin > ZERO ) ctmin = max(ctmin, (thmin + m22 - e1e2)/pq); thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[3]); if ( thmin > ZERO ) ctmax = min(ctmax, (e1e3 - thmin)/pq); thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[3]); if ( thmin > ZERO ) ctmin = max(ctmin, (thmin - e0e3)/pq); Energy ptmin = max(lastCuts().minKT(mePartonData()[2]), lastCuts().minKT(mePartonData()[3])); if ( ptmin > ZERO ) { double ctm = 1.0 - sqr(ptmin/q); if ( ctm <= 0.0 ) return false; ctmin = max(ctmin, -sqrt(ctm)); ctmax = min(ctmax, sqrt(ctm)); } double ymin2 = lastCuts().minYStar(mePartonData()[2]); double ymax2 = lastCuts().maxYStar(mePartonData()[2]); double ymin3 = lastCuts().minYStar(mePartonData()[3]); double ymax3 = lastCuts().maxYStar(mePartonData()[3]); double ytot = lastCuts().Y() + lastCuts().currentYHat(); if ( ymin2 + ytot > -0.9*Constants::MaxRapidity ) ctmin = max(ctmin, sqrt(sqr(q) + m22)*tanh(ymin2)/q); if ( ymax2 + ytot < 0.9*Constants::MaxRapidity ) ctmax = min(ctmax, sqrt(sqr(q) + m22)*tanh(ymax2)/q); if ( ymin3 + ytot > -0.9*Constants::MaxRapidity ) ctmax = min(ctmax, tanh(-ymin3)); if ( ymax3 + ytot < 0.9*Constants::MaxRapidity ) ctmin = max(ctmin, tanh(-ymax3)); if ( ctmin >= ctmax ) return false; } double cth = getCosTheta(ctmin, ctmax, r[0]); Energy pt = q*sqrt(1.0-sqr(cth)); phi(rnd(2.0*Constants::pi)); meMomenta()[2].setVect(Momentum3( pt*sin(phi()), pt*cos(phi()), q*cth)); meMomenta()[3].setVect(Momentum3(-pt*sin(phi()), -pt*cos(phi()), -q*cth)); meMomenta()[2].rescaleEnergy(); meMomenta()[3].rescaleEnergy(); // jacobian tHat(pq*cth + m22 - e0e2); uHat(m22 - shat - tHat()); jacobian(pq/shat*Constants::pi*jacobian()); // end for 2->2 processes if(mePartonData().size()==4) { vector out(2); out[0] = meMomenta()[2]; out[1] = meMomenta()[3]; tcPDVector tout(2); tout[0] = mePartonData()[2]; tout[1] = mePartonData()[3]; if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) ) return false; return true; } // special for 2-3 processes pair x = make_pair(lastX1(),lastX2()); // partons pair partons = make_pair(mePartonData()[0],mePartonData()[1]); // If necessary swap the particle data objects so that // first beam gives the incoming quark if(lastPartons().first ->dataPtr()!=partons.first) { swap(x.first,x.second); } // use vTilde to select the dipole for emission // gamma gamma g processes if(mePartonData()[4]->id()==ParticleID::g) { if(vTilde_<=0.5) { dipole_ = IIQCD1; vTilde_ = 4.*vTilde_; } else { dipole_ = IIQCD2; vTilde_ = 4.*(vTilde_-0.25); } jacobian(2.*jacobian()); } // gamma gamma q processes else if(mePartonData()[4]->id()>0&&mePartonData()[4]->id()<6) { if(vTilde_<=1./3.) { dipole_ = IIQCD2; vTilde_ = 3.*vTilde_; } else if(vTilde_<=2./3.) { dipole_ = IFQED1; vTilde_ = 3.*vTilde_-1.; } else { dipole_ = FIQED1; vTilde_ = 3.*vTilde_-2.; } jacobian(3.*jacobian()); } // gamma gamma qbar processes else if(mePartonData()[4]->id()<0&&mePartonData()[4]->id()>-6) { if(vTilde_<=1./3.) { dipole_ = IIQCD1; vTilde_ = 3.*vTilde_; } else if(vTilde_<=2./3.) { dipole_ = IFQED2; vTilde_ = 3.*vTilde_-1.; } else { dipole_ = FIQED2; vTilde_ = 3.*vTilde_-2.; } jacobian(3.*jacobian()); } else { assert(false); } // initial-initial dipoles if(dipole_<=4) { double z = shat/sHat(); double vt = vTilde_*(1.-z); double vJac = 1.-z; Energy pT = sqrt(shat*vt*(1.-vt-z)/z); if(pT pnew(5); pnew [0] = Lorentz5Momentum(ZERO,ZERO,0.5*rs*x.first, 0.5*rs*x.first,ZERO); pnew [1] = Lorentz5Momentum(ZERO,ZERO,-0.5*rs*x.second, 0.5*rs*x.second,ZERO) ; pnew [2] = meMomenta()[2]; pnew [3] = meMomenta()[3]; pnew [4] = Lorentz5Momentum(pT*cos(phi_),pT*sin(phi_), pT*sinh(rapidity), pT*cosh(rapidity), ZERO); pnew[4].rescaleEnergy(); Lorentz5Momentum K = pnew [0]+pnew [1]-pnew [4]; Lorentz5Momentum Kt = pcmf; Lorentz5Momentum Ksum = K+Kt; Energy2 K2 = K.m2(); Energy2 Ksum2 = Ksum.m2(); for(unsigned int ix=2;ix<4;++ix) { pnew [ix].boost(blab); pnew [ix] = pnew [ix] - 2.*Ksum*(Ksum*pnew [ix])/Ksum2 +2*K*(Kt*pnew [ix])/K2; pnew[ix].rescaleEnergy(); } pcmf = Lorentz5Momentum(ZERO,ZERO, 0.5*rs*(x.first-x.second), 0.5*rs*(x.first+x.second)); pcmf.rescaleMass(); blab = pcmf.boostVector(); for(unsigned int ix=0;ix1e-20) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); } if(abs(1.-q.e()/q.vect().mag())>1e-6) rot.boostZ(q.e()/q.vect().mag()); pin *= rot; if(pin.perp2()/GeV2>1e-20) { Boost trans = -1./pin.e()*pin.vect(); trans.setZ(0.); rot.boost(trans); } rot.invert(); Energy Q = sqrt(-q.m2()); meMomenta()[4] = rot*Lorentz5Momentum( 0.5*Q*xT*cos(phi_), 0.5*Q*xT*sin(phi_), -0.5*Q*x2,0.5*Q*sqrt(sqr(x2)+sqr(xT))); meMomenta()[3] = rot*Lorentz5Momentum(-0.5*Q*xT*cos(phi_),-0.5*Q*xT*sin(phi_), -0.5*Q*x3,0.5*Q*sqrt(sqr(x3)+sqr(xT))); double ratio; if(dipole_<=6) { ratio = 2.*((meMomenta()[3]+meMomenta()[4])*meMomenta()[0])/sHat(); } else { ratio = 2.*((meMomenta()[3]+meMomenta()[4])*meMomenta()[1])/sHat(); } jacobian(jacobian()*ratio); } else { assert(false); } vector out(3); tcPDVector tout(3); for(unsigned int ix=0;ix<3;++ix) { out[ix] = meMomenta() [2+ix]; tout[ix] = mePartonData()[2+ix]; } return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]); } double MEPP2GammaGammaPowheg::me2() const { // Born configurations if(mePartonData().size()==4) { // gamma gamma core process if(mePartonData()[3]->id()==ParticleID::gamma) { return 2.*Constants::twopi*alphaEM_* loGammaGammaME(mePartonData(),meMomenta(),true); } // V jet core process else if(mePartonData()[3]->id()==ParticleID::g) { return 2.*Constants::twopi*alphaS_* loGammagME(mePartonData(),meMomenta(),true); } else if(mePartonData()[3]->id()>0) { return 2.*Constants::twopi*alphaS_* loGammaqME(mePartonData(),meMomenta(),true); } else if(mePartonData()[3]->id()<0) { return 2.*Constants::twopi*alphaS_* loGammaqbarME(mePartonData(),meMomenta(),true); } else assert(false); } // hard emission configurations else { if(mePartonData()[4]->id()==ParticleID::g) return sHat()*realGammaGammagME (mePartonData(),meMomenta(),dipole_,Hard,true); else if(mePartonData()[4]->id()>0&&mePartonData()[4]->id()<6) return sHat()*realGammaGammaqME (mePartonData(),meMomenta(),dipole_,Hard,true); else if(mePartonData()[4]->id()<0&&mePartonData()[4]->id()>-6) return sHat()*realGammaGammaqbarME(mePartonData(),meMomenta(),dipole_,Hard,true); else assert(false); } } CrossSection MEPP2GammaGammaPowheg::dSigHatDR() const { // couplings if(!fixedAlphaS_) alphaS_ = SM().alphaS(scale()); alphaEM_ = SM().alphaEM(); // cross section CrossSection preFactor = jacobian()/(16.0*sqr(Constants::pi)*sHat())*sqr(hbarc); loME_ = me2(); if( contrib_== 0 || mePartonData().size()==5 || (mePartonData().size()==4&& mePartonData()[3]->coloured())) return loME_*preFactor; else return NLOWeight()*preFactor; } Selector MEPP2GammaGammaPowheg::diagrams(const DiagramVector & diags) const { if(mePartonData().size()==4) { if(mePartonData()[3]->id()==ParticleID::gamma) { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ){ sel.insert(meInfo()[abs(diags[i]->id())], i); } return sel; } else { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ){ sel.insert(meInfo()[abs(diags[i]->id())%2], i); } return sel; } } else { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { if(abs(diags[i]->id()) == 10 && dipole_ == IIQCD2 ) sel.insert(1., i); else if(abs(diags[i]->id()) == 12 && dipole_ == IIQCD1 ) sel.insert(1., i); else if(abs(diags[i]->id()) == 20 && dipole_ == IIQCD2 ) sel.insert(1., i); else if(abs(diags[i]->id()) == 21 && dipole_ == IFQED1 ) sel.insert(1., i); else if(abs(diags[i]->id()) == 22 && dipole_ == FIQED1 ) sel.insert(1., i); else sel.insert(0., i); } return sel; } } Selector MEPP2GammaGammaPowheg::colourGeometries(tcDiagPtr diag) const { // colour lines for V gamma static ColourLines cs("1 -2"); static ColourLines ct("1 2 -3"); // colour lines for q qbar -> V g static const ColourLines cqqbar[2]={ColourLines("1 -2 5,-3 -5"), ColourLines("1 5,-5 2 -3")}; // colour lines for q g -> V q static const ColourLines cqg [2]={ColourLines("1 2 -3,3 5"), ColourLines("1 -2,2 3 5")}; // colour lines for g qbar -> V qbar static const ColourLines cgqbar[2]={ColourLines("-3 -2 1,-1 -5"), ColourLines("-2 1,-1 -3 -5")}; // colour lines for q qbar -> V gamma g static const ColourLines cqqbarg[4]={ColourLines("1 2 3 7,-4 -7"), ColourLines("1 2 7,-4 3 -7"), ColourLines("1 7,-4 3 2 -7"), ColourLines("1 2 7,-4 3 -7")}; // colour lines for q g -> V gamma q static const ColourLines cqgq [3]={ColourLines("1 2 3 -4,4 7"), ColourLines("1 2 3 -4,4 7"), ColourLines("1 2 -3,3 5 7")}; // colour lines for gbar -> V gamma qbar static const ColourLines cqbargqbar[3]={ColourLines("1 -2 -3 -4,-1 -7"), ColourLines("1 -2 -3 -4,-1 -7"), ColourLines("1 -2 -3,-1 -5 -7")}; Selector sel; switch(abs(diag->id())) { case 1 :case 2 : sel.insert(1.0, &ct); break; case 3 : sel.insert(1.0, &cs); break; case 4 : sel.insert(1.0, &cqqbar[0]); break; case 5: sel.insert(1.0, &cqqbar[1]); break; case 6: sel.insert(1.0, &cqg[0]); break; case 7: sel.insert(1.0, &cqg[1]); break; case 8: sel.insert(1.0, &cgqbar[0]); break; case 9: sel.insert(1.0, &cgqbar[1]); break; case 10: case 11: case 12: case 13: sel.insert(1.0, &cqqbarg[abs(diag->id())-10]); break; case 20: case 21: case 22: sel.insert(1.0, &cqgq[abs(diag->id())-20]); break; case 30: case 31: case 32: sel.insert(1.0, &cqbargqbar[abs(diag->id())-30]); break; default: assert(false); } return sel; } void MEPP2GammaGammaPowheg::persistentOutput(PersistentOStream & os) const { os << FFPvertex_ << FFGvertex_ << contrib_ << power_ << gluon_ << prefactor_ << process_ << threeBodyProcess_<< maxflavour_ << alphaS_ << fixedAlphaS_ << supressionFunction_ << supressionScale_ << ounit(lambda_,GeV) << alphaQCD_ << alphaQED_ << ounit(minpT_,GeV) << preQCDqqbarq_ << preQCDqqbarqbar_ << preQCDqg_ << preQCDgqbar_ << preQEDqqbarq_ << preQEDqqbarqbar_ << preQEDqgq_ << preQEDgqbarqbar_ << scaleChoice_ << scalePreFactor_; } void MEPP2GammaGammaPowheg::persistentInput(PersistentIStream & is, int) { is >> FFPvertex_ >> FFGvertex_ >> contrib_ >> power_ >> gluon_ >> prefactor_ >> process_ >> threeBodyProcess_ >> maxflavour_ >> alphaS_ >> fixedAlphaS_ >> supressionFunction_ >> supressionScale_ >> iunit(lambda_,GeV) >> alphaQCD_ >> alphaQED_ >> iunit(minpT_,GeV) >> preQCDqqbarq_ >> preQCDqqbarqbar_ >> preQCDqg_ >> preQCDgqbar_ >> preQEDqqbarq_ >> preQEDqqbarqbar_ >> preQEDqgq_ >> preQEDgqbarqbar_ >> scaleChoice_ >> scalePreFactor_; } void MEPP2GammaGammaPowheg::Init() { static ClassDocumentation documentation ("TheMEPP2GammaGammaPowheg class implements gamma gamma production at NLO"); static Switch interfaceProcess ("Process", "Which processes to include", &MEPP2GammaGammaPowheg::process_, 0, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all the processes", 0); static SwitchOption interfaceProcessGammaGamma (interfaceProcess, "GammaGamma", "Only include gamma gamma", 1); static SwitchOption interfaceProcessVJet (interfaceProcess, "VJet", "Only include gamma + jet", 2); static SwitchOption interfaceProcessHard (interfaceProcess, "Hard", "Only include hard radiation contributions", 3); static Switch interfaceThreeBodyProcess ("ThreeBodyProcess", "The possible three body processes to include", &MEPP2GammaGammaPowheg::threeBodyProcess_, 0, false, false); static SwitchOption interfaceThreeBodyProcessAll (interfaceThreeBodyProcess, "All", "Include all processes", 0); static SwitchOption interfaceThreeBodyProcessqqbar (interfaceThreeBodyProcess, "qqbar", "Only include q qbar -> gamma gamma g processes", 1); static SwitchOption interfaceThreeBodyProcessqg (interfaceThreeBodyProcess, "qg", "Only include q g -> gamma gamma q processes", 2); static SwitchOption interfaceThreeBodyProcessgqbar (interfaceThreeBodyProcess, "gqbar", "Only include g qbar -> gamma gamma qbar processes", 3); static Switch interfaceContribution ("Contribution", "Which contributions to the cross section to include", &MEPP2GammaGammaPowheg::contrib_, 1, false, false); static SwitchOption interfaceContributionLeadingOrder (interfaceContribution, "LeadingOrder", "Just generate the leading order cross section", 0); static SwitchOption interfaceContributionPositiveNLO (interfaceContribution, "PositiveNLO", "Generate the positive contribution to the full NLO cross section", 1); static SwitchOption interfaceContributionNegativeNLO (interfaceContribution, "NegativeNLO", "Generate the negative contribution to the full NLO cross section", 2); static Parameter interfaceMaximumFlavour ("MaximumFlavour", "The maximum flavour allowed for the incoming quarks", &MEPP2GammaGammaPowheg::maxflavour_, 5, 1, 5, false, false, Interface::limited); static Parameter interfaceAlphaS ("AlphaS", "The value of alphaS to use if using a fixed alphaS", &MEPP2GammaGammaPowheg::alphaS_, 0.118, 0.0, 0.2, false, false, Interface::limited); static Switch interfaceFixedAlphaS ("FixedAlphaS", "Use a fixed value of alphaS", &MEPP2GammaGammaPowheg::fixedAlphaS_, false, false, false); static SwitchOption interfaceFixedAlphaSYes (interfaceFixedAlphaS, "Yes", "Use a fixed alphaS", true); static SwitchOption interfaceFixedAlphaSNo (interfaceFixedAlphaS, "No", "Use a running alphaS", false); static Switch interfaceSupressionFunction ("SupressionFunction", "Choice of the supression function", &MEPP2GammaGammaPowheg::supressionFunction_, 0, false, false); static SwitchOption interfaceSupressionFunctionNone (interfaceSupressionFunction, "None", "Default POWHEG approach", 0); static SwitchOption interfaceSupressionFunctionThetaFunction (interfaceSupressionFunction, "ThetaFunction", "Use theta functions at scale Lambda", 1); static SwitchOption interfaceSupressionFunctionSmooth (interfaceSupressionFunction, "Smooth", "Supress high pT by pt^2/(pt^2+lambda^2)", 2); static Parameter interfaceSupressionScale ("SupressionScale", "The square of the scale for the supression function", &MEPP2GammaGammaPowheg::lambda_, GeV, 20.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Switch interfaceSupressionScaleChoice ("SupressionScaleChoice", "Choice of the supression scale", &MEPP2GammaGammaPowheg::supressionScale_, 0, false, false); static SwitchOption interfaceSupressionScaleChoiceFixed (interfaceSupressionScaleChoice, "Fixed", "Use a fixed scale", 0); static SwitchOption interfaceSupressionScaleChoiceVariable (interfaceSupressionScaleChoice, "Variable", "Use the pT of the hard process as the scale", 1); static Reference interfaceShowerAlphaQCD ("ShowerAlphaQCD", "Reference to the object calculating the QCD coupling for the shower", &MEPP2GammaGammaPowheg::alphaQCD_, false, false, true, false, false); static Reference interfaceShowerAlphaQED ("ShowerAlphaQED", "Reference to the object calculating the QED coupling for the shower", &MEPP2GammaGammaPowheg::alphaQED_, false, false, true, false, false); static Parameter interfacepreQCDqqbarq ("preQCDqqbarq", "The constant for the Sudakov overestimate for the " "q qbar -> V Gamma +g with emission from the q", &MEPP2GammaGammaPowheg::preQCDqqbarq_, 23.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacepreQCDqqbarqbar ("preQCDqqbarqbar", "The constant for the Sudakov overestimate for the " "q qbar -> V Gamma +g with emission from the qbar", &MEPP2GammaGammaPowheg::preQCDqqbarqbar_, 23.0, 0.0, 1000.0, false, false, Interface::limited); static Switch interfaceScaleChoice ("ScaleChoice", "The scale choice to use", &MEPP2GammaGammaPowheg::scaleChoice_, 0, false, false); static SwitchOption interfaceScaleChoicepT (interfaceScaleChoice, "pT", "Use the pT of the photons", 0); static SwitchOption interfaceScaleChoiceMGammaGamma (interfaceScaleChoice, "MGammaGamma", "Use the mass of the photon pair", 1); static Parameter interfaceScalePreFactor ("ScalePreFactor", "Prefactor to change factorization/renormalisation scale", &MEPP2GammaGammaPowheg::scalePreFactor_, 1.0, 0.1, 10.0, false, false, Interface::limited); // prefactor_.push_back(preQCDqg_); // prefactor_.push_back(preQCDgqbar_); // prefactor_.push_back(preQEDqqbarq_); // prefactor_.push_back(preQEDqqbarqbar_); // prefactor_.push_back(preQEDqgq_); // prefactor_.push_back(preQEDgqbarqbar_); } double MEPP2GammaGammaPowheg::NLOWeight() const { // if leading-order return if(contrib_==0) return loME_; // prefactors CFfact_ = 4./3.*alphaS_/Constants::twopi; TRfact_ = 1./2.*alphaS_/Constants::twopi; // scale Energy2 mu2 = scale(); // virtual pieces double virt = CFfact_*subtractedVirtual(); // extract the partons and stuff for the real emission // and collinear counter terms // hadrons pair hadrons= make_pair(dynamic_ptr_cast(lastParticles().first->dataPtr() ), dynamic_ptr_cast(lastParticles().second->dataPtr())); // momentum fractions pair x = make_pair(lastX1(),lastX2()); // partons pair partons = make_pair(mePartonData()[0],mePartonData()[1]); // If necessary swap the particle data objects so that // first beam gives the incoming quark if(lastPartons().first ->dataPtr()!=partons.first) { swap(x.first,x.second); swap(hadrons.first,hadrons.second); } // convert the values of z tilde to z pair z; pair zJac; double rhomax(pow(1.-x.first,1.-power_)); double rho = zTilde_*rhomax; z.first = 1.-pow(rho,1./(1.-power_)); zJac.first = rhomax*pow(1.-z.first,power_)/(1.-power_); rhomax = pow(1.-x.second,1.-power_); rho = zTilde_*rhomax; z.second = 1.-pow(rho,1./(1.-power_)); zJac.second = rhomax*pow(1.-z.second,power_)/(1.-power_); // calculate the PDFs pair oldqPDF = make_pair(hadrons.first ->pdf()->xfx(hadrons.first ,partons.first ,scale(), x.first )/x.first , hadrons.second->pdf()->xfx(hadrons.second,partons.second,scale(), x.second)/x.second); // real/coll q/qbar pair newqPDF = make_pair(hadrons.first ->pdf()->xfx(hadrons.first ,partons.first ,scale(), x.first /z.first )*z.first /x.first , hadrons.second->pdf()->xfx(hadrons.second,partons.second,scale(), x.second/z.second)*z.second/x.second); // real/coll gluon pair newgPDF = make_pair(hadrons.first ->pdf()->xfx(hadrons.first ,gluon_,scale(), x.first /z.first )*z.first /x.first , hadrons.second->pdf()->xfx(hadrons.second,gluon_,scale(), x.second/z.second)*z.second/x.second); // coll terms // g -> q double collGQ = collinearGluon(mu2,zJac.first,z.first, oldqPDF.first,newgPDF.first); // g -> qbar double collGQbar = collinearGluon(mu2,zJac.second,z.second, oldqPDF.second,newgPDF.second); // q -> q double collQQ = collinearQuark(x.first ,mu2,zJac.first ,z.first , oldqPDF.first ,newqPDF.first ); // qbar -> qbar double collQbarQbar = collinearQuark(x.second,mu2,zJac.second,z.second, oldqPDF.second,newqPDF.second); // collinear remnants double coll = collQQ+collQbarQbar+collGQ+collGQbar; // real emission contribution double real1 = subtractedReal(x,z. first,zJac. first,oldqPDF. first, newqPDF. first,newgPDF. first, true); double real2 = subtractedReal(x,z.second,zJac.second,oldqPDF.second, newqPDF.second,newgPDF.second,false); // the total weight double wgt = loME_ + loME_*virt + loME_*coll + real1 + real2; return contrib_ == 1 ? max(0.,wgt) : max(0.,-wgt); } double MEPP2GammaGammaPowheg::loGammaGammaME(const cPDVector & particles, const vector & momenta, bool first) const { double output(0.); // analytic formula for speed if(!first) { Energy2 th = (momenta[0]-momenta[2]).m2(); Energy2 uh = (momenta[0]-momenta[3]).m2(); output = 4./3.*Constants::pi*SM().alphaEM(ZERO)*(th/uh+uh/th)* pow(double(particles[0]->iCharge())/3.,4); } // HE code result else { // wavefunctions for the incoming fermions SpinorWaveFunction em_in( momenta[0],particles[0],incoming); SpinorBarWaveFunction ep_in( momenta[1],particles[1],incoming); // wavefunctions for the outgoing bosons VectorWaveFunction v1_out(momenta[2],particles[2],outgoing); VectorWaveFunction v2_out(momenta[3],particles[3],outgoing); vector f1; vector a1; vector v1,v2; // calculate the wavefunctions for(unsigned int ix=0;ix<2;++ix) { em_in.reset(ix); f1.push_back(em_in); ep_in.reset(ix); a1.push_back(ep_in); v1_out.reset(2*ix); v1.push_back(v1_out); v2_out.reset(2*ix); v2.push_back(v2_out); } vector me(4,0.0); me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1,PDT::Spin1)); vector diag(2,0.0); SpinorWaveFunction inter; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { for(unsigned int ohel1=0;ohel1<2;++ohel1) { for(unsigned int ohel2=0;ohel2<2;++ohel2) { inter = FFPvertex_->evaluate(ZERO,5,f1[ihel1].particle(), f1[ihel1],v1[ohel1]); diag[0] = FFPvertex_->evaluate(ZERO,inter,a1[ihel2],v2[ohel2]); inter = FFPvertex_->evaluate(ZERO,5,f1[ihel1].particle(), f1[ihel1] ,v2[ohel2]); diag[1] = FFPvertex_->evaluate(ZERO,inter,a1[ihel2],v1[ohel1]); // individual diagrams for (size_t ii=0; ii<2; ++ii) me[ii] += std::norm(diag[ii]); // full matrix element diag[0] += diag[1]; output += std::norm(diag[0]); // storage of the matrix element for spin correlations me_(ihel1,ihel2,2*ohel1,2*ohel2) = diag[0]; } } } } // store diagram info, etc. DVector save(3); for (size_t i = 0; i < 3; ++i) save[i] = 0.25 * me[i]; meInfo(save); // spin and colour factors output *= 0.125/3./norm(FFPvertex_->norm()); } return output; } double MEPP2GammaGammaPowheg::loGammaqME(const cPDVector & particles, const vector & momenta, bool first) const { double output(0.); // analytic formula for speed if(!first) { Energy2 sh = (momenta[0]+momenta[1]).m2(); Energy2 th = (momenta[0]-momenta[2]).m2(); Energy2 uh = (momenta[0]-momenta[3]).m2(); output = -1./3./sh/th*(sh*sh+th*th+2.*uh*(sh+th+uh))* 4.*Constants::pi*SM().alphaEM(ZERO)* sqr(particles[0]->iCharge()/3.); } // HE result else { vector fin; vector gin; vector fout; vector vout; SpinorWaveFunction qin (momenta[0],particles[0],incoming); VectorWaveFunction glin(momenta[1],particles[1],incoming); VectorWaveFunction wout(momenta[2],particles[2],outgoing); SpinorBarWaveFunction qout(momenta[3],particles[3],outgoing); // polarization states for the particles for(unsigned int ix=0;ix<2;++ix) { qin.reset(ix) ; fin.push_back(qin); qout.reset(ix); fout.push_back(qout); glin.reset(2*ix); gin.push_back(glin); wout.reset(2*ix); vout.push_back(wout); } me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1, PDT::Spin1,PDT::Spin1Half)); // compute the matrix elements double me[3]={0.,0.,0.}; Complex diag[2]; SpinorWaveFunction inters; SpinorBarWaveFunction interb; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { for(unsigned int ohel1=0;ohel1<2;++ohel1) { // intermediates for the diagrams interb= FFGvertex_->evaluate(scale(),5,particles[3], fout[ohel1],gin[ihel2]); inters= FFGvertex_->evaluate(scale(),5,particles[0], fin[ihel1],gin[ihel2]); for(unsigned int vhel=0;vhel<2;++vhel) { diag[0] = FFPvertex_->evaluate(ZERO,fin[ihel1],interb,vout[vhel]); diag[1] = FFPvertex_->evaluate(ZERO,inters,fout[ohel1],vout[vhel]); // diagram contributions me[1] += norm(diag[0]); me[2] += norm(diag[1]); // total diag[0] += diag[1]; me[0] += norm(diag[0]); me_(ihel1,2*ihel2,2*vhel,ohel1) = diag[0]; } } } } // results // initial state spin and colour average double colspin = 1./24./4.; // and C_F N_c from matrix element colspin *= 4.; DVector save; for(unsigned int ix=0;ix<3;++ix) { me[ix] *= colspin; if(ix>0) save.push_back(me[ix]); } meInfo(save); output = me[0]/norm(FFGvertex_->norm()); } return output; } double MEPP2GammaGammaPowheg::loGammaqbarME(const cPDVector & particles, const vector & momenta, bool first) const { double output(0.); // analytic formula for speed if(!first) { Energy2 sh = (momenta[0]+momenta[1]).m2(); Energy2 uh = (momenta[0]-momenta[2]).m2(); Energy2 th = (momenta[0]-momenta[3]).m2(); output = -1./3./sh/th*(sh*sh+th*th+2.*uh*(sh+th+uh))* 4.*Constants::pi*SM().alphaEM()* sqr(particles[1]->iCharge()/3.); } // HE result else { vector ain; vector gin; vector aout; vector vout; VectorWaveFunction glin (momenta[0],particles[0],incoming); SpinorBarWaveFunction qbin (momenta[1],particles[1],incoming); VectorWaveFunction wout (momenta[2],particles[2],outgoing); SpinorWaveFunction qbout(momenta[3],particles[3],outgoing); // polarization states for the particles for(unsigned int ix=0;ix<2;++ix) { qbin .reset(ix ); ain .push_back(qbin ); qbout.reset(ix ); aout.push_back(qbout); glin.reset(2*ix); gin.push_back(glin); wout.reset(2*ix); vout.push_back(wout); } // if calculation spin corrections construct the me me_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1Half, PDT::Spin1,PDT::Spin1Half)); // compute the matrix elements double me[3]={0.,0.,0.}; Complex diag[2]; SpinorWaveFunction inters; SpinorBarWaveFunction interb; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { for(unsigned int ohel1=0;ohel1<2;++ohel1) { // intermediates for the diagrams inters= FFGvertex_->evaluate(scale(),5,particles[3], aout[ohel1],gin[ihel1]); interb= FFGvertex_->evaluate(scale(),5,particles[1], ain[ihel2],gin[ihel1]); for(unsigned int vhel=0;vhel<2;++vhel) { diag[0]= FFPvertex_->evaluate(ZERO,inters,ain[ihel2],vout[vhel]); diag[1]= FFPvertex_->evaluate(ZERO,aout[ohel1],interb,vout[vhel]); // diagram contributions me[1] += norm(diag[0]); me[2] += norm(diag[1]); // total diag[0] += diag[1]; me[0] += norm(diag[0]); me_(2*ihel1,ihel2,2*vhel,ohel1) = diag[0]; } } } } // results // initial state spin and colour average double colspin = 1./24./4.; // and C_F N_c from matrix element colspin *= 4.; DVector save; for(unsigned int ix=0;ix<3;++ix) { me[ix] *= colspin; if(ix>0) save.push_back(me[ix]); } meInfo(save); output = me[0]/norm(FFGvertex_->norm()); } return output; } double MEPP2GammaGammaPowheg::loGammagME(const cPDVector & particles, const vector & momenta, bool first) const { double output(0.); // analytic formula for speed if(!first) { Energy2 uh = (momenta[0]-momenta[2]).m2(); Energy2 th = (momenta[0]-momenta[3]).m2(); output = 8./9.*double((th*th+uh*uh)/uh/th)* 4.*Constants::pi*SM().alphaEM(ZERO)* sqr(particles[0]->iCharge()/3.); } else { vector fin; vector ain; vector gout; vector vout; SpinorWaveFunction qin (momenta[0],particles[0],incoming); SpinorBarWaveFunction qbin(momenta[1],particles[1],incoming); VectorWaveFunction wout(momenta[2],particles[2],outgoing); VectorWaveFunction glout(momenta[3],particles[3],outgoing); // polarization states for the particles for(unsigned int ix=0;ix<2;++ix) { qin.reset(ix) ; fin.push_back(qin); qbin.reset(ix) ; ain.push_back(qbin); glout.reset(2*ix); gout.push_back(glout); wout.reset(2*ix); vout.push_back(wout); } // if calculation spin corrections construct the me if(first) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1,PDT::Spin1)); // compute the matrix elements double me[3]={0.,0.,0.}; Complex diag[2]; SpinorWaveFunction inters; SpinorBarWaveFunction interb; for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { for(unsigned int ohel1=0;ohel1<2;++ohel1) { // intermediates for the diagrams inters= FFGvertex_->evaluate(scale(),5,particles[0], fin[ihel1],gout[ohel1]); interb= FFGvertex_->evaluate(scale(),5,particles[1], ain[ihel2],gout[ohel1]); for(unsigned int vhel=0;vhel<2;++vhel) { diag[0]= FFPvertex_->evaluate(ZERO,fin[ihel1],interb,vout[vhel]); diag[1]= FFPvertex_->evaluate(ZERO,inters,ain[ihel2],vout[vhel]); // diagram contributions me[1] += norm(diag[0]); me[2] += norm(diag[1]); // total diag[0] += diag[1]; me[0] += norm(diag[0]); if(first) me_(ihel1,ihel2,vhel,2*ohel1) = diag[0]; } } } } // results // initial state spin and colour average double colspin = 1./9./4.; // and C_F N_c from matrix element colspin *= 4.; DVector save; for(unsigned int ix=0;ix<3;++ix) { me[ix] *= colspin; if(ix>0) save.push_back(me[ix]); } meInfo(save); output = me[0]/norm(FFGvertex_->norm()); } return output; } InvEnergy2 MEPP2GammaGammaPowheg:: realGammaGammagME(const cPDVector & particles, const vector & momenta, DipoleType dipole, RadiationType rad, bool ) const { // matrix element double sum = realME(particles,momenta); // loop over the QCD and QCD dipoles InvEnergy2 dipoles[2]; pair supress[2]; // compute the two dipole terms unsigned int iemit = 4, ihard = 3; double x = (momenta[0]*momenta[1]-momenta[iemit]*momenta[1]- momenta[iemit]*momenta[0])/(momenta[0]*momenta[1]); Lorentz5Momentum Kt = momenta[0]+momenta[1]-momenta[iemit]; vector pa(4),pb(4); // momenta for q -> q g/gamma emission pa[0] = x*momenta[0]; pa[1] = momenta[1]; Lorentz5Momentum K = pa[0]+pa[1]; Lorentz5Momentum Ksum = K+Kt; Energy2 K2 = K.m2(); Energy2 Ksum2 = Ksum.m2(); pa[2] = momenta[2]-2.*Ksum*(Ksum*momenta[2])/Ksum2+2*K*(Kt*momenta[2])/K2; pa[2].setMass(momenta[2].mass()); pa[3] = momenta[ihard] -2.*Ksum*(Ksum*momenta[ihard])/Ksum2+2*K*(Kt*momenta[ihard])/K2; pa[3].setMass(ZERO); cPDVector part(particles.begin(),--particles.end()); part[3] = particles[ihard]; // first leading-order matrix element double lo1 = loGammaGammaME(part,pa); // first dipole dipoles[0] = 1./(momenta[0]*momenta[iemit])/x*(2./(1.-x)-(1.+x))*lo1; supress[0] = supressionFunction(momenta[iemit].perp(),pa[3].perp()); // momenta for qbar -> qbar g/gamma emission pb[0] = momenta[0]; pb[1] = x*momenta[1]; K = pb[0]+pb[1]; Ksum = K+Kt; K2 = K.m2(); Ksum2 = Ksum.m2(); pb[2] = momenta[2]-2.*Ksum*(Ksum*momenta[2])/Ksum2+2*K*(Kt*momenta[2])/K2; pb[2].setMass(momenta[2].mass()); pb[3] = momenta[ihard] -2.*Ksum*(Ksum*momenta[ihard])/Ksum2+2*K*(Kt*momenta[ihard])/K2; pb[3].setMass(ZERO); // second LO matrix element double lo2 = loGammaGammaME(part,pb); // second dipole dipoles[1] = 1./(momenta[1]*momenta[iemit])/x*(2./(1.-x)-(1.+x))*lo2; supress[1] = supressionFunction(momenta[iemit].perp(),pb[3].perp()); for(unsigned int ix=0;ix<2;++ix) dipoles[ix] *= 4./3.; // denominator for the matrix element InvEnergy2 denom = abs(dipoles[0]) + abs(dipoles[1]); // contribution if( denom==ZERO || dipoles[(dipole-1)/2]==ZERO ) return ZERO; sum *= abs(dipoles[(dipole-1)/2])/denom; // final coupling factors InvEnergy2 output; if(rad==Subtraction) { output = alphaS_*alphaEM_* (sum*UnitRemoval::InvE2*supress[(dipole-1)/2].first - dipoles[(dipole-1)/2]); } else { output = alphaS_*alphaEM_*sum*UnitRemoval::InvE2; if(rad==Hard) output *=supress[(dipole-1)/2].second; else if(rad==Shower) output *=supress[(dipole-1)/2].first ; } return output; } InvEnergy2 MEPP2GammaGammaPowheg::realGammaGammaqME(const cPDVector & particles, const vector & momenta, DipoleType dipole, RadiationType rad, bool ) const { double sum = realME(particles,momenta); // initial-state QCD dipole double x = (momenta[0]*momenta[1]-momenta[4]*momenta[1]- momenta[4]*momenta[0])/(momenta[0]*momenta[1]); Lorentz5Momentum Kt = momenta[0]+momenta[1]-momenta[4]; vector pa(4); pa[0] = momenta[0]; pa[1] = x*momenta[1]; Lorentz5Momentum K = pa[0]+pa[1]; Lorentz5Momentum Ksum = K+Kt; Energy2 K2 = K.m2(); Energy2 Ksum2 = Ksum.m2(); pa[2] = momenta[2]-2.*Ksum*(Ksum*momenta[2])/Ksum2+2*K*(Kt*momenta[2])/K2; pa[2].setMass(momenta[2].mass()); pa[3] = momenta[3] -2.*Ksum*(Ksum*momenta[3])/Ksum2+2*K*(Kt*momenta[3])/K2; pa[3].setMass(ZERO); cPDVector part(particles.begin(),--particles.end()); part[1] = particles[4]->CC(); double lo1 = loGammaGammaME(part,pa); InvEnergy2 D1 = 0.5/(momenta[1]*momenta[4])/x*(1.-2.*x*(1.-x))*lo1; // initial-final QED dipole vector pb(4); x = 1.-(momenta[3]*momenta[4])/(momenta[4]*momenta[0]+momenta[0]*momenta[3]); pb[3] = momenta[4]+momenta[3]-(1.-x)*momenta[0]; pb[0] = x*momenta[0]; pb[1] = momenta[1]; pb[2] = momenta[2]; double z = momenta[0]*momenta[3]/(momenta[0]*momenta[3]+momenta[0]*momenta[4]); part[1] = particles[1]; part[3] = particles[4]; double lo2 = loGammaqME(part,pb); Energy pT = sqrt(-(pb[0]-pb[3]).m2()*(1.-x)*(1.-z)*z/x); InvEnergy2 DF = 1./(momenta[4]*momenta[3])/x*(1./(1.-x+z)-2.+z)*lo2; InvEnergy2 DI = 1./(momenta[0]*momenta[3])/x*(1./(1.-x+z)-1.-x)*lo2; DI *= sqr(double(particles[0]->iCharge())/3.); DF *= sqr(double(particles[0]->iCharge())/3.); InvEnergy2 denom = abs(D1)+abs(DI)+abs(DF); pair supress; InvEnergy2 term; if ( dipole == IFQED1 ) { term = DI; supress = supressionFunction(pT,pb[3].perp()); } else if( dipole == FIQED1 ) { term = DF; supress = supressionFunction(pT,pb[3].perp()); } else { term = D1; supress = supressionFunction(momenta[4].perp(),pa[3].perp()); } if( denom==ZERO || term == ZERO ) return ZERO; sum *= abs(term)/denom; // final coupling factors InvEnergy2 output; if(rad==Subtraction) { output = alphaS_*alphaEM_* (sum*UnitRemoval::InvE2*supress.first - term); } else { output = alphaS_*alphaEM_*sum*UnitRemoval::InvE2; if(rad==Hard) output *= supress.second; else if(rad==Shower) output *= supress.first ; } // final coupling factors return output; } InvEnergy2 MEPP2GammaGammaPowheg:: realGammaGammaqbarME(const cPDVector & particles, const vector & momenta, DipoleType dipole, RadiationType rad, bool) const { double sum = realME(particles,momenta); // initial-state QCD dipole double x = (momenta[0]*momenta[1]-momenta[4]*momenta[1]-momenta[4]*momenta[0])/ (momenta[0]*momenta[1]); Lorentz5Momentum Kt = momenta[0]+momenta[1]-momenta[4]; vector pa(4); pa[0] = x*momenta[0]; pa[1] = momenta[1]; Lorentz5Momentum K = pa[0]+pa[1]; Lorentz5Momentum Ksum = K+Kt; Energy2 K2 = K.m2(); Energy2 Ksum2 = Ksum.m2(); pa[2] = momenta[2]-2.*Ksum*(Ksum*momenta[2])/Ksum2+2*K*(Kt*momenta[2])/K2; pa[2].setMass(momenta[2].mass()); pa[3] = momenta[3] -2.*Ksum*(Ksum*momenta[3])/Ksum2+2*K*(Kt*momenta[3])/K2; pa[3].setMass(ZERO); cPDVector part(particles.begin(),--particles.end()); part[0] = particles[4]->CC(); double lo1 = loGammaGammaME(part,pa); InvEnergy2 D1 = 0.5/(momenta[0]*momenta[4])/x*(1.-2.*x*(1.-x))*lo1; // initial-final QED dipole vector pb(4); x = 1.-(momenta[3]*momenta[4])/(momenta[4]*momenta[1]+momenta[1]*momenta[3]); pb[3] = momenta[4]+momenta[3]-(1.-x)*momenta[1]; pb[0] = momenta[0]; pb[1] = x*momenta[1]; pb[2] = momenta[2]; double z = momenta[1]*momenta[3]/(momenta[1]*momenta[3]+momenta[1]*momenta[4]); part[0] = particles[0]; part[3] = particles[4]; double lo2 = loGammaqbarME(part,pb); Energy pT = sqrt(-(pb[1]-pb[3]).m2()*(1.-x)*(1.-z)*z/x); InvEnergy2 DF = 1./(momenta[4]*momenta[3])/x*(2./(1.-x+z)-2.+z)*lo2; InvEnergy2 DI = 1./(momenta[0]*momenta[3])/x*(2./(1.-x+z)-1.-x)*lo2; InvEnergy2 term; DI *= sqr(double(particles[1]->iCharge())/3.); DF *= sqr(double(particles[1]->iCharge())/3.); InvEnergy2 denom = abs(D1)+abs(DI)+abs(DF); pair supress; if ( dipole == IFQED2 ) { term = DI; supress = supressionFunction(pT,pb[3].perp()); } else if( dipole == FIQED2 ) { term = DF; supress = supressionFunction(pT,pb[3].perp()); } else { term = D1; supress = supressionFunction(momenta[4].perp(),pa[3].perp()); } if( denom==ZERO || dipole==ZERO ) return ZERO; sum *= abs(term)/denom; // final coupling factors InvEnergy2 output; if(rad==Subtraction) { output = alphaS_*alphaEM_* (sum*UnitRemoval::InvE2*supress.first - term); } else { output = alphaS_*alphaEM_*sum*UnitRemoval::InvE2; if(rad==Hard) output *= supress.second; else if(rad==Shower) output *= supress.first ; } // final coupling factors return output; } double MEPP2GammaGammaPowheg:: realME(const cPDVector & particles, const vector & momenta) const { vector qin; vector qbarin; vector wout,pout,gout; SpinorWaveFunction q_in; SpinorBarWaveFunction qbar_in; VectorWaveFunction g_out; VectorWaveFunction v_out (momenta[2],particles[2],outgoing); VectorWaveFunction p_out (momenta[3],particles[3],outgoing); // q qbar -> gamma gamma g if(particles[4]->id()==ParticleID::g) { q_in = SpinorWaveFunction (momenta[0],particles[0],incoming); qbar_in = SpinorBarWaveFunction (momenta[1],particles[1],incoming); g_out = VectorWaveFunction (momenta[4],particles[4],outgoing); } // q g -> gamma gamma q else if(particles[4]->id()>0) { q_in = SpinorWaveFunction (momenta[0],particles[0],incoming); qbar_in = SpinorBarWaveFunction (momenta[4],particles[4],outgoing); g_out = VectorWaveFunction (momenta[1],particles[1],incoming); } else if(particles[4]->id()<0) { q_in = SpinorWaveFunction (momenta[4],particles[4],outgoing); qbar_in = SpinorBarWaveFunction (momenta[1],particles[1],incoming); g_out = VectorWaveFunction (momenta[0],particles[0],incoming); } else assert(false); for(unsigned int ix=0;ix<2;++ix) { q_in.reset(ix); qin.push_back(q_in); qbar_in.reset(ix); qbarin.push_back(qbar_in); g_out.reset(2*ix); gout.push_back(g_out); p_out.reset(2*ix); pout.push_back(p_out); v_out.reset(2*ix); wout.push_back(v_out); } vector diag(6 , 0.); Energy2 mu2 = scale(); double sum(0.); for(unsigned int ihel1=0;ihel1<2;++ihel1) { for(unsigned int ihel2=0;ihel2<2;++ihel2) { for(unsigned int whel=0;whel<2;++whel) { for(unsigned int phel=0;phel<2;++phel) { for(unsigned int ghel=0;ghel<2;++ghel) { // first diagram SpinorWaveFunction inters1 = FFPvertex_->evaluate(ZERO,5,qin[ihel1].particle(),qin[ihel1],pout[phel]); SpinorBarWaveFunction inters2 = FFPvertex_->evaluate(ZERO,5,qin[ihel1].particle()->CC(), qbarin[ihel2],wout[whel]); diag[0] = FFGvertex_->evaluate(mu2,inters1,inters2,gout[ghel]); // second diagram SpinorWaveFunction inters3 = FFGvertex_->evaluate(mu2,5,qin[ihel1].particle(),qin[ihel1],gout[ghel]); SpinorBarWaveFunction inters4 = FFPvertex_->evaluate(ZERO,5,qbarin[ihel2].particle(), qbarin[ihel2],pout[phel]); diag[1] = FFPvertex_->evaluate(ZERO,inters3,inters4,wout[whel]); // fourth diagram diag[2] = FFPvertex_->evaluate(ZERO,inters3,inters2,pout[phel]); // fifth diagram SpinorBarWaveFunction inters5 = FFGvertex_->evaluate(mu2,5,qbarin[ihel2].particle(), qbarin[ihel2],gout[ghel]); diag[3] = FFPvertex_->evaluate(ZERO,inters1,inters5,wout[whel]); // sixth diagram SpinorWaveFunction inters6 = FFPvertex_->evaluate(ZERO,5,qbarin[ihel2].particle()->CC(), qin[ihel1],wout[whel]); diag[4] = FFGvertex_->evaluate(mu2,inters6,inters4,gout[ghel]); // eighth diagram diag[5] = FFPvertex_->evaluate(ZERO,inters6,inters5,pout[phel]); // sum Complex dsum = std::accumulate(diag.begin(),diag.end(),Complex(0.)); sum += norm(dsum); } } } } } // divide out the em and strong couplings sum /= norm(FFGvertex_->norm()*FFPvertex_->norm()); // final spin and colour factors spin = 1/4 colour = 4/9 if(particles[4]->id()==ParticleID::g) sum /= 9.; // final spin and colour factors spin = 1/4 colour = 4/(3*8) else sum /= 24.; // finally identical particle factor return 0.5*sum; } double MEPP2GammaGammaPowheg::subtractedVirtual() const { double v = 1+tHat()/sHat(); double born = (1-v)/v+v/(1-v); double finite_term = born* (2./3.*sqr(Constants::pi)-3.+sqr(log(v))+sqr(log(1-v))+3.*log(1-v))+ 2.+2.*log(v)+2.*log(1-v)+3.*(1-v)/v*(log(v)-log(1-v))+ (2.+v/(1-v))*sqr(log(v))+(2.+(1-v)/v)*sqr(log(1-v)); double virt = ((6.-(2./3.)*sqr(Constants::pi))* born-2.+finite_term); return virt/born; } double MEPP2GammaGammaPowheg::subtractedReal(pair x, double z, double zJac, double oldqPDF, double newqPDF, double newgPDF,bool order) const { double vt = vTilde_*(1.-z); double vJac = 1.-z; Energy pT = sqrt(sHat()*vt*(1.-vt-z)/z); // rapidities double rapidity; if(order) { rapidity = -log(x.second*sqrt(lastS())/pT*vt); } else { rapidity = log(x.first *sqrt(lastS())/pT*vt); } // CMS system Energy rs=sqrt(lastS()); Lorentz5Momentum pcmf = Lorentz5Momentum(ZERO,ZERO,0.5*rs*(x.first-x.second), 0.5*rs*(x.first+x.second)); pcmf.rescaleMass(); Boost blab(pcmf.boostVector()); // emission from the quark radiation vector pnew(5); if(order) { pnew [0] = Lorentz5Momentum(ZERO,ZERO,0.5*rs*x.first/z, 0.5*rs*x.first/z,ZERO); pnew [1] = Lorentz5Momentum(ZERO,ZERO,-0.5*rs*x.second, 0.5*rs*x.second,ZERO) ; } else { pnew[0] = Lorentz5Momentum(ZERO,ZERO,0.5*rs*x.first, 0.5*rs*x.first,ZERO); pnew[1] = Lorentz5Momentum(ZERO,ZERO,-0.5*rs*x.second/z, 0.5*rs*x.second/z,ZERO) ; } pnew [2] = meMomenta()[2]; pnew [3] = meMomenta()[3]; pnew [4] = Lorentz5Momentum(pT*cos(phi_),pT*sin(phi_), pT*sinh(rapidity), pT*cosh(rapidity), ZERO); Lorentz5Momentum K = pnew [0]+pnew [1]-pnew [4]; Lorentz5Momentum Kt = pcmf; Lorentz5Momentum Ksum = K+Kt; Energy2 K2 = K.m2(); Energy2 Ksum2 = Ksum.m2(); for(unsigned int ix=2;ix<4;++ix) { pnew [ix].boost(blab); pnew [ix] = pnew [ix] - 2.*Ksum*(Ksum*pnew [ix])/Ksum2 +2*K*(Kt*pnew [ix])/K2; } // phase-space prefactors double phase = zJac*vJac/z; // real emission q qbar vector output(4,0.); double realQQ(0.),realGQ(0.); if(!(zTilde_<1e-7 || vt<1e-7 || 1.-z-vt < 1e-7 )) { cPDVector particles(mePartonData()); particles.push_back(gluon_); // calculate the full 2->3 matrix element realQQ = sHat()*phase*newqPDF/oldqPDF* realGammaGammagME(particles,pnew,order ? IIQCD1 : IIQCD2,Subtraction,false); if(order) { particles[0] = gluon_; particles[4] = mePartonData()[0]->CC(); realGQ = sHat()*phase*newgPDF/oldqPDF* realGammaGammaqbarME(particles,pnew,IIQCD2,Subtraction,false); } else { particles[1] = gluon_; particles[4] = mePartonData()[1]->CC(); realGQ = sHat()*phase*newgPDF/oldqPDF* realGammaGammaqME (particles,pnew,IIQCD1,Subtraction,false); } } // return the answer return realQQ+realGQ; } double MEPP2GammaGammaPowheg::collinearQuark(double x, Energy2 mu2, double jac, double z, double oldPDF, double newPDF) const { if(1.-z < 1.e-8) return 0.; return CFfact_*( // this bit is multiplied by LO PDF sqr(Constants::pi)/3.-5.+2.*sqr(log(1.-x )) +(1.5+2.*log(1.-x ))*log(sHat()/mu2) // NLO PDF bit +jac /z * newPDF /oldPDF * (1.-z -(1.+z )*log(sqr(1.-z )/z ) -(1.+z )*log(sHat()/mu2)-2.*log(z )/(1.-z )) // + function bit +jac /z *(newPDF /oldPDF -z )* 2./(1.-z )*log(sHat()*sqr(1.-z )/mu2)); } double MEPP2GammaGammaPowheg::collinearGluon(Energy2 mu2, double jac, double z, double oldPDF, double newPDF) const { if(1.-z < 1.e-8) return 0.; return TRfact_*jac/z*newPDF/oldPDF* ((sqr(z)+sqr(1.-z))*log(sqr(1.-z)*sHat()/z/mu2) +2.*z*(1.-z)); } void MEPP2GammaGammaPowheg::doinit() { HwMEBase::doinit(); vector mopt(2,1); massOption(mopt); // get the vertices we need // get a pointer to the standard model object in the run static const tcHwSMPtr hwsm = dynamic_ptr_cast(standardModel()); if (!hwsm) throw InitException() << "hwsm pointer is null in" << " MEPP2GammaGamma::doinit()" << Exception::abortnow; // get pointers to all required Vertex objects FFPvertex_ = hwsm->vertexFFP(); FFGvertex_ = hwsm->vertexFFG(); gluon_ = getParticleData(ParticleID::g); // sampling factors prefactor_.push_back(preQCDqqbarq_); prefactor_.push_back(preQCDqqbarqbar_); prefactor_.push_back(preQCDqg_); prefactor_.push_back(preQCDgqbar_); prefactor_.push_back(preQEDqqbarq_); prefactor_.push_back(preQEDqqbarqbar_); prefactor_.push_back(preQEDqgq_); prefactor_.push_back(preQEDgqbarqbar_); } -HardTreePtr MEPP2GammaGammaPowheg:: -generateHardest(ShowerTreePtr tree,ShowerInteraction::Type inter) { +RealEmissionProcessPtr MEPP2GammaGammaPowheg:: +generateHardest(RealEmissionProcessPtr born, + ShowerInteraction::Type inter) { beams_.clear(); partons_.clear(); bool QCDAllowed(false),QEDAllowed(false); if(inter==ShowerInteraction::QCD) QCDAllowed = true; else if(inter==ShowerInteraction::QED) QEDAllowed = true; else if(inter==ShowerInteraction::QEDQCD || inter==ShowerInteraction::ALL) { QEDAllowed = true; QCDAllowed = true; } // find the incoming particles - ShowerParticleVector incoming; - // get the particles to be showered - map::const_iterator cit; - vector particlesToShower; - //progenitor particles are produced in z direction. - for( cit = tree->incomingLines().begin(); - cit != tree->incomingLines().end(); ++cit ) { - incoming.push_back( cit->first->progenitor() ); - beams_.push_back( cit->first->beam() ); - partons_.push_back( cit->first->progenitor()->dataPtr() ); - particlesToShower.push_back( cit->first ); + // and get the particles to be showered + ParticleVector incoming,particlesToShower; + pair x; + for(unsigned int ix=0;ixbornIncoming().size();++ix) { + incoming.push_back( born->bornIncoming()[ix] ); + beams_.push_back(dynamic_ptr_cast(born->hadrons()[ix]->dataPtr())); + partons_.push_back( born->bornIncoming()[ix]->dataPtr() ); + particlesToShower.push_back( born->bornIncoming()[ix] ); + if(ix==0) x.first = incoming.back()->momentum().rho()/born->hadrons()[ix]->momentum().rho(); + else x.second = incoming.back()->momentum().rho()/born->hadrons()[ix]->momentum().rho(); } // find the parton which should be first - if( ( particlesToShower[1]->progenitor()->id() > 0 && - particlesToShower[0]->progenitor()->id() < 0 ) || - ( particlesToShower[0]->progenitor()->id() == ParticleID::g && - particlesToShower[1]->progenitor()->id() < 6 && - particlesToShower[1]->progenitor()->id() > 0 ) ) + if( ( particlesToShower[1]->id() > 0 && particlesToShower[0]->id() < 0 ) || + ( particlesToShower[0]->id() == ParticleID::g && + particlesToShower[1]->id() < 6 && particlesToShower[1]->id() > 0 ) ) { swap(particlesToShower[0],particlesToShower[1]); - // check that quark is along +ve z direction - quarkplus_ = particlesToShower[0]->progenitor()->momentum().z() > ZERO; - if( partons_[0]->id() < 0 || - (partons_[0]->id()==ParticleID::g && partons_[1]->id()>0)) { swap(partons_[0],partons_[1]); swap(beams_ [0],beams_ [1]); + swap(x.first ,x.second ); } + // check that quark is along +ve z direction + quarkplus_ = particlesToShower[0]->momentum().z() > ZERO; // outgoing partons - for( map::const_iterator - cjt= tree->outgoingLines().begin(); - cjt != tree->outgoingLines().end();++cjt ) { - particlesToShower.push_back( cjt->first ); + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + particlesToShower.push_back( born->bornOutgoing()[ix] ); } - if(particlesToShower.size()!=4) return HardTreePtr(); + if(particlesToShower.size()!=4) return RealEmissionProcessPtr(); if(particlesToShower[2]->id()!=ParticleID::gamma) swap(particlesToShower[2],particlesToShower[3]); - if(particlesToShower[3]->progenitor()->id()==ParticleID::gamma) { - if(QCDAllowed) return hardQCDEmission(particlesToShower); + if(particlesToShower[3]->id()==ParticleID::gamma) { + if(QCDAllowed) return hardQCDEmission(born,particlesToShower,x); } else { - if(QEDAllowed) return hardQEDEmission(particlesToShower); + if(QEDAllowed) return hardQEDEmission(born,particlesToShower,x); } - return HardTreePtr(); + return born; } -HardTreePtr MEPP2GammaGammaPowheg:: -hardQCDEmission(vector particlesToShower) { +RealEmissionProcessPtr MEPP2GammaGammaPowheg:: +hardQCDEmission(RealEmissionProcessPtr born, + ParticleVector particlesToShower, + pair x) { Energy rootS = sqrt(lastS()); // limits on the rapidity of the jet double minyj = -8.0,maxyj = 8.0; // generate the hard emission - pair x = make_pair(particlesToShower[0]->progenitor()->x(), - particlesToShower[1]->progenitor()->x()); vector pT; Energy pTmax(-GeV); cPDVector selectedParticles; vector selectedMomenta; int iemit(-1); for(unsigned int ix=0;ix<4;++ix) { pT.push_back(0.5*generator()->maximumCMEnergy()); double a = alphaQCD_->overestimateValue()/Constants::twopi* prefactor_[ix]*(maxyj-minyj); cPDVector particles; for(unsigned int iy=0;iyprogenitor()->dataPtr()); + particles.push_back(particlesToShower[iy]->dataPtr()); if(ix<2) particles.push_back(gluon_); else if(ix==2) { particles.push_back(particles[0]->CC()); particles[0] = gluon_; } else { particles.push_back(particles[1]->CC()); particles[1] = gluon_; } vector momenta(5); do { pT[ix] *= pow(UseRandom::rnd(),1./a); double y = UseRandom::rnd()*(maxyj-minyj)+ minyj; double vt,z; if(ix%2==0) { - vt = pT[ix]*exp(-y)/rootS/x.second; - z = (1.-pT[ix]*exp(-y)/rootS/x.second)/(1.+pT[ix]*exp( y)/rootS/x.first ); - if(z>1.||z1.||z1.||z1.||z1.-z || vt<0.) continue; if(ix%2==0) { - momenta[0] = particlesToShower[0]->progenitor()->momentum()/z; - momenta[1] = particlesToShower[1]->progenitor()->momentum(); + momenta[0] = particlesToShower[0]->momentum()/z; + momenta[1] = particlesToShower[1]->momentum(); } else { - momenta[0] = particlesToShower[0]->progenitor()->momentum(); - momenta[1] = particlesToShower[1]->progenitor()->momentum()/z; + momenta[0] = particlesToShower[0]->momentum(); + momenta[1] = particlesToShower[1]->momentum()/z; } double phi = Constants::twopi*UseRandom::rnd(); - momenta[2] = particlesToShower[2]->progenitor()->momentum(); - momenta[3] = particlesToShower[3]->progenitor()->momentum(); + momenta[2] = particlesToShower[2]->momentum(); + momenta[3] = particlesToShower[3]->momentum(); if(!quarkplus_) y *= -1.; momenta[4] = Lorentz5Momentum(pT[ix]*cos(phi),pT[ix]*sin(phi), - pT[ix]*sinh(y),pT[ix]*cosh(y), ZERO); + pT[ix]*sinh(y),pT[ix]*cosh(y), ZERO); Lorentz5Momentum K = momenta[0] + momenta[1] - momenta[4]; Lorentz5Momentum Kt = momenta[2]+momenta[3]; Lorentz5Momentum Ksum = K+Kt; Energy2 K2 = K.m2(), Ksum2 = Ksum.m2(); for(unsigned int iy=2;iy<4;++iy) { - momenta [iy] = momenta [iy] - 2.*Ksum*(Ksum*momenta [iy])/Ksum2 - +2*K*(Kt*momenta [iy])/K2; + momenta [iy] = momenta [iy] - 2.*Ksum*(Ksum*momenta [iy])/Ksum2 + +2*K*(Kt*momenta [iy])/K2; } // matrix element piece double wgt = alphaQCD_->ratio(sqr(pT[ix]))*z/(1.-vt)/prefactor_[ix]/loME_; if(ix==0) - wgt *= sqr(pT[ix])*realGammaGammagME(particles,momenta,IIQCD1,Shower,false); + wgt *= sqr(pT[ix])*realGammaGammagME(particles,momenta,IIQCD1,Shower,false); else if(ix==1) - wgt *= sqr(pT[ix])*realGammaGammagME(particles,momenta,IIQCD2,Shower,false); + wgt *= sqr(pT[ix])*realGammaGammagME(particles,momenta,IIQCD2,Shower,false); else if(ix==2) - wgt *= sqr(pT[ix])*realGammaGammaqbarME(particles,momenta,IIQCD1,Shower,false); + wgt *= sqr(pT[ix])*realGammaGammaqbarME(particles,momenta,IIQCD1,Shower,false); else if(ix==3) - wgt *= sqr(pT[ix])*realGammaGammaqME(particles,momenta,IIQCD2,Shower,false); + wgt *= sqr(pT[ix])*realGammaGammaqME(particles,momenta,IIQCD2,Shower,false); wgt *= 4.*Constants::pi/alphaS_; // pdf piece double pdf[2]; if(ix%2==0) { - pdf[0] = beams_[0]->pdf()->xfx(beams_[0],partons_ [0], - scale(), x.first ) /x.first; - pdf[1] = beams_[0]->pdf()->xfx(beams_[0],particles[0], - scale()+sqr(pT[ix]),x.first /z)*z/x.first; + pdf[0] = beams_[0]->pdf()->xfx(beams_[0],partons_ [0], + scale(), x.first ) /x.first; + pdf[1] = beams_[0]->pdf()->xfx(beams_[0],particles[0], + scale()+sqr(pT[ix]),x.first /z)*z/x.first; } else { - pdf[0] = beams_[1]->pdf()->xfx(beams_[1],partons_ [1], - scale() ,x.second ) /x.second; - pdf[1] = beams_[1]->pdf()->xfx(beams_[1],particles[1], - scale()+sqr(pT[ix]),x.second/z)*z/x.second; + pdf[0] = beams_[1]->pdf()->xfx(beams_[1],partons_ [1], + scale() ,x.second ) /x.second; + pdf[1] = beams_[1]->pdf()->xfx(beams_[1],particles[1], + scale()+sqr(pT[ix]),x.second/z)*z/x.second; } if(pdf[0]<=0.||pdf[1]<=0.) continue; wgt *= pdf[1]/pdf[0]; if(wgt>1.) generator()->log() << "Weight greater than one in " - << "MEPP2GammaGammaPowheg::hardQCDEmission() " - << "for channel " << ix - << " Weight = " << wgt << "\n"; + << "MEPP2GammaGammaPowheg::hardQCDEmission() " + << "for channel " << ix + << " Weight = " << wgt << "\n"; if(UseRandom::rnd()minpT_); if(pT[ix]>minpT_ && pT[ix]>pTmax) { pTmax = pT[ix]; selectedParticles = particles; selectedMomenta = momenta; iemit=ix; } } // if no emission if(pTmaxmaximumpT(minpT_,ShowerInteraction::QCD); - return HardTreePtr(); + born->pT()[ShowerInteraction::QCD] = minpT_; + return born; } // construct the HardTree object needed to perform the showers // create the partons - ShowerParticleVector newparticles; - newparticles.push_back(new_ptr(ShowerParticle(selectedParticles[0],false))); - newparticles.push_back(new_ptr(ShowerParticle(selectedParticles[1],false))); - newparticles.push_back(new_ptr(ShowerParticle(selectedParticles[4], true))); - // set the momenta - for(unsigned int ix=0;ix<2;++ix) - newparticles[ix]->set5Momentum(selectedMomenta[ix]); - newparticles[2]->set5Momentum(selectedMomenta[4]); - // create the off-shell particle - Lorentz5Momentum poff = selectedMomenta[iemit%2] - selectedMomenta[4]; - poff.rescaleMass(); - newparticles.push_back(new_ptr(ShowerParticle(partons_[iemit%2],false))); - newparticles.back()->set5Momentum(poff); + ParticleVector newparticles; + newparticles.push_back(selectedParticles[0]->produceParticle(selectedMomenta[0])); + newparticles.push_back(selectedParticles[1]->produceParticle(selectedMomenta[1])); for(unsigned int ix=2;ix - progenitor()->dataPtr(),true))); - newparticles.back()->set5Momentum(selectedMomenta[ix]); + newparticles.push_back(particlesToShower[ix]->dataPtr()-> + produceParticle(selectedMomenta[ix])); } - vector inBranch,hardBranch; - // create the branchings for the incoming particles - inBranch.push_back(new_ptr(HardBranching(newparticles[0],SudakovPtr(), - HardBranchingPtr(),HardBranching::Incoming))); - inBranch.push_back(new_ptr(HardBranching(newparticles[1],SudakovPtr(), - HardBranchingPtr(),HardBranching::Incoming))); - // intermediate IS particle - hardBranch.push_back(new_ptr(HardBranching(newparticles[3],SudakovPtr(), - inBranch[iemit%2],HardBranching::Incoming))); - inBranch[iemit%2]->addChild(hardBranch.back()); - if(newparticles[3]->id()>0) - inBranch[iemit%2]->type(ShowerPartnerType::QCDColourLine ); - else - inBranch[iemit%2]->type(ShowerPartnerType::QCDAntiColourLine); - // create the branching for the emitted jet - inBranch[iemit%2]->addChild(new_ptr(HardBranching(newparticles[2],SudakovPtr(), - inBranch[iemit%2], - HardBranching::Outgoing))); - // set the colour partners - hardBranch.back()->colourPartner(inBranch[iemit%2==0 ? 1 : 0]); - inBranch[iemit%2==0 ? 1 : 0]->colourPartner(hardBranch.back()); - // add other particle - hardBranch.push_back(inBranch[iemit%2==0 ? 1 : 0]); - // outgoing particles - for(unsigned int ix=4;ixproduceParticle(selectedMomenta[4])); + // identify the type of process + // gluon emission + if(newparticles.back()->id()==ParticleID::g) { + newparticles[4]->incomingColour(newparticles[0]); + newparticles[4]->incomingColour(newparticles[1],true); } - // make the tree - HardTreePtr hardtree=new_ptr(HardTree(hardBranch,inBranch,ShowerInteraction::QCD)); - // connect the ShowerParticles with the branchings - // and set the maximum pt for the radiation - set hard=hardtree->branchings(); - for(unsigned int ix=0;ixmaximumpT(pTmax,ShowerInteraction::QCD); - for(set::const_iterator mit=hard.begin(); - mit!=hard.end();++mit) { - if(particlesToShower[ix]->progenitor()->id()==(*mit)->branchingParticle()->id()&& - (( particlesToShower[ix]->progenitor()->isFinalState()&& - (**mit).status()==HardBranching::Outgoing)|| - (!particlesToShower[ix]->progenitor()->isFinalState()&& - (**mit).status()==HardBranching::Incoming))) { - hardtree->connect(particlesToShower[ix]->progenitor(),*mit); - if((**mit).status()==HardBranching::Incoming) { - (*mit)->beam(particlesToShower[ix]->original()->parents()[0]); - } - HardBranchingPtr parent=(*mit)->parent(); - while(parent) { - parent->beam(particlesToShower[ix]->original()->parents()[0]); - parent=parent->parent(); - }; - } - } + // quark + else if(newparticles.back()->id()>0) { + iemit=1; + newparticles[4]->incomingColour(newparticles[1]); + newparticles[1]-> colourConnect(newparticles[0]); } - ColinePtr newline=new_ptr(ColourLine()); - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) { - if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3) - newline->addColoured((**cit).branchingParticle()); - else if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3bar) - newline->addAntiColoured((**cit).branchingParticle()); + // antiquark + else { + iemit=0; + newparticles[4]->incomingColour(newparticles[0],true); + newparticles[1]-> colourConnect(newparticles[0]); } - // return the tree - return hardtree; + // add incoming + int ispect = iemit==0 ? 1 : 0; + if(particlesToShower[0]==born->bornIncoming()[0]) { + born->incoming().push_back(newparticles[0]); + born->incoming().push_back(newparticles[1]); + } + else { + born->incoming().push_back(newparticles[1]); + born->incoming().push_back(newparticles[0]); + swap(iemit,ispect); + } + // add the outgoing + for(unsigned int ix=2;ixoutgoing().push_back(newparticles[ix]); + // emitter spectator etc + born->emitter (iemit ); + born->spectator(ispect); + born->emitted(4); + // x values + pair xnew; + for(unsigned int ix=0;ix<2;++ix) { + double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); + if(ix==0) xnew.first = x; + else xnew.second = x; + } + born->x(xnew); + // max pT + born->pT()[ShowerInteraction::QCD] = pTmax; + born->interaction(ShowerInteraction::QCD); + // return the process + return born; } -HardTreePtr MEPP2GammaGammaPowheg:: -hardQEDEmission(vector particlesToShower) { +RealEmissionProcessPtr MEPP2GammaGammaPowheg:: +hardQEDEmission(RealEmissionProcessPtr born, + ParticleVector particlesToShower, + pair x) { // return if not emission from quark - if(particlesToShower[0]->progenitor()->id()!=ParticleID::g && - particlesToShower[1]->progenitor()->id()!=ParticleID::g ) - return HardTreePtr(); + if(particlesToShower[0]->id()!=ParticleID::g && + particlesToShower[1]->id()!=ParticleID::g ) + return RealEmissionProcessPtr(); // generate the hard emission - pair x = make_pair(particlesToShower[0]->progenitor()->x(), - particlesToShower[1]->progenitor()->x()); vector pT; Energy pTmax(-GeV); cPDVector selectedParticles; vector selectedMomenta; int iemit(-1); pair mewgt(make_pair(0.,0.)); for(unsigned int ix=0;ixprogenitor()->dataPtr()); - selectedMomenta.push_back(particlesToShower[ix]->progenitor()->momentum()); + selectedParticles.push_back(particlesToShower[ix]->dataPtr()); + selectedMomenta.push_back(particlesToShower[ix]->momentum()); } selectedParticles.push_back(getParticleData(ParticleID::gamma)); swap(selectedParticles[3],selectedParticles[4]); selectedMomenta.push_back(Lorentz5Momentum()); swap(selectedMomenta[3],selectedMomenta[4]); Lorentz5Momentum pin,pout; double xB; unsigned int iloc; - if(particlesToShower[0]->progenitor()->dataPtr()->charged()) { - pin = particlesToShower[0]->progenitor()->momentum(); + if(particlesToShower[0]->dataPtr()->charged()) { + pin = particlesToShower[0]->momentum(); xB = x.first; iloc = 6; } else { - pin = particlesToShower[1]->progenitor()->momentum(); + pin = particlesToShower[1]->momentum(); xB = x.second; iloc = 7; } - pout = particlesToShower[3]->progenitor()->momentum(); + pout = particlesToShower[3]->momentum(); Lorentz5Momentum q = pout-pin; Axis axis(q.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot = LorentzRotation(); if(axis.perp2()>1e-20) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); } if(abs(1.-q.e()/q.vect().mag())>1e-6) rot.boostZ(q.e()/q.vect().mag()); Lorentz5Momentum ptemp = rot*pin; if(ptemp.perp2()/GeV2>1e-20) { Boost trans = -1./ptemp.e()*ptemp.vect(); trans.setZ(0.); rot.boost(trans); } rot.invert(); Energy Q = sqrt(-q.m2()); double xT = sqrt((1.-xB)/xB); double xTMin = 2.*minpT_/Q; double wgt(0.); double a = alphaQED_->overestimateValue()*prefactor_[iloc]/Constants::twopi; Lorentz5Momentum p1,p2,p3; do { wgt = 0.; // intergration variables dxT/xT^3 xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT)); // dz double zp = UseRandom::rnd(); double xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp)); if(xT1.) continue; // phase-space piece of the weight wgt = 4.*sqr(1.-xp)*(1.-zp)*zp/prefactor_[iloc]/loME_; // coupling Energy2 pT2 = 0.25*sqr(Q*xT); wgt *= alphaQED_->ratio(pT2); // matrix element wgt *= 4.*Constants::pi/alphaEM_; // PDF double pdf[2]; if(iloc==6) { pdf[0] = beams_[0]->pdf()-> - xfx(beams_[0],partons_[0],scale() ,x.first ); + xfx(beams_[0],partons_[0],scale() ,x.first ); pdf[1] = beams_[0]->pdf()-> - xfx(beams_[0],partons_[0],scale()+pT2,x.first /xp); + xfx(beams_[0],partons_[0],scale()+pT2,x.first /xp); } else { pdf[0] = beams_[1]->pdf()-> - xfx(beams_[1],partons_[1],scale() ,x.second ); + xfx(beams_[1],partons_[1],scale() ,x.second ); pdf[1] = beams_[1]->pdf()-> - xfx(beams_[1],partons_[1],scale()+pT2,x.second/xp); + xfx(beams_[1],partons_[1],scale()+pT2,x.second/xp); } if(pdf[0]<=0.||pdf[1]<=0.) { wgt = 0.; continue; } wgt *= pdf[1]/pdf[0]; // matrix element piece double phi = Constants::twopi*UseRandom::rnd(); double x2 = 1.-(1.-zp)/xp; double x3 = 2.-1./xp-x2; p1=Lorentz5Momentum(ZERO,ZERO,0.5*Q/xp,0.5*Q/xp,ZERO); p2=Lorentz5Momentum( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi), - -0.5*Q*x2,0.5*Q*sqrt(sqr(xT)+sqr(x2))); + -0.5*Q*x2,0.5*Q*sqrt(sqr(xT)+sqr(x2))); p3=Lorentz5Momentum(-0.5*Q*xT*cos(phi),-0.5*Q*xT*sin(phi), - -0.5*Q*x3,0.5*Q*sqrt(sqr(xT)+sqr(x3))); + -0.5*Q*x3,0.5*Q*sqrt(sqr(xT)+sqr(x3))); selectedMomenta[iloc-6] = rot*p1; selectedMomenta[3] = rot*p3; selectedMomenta[4] = rot*p2; if(iloc==6) { mewgt.first = - sqr(Q)*realGammaGammaqME(selectedParticles,selectedMomenta,IFQED1,Shower,false); + sqr(Q)*realGammaGammaqME(selectedParticles,selectedMomenta,IFQED1,Shower,false); mewgt.second = - sqr(Q)*realGammaGammaqME(selectedParticles,selectedMomenta,FIQED1,Shower,false); + sqr(Q)*realGammaGammaqME(selectedParticles,selectedMomenta,FIQED1,Shower,false); wgt *= mewgt.first+mewgt.second; } else { mewgt.first = - sqr(Q)*realGammaGammaqbarME(selectedParticles,selectedMomenta,IFQED2,Shower,false); + sqr(Q)*realGammaGammaqbarME(selectedParticles,selectedMomenta,IFQED2,Shower,false); mewgt.second = - sqr(Q)*realGammaGammaqbarME(selectedParticles,selectedMomenta,FIQED2,Shower,false); + sqr(Q)*realGammaGammaqbarME(selectedParticles,selectedMomenta,FIQED2,Shower,false); wgt *= mewgt.first+mewgt.second; } if(wgt>1.) generator()->log() << "Weight greater than one in " - << "MEPP2GammaGammaPowheg::hardQEDEmission() " - << "for IF channel " - << " Weight = " << wgt << "\n"; + << "MEPP2GammaGammaPowheg::hardQEDEmission() " + << "for IF channel " + << " Weight = " << wgt << "\n"; } while(xT>xTMin&&UseRandom::rnd()>wgt); // if no emission if(xTmaximumpT(minpT_,ShowerInteraction::QED); - return HardTreePtr(); + born->pT()[ShowerInteraction::QED] = minpT_; + return born; } pTmax = 0.5*xT*Q; iemit = mewgt.first>mewgt.second ? 2 : 3; - // construct the HardTree object needed to perform the showers + // construct the object needed to perform the showers // create the partons - ShowerParticleVector newparticles; - newparticles.push_back(new_ptr(ShowerParticle(selectedParticles[0],false))); - newparticles.push_back(new_ptr(ShowerParticle(selectedParticles[1],false))); - newparticles.push_back(new_ptr(ShowerParticle(selectedParticles[3], true))); - // set the momenta - for(unsigned int ix=0;ix<2;++ix) - newparticles[ix]->set5Momentum(selectedMomenta[ix]); - newparticles[2]->set5Momentum(selectedMomenta[3]); - // create the off-shell particle - if(iemit==2) { - if(particlesToShower[0]->progenitor()->dataPtr()->charged()) { - Lorentz5Momentum poff = selectedMomenta[0] - selectedMomenta[3]; - poff.rescaleMass(); - newparticles.push_back(new_ptr(ShowerParticle(partons_[0],false))); - newparticles.back()->set5Momentum(poff); - } - else { - Lorentz5Momentum poff = selectedMomenta[1] - selectedMomenta[3]; - poff.rescaleMass(); - newparticles.push_back(new_ptr(ShowerParticle(partons_[1],false))); - newparticles.back()->set5Momentum(poff); - } + ParticleVector newparticles; + newparticles.push_back(selectedParticles[0]->produceParticle(selectedMomenta[0])); + newparticles.push_back(selectedParticles[1]->produceParticle(selectedMomenta[1])); + for(unsigned int ix=2;ix + dataPtr()->produceParticle(selectedMomenta[ix==2 ? 2 : 4 ])); } - else if(iemit==3) { - Lorentz5Momentum poff = selectedMomenta[3]+selectedMomenta[4]; - poff.rescaleMass(); - newparticles.push_back(new_ptr(ShowerParticle(particlesToShower[3] - ->progenitor()->dataPtr(),true))); - newparticles.back()->set5Momentum(poff); - } - else - assert(false); - for(unsigned int ix=2;ix - progenitor()->dataPtr(),true))); - newparticles.back()->set5Momentum(selectedMomenta[ix==2 ? 2 : 4 ]); - } - vector inBranch,hardBranch; - // create the branchings for the incoming particles - inBranch.push_back(new_ptr(HardBranching(newparticles[0],SudakovPtr(), - HardBranchingPtr(),HardBranching::Incoming))); - inBranch.push_back(new_ptr(HardBranching(newparticles[1],SudakovPtr(), - HardBranchingPtr(),HardBranching::Incoming))); - if(iemit<3) { - int icharged = iemit; - if(icharged==2) icharged = particlesToShower[0]->progenitor()-> - dataPtr()->charged() ? 0 : 1; - // intermediate IS particle - hardBranch.push_back(new_ptr(HardBranching(newparticles[3],SudakovPtr(), - inBranch[icharged],HardBranching::Incoming))); - inBranch[icharged]->addChild(hardBranch.back()); - inBranch[icharged]->type(ShowerPartnerType::QED); - // create the branching for the emitted jet - inBranch[icharged]->addChild(new_ptr(HardBranching(newparticles[2],SudakovPtr(), - inBranch[icharged], - HardBranching::Outgoing))); - // set the colour partners - if(iemit<2) { - hardBranch.back()->colourPartner(inBranch[icharged==0 ? 1 : 0]); - inBranch[icharged==0 ? 1 : 0]->colourPartner(hardBranch.back()); - } - // add other particle - hardBranch.push_back(inBranch[icharged == 0 ? 1 : 0]); - // outgoing particles - for(unsigned int ix=4;ixcolourPartner(hardBranch[0]); - hardBranch[0]->colourPartner(hardBranch.back()); - } + newparticles.push_back(selectedParticles[3]->produceParticle(selectedMomenta[3])); + // make the colour connections + bool col = newparticles[3]->id()<0; + if(particlesToShower[0]->dataPtr()->charged()) { + newparticles[3]->incomingColour(newparticles[1],col); + newparticles[1]->colourConnect (newparticles[0],col); } else { - for(unsigned int ix=0;ix<2;++ix) - hardBranch.push_back(inBranch[ix]); - hardBranch.push_back(new_ptr(HardBranching(newparticles[4],SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - hardBranch.push_back(new_ptr(HardBranching(newparticles[3],SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - hardBranch.back()->type(ShowerPartnerType::QED); - hardBranch.back()->addChild(new_ptr(HardBranching(newparticles[5],SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - hardBranch.back()->addChild(new_ptr(HardBranching(newparticles[2],SudakovPtr(), - HardBranchingPtr(), - HardBranching::Outgoing))); - if(hardBranch[0]->branchingParticle()->dataPtr()->charged()) { - hardBranch.back()->colourPartner(hardBranch[0]); - hardBranch[0]->colourPartner(hardBranch.back()); - } - else { - hardBranch.back()->colourPartner(hardBranch[1]); - hardBranch[1]->colourPartner(hardBranch.back()); - } + newparticles[3]->incomingColour(newparticles[0],col); + newparticles[0]->colourConnect (newparticles[1],col); } - // make the tree - HardTreePtr hardtree=new_ptr(HardTree(hardBranch,inBranch,ShowerInteraction::QED)); - // connect the ShowerParticles with the branchings - // and set the maximum pt for the radiation - set hard=hardtree->branchings(); - for(unsigned int ix=0;ixmaximumpT(pTmax,ShowerInteraction::QED); - for(set::const_iterator mit=hard.begin(); - mit!=hard.end();++mit) { - if(particlesToShower[ix]->progenitor()->id()==(*mit)->branchingParticle()->id()&& - (( particlesToShower[ix]->progenitor()->isFinalState()&& - (**mit).status()==HardBranching::Outgoing)|| - (!particlesToShower[ix]->progenitor()->isFinalState()&& - (**mit).status()==HardBranching::Incoming))) { - hardtree->connect(particlesToShower[ix]->progenitor(),*mit); - if((**mit).status()==HardBranching::Incoming) { - (*mit)->beam(particlesToShower[ix]->original()->parents()[0]); - } - HardBranchingPtr parent=(*mit)->parent(); - while(parent) { - parent->beam(particlesToShower[ix]->original()->parents()[0]); - parent=parent->parent(); - }; - } - } + bool FSR = iemit==3; + // add incoming particles + if(particlesToShower[0]==born->bornIncoming()[0]) { + born->incoming().push_back(newparticles[0]); + born->incoming().push_back(newparticles[1]); } - ColinePtr newline1 = new_ptr(ColourLine()); - ColinePtr newline2 = new_ptr(ColourLine()); - HardBranchingPtr gluon,quark,antiQuark; - for(set::const_iterator cit=hardtree->branchings().begin(); - cit!=hardtree->branchings().end();++cit) { - if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour8) { - gluon = *cit; - if((**cit).status()==HardBranching::Incoming) { - newline1->addColoured ((**cit).branchingParticle()); - newline2->addAntiColoured((**cit).branchingParticle()); - } - else { - newline2->addColoured ((**cit).branchingParticle()); - newline1->addAntiColoured((**cit).branchingParticle()); - } - } - else if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3) { - if((**cit).status()==HardBranching::Incoming) { - antiQuark = *cit; - newline2->addColoured((**cit).branchingParticle()); - } - else { - quark = *cit; - newline1->addColoured((**cit).branchingParticle()); - } - } - else if((**cit).branchingParticle()->dataPtr()->iColour()==PDT::Colour3bar) { - if((**cit).status()==HardBranching::Incoming) { - quark = *cit; - newline1->addAntiColoured((**cit).branchingParticle()); - } - else { - antiQuark = *cit; - newline2->addAntiColoured((**cit).branchingParticle()); - } - } + else { + born->incoming().push_back(newparticles[1]); + born->incoming().push_back(newparticles[0]); } - assert(quark&&antiQuark&&gluon); - gluon->colourPartner(UseRandom::rndbool() ? quark : antiQuark); - // return the tree - return hardtree; + // IS radiatng particle + unsigned int iemitter = born->incoming()[0]->dataPtr()->charged() ? 0 : 1; + // add outgoing particles + if(particlesToShower[2]==born->bornOutgoing()[0]) { + born->outgoing().push_back(newparticles[2]); + born->outgoing().push_back(newparticles[3]); + } + else { + born->outgoing().push_back(newparticles[3]); + born->outgoing().push_back(newparticles[2]); + } + born->outgoing().push_back(newparticles[4]); + // outgoing radiating particle + unsigned int ispectator = born->outgoing()[0]->dataPtr()->charged() ? 2 : 3; + // get emitter and spectator right + if(FSR) swap(iemitter,ispectator); + born->emitter (iemitter ); + born->spectator(ispectator); + born->emitted(4); + // x values + pair xnew; + for(unsigned int ix=0;ix<2;++ix) { + double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); + if(ix==0) xnew.first = x; + else xnew.second = x; + } + born->x(xnew); + // max pT + born->pT()[ShowerInteraction::QED] = pTmax; + // return the process + born->interaction(ShowerInteraction::QED); + return born; } diff --git a/MatrixElement/Powheg/MEPP2GammaGammaPowheg.h b/MatrixElement/Powheg/MEPP2GammaGammaPowheg.h --- a/MatrixElement/Powheg/MEPP2GammaGammaPowheg.h +++ b/MatrixElement/Powheg/MEPP2GammaGammaPowheg.h @@ -1,537 +1,542 @@ // -*- C++ -*- #ifndef HERWIG_MEPP2GammaGammaPowheg_H #define HERWIG_MEPP2GammaGammaPowheg_H // // This is the declaration of the MEPP2GammaGammaPowheg class. // #include "Herwig/MatrixElement/HwMEBase.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the MEPP2GammaGammaPowheg class. * * @see \ref MEPP2GammaGammaPowhegInterfaces "The interfaces" * defined for MEPP2GammaGammaPowheg. */ class MEPP2GammaGammaPowheg: public HwMEBase { enum DipoleType { IIQCD1=2, IIQCD2=4, IFQED1=5, FIQED1=6, IFQED2=7, FIQED2=8 }; enum RadiationType {Subtraction,Hard,Shower}; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ MEPP2GammaGammaPowheg(); //@} /** @name Member functions for the generation of hard QCD radiation */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return ISR;} /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr,ShowerInteraction::Type); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, + ShowerInteraction::Type); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EW}\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * The number of internal degrees of freedom used in the matrix * element. */ virtual int nDim() const; /** * Generate internal degrees of freedom given nDim() uniform * random numbers in the interval \f$ ]0,1[ \f$. To help the phase space * generator, the dSigHatDR should be a smooth function of these * numbers, although this is not strictly necessary. * @param r a pointer to the first of nDim() consecutive random numbers. * @return true if the generation succeeded, otherwise false. */ virtual bool generateKinematics(const double * r); /** * Return the matrix element squared differential in the variables * given by the last call to generateKinematics(). */ virtual CrossSection dSigHatDR() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; //@} 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: /** * Calculate of the full next-to-leading order weight */ virtual double NLOWeight() const; /** * Leading-order matrix element for \f$q\bar q\to \gamma\gamma\f$ */ double loGammaGammaME(const cPDVector & particles, const vector & momenta, bool first=false) const; /** * Leading-order matrix element for \f$qg\to \gamma q\f$ */ double loGammaqME(const cPDVector & particles, const vector & momenta, bool first=false) const; /** * Leading-order matrix element for \f$g\bar q\to \gamma \bar q\f$ */ double loGammaqbarME(const cPDVector & particles, const vector & momenta, bool first=false) const; /** * Leading-order matrix element for \f$q\bar q\to \gamma g\f$ */ double loGammagME(const cPDVector & particles, const vector & momenta, bool first=false) const; /** * Real emission matrix element for \f$q\bar q\to \gamma \gamma g\f$ */ InvEnergy2 realGammaGammagME(const cPDVector & particles, const vector & momenta, DipoleType dipole, RadiationType rad, bool first=false) const; /** * Real emission matrix element for \f$qg\to \gamma \gamma q\f$ */ InvEnergy2 realGammaGammaqME(const cPDVector & particles, const vector & momenta, DipoleType dipole, RadiationType rad, bool first=false) const; /** * Real emission matrix element for \f$g\bar q\to \gamma \gamma \bar q\f$ */ InvEnergy2 realGammaGammaqbarME(const cPDVector & particles, const vector & momenta, DipoleType dipole, RadiationType rad, bool first=false) const; /** * The dipole subtractedvirtual contribution */ double subtractedVirtual() const; /** * Subtracted real contribution */ double subtractedReal(pair x, double z, double zJac, double oldqPDF, double newqPDF, double newgPDF,bool order) const; /** * Calculate of the collinear counterterms */ //@{ /** * Quark collinear counter term */ double collinearQuark(double x, Energy2 mu2, double jac, double z, double oldPDF, double newPDF) const; /** * Gluon collinear counter term */ double collinearGluon(Energy2 mu2, double jac, double z, double oldPDF, double newPDF) const; //@} /** * The real matrix element divided by \f$2 g_S^2\f$, to be implemented in the * inheriting classes. * @param particles The ParticleData objects of the particles * @param momenta The momenta of the particles */ double realME(const cPDVector & particles, const vector & momenta) const; /** * Generate hard QCD emission */ - HardTreePtr hardQCDEmission(vector); + RealEmissionProcessPtr hardQCDEmission(RealEmissionProcessPtr, + ParticleVector, + pair); /** * Generate hard QED emission */ - HardTreePtr hardQEDEmission(vector); + RealEmissionProcessPtr hardQEDEmission(RealEmissionProcessPtr, + ParticleVector, + pair); /** * The supression function */ pair supressionFunction(Energy pT,Energy scale) const { if(supressionScale_==0) scale = lambda_; Energy2 scale2 = sqr(scale), pT2 = sqr(pT); switch( supressionFunction_ ) { case 0: return make_pair(1.,0.); case 1: if(pT < scale ) return make_pair(1.,0.); else return make_pair(0.,1.); case 2: return make_pair(scale2/(pT2+scale2),pT2/(pT2+scale2)); default: assert(false); } } 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEPP2GammaGammaPowheg & operator=(const MEPP2GammaGammaPowheg &); private: /** * Vertices */ //@{ /** * FFPVertex */ AbstractFFVVertexPtr FFPvertex_; /** * FFGVertex */ AbstractFFVVertexPtr FFGvertex_; //@} /** * Kinematic variables for the real radiation */ //@{ /** * First variable */ mutable double zTilde_; /** * Second variable */ mutable double vTilde_; /** * Azimuthal angle */ mutable double phi_; //@} /** * Whether to generate the positive, negative or leading order contribution */ unsigned int contrib_; /** * Power for sampling \f$x_p\f$ */ double power_; /** * Pointer to the gluon ParticleData object */ tcPDPtr gluon_; /** * Processes */ unsigned int process_; /** * Processes */ unsigned int threeBodyProcess_; /** * Allowed flavours of the incoming quarks */ int maxflavour_; /** * Factor for \f$C_F\f$ dependent pieces */ mutable double CFfact_; /** * Factor for \f$T_R\f$ dependent pieces */ mutable double TRfact_; /** * Strong coupling */ mutable double alphaS_; /** * Use a fixed value of \f$\alpha_S\f$ */ bool fixedAlphaS_; /** * Electromagnetic coupling */ mutable double alphaEM_; /** * Leading-order matrix element */ mutable double loME_; /** * The matrix element */ mutable ProductionMatrixElement me_; /** * the selected dipole */ mutable DipoleType dipole_; /** * Supression Function */ //@{ /** * Choice of the supression function */ unsigned int supressionFunction_; /** * Choice for the scale in the supression function */ unsigned int supressionScale_; /** * Scalar for the supression function */ Energy lambda_; //@} /** * Hard emission stuff */ //@{ /** * Whether the quark is in the + or - z direction */ bool quarkplus_; //@} /** * Properties of the incoming particles */ //@{ /** * Pointers to the BeamParticleData objects */ vector beams_; /** * Pointers to the ParticleDataObjects for the partons */ vector partons_; //@} /** * Constants for the sampling. The distribution is assumed to have the * form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$ */ //@{ /** * The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel */ double preQCDqqbarq_; /** * The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel */ double preQCDqqbarqbar_; /** * The prefactor, \f$c\f$ for the \f$qg\f$ channel */ double preQCDqg_; /** * The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel */ double preQCDgqbar_; double preQEDqqbarq_; double preQEDqqbarqbar_; double preQEDqgq_; double preQEDgqbarqbar_; /** * The prefactors as a vector for easy use */ vector prefactor_; //@} /** * The transverse momentum of the jet */ Energy minpT_; /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alphaQCD_; /** * Pointer to the object calculating the EM */ ShowerAlphaPtr alphaQED_; /** * Scale choice */ unsigned int scaleChoice_; /** * Scale factor */ double scalePreFactor_; }; } #endif /* HERWIG_MEPP2GammaGammaPowheg_H */ diff --git a/MatrixElement/Powheg/MEPP2HiggsVBFPowheg.cc b/MatrixElement/Powheg/MEPP2HiggsVBFPowheg.cc --- a/MatrixElement/Powheg/MEPP2HiggsVBFPowheg.cc +++ b/MatrixElement/Powheg/MEPP2HiggsVBFPowheg.cc @@ -1,722 +1,722 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2HiggsVBFPowheg class. // #include "MEPP2HiggsVBFPowheg.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "Herwig/PDT/StandardMatchers.h" #include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" //ACDC test //#include "ThePEG/Repository/UseRandom.h" using namespace Herwig; MEPP2HiggsVBFPowheg::MEPP2HiggsVBFPowheg() : scaleOpt_(1), muF_(100.*GeV), scaleFact_(1.), contrib_(1), power_(0.1) {} int MEPP2HiggsVBFPowheg::nDim() const { //ACDC test // return 0; return MEPP2HiggsVBF::nDim()+3; } //ACDC test (delete r) bool MEPP2HiggsVBFPowheg::generateKinematics(const double * r) { //bool MEPP2HiggsVBFPowheg::generateKinematics(const double * ) { int ndim = nDim(); //ACDC test double r3 = r[ndim-3]; //double r3 = UseRandom::rnd(); // Born kinematics //ACDC test (comment next line out) if(!MEPP2HiggsVBF::generateKinematics(r)) return false; // hadron and momentum fraction // set Q2 process momenta if(r3 > 0.5) { r3 = 2.*(r3-0.5); if(lastPartons().first ->dataPtr()==mePartonData()[0]&& lastPartons().second->dataPtr()==mePartonData()[1]) { _hadron = dynamic_ptr_cast(lastParticles().first->dataPtr()); _xB = lastX1(); } else { _hadron = dynamic_ptr_cast(lastParticles().second->dataPtr()); _xB = lastX2(); } _partons[0] = mePartonData()[0]; _partons[1] = mePartonData()[1]; _partons[4] = mePartonData()[4]; if(!swapOrder()) { _pb = meMomenta()[0]; _pc = meMomenta()[2]; _pbother = meMomenta()[1]; _pcother = meMomenta()[3]; _partons[2] = mePartonData()[2]; _partons[3] = mePartonData()[3]; } else { _pb = meMomenta()[0]; _pc = meMomenta()[3]; _pbother = meMomenta()[1]; _pcother = meMomenta()[2]; _partons[2] = mePartonData()[3]; _partons[3] = mePartonData()[2]; } } else { r3 = 2.*r3; if(lastPartons().first ->dataPtr()==mePartonData()[0]&& lastPartons().second->dataPtr()==mePartonData()[1]) { _hadron = dynamic_ptr_cast(lastParticles().second->dataPtr()); _xB = lastX2(); } else { _hadron = dynamic_ptr_cast(lastParticles().first->dataPtr()); _xB = lastX1(); } _partons[0] = mePartonData()[1]; _partons[1] = mePartonData()[0]; _partons[4] = mePartonData()[4]; if(!swapOrder()) { _pb = meMomenta()[1]; _pc = meMomenta()[3]; _pbother = meMomenta()[0]; _pcother = meMomenta()[2]; _partons[2] = mePartonData()[3]; _partons[3] = mePartonData()[2]; } else { _pb = meMomenta()[1]; _pc = meMomenta()[2]; _pbother = meMomenta()[0]; _pcother = meMomenta()[3]; _partons[2] = mePartonData()[2]; _partons[3] = mePartonData()[3]; } } // LO Momenta assignment _loMomenta[0] = _pb; _loMomenta[1] = _pbother; _loMomenta[2] = _pc; _loMomenta[3] = _pcother; _pa = _pc-_pb; // xp double rhomin = pow(1.-_xB,1.-power_); //ACDC test double rho = r[ndim-1]*rhomin; //double rho = UseRandom::rnd()*rhomin; _xp = 1.-pow(rho,1./(1.-power_)); // zp //ACDC test _zp = r[ndim-2]; //_zp = UseRandom::rnd(); // phi _phi = r3*Constants::twopi; jac_ = rhomin/(1.-power_)*pow(1.-_xp,power_); return true; } IBPtr MEPP2HiggsVBFPowheg::clone() const { return new_ptr(*this); } IBPtr MEPP2HiggsVBFPowheg::fullclone() const { return new_ptr(*this); } void MEPP2HiggsVBFPowheg::persistentOutput(PersistentOStream & os) const { os << ounit(muF_,GeV) << scaleFact_ << scaleOpt_ << contrib_ << ounit(_mz2,GeV2) << ounit(_mw2,GeV2) << power_; } void MEPP2HiggsVBFPowheg::persistentInput(PersistentIStream & is, int) { is >> iunit(muF_,GeV) >> scaleFact_ >> scaleOpt_ >> contrib_ >> iunit(_mz2,GeV2) >> iunit(_mw2,GeV2) >> power_; } ClassDescription MEPP2HiggsVBFPowheg::initMEPP2HiggsVBFPowheg; // Definition of the static class description member. void MEPP2HiggsVBFPowheg::Init() { static ClassDocumentation documentation ("The MENeutralCurrentDISPowheg class implements the NLO matrix element" " for neutral current DIS in the Powheg scheme."); static Switch interfaceContribution ("Contribution", "Which contributions to the cross section to include", &MEPP2HiggsVBFPowheg::contrib_, 1, false, false); static SwitchOption interfaceContributionLeadingOrder (interfaceContribution, "LeadingOrder", "Just generate the leading order cross section", 0); static SwitchOption interfaceContributionPositiveNLO (interfaceContribution, "PositiveNLO", "Generate the positive contribution to the full NLO cross section", 1); static SwitchOption interfaceContributionNegativeNLO (interfaceContribution, "NegativeNLO", "Generate the negative contribution to the full NLO cross section", 2); static Switch interfaceScaleOption ("ScaleOption", "Option for the choice of factorization (and renormalization) scale", &MEPP2HiggsVBFPowheg::scaleOpt_, 1, false, false); static SwitchOption interfaceDynamic (interfaceScaleOption, "Dynamic", "Dynamic factorization scale equal to the current sqrt(sHat())", 1); static SwitchOption interfaceFixed (interfaceScaleOption, "Fixed", "Use a fixed factorization scale set with FactorizationScaleValue", 2); static Parameter interfaceFactorizationScale ("FactorizationScale", "Value to use in the event of a fixed factorization scale", &MEPP2HiggsVBFPowheg::muF_, GeV, 100.0*GeV, 1.0*GeV, 500.0*GeV, true, false, Interface::limited); static Parameter interfaceScaleFactor ("ScaleFactor", "The factor used before Q2 if using a running scale", &MEPP2HiggsVBFPowheg::scaleFact_, 1.0, 0.0, 10.0, false, false, Interface::limited); static Parameter interfaceSamplingPower ("SamplingPower", "Power for the sampling of xp", &MEPP2HiggsVBFPowheg::power_, 0.6, 0.0, 1., false, false, Interface::limited); } Energy2 MEPP2HiggsVBFPowheg::scale() const { return scaleOpt_ == 1 ? sqr(scaleFact_)*MEPP2HiggsVBF::scale() : sqr(scaleFact_*muF_); } CrossSection MEPP2HiggsVBFPowheg::dSigHatDR() const { return NLOWeight()*MEPP2HiggsVBF::dSigHatDR(); } double MEPP2HiggsVBFPowheg::NLOWeight() const { // If only leading order is required return 1: if(contrib_==0) return 1.; // Boost Axis axis(_pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot = LorentzRotation(); if(axis.perp2()>1e-20) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); } if(abs(1.-_pa.e()/_pa.vect().mag())>1e-6) rot.boostZ(_pa.e()/_pa.vect().mag()); _pb *= rot; if(_pb.perp2()/GeV2>1e-20) { Boost trans = -1./_pb.e()*_pb.vect(); trans.setZ(0.); rot.boost(trans); } // momenta of particles Lorentz5Momentum p1, p2,p1other,p2other; _pa *= rot; _q2 = -_pa.m2(); p1 = rot*_loMomenta[0]; p2 = rot*_loMomenta[2]; p1other = rot*_loMomenta[1]; p2other = rot*_loMomenta[3]; // scale and prefactors Energy2 mu2 = scale(); Energy Q = sqrt(_q2); // double aS = 2.*SM().alphaS(mu2); double aS = 2*0.113291076960184; double CFfact = 4./3.*aS/Constants::twopi; double TRfact = 1./2.*aS/Constants::twopi; double wgt = 0.; // Breit frame variables double x1 = -1./_xp; double x2 = 1.-(1.-_zp)/_xp; double x3 = 2.+x1-x2; double xT = 2*sqrt((1.-_xp)*(1.-_zp)*_zp/_xp); vector nloMomenta; nloMomenta.resize(3); nloMomenta[0] = Lorentz5Momentum(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1); nloMomenta[1] = Lorentz5Momentum( 0.5*Q*xT*cos(_phi), 0.5*Q*xT*sin(_phi), -0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2))); nloMomenta[2] = Lorentz5Momentum(-0.5*Q*xT*cos(_phi), -0.5*Q*xT*sin(_phi), -0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3))); Lorentz5Momentum qnlo = nloMomenta[2]+nloMomenta[1]-nloMomenta[0]; Lorentz5Momentum r1 = -nloMomenta[0]/x1; Lorentz5Momentum r2 = nloMomenta[1]/x2; Lorentz5Momentum r3 = -nloMomenta[2]/x3; // LO + dipole subtracted virtual + collinear quark bit with LO pdf double virt = 1.+CFfact*(-4.5-1./3.*sqr(Constants::pi)+ 1.5*log(_q2/mu2/(1.-_xB))+ 2.*log(1.-_xB)*log(_q2/mu2)+ sqr(log(1.-_xB))); // PDF from leading-order double loPDF = _hadron->pdf()->xfx(_hadron,_partons[0],mu2,_xB)/_xB; // NLO gluon PDF tcPDPtr gluon = getParticleData(ParticleID::g); double gPDF = _hadron->pdf()->xfx(_hadron,gluon,mu2,_xB/_xp)*_xp/_xB; // NLO quark PDF double qPDF = _hadron->pdf()->xfx(_hadron,_partons[0],mu2,_xB/_xp)*_xp/_xB; // collinear counterterms // gluon double collg = TRfact/_xp*gPDF*(2.*_xp*(1.-_xp)+(sqr(_xp)+sqr(1.-_xp))* log((1.-_xp)*_q2/_xp/mu2)); // quark double collq = CFfact/_xp*qPDF*(1-_xp-2./(1.-_xp)*log(_xp)-(1.+_xp)* log((1.-_xp)/_xp*_q2/mu2))+ CFfact/_xp*(qPDF-_xp*loPDF)*(2./(1.-_xp)* log(_q2*(1.-_xp)/mu2)-1.5/(1.-_xp)); // Electroweak coefficients double c0L,c1L,c0R,c1R; //Energy2 mb2; // W if(_partons[0]->id()!=_partons[2]->id()) { //mb2 = _mw2; c0L = sqrt(0.5); c0R = 0; c1L = sqrt(0.5); c1R = 0; } // Z else { //mb2 = _mz2; if(abs(_partons[0]->id())%2==0) { c0L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c0R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c0L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c0R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } if(abs(_partons[1]->id())%2==0) { c1L = generator()->standardModel()->vu()+ generator()->standardModel()->au(); c1R = generator()->standardModel()->vu()- generator()->standardModel()->au(); } else { c1L = generator()->standardModel()->vd()+ generator()->standardModel()->ad(); c1R = generator()->standardModel()->vd()- generator()->standardModel()->ad(); } c0L *= 0.25; c0R *= 0.25; c1L *= 0.25; c1R *= 0.25; } // Matrix element variables double G1 = sqr(c0L*c1L)+sqr(c0R*c1R); double G2 = sqr(c0L*c1R)+sqr(c0R*c1L); Energy4 term1,term2,term3,loME; if(_partons[0]->id()>0) { if(_partons[1]->id()>0) { term1 = loMatrixElement(r1 ,p1other,qnlo+r1,p2other,G1,G2); term2 = loMatrixElement(r2-qnlo,p1other,r2 ,p2other,G1,G2); term3 = loMatrixElement(r3 ,p1other,qnlo+r3,p2other,G1,G2); loME = loMatrixElement(p1 ,p1other,p2 ,p2other,G1,G2); } else { term1 = loMatrixElement(r1 ,p2other,qnlo+r1,p1other,G1,G2); term2 = loMatrixElement(r2-qnlo,p2other,r2 ,p1other,G1,G2); term3 = loMatrixElement(r3 ,p2other,qnlo+r3,p1other,G1,G2); loME = loMatrixElement(p1 ,p2other,p2 ,p1other,G1,G2); } } else { if(_partons[1]->id()>0) { term1 = loMatrixElement(qnlo+r1,p1other,r1 ,p2other,G1,G2); term2 = loMatrixElement(r2 ,p1other,r2-qnlo,p2other,G1,G2); term3 = loMatrixElement(qnlo+r3,p1other,r3 ,p2other,G1,G2); loME = loMatrixElement(p2 ,p1other,p1 ,p2other,G1,G2); } else { term1 = loMatrixElement(qnlo+r1,p2other,r1 ,p1other,G1,G2); term2 = loMatrixElement(r2 ,p2other,r2-qnlo,p1other,G1,G2); term3 = loMatrixElement(qnlo+r3,p2other,r3 ,p1other,G1,G2); loME = loMatrixElement(p2 ,p2other,p1 ,p1other,G1,G2); } } if(1-_xp > 1e-10 && 1.-_zp > 1e-10){ // q -> qg term double real1 = (term1+sqr(_xp)*sqr(x2)*term2)/loME; double dipole1 = (sqr(_xp)+sqr(_zp)); double realq = CFfact*qPDF/loPDF/_xp/((1.-_xp)*(1.-_zp))*(real1-dipole1); // g -> q qbar term double real2 = sqr(_xp)/loME*(sqr(x2)*term2+sqr(x3)*term3); double dipole2 = sqr(_xp)+sqr(1.-_xp); double realg = TRfact*gPDF/loPDF/_xp/(1.-_zp)*(real2-dipole2); // Return The Full Result wgt = virt+jac_*((collq+collg)/loPDF+realq+realg); } return contrib_ == 1 ? max(0.,wgt) : max(0.,-wgt); } void MEPP2HiggsVBFPowheg::doinit() { MEPP2HiggsVBF::doinit(); // electroweak parameters _mz2 = sqr(getParticleData(ParticleID::Z0)->mass()); _mw2 = sqr(getParticleData(ParticleID::Wplus)->mass()); tcPDPtr gluon = getParticleData(ParticleID::g); } Energy4 MEPP2HiggsVBFPowheg:: loMatrixElement(const Lorentz5Momentum &p1, const Lorentz5Momentum &p2, const Lorentz5Momentum &q1, const Lorentz5Momentum &q2, double G1, double G2) const { return G1*(p1*p2)*(q1*q2) + G2*(p1*q2)*(q1*p2); } // double g; // g = 1./sqrt(SM().sin2ThetaW()); // g = 1./sqrt((1.-SM().sin2ThetaW())*SM().sin2ThetaW()); // vector f1,f2; // vector a1,a2; // Lorentz5Momentum phiggs = rot*meMomenta()[4]; // ScalarWaveFunction higgs(phiggs,mePartonData()[4],1.,outgoing); // SpinorWaveFunction fin1,fin2; // SpinorBarWaveFunction ain1,ain2; // if(_partons[0]->id()>0) { // fin1 = SpinorWaveFunction(nloMomenta[0],_partons[0],incoming); // ain1 = SpinorBarWaveFunction(nloMomenta[1],_partons[2],outgoing); // } // else { // fin1 = SpinorWaveFunction(nloMomenta[1],_partons[2],outgoing); // ain1 = SpinorBarWaveFunction(nloMomenta[0],_partons[0],incoming); // } // if(_partons[1]->id()>0) { // fin2 = SpinorWaveFunction(p1other,_partons[1],incoming); // ain2 = SpinorBarWaveFunction(p2other,_partons[3],outgoing); // } // else { // fin2 = SpinorWaveFunction(p2other,_partons[3],outgoing); // ain2 = SpinorBarWaveFunction(p1other,_partons[1],incoming); // } // VectorWaveFunction gwave(nloMomenta[2],gluon,outgoing); // vector g1; // for(unsigned int ix=0;ix<2;++ix) { // fin1.reset(ix); f1.push_back(fin1); // fin2.reset(ix); f2.push_back(fin2); // ain1.reset(ix); a1.push_back(ain1); // ain2.reset(ix); a2.push_back(ain2); // gwave.reset(2*ix); g1.push_back(gwave); // } // AbstractFFVVertexPtr vertex[2]; // tcPDPtr vec[2]; // for(unsigned int ix=0;ix<2;++ix) { // int icharge; // icharge = _partons[ix]->iCharge()-_partons[ix+2]->iCharge(); // if(icharge==0) vec[ix] = _z0; // else if(icharge>0) vec[ix] = _wplus; // else vec[ix] = _wminus; // vertex[ix] = vec[ix]==_z0 ? _vertexFFZ : _vertexFFW; // } // tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); // AbstractFFVVertexPtr gvertex = hwsm->vertexFFG(); // VectorWaveFunction inter[2]; // Complex diag[2]; // double me(0.); // nloMomenta[0].setMass(ZERO); // nloMomenta[1].setMass(ZERO); // nloMomenta[2].setMass(ZERO); // for(unsigned int i1=0;i1<2;++i1) { // unsigned int i2=i1; // // wavefunction for the 1st intermediate vector // inter[0] = vertex[1]->evaluate(scale(),1,vec[1],f2[i1],a2[i2]); // for(unsigned int i3=0;i3<2;++i3) { // unsigned int i4=i3; // for(unsigned int ig=0;ig<2;++ig) { // SpinorWaveFunction soff = // gvertex->evaluate(scale(),5,f1[i3].getParticle(), // f1[i3],g1[ig]); // SpinorBarWaveFunction aoff = // gvertex->evaluate(scale(),5,a1[i4].getParticle(), // a1[i4],g1[ig]); // inter[1] = vertex[0]->evaluate(scale(),1,vec[0],soff,a1[i4]); // diag[0] = _vertexWWH->evaluate(scale(),inter[0],inter[1],higgs); // inter[1] = vertex[0]->evaluate(scale(),1,vec[0],f1[i3],aoff); // diag[1] = _vertexWWH->evaluate(scale(),inter[0],inter[1],higgs); // // cerr << "testing helicity " // // << i1 << " " << i2 << " " << i3 << " " << i4 << " " // // << ig << " " << (diag[0]+diag[1])/(abs(diag[0])+abs(diag[1])) // // << "\n"; // me += norm(diag[0]+diag[1]); // } // } // } // // spin factor // me *=0.25; // cerr << "testing the quark emission " // << fact*8.*Constants::pi*SM().alphaS(scale())/(-1.-x1)/(1.-x2)/_q2 // *(sqr(x1)*term1+sqr(x2)*term2)*sqr(MeV2)/me << "\n"; // vector f1,f2; // vector a1,a2; // Lorentz5Momentum phiggs = rot*meMomenta()[4]; // ScalarWaveFunction higgs(phiggs,mePartonData()[4],1.,outgoing); // SpinorWaveFunction fin1,fin2; // SpinorBarWaveFunction ain1,ain2; // if(_partons[0]->id()>0) { // fin1 = SpinorWaveFunction(nloMomenta[2],_partons[0]->CC(),outgoing); // ain1 = SpinorBarWaveFunction(nloMomenta[1],_partons[2],outgoing); // } // else { // fin1 = SpinorWaveFunction(nloMomenta[1],_partons[2],outgoing); // ain1 = SpinorBarWaveFunction(nloMomenta[2],_partons[0]->CC(),outgoing); // } // if(_partons[1]->id()>0) { // fin2 = SpinorWaveFunction(p1other,_partons[1],incoming); // ain2 = SpinorBarWaveFunction(p2other,_partons[3],outgoing); // } // else { // fin2 = SpinorWaveFunction(p2other,_partons[3],outgoing); // ain2 = SpinorBarWaveFunction(p1other,_partons[1],incoming); // } // VectorWaveFunction gwave(nloMomenta[0],gluon,incoming); // vector g1; // for(unsigned int ix=0;ix<2;++ix) { // fin1.reset(ix); f1.push_back(fin1); // fin2.reset(ix); f2.push_back(fin2); // ain1.reset(ix); a1.push_back(ain1); // ain2.reset(ix); a2.push_back(ain2); // gwave.reset(2*ix); // g1.push_back(gwave); // } // AbstractFFVVertexPtr vertex[2]; // tcPDPtr vec[2]; // for(unsigned int ix=0;ix<2;++ix) { // int icharge; // icharge = _partons[ix]->iCharge()-_partons[ix+2]->iCharge(); // if(icharge==0) vec[ix] = _z0; // else if(icharge>0) vec[ix] = _wplus; // else vec[ix] = _wminus; // vertex[ix] = vec[ix]==_z0 ? _vertexFFZ : _vertexFFW; // } // tcHwSMPtr hwsm= dynamic_ptr_cast(standardModel()); // AbstractFFVVertexPtr gvertex = hwsm->vertexFFG(); // VectorWaveFunction inter[2]; // Complex diag[2]; // double me(0.); // nloMomenta[0].setMass(ZERO); // nloMomenta[1].setMass(ZERO); // nloMomenta[2].setMass(ZERO); // unsigned int o[2]={1,0}; // for(unsigned int i1=0;i1<2;++i1) { // unsigned int i2=i1; // // wavefunction for the 1st intermediate vector // inter[0] = vertex[1]->evaluate(scale(),1,vec[1],f2[i1],a2[i2]); // for(unsigned int i3=0;i3<2;++i3) { // unsigned int i4=o[i3]; // for(unsigned int ig=0;ig<2;++ig) { // SpinorWaveFunction soff = // gvertex->evaluate(scale(),5,f1[i3].getParticle(), // f1[i3],g1[ig]); // SpinorBarWaveFunction aoff = // gvertex->evaluate(scale(),5,a1[i4].getParticle(), // a1[i4],g1[ig]); // inter[1] = vertex[0]->evaluate(scale(),1,vec[0],soff,a1[i4]); // diag[0] = _vertexWWH->evaluate(scale(),inter[0],inter[1],higgs); // inter[1] = vertex[0]->evaluate(scale(),1,vec[0],f1[i3],aoff); // diag[1] = _vertexWWH->evaluate(scale(),inter[0],inter[1],higgs); // // cerr << "testing helicity " // // << i1 << " " << i2 << " " << i3 << " " << i4 << " " // // << ig << " " << (diag[0]+diag[1])/(abs(diag[0])+abs(diag[1])) // // << "\n"; // me += norm(diag[0]+diag[1]); // } // } // } // // spin factor // me *=0.25; // cerr << "testing the gluon emission " // << fact*8.*Constants::pi*SM().alphaS(scale())/(1.-x2)/(1.-x3)/_q2 // *(sqr(x3)*term3+sqr(x2)*term2)*sqr(MeV2)/me << "\n"; // Energy2 D1 = -_q2-mb2; // Energy2 D2 = (p1other-p2other).m2()-mb2; // double e = sqrt(4.*Constants::pi*SM().alphaEM(scale())); // InvEnergy6 fact = 4.*pow(e*g,6)*mb2/sqr(D1)/sqr(D2); // cerr << "testing LO ME in NLO code " // << fact*loME*MeV2/_mestore << "\n"; // vector f1,f2; // vector a1,a2; // Lorentz5Momentum phiggs = rot*meMomenta()[4]; // ScalarWaveFunction higgs(phiggs,mePartonData()[4],1.,outgoing); // SpinorWaveFunction fin1,fin2; // SpinorBarWaveFunction ain1,ain2; // if(_partons[0]->id()>0) { // fin1 = SpinorWaveFunction(p1,_partons[0],incoming); // ain1 = SpinorBarWaveFunction(p2,_partons[2],outgoing); // } // else { // fin1 = SpinorWaveFunction(p2,_partons[2],outgoing); // ain1 = SpinorBarWaveFunction(p1,_partons[0],incoming); // } // if(_partons[1]->id()>0) { // fin2 = SpinorWaveFunction(p1other,_partons[1],incoming); // ain2 = SpinorBarWaveFunction(p2other,_partons[3],outgoing); // } // else { // fin2 = SpinorWaveFunction(p2other,_partons[3],outgoing); // ain2 = SpinorBarWaveFunction(p1other,_partons[1],incoming); // } // for(unsigned int ix=0;ix<2;++ix) { // fin1.reset(ix); f1.push_back(fin1); // fin2.reset(ix); f2.push_back(fin2); // ain1.reset(ix); a1.push_back(ain1); // ain2.reset(ix); a2.push_back(ain2); // } // AbstractFFVVertexPtr vertex[2]; // tcPDPtr vec[2]; // for(unsigned int ix=0;ix<2;++ix) { // int icharge; // icharge = _partons[ix]->iCharge()-_partons[ix+2]->iCharge(); // if(icharge==0) vec[ix] = _z0; // else if(icharge>0) vec[ix] = _wplus; // else vec[ix] = _wminus; // vertex[ix] = vec[ix]==_z0 ? _vertexFFZ : _vertexFFW; // } // VectorWaveFunction inter[2]; // Complex diag; // double me(0.); // for(unsigned int i1=0;i1<2;++i1) { // for(unsigned int i2=0;i2<2;++i2) { // // wavefunction for the 1st intermediate vector // inter[0] = vertex[0]->evaluate(scale(),1,vec[1],f2[i1],a2[i2]); // for(unsigned int i3=0;i3<2;++i3) { // for(unsigned int i4=0;i4<2;++i4) { // // wavefunction for the 2nd intermediate vector // inter[1] = vertex[1]->evaluate(scale(),1,vec[0],f1[i3],a1[i4]); // // matrix element // diag = _vertexWWH->evaluate(scale(),inter[0],inter[1],higgs); // me += norm(diag); // } // } // } // } // // spin factor // me *=0.25; // cerr << "testing helicity computation " << me/_mestore << "\n"; diff --git a/MatrixElement/Powheg/MEPP2VVPowheg.cc b/MatrixElement/Powheg/MEPP2VVPowheg.cc --- a/MatrixElement/Powheg/MEPP2VVPowheg.cc +++ b/MatrixElement/Powheg/MEPP2VVPowheg.cc @@ -1,5410 +1,5281 @@ // -*- C++ -*- // // MEPP2VVPowheg.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 MEPP2VVPowheg class. // #include "MEPP2VVPowheg.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/MatrixElement/HardVertex.h" #include "Herwig/Decay/GeneralDecayMatrixElement.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/Branching.h" -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; MEPP2VVPowheg::MEPP2VVPowheg() : tiny(1.e-10), CF_(4./3.), TR_(0.5), NC_(3.), contrib_(1), channels_(0), nlo_alphaS_opt_(0) , fixed_alphaS_(0.1180346226), removebr_(1), scaleopt_(1), mu_F_(100.*GeV), mu_UV_(100.*GeV), ckm_(3,vector(3,0.0)), helicityConservation_(true), realMESpinCorrelations_(true), power_(2.0), preqqbar_(3.7),preqg_(16.0),pregqbar_(11.0), b0_((11.-2./3.*5.)/4./Constants::pi), LambdaQCD_(91.118*GeV*exp(-1./2./((11.-2./3.*5.)/4./Constants::pi)/0.118)), min_pT_(2.*GeV){ massOption(vector(2,1)); } void MEPP2VVPowheg::persistentOutput(PersistentOStream & os) const { os << contrib_ << channels_ << nlo_alphaS_opt_ << fixed_alphaS_ << removebr_ << scaleopt_ << ounit(mu_F_,GeV) << ounit(mu_UV_,GeV) << ckm_ << helicityConservation_ << FFPvertex_ << FFWvertex_ << FFZvertex_ << WWWvertex_ << FFGvertex_ << realMESpinCorrelations_ << showerAlphaS_ << power_ << preqqbar_ << preqg_ << pregqbar_ << prefactor_ << b0_ << ounit(LambdaQCD_,GeV) << ounit( min_pT_,GeV ); } void MEPP2VVPowheg::persistentInput(PersistentIStream & is, int) { is >> contrib_ >> channels_ >> nlo_alphaS_opt_ >> fixed_alphaS_ >> removebr_ >> scaleopt_ >> iunit(mu_F_,GeV) >> iunit(mu_UV_,GeV) >> ckm_ >> helicityConservation_ >> FFPvertex_ >> FFWvertex_ >> FFZvertex_ >> WWWvertex_ >> FFGvertex_ >> realMESpinCorrelations_ >> showerAlphaS_ >> power_ >> preqqbar_ >> preqg_ >> pregqbar_ >> prefactor_ >> b0_ >> iunit(LambdaQCD_,GeV) >> iunit( min_pT_, GeV ); } ClassDescription MEPP2VVPowheg::initMEPP2VVPowheg; // Definition of the static class description member. void MEPP2VVPowheg::Init() { static ClassDocumentation documentation ("The MEPP2VVPowheg class implements the NLO matrix elements for the production of" "pairs of electroweak vector bosons.", "The calcultaion of $W^+W^-$, $W^\\pm Z^0$ and $Z^0Z^0$ production" " in hadron collisions at next-to-leading order in the POWHEG scheme" " is described in \\cite{Hamilton:2010mb}.", "\\bibitem{Hamilton:2010mb}\n" " K.~Hamilton,\n" "%``A positive-weight next-to-leading order simulation of weak boson pair\n" "%production,''\n" "JHEP {\bf 1101} (2011) 009\n" "[arXiv:1009.5391 [hep-ph]].\n" "%%CITATION = JHEPA,1101,009;%%\n"); static Switch interfaceContribution ("Contribution", "Which contributions to the cross section to include", &MEPP2VVPowheg::contrib_, 1, false, false); static SwitchOption interfaceContributionLeadingOrder (interfaceContribution, "LeadingOrder", "Just generate the leading order cross section", 0); static SwitchOption interfaceContributionPositiveNLO (interfaceContribution, "PositiveNLO", "Generate the positive contribution to the full NLO cross section", 1); static SwitchOption interfaceContributionNegativeNLO (interfaceContribution, "NegativeNLO", "Generate the negative contribution to the full NLO cross section", 2); static Switch interfaceChannels ("Channels", "Which channels to include in the cross section", &MEPP2VVPowheg::channels_, 0, false, false); static SwitchOption interfaceChannelsAll (interfaceChannels, "All", "All channels required for the full NLO cross section: qqb, qg, gqb", 0); static SwitchOption interfaceChannelsAnnihilation (interfaceChannels, "Annihilation", "Only include the qqb annihilation channel, omitting qg and gqb channels", 1); static SwitchOption interfaceChannelsCompton (interfaceChannels, "Compton", "Only include the qg and gqb compton channels, omitting all qqb processes", 2); static Switch interfaceNLOalphaSopt ("NLOalphaSopt", "An option allowing you to supply a fixed value of alpha_S " "through the FixedNLOAlphaS interface.", &MEPP2VVPowheg::nlo_alphaS_opt_, 0, false, false); static SwitchOption interfaceNLOalphaSoptRunningAlphaS (interfaceNLOalphaSopt, "RunningAlphaS", "Use the usual running QCD coupling evaluated at scale mu_UV2()", 0); static SwitchOption interfaceNLOalphaSoptFixedAlphaS (interfaceNLOalphaSopt, "FixedAlphaS", "Use a constant QCD coupling for comparison/debugging purposes", 1); static Parameter interfaceFixedNLOalphaS ("FixedNLOalphaS", "The value of alphaS to use for the nlo weight if nlo_alphaS_opt_=1", &MEPP2VVPowheg::fixed_alphaS_, 0.1180346226, 0., 1.0, false, false, Interface::limited); static Switch interfaceremovebr ("removebr", "Whether to multiply the event weights by the MCFM branching ratios", &MEPP2VVPowheg::removebr_, 1, false, false); static SwitchOption interfaceProductionCrossSection (interfaceremovebr, "true", "Do not multiply in the branching ratios (default running)", 1); static SwitchOption interfaceIncludeBRs (interfaceremovebr, "false", "Multiply by MCFM branching ratios for comparison/debugging purposes", 0); static Switch interfaceScaleOption ("ScaleOption", "Option for running / fixing EW and QCD factorization & renormalization scales", &MEPP2VVPowheg::scaleopt_, 1, false, false); static SwitchOption interfaceDynamic (interfaceScaleOption, "Dynamic", "QCD factorization & renormalization scales are sqr(pV1+pV2). " "EW scale is (mV1^2+mV2^2)/2 (similar to MCatNLO)", 1); static SwitchOption interfaceFixed (interfaceScaleOption, "Fixed", "QCD factorization fixed to value by FactorizationScaleValue." "EW and QCD renormalization scales fixed by RenormalizationScaleValue.", 2); static Parameter interfaceFactorizationScaleValue ("FactorizationScaleValue", "Value to use for the QCD factorization scale if fixed scales" "have been requested with the ScaleOption interface.", &MEPP2VVPowheg::mu_F_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV, true, false, Interface::limited); static Parameter interfaceRenormalizationScaleValue ("RenormalizationScaleValue", "Value to use for the EW and QCD renormalization scales if fixed " "scales have been requested with the ScaleOption interface.", &MEPP2VVPowheg::mu_UV_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV, true, false, Interface::limited); static Switch interfaceSpinCorrelations ("SpinCorrelations", "Flag to select leading order spin correlations or a " "calculation taking into account the real NLO effects", &MEPP2VVPowheg::realMESpinCorrelations_, 1, false, false); static SwitchOption interfaceSpinCorrelationsLeadingOrder (interfaceSpinCorrelations, "LeadingOrder", "Decay bosons using a leading order 2->2 calculation of the " "production spin density matrix", 0); static SwitchOption interfaceSpinCorrelationsRealNLO (interfaceSpinCorrelations, "RealNLO", "Decay bosons using a production spin density matrix which " "takes into account the effects of real radiation", 1); static Reference interfaceCoupling ("Coupling", "The object calculating the strong coupling constant", &MEPP2VVPowheg::showerAlphaS_, false, false, true, false, false); static Parameter interfacePower ("Power", "The power for the sampling of the matrix elements", &MEPP2VVPowheg::power_, 2.0, 1.0, 10.0, false, false, Interface::limited); static Parameter interfacePrefactorqqbar ("Prefactorqqbar", "The prefactor for the sampling of the q qbar channel", &MEPP2VVPowheg::preqqbar_, 5.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorqg ("Prefactorqg", "The prefactor for the sampling of the q g channel", &MEPP2VVPowheg::preqg_, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorgqbar ("Prefactorgqbar", "The prefactor for the sampling of the g qbar channel", &MEPP2VVPowheg::pregqbar_, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacepTMin ("minPt", "The pT cut on hardest emision generation" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &MEPP2VVPowheg::min_pT_, GeV, 2.*GeV, ZERO, 100000.0*GeV, false, false, Interface::limited); } Energy2 MEPP2VVPowheg::scale() const { // N.B. This scale is the electroweak scale! // It is used in the evaluation of the LO code // in the MEPP2VV base class. This means it // should appear in the denominator of the // NLOweight here and all other LO parts like // the function for the lumi ratio (Lhat). It // should also be used for evaluating any EW // parameters / vertices in the numerator. // The scaleopt_ == 1 "running" option is // chosen to be like the MC@NLO one (it ought // to be more like sHat instead?). return scaleopt_ == 1 ? // 0.5*(meMomenta()[2].m2()+meMomenta()[3].m2()) : sqr(mu_UV_); sHat() : sqr(mu_UV_); } Energy2 MEPP2VVPowheg::mu_F2() const { return scaleopt_ == 1 ? // ((H_.k1r()).m2()+k1r_perp2_lab_+(H_.k2r()).m2()+k2r_perp2_lab_)/2. : sqr(mu_F_); sHat() : sqr(mu_F_); } Energy2 MEPP2VVPowheg::mu_UV2() const { return scaleopt_ == 1 ? // ((H_.k1r()).m2()+k1r_perp2_lab_+(H_.k2r()).m2()+k2r_perp2_lab_)/2. : sqr(mu_UV_); sHat() : sqr(mu_UV_); } void MEPP2VVPowheg::doinit() { MEPP2VV::doinit(); // get the vertices we need // get a pointer to the standard model object in the run static const tcHwSMPtr hwsm = dynamic_ptr_cast(standardModel()); if (!hwsm) throw InitException() << "missing hwsm pointer in MEPP2VVPowheg::doinit()" << Exception::abortnow; // get pointers to all required Vertex objects FFPvertex_ = hwsm->vertexFFP(); FFZvertex_ = hwsm->vertexFFZ(); WWWvertex_ = hwsm->vertexWWW(); FFWvertex_ = hwsm->vertexFFW(); FFGvertex_ = hwsm->vertexFFG(); // get the ckm object Ptr::pointer theCKM=dynamic_ptr_cast::pointer>(SM().CKM()); if(!theCKM) throw InitException() << "MEPP2VVPowheg::doinit() " << "the CKM object must be the Herwig one" << Exception::runerror; unsigned int ix,iy; // get the CKM matrix (unsquared for interference) vector< vector > CKM(theCKM->getUnsquaredMatrix(SM().families())); for(ix=0;ix<3;++ix){for(iy=0;iy<3;++iy){ckm_[ix][iy]=CKM[ix][iy];}} // insert the different prefactors in the vector for easy look up prefactor_.push_back(preqqbar_); prefactor_.push_back(preqg_); prefactor_.push_back(pregqbar_); } int MEPP2VVPowheg::nDim() const { int output = MEPP2VV::nDim(); // See related comment in MEPP2VVPowheg::generateKinematics! if(contrib_>0) output += 2; return output; } bool MEPP2VVPowheg::generateKinematics(const double * r) { // N.B. A fix was made to make theta2 a radiative // variable in r4532. Originally theta2 was take to // be the azimuthal angle coming from the generation // of the Born kinematics inherited from MEPP2VV i.e. // before the change theta2 was a random number between // 0 and 2pi. On changing theta2 was set to be // theta2 = (*(r+3)) * 2.*Constants::pi; // and nDim returned if(contrib_>0) output += 3; // In the months following it was noticed that agreement // with MCFM was per mille at Tevatron energies but got // close to 1 percent for LHC energies (for all VV // processes). After searching back up the svn branch // running 2M events each time, the change was spotted // to occur on r4532. Changing: // if(contrib_>0) output += 3; // in ::nDim() and also, // xt = (*(r +nDim() -3)); // y = (*(r +nDim() -2)) * 2. - 1.; // theta2 = (*(r +nDim() -1)) * 2.*Constants::pi; // did not fix the problem. The following code gives the // same good level of agreement at LHC and TVT: double xt( -999.); double y( -999.); double theta2( -999.); if(contrib_>0) { // Generate the radiative integration variables: xt = (*(r +nDim() -2)); y = (*(r +nDim() -1)) * 2. - 1.; // KH 19th August - next line changed for phi in 0->pi not 0->2pi // theta2 = UseRandom::rnd() * 2.*Constants::pi; theta2 = UseRandom::rnd() *Constants::pi; } // Continue with lo matrix element code: bool output(MEPP2VV::generateKinematics(r)); // Work out the kinematics for the leading order / virtual process // and also get the leading order luminosity function: getKinematics(xt,y,theta2); return output; } double MEPP2VVPowheg::me2() const { double output(0.0); useMe(); output = MEPP2VV::me2(); double mcfm_brs(1.); if(!removebr_) { switch(MEPP2VV::process()) { case 1: // W+(->e+,nu_e) W-(->e-,nu_ebar) (MCFM: 61 [nproc]) mcfm_brs *= 0.109338816; mcfm_brs *= 0.109338816; break; case 2: // W+/-(mu+,nu_mu / mu-,nu_mubar) Z(nu_e,nu_ebar) // (MCFM: 72+77 [nproc]) mcfm_brs *= 0.109338816; mcfm_brs *= 0.06839002; break; case 3: // Z(mu-,mu+) Z(e-,e+) (MCFM: 86 [nproc]) mcfm_brs *= 0.034616433; mcfm_brs *= 0.034616433; mcfm_brs *= 2.; // as identical particle factor 1/2 is now obsolete. break; case 4: // W+(mu+,nu_mu) Z(nu_e,nu_ebar) (MCFM: 72 [nproc]) mcfm_brs *= 0.109338816; mcfm_brs *= 0.06839002; break; case 5: // W-(mu-,nu_mubar) Z(nu_e,nu_ebar) (MCFM: 77 [nproc]) mcfm_brs *= 0.109338816; mcfm_brs *= 0.06839002; break; } } // Store the value of the leading order squared matrix element: lo_me2_ = output; output *= NLOweight(); output *= mcfm_brs; return output; } void MEPP2VVPowheg::getKinematics(double xt, double y, double theta2) { // In this member we want to get the lo_lumi_ as this is a // common denominator in the NLO weight. We want also the // bornVVKinematics object and all of the realVVKinematics // objects needed for the NLO weight. // Check if the W- is first in W+W- production. Already confirmed // mePartonData()[0] is a quark, and mePartonData()[1] is an antiquark. // We assume mePartonData[2] and mePartonData[3] are, respectively, // W+/- Z, W+/- W-/+, or Z Z. bool wminus_first(false); if((mePartonData()[2]->id()==-24)&&(mePartonData()[3]->id()==24)) wminus_first=true; // Now get all data on the LO process needed for the NLO computation: // The +z hadron in the lab: hadron_A_=dynamic_ptr_cast::transient_const_pointer> (lastParticles().first->dataPtr()); // The -z hadron in the lab: hadron_B_=dynamic_ptr_cast::transient_const_pointer> (lastParticles().second->dataPtr()); // Leading order momentum fractions: double xa(lastX1()); // The +z momentum fraction in the lab. double xb(lastX2()); // The -z momentum fraction in the lab. // Particle data for incoming +z & -z QCD particles respectively: ab_ = lastPartons().first ->dataPtr(); // The +z momentum parton in the lab. bb_ = lastPartons().second->dataPtr(); // The -z momentum parton in the lab. // We checked TVT & LHC for all VV channels with 10K events: // lastParticles().first ->momentum().z() is always positive // lastParticles().second->momentum().z() is always negative // lastParticles().first ->momentum().z()*xa=lastPartons().first ->momentum().z() 1 in 10^6 // lastParticles().second->momentum().z()*xb=lastPartons().second->momentum().z() 1 in 10^6 // Set the quark and antiquark data pointers. quark_ = mePartonData()[0]; antiquark_ = mePartonData()[1]; if(quark_->id()<0) swap(quark_,antiquark_); // Now in _our_ calculation we basically define the +z axis as being // given by the direction of the incoming quark for q+qb & q+g processes // and the incoming gluon for g+qbar processes. So now we might need to // flip the values of hadron_A_, hadron_B_, ab_, bb_, xa, xb accordingly: if(ab_->id()!=quark_->id()) { swap(hadron_A_,hadron_B_); swap(ab_,bb_); swap(xa,xb); } // So hadron_A_ is the thing containing a quark (ab_) with momentum frac xa, // hadron_B_ is the thing containing an antiquark (bb_) with momentum frac xb. // Now get the partonic flux for the Born process: lo_lumi_ = hadron_A_->pdf()->xfx(hadron_A_,ab_,scale(),xa)/xa * hadron_B_->pdf()->xfx(hadron_B_,bb_,scale(),xb)/xb; // For W+W- events make sure k1 corresponds to the W+ momentum: if(MEPP2VV::process()==1&&wminus_first) swap(meMomenta()[2],meMomenta()[3]); // Create the object containing all 2->2 __kinematic__ information: B_ = bornVVKinematics(meMomenta(),xa,xb); // We checked that meMomenta()[0] (quark) is in the +z direction and meMomenta()[1] // is in the -z direction (antiquark). // Revert momentum swap in case meMomenta and mePartonData correlation // needs preserving for other things. if(MEPP2VV::process()==1&&wminus_first) swap(meMomenta()[2],meMomenta()[3]); // Check the Born kinematics objects is internally consistent: // B_.sanityCheck(); // If we are going beyond leading order then lets calculate all of // the necessary real emission kinematics. if(contrib_>0) { // Soft limit of the 2->3 real emission kinematics: S_ = realVVKinematics(B_, 1., y, theta2); // Soft-collinear limit of the 2->3 kinematics (emission in +z direction): SCp_ = realVVKinematics(B_, 1., 1., theta2); // Soft-collinear limit of the 2->3 kinematics (emission in -z direction): SCm_ = realVVKinematics(B_, 1.,-1., theta2); // Collinear limit of the 2->3 kinematics (emission in +z direction): Cp_ = realVVKinematics(B_, xt, 1., theta2); // Collinear limit of the 2->3 kinematics (emission in -z direction): Cm_ = realVVKinematics(B_, xt,-1., theta2); // The resolved 2->3 real emission kinematics: H_ = realVVKinematics(B_, xt, y, theta2); // Borrowed from VVhardGenerator (lab momenta of k1,k2): Energy pT(sqrt(H_.pT2_in_lab())); LorentzRotation yzRotation; yzRotation.setRotateX(-atan2(pT/GeV,sqrt(B_.sb())/GeV)); LorentzRotation boostFrompTisZero; boostFrompTisZero.setBoostY(-pT/sqrt(B_.sb()+pT*pT)); LorentzRotation boostFromYisZero; boostFromYisZero.setBoostZ(tanh(B_.Yb())); k1r_perp2_lab_ = (boostFromYisZero*boostFrompTisZero*yzRotation*(H_.k1r())).perp2(); k2r_perp2_lab_ = (boostFromYisZero*boostFrompTisZero*yzRotation*(H_.k2r())).perp2(); // Check all the real kinematics objects are internally consistent: // S_.sanityCheck(); // SCp_.sanityCheck(); // SCm_.sanityCheck(); // Cp_.sanityCheck(); // Cm_.sanityCheck(); // H_.sanityCheck(); } return; } double MEPP2VVPowheg::NLOweight() const { // If only leading order is required return 1: if(contrib_==0) return lo_me()/lo_me2_; // Calculate alpha_S and alpha_S/(2*pi). alphaS_ = nlo_alphaS_opt_==1 ? fixed_alphaS_ : SM().alphaS(mu_UV2()); double alsOn2pi(alphaS_/2./pi); // Particle data objects for the new plus and minus colliding partons. tcPDPtr gluon; gluon = getParticleData(ParticleID::g); // Get the all couplings. gW_ = sqrt(4.0*pi*SM().alphaEM(scale())/SM().sin2ThetaW()); sin2ThetaW_ = SM().sin2ThetaW(); double cosThetaW(sqrt(1.-sin2ThetaW_)); guL_ = gW_/2./cosThetaW*( 1.-4./3.*sin2ThetaW_); gdL_ = gW_/2./cosThetaW*(-1.+2./3.*sin2ThetaW_); guR_ = gW_/2./cosThetaW*( -4./3.*sin2ThetaW_); gdR_ = gW_/2./cosThetaW*( +2./3.*sin2ThetaW_); eZ_ = gW_*cosThetaW; eZ2_ = sqr(eZ_); // MCFM has gwsq = 0.4389585130009 -> gw = 0.662539442600115 // Here we have gW_ = 0.662888 // MCFM has xw = 0.22224653300000 -> sqrt(xw) = 0.471430306 // Here we have 0.222247 // MCFM has esq = 0.097557007645279 -> e = 0.31234117187024679 // Here we have 4.0*pi*SM().alphaEM(sqr(100.*GeV)) = 0.0976596 // If the process is W-Z instead of W+Z we must transform these // couplings as follows, according to NPB 383(1992)3-44 Eq.3.23 if(mePartonData()[2]->id()==-24&&mePartonData()[3]->id()==23) { swap(guL_,gdL_); eZ_ *= -1.; } // Get the CKM entry. Note that this code was debugged // considerably; the call to CKM(particle,particle) // did not appear to work, so we extract the elements // as follows below. The right numbers now appear to // to be associated with the right quarks. double Kij(-999.); // W+Z / W-Z if(abs(mePartonData()[2]->id())==24&&mePartonData()[3]->id()==23) { int up_id(-999),dn_id(-999); if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==1) { up_id = abs(quark_->id()); dn_id = abs(antiquark_->id()); } else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==0) { up_id = abs(antiquark_->id()); dn_id = abs(quark_->id()); } else { cout << "MEPP2VVPowheg:" << endl; cout << "WZ needs an up and a down type quark as incoming!" << endl; } up_id /= 2; up_id -= 1; dn_id -= 1; dn_id /= 2; Kij = sqrt(SM().CKM(up_id,dn_id)); } // W+W- else if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) { if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) { int up_ida(abs(quark_->id())/2-1); int up_idb(abs(antiquark_->id())/2-1); Kij = sqrt(std::norm( CKM(up_ida,0)*CKM(up_idb,0) + CKM(up_ida,1)*CKM(up_idb,1) + CKM(up_ida,2)*CKM(up_idb,2))); } else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) { int dn_ida((abs(quark_->id())-1)/2); int dn_idb((abs(antiquark_->id())-1)/2); Kij = sqrt(std::norm( CKM(0,dn_ida)*CKM(0,dn_idb) + CKM(1,dn_ida)*CKM(1,dn_idb) + CKM(2,dn_ida)*CKM(2,dn_idb))); } else { cout << "MEPP2VVPowheg:" << endl; cout << "WW needs 2 down-type / 2 up-type!" << endl; } } // ZZ else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) { Kij = 2.*sqrt(2.)/gW_; } else { cout << "MEPP2VVPowheg: incompatible final state particles!" << endl; } Fij2_ = sqr(gW_/2./sqrt(2.)*Kij); // Get the leading order matrix element (this is necessary!) M_Born_ = M_Born_WZ(B_); // // Get the regular part of the virtual correction (only needed for sanityCheck()!) // M_V_regular_ = M_V_regular(S_); // // Get the q + qbar real emission matrix element (only needed for sanityCheck()!) // t_u_M_R_qqb_ = t_u_M_R_qqb(H_); // Calculate the integrand double wgt(0.); double wqqb(0.); double wgqb(0.); double wqg(0.); double wqqbvirt(0.); double wqqbcollin(0.); double wqqbreal(0.); double wqgcollin(0.); double wqgreal(0.); double wgqbcollin(0.); double wgqbreal(0.); if(channels_==0||channels_==1) { // q+qb wqqbvirt = Vtilde_universal(S_) + M_V_regular(S_)/lo_me2_; wqqbcollin = alsOn2pi*( Ctilde_Ltilde_qq_on_x(quark_,antiquark_,Cp_) + Ctilde_Ltilde_qq_on_x(quark_,antiquark_,Cm_) ); wqqbreal = alsOn2pi*Rtilde_Ltilde_qqb_on_x(quark_,antiquark_); wqqb = wqqbvirt + wqqbcollin + wqqbreal; } if(channels_==0||channels_==2) { // q+g wqgcollin = alsOn2pi*Ctilde_Ltilde_gq_on_x(quark_,gluon,Cm_); wqgreal = alsOn2pi*Rtilde_Ltilde_qg_on_x(quark_,gluon); wqg = wqgreal + wqgcollin; // g+qb wgqbcollin = alsOn2pi*Ctilde_Ltilde_gq_on_x(gluon,antiquark_,Cp_); wgqbreal = alsOn2pi*Rtilde_Ltilde_gqb_on_x(gluon,antiquark_); wgqb = wgqbreal+wgqbcollin; } // total contribution wgt = 1.+(wqqb+wgqb+wqg); // If restricting to qg, gqb channels then subtract the LO contribution: if(channels_==2) wgt -= 1.; if(isnan(wgt)||isinf(wgt)) { cout << "MEPP2VVPowheg:: NLO weight " << "is bad: wgt = " << wgt << endl; cout << "MEPP2VVPowheg sanityCheck invoked!" << endl; cout << ab_->PDGName() << ", " << bb_->PDGName() << ", " << mePartonData()[2]->PDGName() << ", " << mePartonData()[3]->PDGName() << endl; cout << "lo_me2_ - M_Born_ (rel) = " << lo_me2_-M_Born_ << " (" << (lo_me2_-M_Born_)/M_Born_ << ")\n"; cout << "lo_me2_, M_Born_ " << lo_me2_ << ", " << M_Born_ << endl; cout << "xr = " << H_.xr() << " 1-xr = " << 1.-H_.xr() << " y = " << H_.y() << endl; cout << "tkr = " << H_.tkr()/GeV2 << " ukr = " << H_.ukr()/GeV2 << endl; cout << "root(sb) = " << sqrt(B_.sb())/GeV << endl; cout << "sb+tb+ub = " << B_.sb()/GeV2 << " + " << B_.tb()/GeV2 << " + " << B_.ub()/GeV2 << endl; cout << "sqrt(k12) " << sqrt(H_.k12r())/GeV << endl; cout << "sqrt(k22) " << sqrt(H_.k22r())/GeV << endl; cout << "sqr(Kij) " << Kij*Kij << endl; cout << "wqqbvirt " << wqqbvirt << endl; cout << "wqqbcollin " << wqqbcollin << endl; cout << "wqqbreal " << wqqbreal << endl; cout << "wqqb " << wqqb << endl; cout << "wqgcollin " << wqgcollin << endl; cout << "wqgreal " << wqgreal << endl; cout << "wqg " << wqg << endl; cout << "wgqbcollin " << wgqbcollin << endl; cout << "wgqbreal " << wgqbreal << endl; cout << "wgqb " << wgqb << endl; cout << "wgt " << wgt << endl; throw Exception() << "MEPP2VVPowheg:: NLO weight " << "is bad: " << wgt << Exception::eventerror; } return contrib_==1 ? max(0.,wgt) : max(0.,-wgt); } double MEPP2VVPowheg::Lhat_ab(tcPDPtr a, tcPDPtr b, realVVKinematics Kinematics) const { if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21)) cout << "MEPP2VVPowheg::Lhat_ab: Error," << "particle a = " << a->PDGName() << ", " << "particle b = " << b->PDGName() << endl; double nlo_lumi(-999.); double x1(Kinematics.x1r()),x2(Kinematics.x2r()); nlo_lumi = (hadron_A_->pdf()->xfx(hadron_A_,a,mu_F2(),x1)/x1) * (hadron_B_->pdf()->xfx(hadron_B_,b,mu_F2(),x2)/x2); return nlo_lumi / lo_lumi_; } double MEPP2VVPowheg::Vtilde_universal(realVVKinematics S) const { double xbar_y = S.xbar(); double y = S.y(); double eta1b(S.bornVariables().eta1b()); double eta2b(S.bornVariables().eta2b()); Energy2 sb(S.s2r()); return alphaS_/2./pi*CF_ * ( log(sb/mu_F2()) * (3. + 4.*log(eta1b)+4.*log(eta2b)) + 8.*sqr(log(eta1b)) +8.*sqr(log(eta2b)) - 2.*sqr(pi)/3. ) + alphaS_/2./pi*CF_ * ( 8./(1.+y)*log(sqrt(1.-xbar_y)/eta2b) + 8./(1.-y)*log(sqrt(1.-xbar_y)/eta1b) ); } double MEPP2VVPowheg::Ctilde_Ltilde_qq_on_x(tcPDPtr a, tcPDPtr b, realVVKinematics C) const { if(C.y()!= 1.&&C.y()!=-1.) cout << "\nCtilde_qq::y value not allowed."; if(C.y()== 1.&&!(abs(a->id())>0&&abs(a->id())<7)) cout << "\nCtilde_qq::for Cqq^plus a must be a quark! id = " << a->id() << "\n"; if(C.y()==-1.&&!(abs(b->id())>0&&abs(b->id())<7)) cout << "\nCtilde_qq::for Cqq^minus b must be a quark! id = " << b->id() << "\n"; double xt = C.xt(); double x = C.xr(); double etab = C.y() == 1. ? C.bornVariables().eta1b() : C.bornVariables().eta2b() ; Energy2 sb(C.s2r()); if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.; return ( ( (1./(1.-xt))*log(sb/mu_F2()/x)+4.*log(etab)/(1.-xt) + 2.*log(1.-xt)/(1.-xt) )*CF_*(1.+sqr(x)) + sqr(etab)*CF_*(1.-x) )*Lhat_ab(a,b,C) / x - ( ( (1./(1.-xt))*log(sb/mu_F2() )+4.*log(etab)/(1.-xt) + 2.*log(1.-xt)/(1.-xt) )*CF_*2. )*Lhat_ab(a,b,S_); } double MEPP2VVPowheg::Ctilde_Ltilde_gq_on_x(tcPDPtr a, tcPDPtr b, realVVKinematics C) const { if(C.y()!= 1.&&C.y()!=-1.) cout << "\nCtilde_gq::y value not allowed."; if(C.y()== 1.&&a->id()!=21) cout << "\nCtilde_gq::for Cgq^plus a must be a gluon! id = " << a->id() << "\n"; if(C.y()==-1.&&b->id()!=21) cout << "\nCtilde_gq::for Cgq^minus b must be a gluon! id = " << b->id() << "\n"; double xt = C.xt(); double x = C.xr(); double etab = C.y() == 1. ? C.bornVariables().eta1b() : C.bornVariables().eta2b() ; Energy2 sb(C.s2r()); return ( ( (1./(1.-xt))*log(sb/mu_F2()/x)+4.*log(etab)/(1.-xt) + 2.*log(1.-xt)/(1.-xt) )*(1.-x)*TR_*(sqr(x)+sqr(1.-x)) + sqr(etab)*TR_*2.*x*(1.-x) )*Lhat_ab(a,b,C) / x; } double MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x(tcPDPtr a , tcPDPtr b) const { if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21)) cout << "MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x: Error," << "particle a = " << a->PDGName() << ", " << "particle b = " << b->PDGName() << endl; double xt(H_.xt()); double y(H_.y()); Energy2 s(H_.sr()); Energy2 sCp(Cp_.sr()); Energy2 sCm(Cm_.sr()); Energy2 t_u_M_R_qqb_H (t_u_M_R_qqb(H_ )); Energy2 t_u_M_R_qqb_Cp(t_u_M_R_qqb(Cp_)); Energy2 t_u_M_R_qqb_Cm(t_u_M_R_qqb(Cm_)); // Energy2 t_u_M_R_qqb_H (t_u_M_R_qqb_hel_amp(H_)); // Energy2 t_u_M_R_qqb_Cp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr() // *CF_*(1.+sqr(Cp_.xr()))*lo_me2_); // Energy2 t_u_M_R_qqb_Cm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr() // *CF_*(1.+sqr(Cm_.xr()))*lo_me2_); int config(0); if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.; if(fabs(1.-y )<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cp ; config = 1; } if(fabs(1.+y )<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cm ; config = -1; } if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cp ; config = 1; } if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cm ; config = -1; } if(config== 0) return ( ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cp*Lhat_ab(a,b,Cp_)/sCp) )*2./(1.-y)/(1.-xt) + ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cm*Lhat_ab(a,b,Cm_)/sCm) )*2./(1.+y)/(1.-xt) ) / lo_me2_ / 8. / pi / alphaS_; else if(config== 1) return ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cm*Lhat_ab(a,b,Cm_)/sCm) )*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_; else if(config==-1) return ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cp*Lhat_ab(a,b,Cp_)/sCp) )*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_; else throw Exception() << "MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x\n" << "The configuration is not identified as hard / soft / fwd collinear or bwd collinear." << "config = " << config << "\n" << "xt = " << xt << " 1.-xt = " << 1.-xt << "\n" << "y = " << y << " 1.-y = " << 1.-y << "\n" << Exception::eventerror; } double MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x(tcPDPtr a , tcPDPtr b) const { if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21)) cout << "MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x: Error," << "particle a = " << a->PDGName() << ", " << "particle b = " << b->PDGName() << endl; double xt(H_.xt()); double y(H_.y()); Energy2 s(H_.sr()); Energy2 sCp(Cp_.sr()); Energy2 sCm(Cm_.sr()); Energy2 t_u_M_R_gqb_H (t_u_M_R_gqb(H_ )); Energy2 t_u_M_R_gqb_Cp(t_u_M_R_gqb(Cp_)); Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb(Cm_)); // Energy2 t_u_M_R_gqb_H (t_u_M_R_gqb_hel_amp(H_)); // Energy2 t_u_M_R_gqb_Cp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr()*(1.-Cp_.xr()) // *TR_*(sqr(Cp_.xr())+sqr(1.-Cp_.xr()))*lo_me2_); // Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb(Cm_)); // // Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb_hel_amp(Cm_)); int config(0); if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.; if(fabs(1.-y )<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cp ; config = 1; } if(fabs(1.+y )<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cm ; config = -1; } if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cp ; config = 1; } if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cm ; config = -1; } if(config== 0) return ( ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cp*Lhat_ab(a,b,Cp_)/sCp) )*2./(1.-y)/(1.-xt) + ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cm*Lhat_ab(a,b,Cm_)/sCm) )*2./(1.+y)/(1.-xt) ) / lo_me2_ / 8. / pi / alphaS_; else if(config== 1) return ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cm*Lhat_ab(a,b,Cm_)/sCm) )*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_; else if(config==-1) return ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cp*Lhat_ab(a,b,Cp_)/sCp) )*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_; else throw Exception() << "MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x\n" << "The configuration is not identified as hard / soft / fwd collinear or bwd collinear." << "config = " << config << "\n" << "xt = " << xt << " 1.-xt = " << 1.-xt << "\n" << "y = " << y << " 1.-y = " << 1.-y << "\n" << Exception::eventerror; } double MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x(tcPDPtr a , tcPDPtr b) const { if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21)) cout << "MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x: Error," << "particle a = " << a->PDGName() << ", " << "particle b = " << b->PDGName() << endl; double xt(H_.xt()); double y(H_.y()); Energy2 s(H_.sr()); Energy2 sCp(Cp_.sr()); Energy2 sCm(Cm_.sr()); Energy2 t_u_M_R_qg_H (t_u_M_R_qg(H_ )); Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg(Cp_)); Energy2 t_u_M_R_qg_Cm(t_u_M_R_qg(Cm_)); // Energy2 t_u_M_R_qg_H (t_u_M_R_qg_hel_amp(H_)); // Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg(Cp_)); // // Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg_hel_amp(Cp_)); // Energy2 t_u_M_R_qg_Cm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr()*(1.-Cm_.xr()) // *TR_*(sqr(Cm_.xr())+sqr(1.-Cm_.xr()))*lo_me2_); int config(0); if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.; if(fabs(1.-y )<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cp ; config = 1; } if(fabs(1.+y )<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cm ; config = -1; } if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cp ; config = 1; } if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cm ; config = -1; } if(config== 0) return ( ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cp*Lhat_ab(a,b,Cp_)/sCp) )*2./(1.-y)/(1.-xt) + ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cm*Lhat_ab(a,b,Cm_)/sCm) )*2./(1.+y)/(1.-xt) ) / lo_me2_ / 8. / pi / alphaS_; else if(config== 1) return ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cm*Lhat_ab(a,b,Cm_)/sCm) )*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_; else if(config==-1) return ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cp*Lhat_ab(a,b,Cp_)/sCp) )*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_; else throw Exception() << "MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x\n" << "The configuration is not identified as hard / soft / fwd collinear or bwd collinear." << "config = " << config << "\n" << "xt = " << xt << " 1.-xt = " << 1.-xt << "\n" << "y = " << y << " 1.-y = " << 1.-y << "\n" << Exception::eventerror; } /***************************************************************************/ // The following three functions are identically \tilde{I}_{4,t}, // \tilde{I}_{3,WZ} and \tilde{I}_{3,W} given in Eqs. B.8,B.9,B.10 // of NPB 383(1992)3-44, respectively. They are related to / derived // from the loop integrals in Eqs. A.3, A.5 and A.8 of the same paper. InvEnergy4 TildeI4t(Energy2 s, Energy2 t, Energy2 mW2, Energy2 mZ2); InvEnergy2 TildeI3WZ(Energy2 s, Energy2 mW2, Energy2 mZ2, double beta); InvEnergy2 TildeI3W(Energy2 s, Energy2 t, Energy2 mW2); /***************************************************************************/ // The following six functions are identically I_{dd}^{(1)}, I_{ud}^{(1)}, // I_{uu}^{(1)}, F_{u}^{(1)}, F_{d}^{(1)}, H^{(1)} from Eqs. B.4, B.5, B.3, // B.3, B.6, B.7 of NPB 383(1992)3-44, respectively. They make up the // one-loop matrix element. Ixx functions correspond to the graphs // with no TGC, Fx functions are due to non-TGC graphs interfering // with TGC graphs, while the H function is due purely to TGC graphs. double Idd1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta); double Iud1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta); double Iuu1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta); Energy2 Fu1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta); Energy2 Fd1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta); Energy4 H1 (Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2); /***************************************************************************/ // M_V_Regular is the regular part of the one-loop matrix element // exactly as defined in Eqs. B.1 and B.2 of of NPB 383(1992)3-44. double MEPP2VVPowheg::M_V_regular(realVVKinematics S) const { Energy2 s(S.bornVariables().sb()); Energy2 t(S.bornVariables().tb()); Energy2 u(S.bornVariables().ub()); Energy2 mW2(S.k12r()); // N.B. the diboson masses are preserved in getting Energy2 mZ2(S.k22r()); // the 2->2 from the 2->3 kinematics. double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44. double cosThetaW(sqrt(1.-sin2ThetaW_)); double eZ2(eZ2_); double eZ(eZ_); double gdL(gdL_); double guL(guL_); double gdR(gdR_); double guR(guR_); // W+W- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) { double e2(sqr(gW_)*sin2ThetaW_); if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s-mW2)/Fij2_ * (e2*e2/s/s*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s/(s-mW2/sqr(cosThetaW))) +sqr( eZ*(guL-guR)/2./e2*s/(s-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2) * (gW_*gW_*e2/4./s *( 2./3.+2.*eZ*guL/2./e2*s/(s-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } gdL = gW_/sqrt(2.); guL = 0.; } else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s-mW2)/Fij2_ * (e2*e2/s/s*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s/(s-mW2/sqr(cosThetaW))) +sqr( eZ*(gdL-gdR)/2./e2*s/(s-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2) * (gW_*gW_*e2/4./s *(-1./3.+2.*eZ*gdL/2./e2*s/(s-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } guL = gW_/sqrt(2.); gdL = 0.; } } // ZZ else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) { eZ = 0.; eZ2 = 0.; double gV2,gA2; gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_); gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_); guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_); gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_); gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL; else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL; else { cout << "MEPP2VVPowheg:" << endl; cout << "ZZ needs 2 down-type / 2 up-type!" << endl; } } return 4.*pi*alphaS_*Fij2_*CF_*(1./sqr(4.*pi))/NC_ * ( gdL*gdL*Idd1(s,t,u,mW2,mZ2,beta) + gdL*guL*Iud1(s,t,u,mW2,mZ2,beta) + guL*guL*Iuu1(s,t,u,mW2,mZ2,beta) - eZ/(s-mW2) * ( gdL*Fd1(s,t,u,mW2,mZ2,beta) - guL*Fu1(s,t,u,mW2,mZ2,beta) ) + eZ2/sqr(s-mW2) * H1(s,t,u,mW2,mZ2) ); } /***************************************************************************/ InvEnergy4 TildeI4t(Energy2 s, Energy2 t, Energy2 mW2, Energy2 mZ2) { double sqrBrackets; sqrBrackets = ( sqr(log(-t/mW2))/2.+log(-t/mW2)*log(-t/mZ2)/2. - 2.*log(-t/mW2)*log((mW2-t)/mW2)-2.*ReLi2(t/mW2) ); swap(mW2,mZ2); sqrBrackets+= ( sqr(log(-t/mW2))/2.+log(-t/mW2)*log(-t/mZ2)/2. - 2.*log(-t/mW2)*log((mW2-t)/mW2)-2.*ReLi2(t/mW2) ); swap(mW2,mZ2); return sqrBrackets/s/t; } InvEnergy2 TildeI3WZ(Energy2 s, Energy2 mW2, Energy2 mZ2, double beta) { Energy2 sig(mZ2+mW2); Energy2 del(mZ2-mW2); double sqrBrackets ; sqrBrackets = ( ReLi2(2.*mW2/(sig-del*(del/s+beta))) + ReLi2((1.-del/s+beta)/2.) + sqr(log((1.-del/s+beta)/2.))/2. + log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.) ); beta *= -1; sqrBrackets -= ( ReLi2(2.*mW2/(sig-del*(del/s+beta))) + ReLi2((1.-del/s+beta)/2.) + sqr(log((1.-del/s+beta)/2.))/2. + log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.) ); beta *= -1; swap(mW2,mZ2); del *= -1.; sqrBrackets += ( ReLi2(2.*mW2/(sig-del*(del/s+beta))) + ReLi2((1.-del/s+beta)/2.) + sqr(log((1.-del/s+beta)/2.))/2. + log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.) ); swap(mW2,mZ2); del *= -1.; beta *= -1; swap(mW2,mZ2); del *= -1.; sqrBrackets -= ( ReLi2(2.*mW2/(sig-del*(del/s+beta))) + ReLi2((1.-del/s+beta)/2.) + sqr(log((1.-del/s+beta)/2.))/2. + log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.) ); beta *= -1; swap(mW2,mZ2); del *= -1.; return sqrBrackets/s/beta; } InvEnergy2 TildeI3W(Energy2 s, Energy2 t, Energy2 mW2) { return 1./(mW2-t)*(sqr(log(mW2/s))/2.-sqr(log(-t/s))/2.-sqr(pi)/2.); } /***************************************************************************/ double Idd1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) { Energy2 sig(mZ2+mW2); Energy2 del(mZ2-mW2); double Val(0.); Val += 2.*(22.*t*t+t*(19.*s-18.*sig)+18.*mW2*mZ2)/t/t - 8.*(u*t+2*s*sig)/mW2/mZ2 - 2.*sqr(t-u)/t/s/sqr(beta); Val += +( 2.*(8.*t*t+4.*t*(s-3.*sig)+4*sqr(sig)-5.*s*sig+s*s)/t/s/sqr(beta) + 4.*(t*(3.*u+s)-3.*mW2*mZ2)/t/t + 6.*(t+u)*sqr(t-u)/t/s/s/sqr(sqr(beta)) )*log(-t/s); Val += +( ( 8.*t*t*(-2.*s+del)+8.*t*(-s*s+3.*s*sig-2.*del*sig) - 2.*(s-sig)*(s*s-4.*s*sig+3.*del*sig) )/t/s/s/beta/beta + 16.*s*(t-mZ2)/(t*(u+s)-mW2*mZ2) + 2.*(4.*t*t+t*(10.*s-3.*mZ2-9.*mW2)+12.*mW2*mZ2)/t/t -6.*(s-del)*(t+u)*sqr(t-u)/t/s/s/s/sqr(sqr(beta)) )*log(-t/mW2); Val += ( - ( 4.*t*t*(2.*sig-3.*s) - 4.*t*(s-sig)*(2.*s-3.*sig) - 2.*(s-2.*sig)*sqr(s-sig) )/t/s/beta/beta + ( 4.*sig*t-3.*s*s+4.*s*sig - 4.*(mW2*mW2+mZ2*mZ2) )/t - 3.*sqr(t*t-u*u)/t/s/s/sqr(sqr(beta)) )*TildeI3WZ(s,mW2,mZ2,beta); Val += +( 4.*(t*u+2.*s*sig)/3./mW2/mZ2 - 4.*(t-2.*u)/3./t )*pi*pi; Val += -( 4.*s*(t*u-2.*mW2*mZ2)/t )*TildeI4t(s,t,mW2,mZ2); Val += ( 8.*(t-mW2)*(u*t-2.*mW2*mZ2)/t/t )*TildeI3W(s,t,mW2); swap(mW2,mZ2); del *= -1; Val += 2.*(22.*t*t+t*(19.*s-18.*sig)+18.*mW2*mZ2)/t/t - 8.*(u*t+2*s*sig)/mW2/mZ2 - 2.*sqr(t-u)/t/s/sqr(beta); Val += +( 2.*(8.*t*t+4.*t*(s-3.*sig)+4*sqr(sig)-5.*s*sig+s*s)/t/s/sqr(beta) + 4.*(t*(3.*u+s)-3.*mW2*mZ2)/t/t + 6.*(t+u)*sqr(t-u)/t/s/s/sqr(sqr(beta)) )*log(-t/s); Val += +( ( 8.*t*t*(-2.*s+del)+8.*t*(-s*s+3.*s*sig-2.*del*sig) - 2.*(s-sig)*(s*s-4.*s*sig+3.*del*sig) )/t/s/s/beta/beta + 16.*s*(t-mZ2)/(t*(u+s)-mW2*mZ2) + 2.*(4.*t*t+t*(10.*s-3.*mZ2-9.*mW2)+12.*mW2*mZ2)/t/t -6.*(s-del)*(t+u)*sqr(t-u)/t/s/s/s/sqr(sqr(beta)) )*log(-t/mW2); Val += ( - ( 4.*t*t*(2.*sig-3.*s) - 4.*t*(s-sig)*(2.*s-3.*sig) - 2.*(s-2.*sig)*sqr(s-sig) )/t/s/beta/beta + ( 4.*sig*t-3.*s*s+4.*s*sig - 4.*(mW2*mW2+mZ2*mZ2) )/t - 3.*sqr(t*t-u*u)/t/s/s/sqr(sqr(beta)) )*TildeI3WZ(s,mW2,mZ2,beta); Val += +( 4.*(t*u+2.*s*sig)/3./mW2/mZ2 - 4.*(t-2.*u)/3./t )*pi*pi; Val += -( 4.*s*(t*u-2.*mW2*mZ2)/t )*TildeI4t(s,t,mW2,mZ2); Val += ( 8.*(t-mW2)*(u*t-2.*mW2*mZ2)/t/t )*TildeI3W(s,t,mW2); swap(mW2,mZ2); del *= -1; return Val; } /***************************************************************************/ double Iud1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) { Energy2 sig(mZ2+mW2); Energy2 del(mZ2-mW2); double Val(0.); Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u + 8.*(t*u+2.*s*sig)/mW2/mZ2 + 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s)) - 2.*sqr(t-u)/u/s/sqr(beta); Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta) + 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta)) - 12.*s*(t-sig)/t/u )*log(-t/s); Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del) + 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del) + (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del) ) + (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u - 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig)) /u/(mW2*mZ2-t*(u+s)) - 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s)) + 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta)) )*log(-t/mW2); Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig)) /u/s/sqr(beta) +3.*s*(4.*t-4.*sig-s)/u -3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta)) )*TildeI3WZ(s,mW2,mZ2,beta); Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2 )*pi*pi; Val += -( 16.*s*(t-sig)*(t-mW2)/t/u )*TildeI3W(s,t,mW2); Val += ( 8.*s*s*(t-sig)/u )*TildeI4t(s,t,mW2,mZ2); swap(t,u); Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u + 8.*(t*u+2.*s*sig)/mW2/mZ2 + 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s)) - 2.*sqr(t-u)/u/s/sqr(beta); Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta) + 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta)) - 12.*s*(t-sig)/t/u )*log(-t/s); Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del) + 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del) + (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del) ) + (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u - 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig)) /u/(mW2*mZ2-t*(u+s)) - 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s)) + 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta)) )*log(-t/mW2); Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig)) /u/s/sqr(beta) +3.*s*(4.*t-4.*sig-s)/u -3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta)) )*TildeI3WZ(s,mW2,mZ2,beta); Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2 )*pi*pi; Val += -( 16.*s*(t-sig)*(t-mW2)/t/u )*TildeI3W(s,t,mW2); Val += ( 8.*s*s*(t-sig)/u )*TildeI4t(s,t,mW2,mZ2); swap(t,u); swap(mW2,mZ2); del *= -1; Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u + 8.*(t*u+2.*s*sig)/mW2/mZ2 + 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s)) - 2.*sqr(t-u)/u/s/sqr(beta); Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta) + 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta)) - 12.*s*(t-sig)/t/u )*log(-t/s); Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del) + 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del) + (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del) ) + (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u - 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig)) /u/(mW2*mZ2-t*(u+s)) - 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s)) + 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta)) )*log(-t/mW2); Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig)) /u/s/sqr(beta) +3.*s*(4.*t-4.*sig-s)/u -3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta)) )*TildeI3WZ(s,mW2,mZ2,beta); Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2 )*pi*pi; Val += -( 16.*s*(t-sig)*(t-mW2)/t/u )*TildeI3W(s,t,mW2); Val += ( 8.*s*s*(t-sig)/u )*TildeI4t(s,t,mW2,mZ2); swap(mW2,mZ2); del *= -1; swap(t,u); swap(mW2,mZ2); del *= -1; Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u + 8.*(t*u+2.*s*sig)/mW2/mZ2 + 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s)) - 2.*sqr(t-u)/u/s/sqr(beta); Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta) + 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta)) - 12.*s*(t-sig)/t/u )*log(-t/s); Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del) + 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del) + (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del) ) + (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u - 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig)) /u/(mW2*mZ2-t*(u+s)) - 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s)) + 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta)) )*log(-t/mW2); Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig)) /u/s/sqr(beta) +3.*s*(4.*t-4.*sig-s)/u -3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta)) )*TildeI3WZ(s,mW2,mZ2,beta); Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2 )*pi*pi; Val += -( 16.*s*(t-sig)*(t-mW2)/t/u )*TildeI3W(s,t,mW2); Val += ( 8.*s*s*(t-sig)/u )*TildeI4t(s,t,mW2,mZ2); swap(t,u); swap(mW2,mZ2); del *= -1; return Val; } /***************************************************************************/ double Iuu1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) { double Val(Idd1(s,u,t,mW2,mZ2,beta)); return Val; } /***************************************************************************/ Energy2 Fd1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) { Energy2 sig(mZ2+mW2); Energy2 del(mZ2-mW2); Energy2 Val(0.*GeV2); Val += 4.*(17.*t*t+t*(11.*s-13.*sig)+17.*(s*sig+mW2*mZ2))/t + 16.*(s-sig)*(t*u+2.*s*sig)/mW2/mZ2 + 4*s*s*(2.*t-sig)/(t*(u+s)-mW2*mZ2); Val += ( 8.*(t-u)/sqr(beta) - 4.*(3.*t*t-t*(s+3.*sig)+3.*(s*sig+mW2*mZ2))/t )*log(-t/s); Val += ( 8.*(t*t-t*(2.*s+3.*mW2+mZ2)+3.*(s*sig+mW2*mZ2))/t + 8.*s*(t*(3.*s+2.*sig)-2.*mZ2*(s+sig))/(t*(u+s)-mW2*mZ2) + 8.*s*s*t*(2.*t-sig)*(t-mZ2)/sqr(t*(u+s)-mW2*mZ2) - 8.*(s-del)*(t-u)/s/sqr(beta) )*log(-t/mW2); Val += ( 4.*(s-sig)*(t-u)/sqr(beta) + 4.*(sig-3.*s)*t + 4.*(4.*s*sig-mZ2*mZ2-mW2*mW2) )*TildeI3WZ(s,mW2,mZ2,beta); Val += -( 8.*(3.*t*t+2.*t*(2.*s-sig)+2.*(s*sig+mW2*mZ2))/3./t + 8.*(s-sig)*(t*u+2.*s*sig)/3./mW2/mZ2 )*pi*pi; Val += ( 4.*(s*t*t-s*(s+sig)*t+2.*s*(s*sig+mW2*mZ2)) )*TildeI4t(s,t,mW2,mZ2); Val += -( 8.*(t-mW2)*(t*t-t*(s+sig)+2.*(s*sig+mW2*mZ2))/t )*TildeI3W(s,t,mW2); swap(mW2,mZ2); del *= -1; Val += 4.*(17.*t*t+t*(11.*s-13.*sig)+17.*(s*sig+mW2*mZ2))/t + 16.*(s-sig)*(t*u+2.*s*sig)/mW2/mZ2 + 4*s*s*(2.*t-sig)/(t*(u+s)-mW2*mZ2); Val += ( 8.*(t-u)/sqr(beta) - 4.*(3.*t*t-t*(s+3.*sig)+3.*(s*sig+mW2*mZ2))/t )*log(-t/s); Val += ( 8.*(t*t-t*(2.*s+3.*mW2+mZ2)+3.*(s*sig+mW2*mZ2))/t + 8.*s*(t*(3.*s+2.*sig)-2.*mZ2*(s+sig))/(t*(u+s)-mW2*mZ2) + 8.*s*s*t*(2.*t-sig)*(t-mZ2)/sqr(t*(u+s)-mW2*mZ2) - 8.*(s-del)*(t-u)/s/sqr(beta) )*log(-t/mW2); Val += ( 4.*(s-sig)*(t-u)/sqr(beta) + 4.*(sig-3.*s)*t + 4.*(4.*s*sig-mZ2*mZ2-mW2*mW2) )*TildeI3WZ(s,mW2,mZ2,beta); Val += -( 8.*(3.*t*t+2.*t*(2.*s-sig)+2.*(s*sig+mW2*mZ2))/3./t + 8.*(s-sig)*(t*u+2.*s*sig)/3./mW2/mZ2 )*pi*pi; Val += ( 4.*(s*t*t-s*(s+sig)*t+2.*s*(s*sig+mW2*mZ2)) )*TildeI4t(s,t,mW2,mZ2); Val += -( 8.*(t-mW2)*(t*t-t*(s+sig)+2.*(s*sig+mW2*mZ2))/t )*TildeI3W(s,t,mW2); swap(mW2,mZ2); del *= -1; return Val; } /***************************************************************************/ Energy2 Fu1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) { Energy2 Val(Fd1(s,u,t,mW2,mZ2,beta)); return Val; } /***************************************************************************/ Energy4 H1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) { Energy2 sig(mZ2+mW2); Energy4 Val(0.*GeV2*GeV2); Val = 8.*t*t+8.*t*(s-sig)+s*s+6.*s*sig+mZ2*mZ2+10.*mW2*mZ2+mW2*mW2 - sqr(s-sig)*(t*u+2.*s*sig)/mW2/mZ2; Val *= ( 16.-8.*pi*pi/3.); return Val; } Energy2 t_u_Rdd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2, Energy2 mW2, Energy2 mZ2); Energy2 t_u_Rud(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2, Energy2 q1h, Energy2 q2h, Energy2 mW2, Energy2 mZ2); Energy2 t_u_Ruu(Energy2 s , Energy2 tk , Energy2 uk, Energy2 q1h, Energy2 q2h, Energy2 mW2, Energy2 mZ2); Energy4 t_u_RZds(Energy2 s ,Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2, Energy2 s2,Energy2 mW2, Energy2 mZ2); Energy4 t_u_RZda(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2, Energy2 s2, Energy2 mW2, Energy2 mZ2); Energy4 t_u_RZd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2 , Energy2 s2 , Energy2 mW2, Energy2 mZ2); Energy4 t_u_RZu(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1h, Energy2 q2h, Energy2 s2 , Energy2 mW2, Energy2 mZ2); Energy6 t_u_RZs(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2, Energy2 s2, Energy2 mW2, Energy2 mZ2); Energy6 t_u_RZa(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2, Energy2 s2, Energy2 mW2, Energy2 mZ2); Energy6 t_u_RZ(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2, Energy2 s2 , Energy2 mW2, Energy2 mZ2); /***************************************************************************/ // t_u_M_R_qqb is the real emission q + qb -> n + g matrix element // exactly as defined in Eqs. C.1 of NPB 383(1992)3-44, multiplied by // tk * uk! Energy2 MEPP2VVPowheg::t_u_M_R_qqb(realVVKinematics R) const { // First the Born variables: Energy2 s2(R.s2r()); Energy2 mW2(R.k12r()); Energy2 mZ2(R.k22r()); // Then the rest: Energy2 s(R.sr()); Energy2 tk(R.tkr()); Energy2 uk(R.ukr()); Energy2 q1(R.q1r()); Energy2 q2(R.q2r()); Energy2 q1h(R.q1hatr()); Energy2 q2h(R.q2hatr()); double cosThetaW(sqrt(1.-sin2ThetaW_)); double eZ2(eZ2_); double eZ(eZ_); double gdL(gdL_); double guL(guL_); double gdR(gdR_); double guR(guR_); // W+W- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) { double e2(sqr(gW_)*sin2ThetaW_); if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s2-mW2)/Fij2_ * (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))) +sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2) * (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } gdL = gW_/sqrt(2.); guL = 0.; } else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s2-mW2)/Fij2_ * (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))) +sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2) * (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } guL = gW_/sqrt(2.); gdL = 0.; } } // ZZ else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) { eZ = 0.; eZ2 = 0.; double gV2,gA2; gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_); gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_); guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_); gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_); gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL; else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL; else { cout << "MEPP2VVPowheg:" << endl; cout << "ZZ needs 2 down-type / 2 up-type!" << endl; } } return -2.*pi*alphaS_*Fij2_*CF_/NC_ * ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2) + 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2) + guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2) - 2.*eZ/(s2-mW2) * ( gdL * t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2) - guL * t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2) ) + eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2) ); } Energy2 t_u_Rdd(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2, Energy2 mW2, Energy2 mZ2) { Energy2 Val(0.*GeV2); Val += 4.*(q2*(uk+2.*s+q2)+q1*(s+q1))/mW2/mZ2*uk + 16.*(uk+s)/q2*uk - 4.*(2.*uk+4.*s+q2)/mW2*uk - 4.*(2.*uk+5.*s+q2+2.*q1-mW2)/mZ2*uk + 4.*q1*s*(s+q1)/mW2/mZ2 + 16.*s*(s+q2-mZ2-mW2)/q1 - 4.*s*(4.*s+q2+q1)/mW2 + 16.*mW2*mZ2*s/q1/q2 + 4.*s + 16.*mZ2*(tk-2.*mW2)/q1/q2/q2*tk*uk + 16.*(2.*mZ2+mW2-tk)/q1/q2*tk*uk + 16.*mW2*(s-mZ2-mW2)/q1/q2*uk + 16.*mZ2*(q1-2.*mW2)/q2/q2*uk + 32.*mW2*mW2*mZ2/q1/q2/q2*uk + 16.*mW2/q1*uk + 4.*uk + 8./q2*tk*uk + 4.*q1/mW2/mZ2*tk*uk - 24./q1*tk*uk - 4./mW2*tk*uk; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); Val += 4.*(q2*(uk+2.*s+q2)+q1*(s+q1))/mW2/mZ2*uk + 16.*(uk+s)/q2*uk - 4.*(2.*uk+4.*s+q2)/mW2*uk - 4.*(2.*uk+5.*s+q2+2.*q1-mW2)/mZ2*uk + 4.*q1*s*(s+q1)/mW2/mZ2 + 16.*s*(s+q2-mZ2-mW2)/q1 - 4.*s*(4.*s+q2+q1)/mW2 + 16.*mW2*mZ2*s/q1/q2 + 4.*s + 16.*mZ2*(tk-2.*mW2)/q1/q2/q2*tk*uk + 16.*(2.*mZ2+mW2-tk)/q1/q2*tk*uk + 16.*mW2*(s-mZ2-mW2)/q1/q2*uk + 16.*mZ2*(q1-2.*mW2)/q2/q2*uk + 32.*mW2*mW2*mZ2/q1/q2/q2*uk + 16.*mW2/q1*uk + 4.*uk + 8./q2*tk*uk + 4.*q1/mW2/mZ2*tk*uk - 24./q1*tk*uk - 4./mW2*tk*uk; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); return Val; } Energy2 t_u_Rud(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2, Energy2 q1h,Energy2 q2h,Energy2 mW2, Energy2 mZ2) { Energy2 Val(0.*GeV2); Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h) ) * 8./q1/q2h/q2*uk - (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2 ) * 4.*s/mZ2/q1/q2h*uk - 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk + 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk + 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk + ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h ) /mW2/mZ2*uk + 8.*s*(uk-q1h+mZ2)/q1/q2*uk + 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk + 4.*s*(-uk-q2+q1h)/mZ2/q1*uk + 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk + 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk + 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk + 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk - 8.*s*(tk+s+q1h)/mW2/q2*tk + 2.*(-tk+3.*s+q2-q1h)/mW2*tk - 8.*s*s*s/q1h/q2 - 2.*s*q2*(s+q2)/mW2/mZ2 + 2.*s*(2.*s+q2)/mZ2 + 2.*s*(2.*s+q2)/mW2 - 16.*s*s/q1h - 2.*s - 16.*s*s/q1h/q2*tk - 8.*s/q2*tk - 16.*s/q1h*tk + 6.*s/mZ2*tk + 4.*s/q1*uk + 4.*s/mZ2*uk + 12.*uk + 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk + 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk - 4.*s*s*s/q1h/q1/q2h/q2*tk*uk - 4.*s*s/q1h/q2h/q2*tk*uk - 4.*s*s/q1h/q1/q2*tk*uk + 8.*s*s/mW2/q1h/q2*tk*uk - 4.*s*s/q1h/q1/q2h*tk*uk + 4.*(s+mZ2)/mW2/q2*tk*uk - 4.*s/q1h/q2h*tk*uk - 4.*s/q1h/q1*tk*uk + 12.*s/mW2/q1h*tk*uk - (s+4.*q2)/mW2/mZ2*tk*uk - 4.*(s+2.*mZ2)/q2h/q2*tk*uk - 4.*(3.*s+2.*q1h)/q1/q2*tk*uk - 8.*mW2/q1/q2h*tk*uk + 8./q2h*tk*uk + 8./q1*tk*uk; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); swap(q1h,q2h); // Note this swap is done in accordance with MC@NLO. // It is not in NPB 383(1992)3-44 Eq.C.4! Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h) ) * 8./q1/q2h/q2*uk - (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2 ) * 4.*s/mZ2/q1/q2h*uk - 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk + 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk + 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk + ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h ) /mW2/mZ2*uk + 8.*s*(uk-q1h+mZ2)/q1/q2*uk + 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk + 4.*s*(-uk-q2+q1h)/mZ2/q1*uk + 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk + 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk + 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk + 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk - 8.*s*(tk+s+q1h)/mW2/q2*tk + 2.*(-tk+3.*s+q2-q1h)/mW2*tk - 8.*s*s*s/q1h/q2 - 2.*s*q2*(s+q2)/mW2/mZ2 + 2.*s*(2.*s+q2)/mZ2 + 2.*s*(2.*s+q2)/mW2 - 16.*s*s/q1h - 2.*s - 16.*s*s/q1h/q2*tk - 8.*s/q2*tk - 16.*s/q1h*tk + 6.*s/mZ2*tk + 4.*s/q1*uk + 4.*s/mZ2*uk + 12.*uk + 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk + 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk - 4.*s*s*s/q1h/q1/q2h/q2*tk*uk - 4.*s*s/q1h/q2h/q2*tk*uk - 4.*s*s/q1h/q1/q2*tk*uk + 8.*s*s/mW2/q1h/q2*tk*uk - 4.*s*s/q1h/q1/q2h*tk*uk + 4.*(s+mZ2)/mW2/q2*tk*uk - 4.*s/q1h/q2h*tk*uk - 4.*s/q1h/q1*tk*uk + 12.*s/mW2/q1h*tk*uk - (s+4.*q2)/mW2/mZ2*tk*uk - 4.*(s+2.*mZ2)/q2h/q2*tk*uk - 4.*(3.*s+2.*q1h)/q1/q2*tk*uk - 8.*mW2/q1/q2h*tk*uk + 8./q2h*tk*uk + 8./q1*tk*uk; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); swap(q1h,q2h); // Note this swap is done in accordance with MC@NLO. // It is not in NPB 383(1992)3-44 Eq.C.4! swap(tk,uk); swap(q1,q2h); swap(q2,q1h); Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h) ) * 8./q1/q2h/q2*uk - (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2 ) * 4.*s/mZ2/q1/q2h*uk - 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk + 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk + 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk + ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h ) /mW2/mZ2*uk + 8.*s*(uk-q1h+mZ2)/q1/q2*uk + 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk + 4.*s*(-uk-q2+q1h)/mZ2/q1*uk + 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk + 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk + 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk + 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk - 8.*s*(tk+s+q1h)/mW2/q2*tk + 2.*(-tk+3.*s+q2-q1h)/mW2*tk - 8.*s*s*s/q1h/q2 - 2.*s*q2*(s+q2)/mW2/mZ2 + 2.*s*(2.*s+q2)/mZ2 + 2.*s*(2.*s+q2)/mW2 - 16.*s*s/q1h - 2.*s - 16.*s*s/q1h/q2*tk - 8.*s/q2*tk - 16.*s/q1h*tk + 6.*s/mZ2*tk + 4.*s/q1*uk + 4.*s/mZ2*uk + 12.*uk + 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk + 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk - 4.*s*s*s/q1h/q1/q2h/q2*tk*uk - 4.*s*s/q1h/q2h/q2*tk*uk - 4.*s*s/q1h/q1/q2*tk*uk + 8.*s*s/mW2/q1h/q2*tk*uk - 4.*s*s/q1h/q1/q2h*tk*uk + 4.*(s+mZ2)/mW2/q2*tk*uk - 4.*s/q1h/q2h*tk*uk - 4.*s/q1h/q1*tk*uk + 12.*s/mW2/q1h*tk*uk - (s+4.*q2)/mW2/mZ2*tk*uk - 4.*(s+2.*mZ2)/q2h/q2*tk*uk - 4.*(3.*s+2.*q1h)/q1/q2*tk*uk - 8.*mW2/q1/q2h*tk*uk + 8./q2h*tk*uk + 8./q1*tk*uk; swap(tk,uk); swap(q1,q2h); swap(q2,q1h); swap(mW2,mZ2); swap(q1,q1h); swap(q2,q2h); Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h) ) * 8./q1/q2h/q2*uk - (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2 ) * 4.*s/mZ2/q1/q2h*uk - 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk + 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk + 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk + ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h ) /mW2/mZ2*uk + 8.*s*(uk-q1h+mZ2)/q1/q2*uk + 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk + 4.*s*(-uk-q2+q1h)/mZ2/q1*uk + 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk + 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk + 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk + 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk - 8.*s*(tk+s+q1h)/mW2/q2*tk + 2.*(-tk+3.*s+q2-q1h)/mW2*tk - 8.*s*s*s/q1h/q2 - 2.*s*q2*(s+q2)/mW2/mZ2 + 2.*s*(2.*s+q2)/mZ2 + 2.*s*(2.*s+q2)/mW2 - 16.*s*s/q1h - 2.*s - 16.*s*s/q1h/q2*tk - 8.*s/q2*tk - 16.*s/q1h*tk + 6.*s/mZ2*tk + 4.*s/q1*uk + 4.*s/mZ2*uk + 12.*uk + 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk + 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk - 4.*s*s*s/q1h/q1/q2h/q2*tk*uk - 4.*s*s/q1h/q2h/q2*tk*uk - 4.*s*s/q1h/q1/q2*tk*uk + 8.*s*s/mW2/q1h/q2*tk*uk - 4.*s*s/q1h/q1/q2h*tk*uk + 4.*(s+mZ2)/mW2/q2*tk*uk - 4.*s/q1h/q2h*tk*uk - 4.*s/q1h/q1*tk*uk + 12.*s/mW2/q1h*tk*uk - (s+4.*q2)/mW2/mZ2*tk*uk - 4.*(s+2.*mZ2)/q2h/q2*tk*uk - 4.*(3.*s+2.*q1h)/q1/q2*tk*uk - 8.*mW2/q1/q2h*tk*uk + 8./q2h*tk*uk + 8./q1*tk*uk; swap(mW2,mZ2); swap(q1,q1h); swap(q2,q2h); return Val; } Energy2 t_u_Ruu(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1h,Energy2 q2h, Energy2 mW2, Energy2 mZ2) { return t_u_Rdd(s,tk,uk,q1h,q2h,mZ2,mW2); } Energy4 t_u_RZds(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2, Energy2 s2, Energy2 mW2, Energy2 mZ2) { Energy4 Val(0.*GeV2*GeV2); Energy2 sig(mZ2+mW2); Val += ( q1*q2*(5./2.*s*s+5.*s*tk+3.*tk*tk)+(tk*uk*uk+q1*q1*q2)*(tk+s) + q1*(tk*tk*uk+s*uk*uk-s*s*tk+s*s*uk)+q1*q1*q1*(uk+s)-q1*q1*s*s2 ) * 8./q1/q2 - ( tk*tk*(4.*uk+s+q1-2.*q2)+tk*(sqr(q1+q2)-q1*s-3.*q2*s-2.*q1*q1) - q1*s*(4.*s-2.*q1-q2)+tk*uk*(q1+3.*s) ) * 4.*sig/q1/q2 - 4.*sig*sig*(s*(2.*s+q1)+tk*(uk+5./2.*tk+5.*s+q1+q2) )/mW2/mZ2 + 2.*sig*s2*(4.*sqr(s+tk)+tk*(uk+s+4.*q1+2.*q2)+2.*q1*(2.*s+q1) )/mW2/mZ2 + 4.*sig*sig*(s2+s-q1+q2)/q1/q2*tk - 16.*mW2*mZ2*(tk*uk/2.+q2*tk-q1*s)/q1/q2 - 4.*s2*s2*q1*(tk+s+q1)/mW2/mZ2 + sig*sig*sig*(uk+tk)/mW2/mZ2 + 4.*mW2*mZ2*sig*(uk+tk)/q1/q2; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); Val += ( q1*q2*(5./2.*s*s+5.*s*tk+3.*tk*tk)+(tk*uk*uk+q1*q1*q2)*(tk+s) + q1*(tk*tk*uk+s*uk*uk-s*s*tk+s*s*uk)+q1*q1*q1*(uk+s)-q1*q1*s*s2 ) * 8./q1/q2 - ( tk*tk*(4.*uk+s+q1-2.*q2)+tk*(sqr(q1+q2)-q1*s-3.*q2*s-2.*q1*q1) - q1*s*(4.*s-2.*q1-q2)+tk*uk*(q1+3.*s) ) * 4.*sig/q1/q2 - 4.*sig*sig*(s*(2.*s+q1)+tk*(uk+5./2.*tk+5.*s+q1+q2) )/mW2/mZ2 + 2.*sig*s2*(4.*sqr(s+tk)+tk*(uk+s+4.*q1+2.*q2)+2.*q1*(2.*s+q1) )/mW2/mZ2 + 4.*sig*sig*(s2+s-q1+q2)/q1/q2*tk - 16.*mW2*mZ2*(tk*uk/2.+q2*tk-q1*s)/q1/q2 - 4.*s2*s2*q1*(tk+s+q1)/mW2/mZ2 + sig*sig*sig*(uk+tk)/mW2/mZ2 + 4.*mW2*mZ2*sig*(uk+tk)/q1/q2; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); return Val; } Energy4 t_u_RZda(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2, Energy2 s2, Energy2 mW2, Energy2 mZ2) { Energy4 Val(0.*GeV2*GeV2); Val += 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2) ) /q1/q2*tk - 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk - 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk - 2.*s2*(s+2.*q2)/mZ2*tk + 8.*mW2*mZ2*mZ2/q1/q2*tk + 2.*mZ2*mZ2/mW2*tk; swap(mW2,mZ2); // N.B. Here we subtract! Val -= 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2) ) /q1/q2*tk - 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk - 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk - 2.*s2*(s+2.*q2)/mZ2*tk + 8.*mW2*mZ2*mZ2/q1/q2*tk + 2.*mZ2*mZ2/mW2*tk; swap(mW2,mZ2); swap(q1,q2); // N.B. Here we subtract! swap(tk,uk); Val -= 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2) ) /q1/q2*tk - 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk - 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk - 2.*s2*(s+2.*q2)/mZ2*tk + 8.*mW2*mZ2*mZ2/q1/q2*tk + 2.*mZ2*mZ2/mW2*tk; swap(q1,q2); swap(tk,uk); swap(mW2,mZ2); // N.B. Here we add! swap(q1,q2); swap(tk,uk); Val += 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2) ) /q1/q2*tk - 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk - 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk - 2.*s2*(s+2.*q2)/mZ2*tk + 8.*mW2*mZ2*mZ2/q1/q2*tk + 2.*mZ2*mZ2/mW2*tk; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); return Val; } Energy4 t_u_RZd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2 , Energy2 s2, Energy2 mW2, Energy2 mZ2) { Energy4 Val(0.*GeV2*GeV2); Val = t_u_RZds(s,tk,uk,q1,q2,s2,mW2,mZ2) + t_u_RZda(s,tk,uk,q1,q2,s2,mW2,mZ2); return Val; } Energy4 t_u_RZu(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1h, Energy2 q2h, Energy2 s2, Energy2 mW2, Energy2 mZ2) { Energy4 Val(0.*GeV2*GeV2); Val = t_u_RZd(s,tk,uk,q1h,q2h,s2,mZ2,mW2); return Val; } Energy6 t_u_RZs(Energy2 s,Energy2 tk,Energy2 uk,Energy2 q1,Energy2 q2, Energy2 s2,Energy2 mW2,Energy2 mZ2) { Energy6 Val(0.*GeV2*GeV2*GeV2); Energy2 sig(mZ2+mW2); Val += 2.*sig*sig*s2*( tk*(3.*uk+9.*tk+19.*s+6.*q1+4.*q2)+8.*s*s+6.*q1*s + 2.*q1*q1 )/mW2/mZ2 - 2.*sig*sig*sig*(tk*(3.*uk+6.*tk+11.*s+2.*q1+2.*q2)+2.*s*(2.*s+q1)) / mW2/mZ2 - 2.*sig*s2*s2*(tk*(uk+4.*tk+9.*s+6.*q1+2.*q2)+4.*sqr(s+q1)-2.*q1*s) /mW2/mZ2 - 16.*sig*(2.*tk*(uk/2.-tk-s+q1+q2)-s*(3.*s/2.-2.*q1)) + 8.*s2*(s*(s/2.+tk)+4.*q1*(tk+s+q1)) + 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mZ2 + 8.*sig*sig*(2.*tk+s/2.) + 2.*sig*sig*sig*sig*tk/mW2/mZ2 + 32.*mW2*mZ2*s; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); Val += 2.*sig*sig*s2*( tk*(3.*uk+9.*tk+19.*s+6.*q1+4.*q2)+8.*s*s+6.*q1*s + 2.*q1*q1 )/mW2/mZ2 - 2.*sig*sig*sig*(tk*(3.*uk+6.*tk+11.*s+2.*q1+2.*q2)+2.*s*(2.*s+q1)) / mW2/mZ2 - 2.*sig*s2*s2*(tk*(uk+4.*tk+9.*s+6.*q1+2.*q2)+4.*sqr(s+q1)-2.*q1*s) /mW2/mZ2 - 16.*sig*(2.*tk*(uk/2.-tk-s+q1+q2)-s*(3.*s/2.-2.*q1)) + 8.*s2*(s*(s/2.+tk)+4.*q1*(tk+s+q1)) + 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mZ2 + 8.*sig*sig*(2.*tk+s/2.) + 2.*sig*sig*sig*sig*tk/mW2/mZ2 + 32.*mW2*mZ2*s; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); return Val; } Energy6 t_u_RZa(Energy2 s,Energy2 tk,Energy2 uk,Energy2 q1,Energy2 q2, Energy2 s2,Energy2 mW2,Energy2 mZ2) { Energy6 Val(0.*GeV2*GeV2*GeV2); Val += - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk - 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk + 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk - 2.*s2*s2*(s+2.*q2)/mW2*tk + 2.*mZ2*mZ2*mZ2/mW2*tk + 20.*mZ2*mZ2*tk; swap(mW2,mZ2); Val -= - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk - 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk + 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk - 2.*s2*s2*(s+2.*q2)/mW2*tk + 2.*mZ2*mZ2*mZ2/mW2*tk + 20.*mZ2*mZ2*tk; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); Val -= - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk - 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk + 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk - 2.*s2*s2*(s+2.*q2)/mW2*tk + 2.*mZ2*mZ2*mZ2/mW2*tk + 20.*mZ2*mZ2*tk; swap(q1,q2); swap(tk,uk); swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); Val += - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk - 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk + 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk - 2.*s2*s2*(s+2.*q2)/mW2*tk + 2.*mZ2*mZ2*mZ2/mW2*tk + 20.*mZ2*mZ2*tk; swap(mW2,mZ2); swap(q1,q2); swap(tk,uk); return Val; } Energy6 t_u_RZ(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2, Energy2 s2, Energy2 mW2, Energy2 mZ2) { Energy6 Val(0.*GeV2*GeV2*GeV2); Val = t_u_RZs(s,tk,uk,q1,q2,s2,mW2,mZ2) + t_u_RZa(s,tk,uk,q1,q2,s2,mW2,mZ2); return Val; } /***************************************************************************/ // t_u_M_R_qg is the real emission q + qb -> n + g matrix element // exactly as defined in Eqs. C.9 of NPB 383(1992)3-44, multiplied by // tk * uk! Energy2 MEPP2VVPowheg::t_u_M_R_qg(realVVKinematics R) const { // First the Born variables: Energy2 s2(R.s2r()); Energy2 mW2(R.k12r()); Energy2 mZ2(R.k22r()); // Then the rest: Energy2 s(R.sr()); Energy2 tk(R.tkr()); Energy2 uk(R.ukr()); Energy2 q1(R.q1r()); Energy2 q2(R.q2r()); Energy2 q1h(R.q1hatr()); Energy2 q2h(R.q2hatr()); Energy2 w1(R.w1r()); Energy2 w2(R.w2r()); double cosThetaW(sqrt(1.-sin2ThetaW_)); double eZ2(eZ2_); double eZ(eZ_); double gdL(gdL_); double guL(guL_); double gdR(gdR_); double guR(guR_); // W+W- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) { double e2(sqr(gW_)*sin2ThetaW_); if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s2-mW2)/Fij2_ * (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))) +sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2) * (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } gdL = gW_/sqrt(2.); guL = 0.; } else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s2-mW2)/Fij2_ * (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))) +sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2) * (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } guL = gW_/sqrt(2.); gdL = 0.; } } // ZZ else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) { eZ = 0.; eZ2 = 0.; double gV2,gA2; gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_); gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_); guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_); gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_); gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL; else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL; else { cout << "MEPP2VVPowheg:" << endl; cout << "ZZ needs 2 down-type / 2 up-type!" << endl; } } Energy2 Val(0.*GeV2); swap(s,tk); swap(q2,w2); swap(q2h,w1); Val = -2.*pi*alphaS_*Fij2_*CF_/NC_ * ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2) + 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2) + guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2) - 2.*eZ/(s2-mW2) * ( gdL * t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2) - guL * t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2) ) + eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2) ); swap(s,tk); swap(q2,w2); swap(q2h,w1); Val *= -tk/s * TR_/CF_; return Val; } /***************************************************************************/ // t_u_M_R_gqb is the real emission g + qb -> n + q matrix element // exactly as defined in Eqs. C.9 of NPB 383(1992)3-44, multiplied by // tk * uk! Energy2 MEPP2VVPowheg::t_u_M_R_gqb(realVVKinematics R) const { // First the Born variables: Energy2 s2(R.s2r()); Energy2 mW2(R.k12r()); Energy2 mZ2(R.k22r()); // Then the rest: Energy2 s(R.sr()); Energy2 tk(R.tkr()); Energy2 uk(R.ukr()); Energy2 q1(R.q1r()); Energy2 q2(R.q2r()); Energy2 q1h(R.q1hatr()); Energy2 q2h(R.q2hatr()); Energy2 w1(R.w1r()); Energy2 w2(R.w2r()); double cosThetaW(sqrt(1.-sin2ThetaW_)); double eZ2(eZ2_); double eZ(eZ_); double gdL(gdL_); double guL(guL_); double gdR(gdR_); double guR(guR_); // W+W- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) { double e2(sqr(gW_)*sin2ThetaW_); if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s2-mW2)/Fij2_ * (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))) +sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2) * (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } gdL = gW_/sqrt(2.); guL = 0.; } else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s2-mW2)/Fij2_ * (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))) +sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2) * (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } guL = gW_/sqrt(2.); gdL = 0.; } } // ZZ else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) { eZ = 0.; eZ2 = 0.; double gV2,gA2; gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_); gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_); guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_); gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_); gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL; else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL; else { cout << "MEPP2VVPowheg:" << endl; cout << "ZZ needs 2 down-type / 2 up-type!" << endl; } } Energy2 Val(0.*GeV2); swap(s,uk); swap(q1,w1); swap(q1h,w2); Val = -2.*pi*alphaS_*Fij2_*CF_/NC_ * ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2) + 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2) + guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2) - 2.*eZ/(s2-mW2) * ( gdL * t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2) - guL * t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2) ) + eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2) ); swap(s,uk); swap(q1,w1); swap(q1h,w2); Val *= -uk/s * TR_/CF_; return Val; } /***************************************************************************/ // The following six functions are I_{dd}^{(0)}, I_{ud}^{(0)}, // I_{uu}^{(0)}, F_{u}^{(0)}, F_{d}^{(0)}, H^{(0)} from Eqs. 3.9 - 3.14 // They make up the Born matrix element. Ixx functions correspond to the // graphs with no TGC, Fx functions are due to non-TGC graphs interfering // with TGC graphs, while the H function is due purely to TGC graphs. double Idd0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2); double Iud0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2); double Iuu0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2); Energy2 Fu0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2); Energy2 Fd0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2); Energy4 H0 (Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2); /***************************************************************************/ // M_Born_WZ is the Born matrix element exactly as defined in Eqs. 3.3-3.14 // of of NPB 383(1992)3-44 (with a spin*colour averaging factor 1./4./NC_/NC_). double MEPP2VVPowheg::M_Born_WZ(bornVVKinematics B) const { Energy2 s(B.sb()); Energy2 t(B.tb()); Energy2 u(B.ub()); Energy2 mW2(B.k12b()); // N.B. the diboson masses are preserved in getting Energy2 mZ2(B.k22b()); // the 2->2 from the 2->3 kinematics. double cosThetaW(sqrt(1.-sin2ThetaW_)); double eZ2(eZ2_); double eZ(eZ_); double gdL(gdL_); double guL(guL_); double gdR(gdR_); double guR(guR_); // W+W- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) { double e2(sqr(gW_)*sin2ThetaW_); if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s-mW2)/Fij2_ * (e2*e2/s/s*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s/(s-mW2/sqr(cosThetaW))) +sqr( eZ*(guL-guR)/2./e2*s/(s-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2) * (gW_*gW_*e2/4./s *( 2./3.+2.*eZ*guL/2./e2*s/(s-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } gdL = gW_/sqrt(2.); guL = 0.; } else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) { // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set! if(quark_->id()==-antiquark_->id()) { eZ2 = 1./2.*sqr(s-mW2)/Fij2_ * (e2*e2/s/s*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s/(s-mW2/sqr(cosThetaW))) +sqr( eZ*(gdL-gdR)/2./e2*s/(s-mW2/sqr(cosThetaW)))) ); eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2) * (gW_*gW_*e2/4./s *(-1./3.+2.*eZ*gdL/2./e2*s/(s-mW2/sqr(cosThetaW)))); } else { eZ2 =0.; eZ =0.; } guL = gW_/sqrt(2.); gdL = 0.; } } // ZZ else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) { eZ = 0.; eZ2 = 0.; double gV2,gA2; gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_); gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_); guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_); gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_); gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL; else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL; else { cout << "MEPP2VVPowheg:" << endl; cout << "ZZ needs 2 down-type / 2 up-type!" << endl; } } return Fij2_/2./NC_ * ( gdL*gdL*Idd0(s,t,u,mW2,mZ2) + 2.*gdL*guL*Iud0(s,t,u,mW2,mZ2) + guL*guL*Iuu0(s,t,u,mW2,mZ2) - 2.*eZ/(s-mW2) * ( gdL*Fd0(s,t,u,mW2,mZ2) - guL*Fu0(s,t,u,mW2,mZ2) ) + eZ2/sqr(s-mW2) * H0(s,t,u,mW2,mZ2) ); } /***************************************************************************/ double Idd0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) { return 8.*((u*t/mW2/mZ2-1.)/4.+s/2.*(mW2+mZ2)/mW2/mZ2) + 8.*(u/t-mW2*mZ2/t/t); } /***************************************************************************/ double Iud0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) { return - 8.*((u*t/mW2/mZ2-1.)/4.+s/2.*(mW2+mZ2)/mW2/mZ2) + 8.*s/t/u*(mW2+mZ2); } /***************************************************************************/ double Iuu0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) { return Idd0(s,u,t,mW2,mZ2); } /***************************************************************************/ Energy2 Fd0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) { return - 8.*s*( (u*t/mW2/mZ2-1.)*(1.-(mW2+mZ2)/s-4.*mW2*mZ2/s/t)/4. + (mW2+mZ2)/2./mW2/mZ2*(s-mW2-mZ2+2.*mW2*mZ2/t) ); } /***************************************************************************/ Energy2 Fu0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) { return Fd0(s,u,t,mW2,mZ2); } /***************************************************************************/ Energy4 H0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) { return 8.*s*s*(u*t/mW2/mZ2-1.)*( 1./4.-(mW2+mZ2)/2./s + (sqr(mW2+mZ2)+8.*mW2*mZ2)/4./s/s ) + 8.*s*s*(mW2+mZ2)/mW2/mZ2*(s/2.-mW2-mZ2+sqr(mW2-mZ2)/2./s); } /***************************************************************************/ bool MEPP2VVPowheg::sanityCheck() const { bool alarm(false); Energy2 prefacs(8.*pi*alphaS_*S_.sr() /S_.xr() ); Energy2 prefacsp(8.*pi*alphaS_*SCp_.sr() /SCp_.xr() ); Energy2 prefacsm(8.*pi*alphaS_*SCm_.sr() /SCm_.xr() ); Energy2 prefacp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr()); Energy2 prefacm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr()); double xp(Cp_.xr()); double xm(Cm_.xr()); double M_B_WW(M_Born_WW(B_)); double M_B_ZZ(M_Born_ZZ(B_)); double M_V_reg_WW(M_V_regular_WW(S_)); double M_V_reg_ZZ(M_V_regular_ZZ(S_)); Energy2 t_u_qqb_WW(t_u_M_R_qqb_WW(H_)); Energy2 t_u_qqb_ZZ(t_u_M_R_qqb_ZZ(H_)); // Check that the native leading order Herwig matrix // element is equivalent to the WZ leading order matrix // element in NPB 383 (1992) 3-44, with the relevant WZ->WW // WZ->ZZ transformation applied (M_Born_). // if(fabs((lo_me2_ - M_Born_)/M_Born_)>1.e-2) { // alarm=true; // cout << "lo_me2_ - M_Born_ (%) = " // << lo_me2_ - M_Born_ << " (" // << (lo_me2_ - M_Born_)/M_Born_*100. << ")\n"; // } // Check that the transformation from NPB 383 (1992) 3-44 WZ // matrix elements to WW matrix elements actually works, by // comparing them to the explicit WW matrix elements in // NPB 410 (1993) 280-324. if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) { if(fabs((M_Born_ -M_B_WW )/M_B_WW )>1.e-6) { alarm=true; cout << "WZ->WW transformation error!\n"; cout << "M_Born_ - M_B_WW (rel) = " << M_Born_ - M_B_WW << " (" << (M_Born_ - M_B_WW)/M_B_WW << ")\n"; cout << "M_Born_ = " << M_Born_ << endl; cout << "M_B_WW = " << M_B_WW << endl; } if(fabs((M_V_regular_-M_V_reg_WW)/M_V_reg_WW)>1.e-6) { alarm=true; cout << "WZ->WW transformation error!\n"; cout << "M_V_regular_ - M_V_reg_WW (rel) = " << M_V_regular_ - M_V_reg_WW << " (" << (M_V_regular_ - M_V_reg_WW)/M_V_reg_WW << ")\n"; cout << "M_V_regular_ = " << M_V_regular_ << endl; cout << "M_V_reg_WW = " << M_V_reg_WW << endl; } if(fabs((t_u_M_R_qqb_-t_u_qqb_WW)/t_u_qqb_WW)>1.e-6) { alarm=true; cout << "WZ->WW transformation error!\n"; cout << "t_u_M_R_qqb_ - t_u_qqb_WW (rel) = " << (t_u_M_R_qqb_ - t_u_qqb_WW)/GeV2 << " (" << (t_u_M_R_qqb_ - t_u_qqb_WW)/t_u_qqb_WW << ")\n"; cout << "t_u_M_R_qqb_ = " << t_u_M_R_qqb_/GeV2 << endl; cout << "t_u_qqb_WW = " << t_u_qqb_WW /GeV2 << endl; } } // Check that the transformation from NPB 383 (1992) 3-44 WZ // matrix elements to ZZ matrix elements actually works, by // comparing them to the explicit ZZ matrix elements in // NPB 357 (1991) 409-438. if(abs(mePartonData()[2]->id())==23&&abs(mePartonData()[3]->id())==23) { if(fabs((M_Born_ -M_B_ZZ )/M_B_ZZ )>1.e-6) { alarm=true; cout << "WZ->ZZ transformation error!\n"; cout << "M_Born_ - M_B_ZZ (rel) = " << M_Born_ - M_B_ZZ << " (" << (M_Born_ - M_B_ZZ)/M_B_ZZ << ")\n"; cout << "M_Born_ = " << M_Born_ << endl; cout << "M_B_ZZ = " << M_B_ZZ << endl; } if(fabs((M_V_regular_-M_V_reg_ZZ)/M_V_reg_ZZ)>1.e-6) { alarm=true; cout << "WZ->ZZ transformation error!\n"; cout << "M_V_regular_ - M_V_reg_ZZ (rel) = " << M_V_regular_ - M_V_reg_ZZ << " (" << (M_V_regular_ - M_V_reg_ZZ)/M_V_reg_ZZ << ")\n"; cout << "M_V_regular_ = " << M_V_regular_ << endl; cout << "M_V_reg_ZZ = " << M_V_reg_ZZ << endl; } if(fabs((t_u_M_R_qqb_-t_u_qqb_ZZ)/t_u_qqb_ZZ)>1.e-6) { alarm=true; cout << "WZ->ZZ transformation error!\n"; cout << "t_u_M_R_qqb_ - t_u_qqb_ZZ (rel) = " << (t_u_M_R_qqb_ - t_u_qqb_ZZ)/GeV2 << " (" << (t_u_M_R_qqb_ - t_u_qqb_ZZ)/t_u_qqb_ZZ << ")\n"; cout << "t_u_M_R_qqb_ = " << t_u_M_R_qqb_/GeV2 << endl; cout << "t_u_qqb_ZZ = " << t_u_qqb_ZZ /GeV2 << endl; } } // Check the soft limit of the q + qbar matrix element. Energy2 absDiff_qqbs = t_u_M_R_qqb(S_) - prefacs*2.*CF_*M_Born_; double relDiff_qqbs = absDiff_qqbs / t_u_M_R_qqb(S_); if(fabs(relDiff_qqbs)>1.e-6) { alarm=true; cout << "\n"; cout << "t_u_M_R_qqb(S_) " << t_u_M_R_qqb(S_) /GeV2 << endl; cout << "t_u_M_R_qqb(S_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n" << absDiff_qqbs / GeV2 << " (" << relDiff_qqbs << ")\n"; } // Check the positive soft-collinearlimit of the q + qbar matrix element. Energy2 absDiff_qqbsp = t_u_M_R_qqb(SCp_) - prefacsp*2.*CF_*M_Born_; double relDiff_qqbsp = absDiff_qqbsp / t_u_M_R_qqb(SCp_); if(fabs(relDiff_qqbsp)>1.e-6) { alarm=true; cout << "\n"; cout << "t_u_M_R_qqb(SCp_) " << t_u_M_R_qqb(SCp_)/GeV2 << endl; cout << "t_u_M_R_qqb(SCp_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n" << absDiff_qqbsp / GeV2 << " (" << relDiff_qqbsp << ")\n"; } // Check the negative soft-collinearlimit of the q + qbar matrix element. Energy2 absDiff_qqbsm = t_u_M_R_qqb(SCm_) - prefacsm*2.*CF_*M_Born_; double relDiff_qqbsm = absDiff_qqbsm / t_u_M_R_qqb(SCm_); if(fabs(relDiff_qqbsm)>1.e-6) { alarm=true; cout << "\n"; cout << "t_u_M_R_qqb(SCm_) " << t_u_M_R_qqb(SCm_)/GeV2 << endl; cout << "t_u_M_R_qqb(SCm_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n" << absDiff_qqbsm / GeV2 << " (" << relDiff_qqbsm << ")\n"; } // Check the positive collinearlimit of the q + qbar matrix element. Energy2 absDiff_qqbp = t_u_M_R_qqb(Cp_) - prefacp*CF_*(1.+xp*xp)*M_Born_; double relDiff_qqbp = absDiff_qqbp / t_u_M_R_qqb(Cp_); if(fabs(relDiff_qqbp)>1.e-6) { alarm=true; cout << "\n"; cout << "t_u_M_R_qqb(Cp_) " << t_u_M_R_qqb(Cp_) /GeV2 << endl; cout << "t_u_M_R_qqb(Cp_)-8*pi*alphaS*sHat/x*(1-x)*Pqq*M_Born_ (rel):\n" << absDiff_qqbp / GeV2 << " (" << relDiff_qqbp << ")\n"; } // Check the negative collinearlimit of the q + qbar matrix element. Energy2 absDiff_qqbm = t_u_M_R_qqb(Cm_) - prefacm*CF_*(1.+xm*xm)*M_Born_; double relDiff_qqbm = absDiff_qqbm / t_u_M_R_qqb(Cm_); if(fabs(relDiff_qqbm)>1.e-6) { alarm=true; cout << "\n"; cout << "t_u_M_R_qqb(Cm_) " << t_u_M_R_qqb(Cm_) /GeV2 << endl; cout << "t_u_M_R_qqb(Cm_)-8*pi*alphaS*sHat/x*(1-x)*Pqq*M_Born_ (rel):\n" << absDiff_qqbm / GeV2 << " (" << relDiff_qqbm << ")\n"; } // Check the positive collinear limit of the g + qbar matrix element. Energy2 absDiff_gqbp = t_u_M_R_gqb(Cp_) - prefacp*(1.-xp)*TR_*(xp*xp+sqr(1.-xp))*M_Born_; double relDiff_gqbp = absDiff_gqbp/ t_u_M_R_gqb(Cp_); if(fabs(relDiff_gqbp)>1.e-6) { alarm=true; cout << "\n"; cout << "t_u_M_R_gqb(Cp_) " << t_u_M_R_gqb(Cp_) /GeV2 << endl; cout << "t_u_M_R_gqb(Cp_)-8*pi*alphaS*sHat/x*(1-x)*Pgq*M_Born_ (rel):\n" << absDiff_gqbp / GeV2 << " (" << relDiff_gqbp << ")\n"; } // Check the negative collinear limit of the q + g matrix element. Energy2 absDiff_qgm = t_u_M_R_qg(Cm_) - prefacm*(1.-xm)*TR_*(xm*xm+sqr(1.-xm))*M_Born_; double relDiff_qgm = absDiff_qgm / t_u_M_R_qg(Cm_); if(fabs(relDiff_qgm)>1.e-6) { alarm=true; cout << "\n"; cout << "t_u_M_R_qg(Cm_) " << t_u_M_R_qg(Cm_) /GeV2 << endl; cout << "t_u_M_R_qg(Cm_)-8*pi*alphaS*sHat/x*(1-x)*Pgq*M_Born_ (rel):\n" << absDiff_qgm / GeV2 << " (" << relDiff_qgm << ")\n"; } return alarm; } /***************************************************************************/ // M_Born_ZZ is the Born matrix element exactly as defined in Eqs. 2.18-2.19 // of of NPB 357(1991)409-438. double MEPP2VVPowheg::M_Born_ZZ(bornVVKinematics B) const { Energy2 s(B.sb()); Energy2 t(B.tb()); Energy2 u(B.ub()); Energy2 mZ2(B.k22b()); // the 2->2 from the 2->3 kinematics. double cosThetaW(sqrt(1.-sin2ThetaW_)); double gV2,gA2,gX,gY,gZ; gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_); gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_); gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_); gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_); gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gZ = gX; if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY; return 1./NC_*sqr(gZ*2.)*(t/u+u/t+4.*mZ2*s/t/u-mZ2*mZ2*(1./t/t+1./u/u)); } /***************************************************************************/ // M_V_regular_ZZ is the one-loop ZZ matrix element exactly as defined in // Eqs. B.1 & B.2 of NPB 357(1991)409-438. double MEPP2VVPowheg::M_V_regular_ZZ(realVVKinematics S) const { Energy2 s(S.bornVariables().sb()); Energy2 t(S.bornVariables().tb()); Energy2 u(S.bornVariables().ub()); Energy2 mZ2(S.k22r()); // the 2->2 from the 2->3 kinematics. double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44. double cosThetaW(sqrt(1.-sin2ThetaW_)); double gV2,gA2,gX,gY,gZ; gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_); gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_); gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_); gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_); gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gZ = gX; if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY; double M_V_reg(0.); M_V_reg = 2.*s*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/sqr(4.*pi)/2. *( 2.*sqr(t+mZ2)/sqr(beta)/s/t/u + 4.*s/(t-mZ2)/u - ( 16.*t*t*t+(28.*s-68.*mZ2)*t*t+(18.*s*s-36.*mZ2*s+88.*mZ2*mZ2)*t + 18.*mZ2*mZ2*s-36.*mZ2*mZ2*mZ2 )/t/t/s/u + ( 12.*s/(t-mZ2)/u-4.*mZ2*s/sqr(t-mZ2)/u+2.*(t+4.*s)/s/u - 6.*(s*s+mZ2*mZ2)/s/t/u+6.*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u )*log(-t/mZ2) + ( - ( 5.*t*t*t+(8.*s-18.*mZ2)*t*t+(6.*s*s+25.*mZ2*mZ2)*t + 6.*mZ2*mZ2*s-12.*mZ2*mZ2*mZ2 )/t/t/s/u - 12.*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u + ( 3.*t*t-26.*mZ2*t-25.*mZ2*mZ2)/sqr(beta)/s/t/u )*log(s/mZ2) + ( (-2.*t*t+8.*mZ2*t-2.*s*s-12.*mZ2*mZ2)/u + 4.*mZ2*mZ2*(2.*mZ2-s)/t/u) / (s*t) * ( 2.*sqr(log(-t/mZ2))-4.*log(-t/mZ2)*log((mZ2-t)/mZ2)-4.*ReLi2(t/mZ2)) + ( 4.*(t*t-5.*mZ2*t+s*s+10.*mZ2*mZ2)/s/u + 4.*mZ2*(-s*s+2.*mZ2*s-10.*mZ2*mZ2)/s/t/u + 8.*mZ2*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u ) / (t-mZ2) * (pi*pi/2.+log(-t/mZ2)*log(-t/s)-1./2.*sqr(log(-t/mZ2))) + ( ( (2.*s-3.*mZ2)*t*t+(6.*mZ2*mZ2-8.*mZ2*s)*t+2.*s*s*s-4.*mZ2*s*s + 12.*mZ2*mZ2*s-3.*mZ2*mZ2*mZ2 ) /s/t/u + 12.*mZ2*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u - (mZ2*t*t-30.*mZ2*mZ2*t-27.*mZ2*mZ2*mZ2)/beta/beta/s/t/u ) / (beta*s) * (pi*pi/3.+sqr(log((1.-beta)/(1.+beta)))+4.*ReLi2(-(1.-beta)/(1.+beta))) + (4.*(t+4.*s-4.*mZ2)/3./s/u+4.*sqr(s-2.*mZ2)/3./s/t/u)*pi*pi ); swap(t,u); M_V_reg += 2.*s*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/sqr(4.*pi)/2. *( 2.*sqr(t+mZ2)/sqr(beta)/s/t/u + 4.*s/(t-mZ2)/u - ( 16.*t*t*t+(28.*s-68.*mZ2)*t*t+(18.*s*s-36.*mZ2*s+88.*mZ2*mZ2)*t + 18.*mZ2*mZ2*s-36.*mZ2*mZ2*mZ2 )/t/t/s/u + ( 12.*s/(t-mZ2)/u-4.*mZ2*s/sqr(t-mZ2)/u+2.*(t+4.*s)/s/u - 6.*(s*s+mZ2*mZ2)/s/t/u+6.*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u )*log(-t/mZ2) + ( - ( 5.*t*t*t+(8.*s-18.*mZ2)*t*t+(6.*s*s+25.*mZ2*mZ2)*t + 6.*mZ2*mZ2*s-12.*mZ2*mZ2*mZ2 )/t/t/s/u - 12.*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u + ( 3.*t*t-26.*mZ2*t-25.*mZ2*mZ2)/sqr(beta)/s/t/u )*log(s/mZ2) + ( (-2.*t*t+8.*mZ2*t-2.*s*s-12.*mZ2*mZ2)/u + 4.*mZ2*mZ2*(2.*mZ2-s)/t/u) / (s*t) * ( 2.*sqr(log(-t/mZ2))-4.*log(-t/mZ2)*log((mZ2-t)/mZ2)-4.*ReLi2(t/mZ2)) + ( 4.*(t*t-5.*mZ2*t+s*s+10.*mZ2*mZ2)/s/u + 4.*mZ2*(-s*s+2.*mZ2*s-10.*mZ2*mZ2)/s/t/u + 8.*mZ2*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u ) / (t-mZ2) * (pi*pi/2.+log(-t/mZ2)*log(-t/s)-1./2.*sqr(log(-t/mZ2))) + ( ( (2.*s-3.*mZ2)*t*t+(6.*mZ2*mZ2-8.*mZ2*s)*t+2.*s*s*s-4.*mZ2*s*s + 12.*mZ2*mZ2*s-3.*mZ2*mZ2*mZ2 ) /s/t/u + 12.*mZ2*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u - (mZ2*t*t-30.*mZ2*mZ2*t-27.*mZ2*mZ2*mZ2)/beta/beta/s/t/u ) / (beta*s) * (pi*pi/3.+sqr(log((1.-beta)/(1.+beta)))+4.*ReLi2(-(1.-beta)/(1.+beta))) + (4.*(t+4.*s-4.*mZ2)/3./s/u+4.*sqr(s-2.*mZ2)/3./s/t/u)*pi*pi ); return M_V_reg; } /***************************************************************************/ // t_u_M_R_qqb_ZZ is the real emission q + qb -> n + g matrix element // exactly as defined in Eqs. C.1 of NPB 357(1991)409-438, multiplied by // tk * uk! Energy2 MEPP2VVPowheg::t_u_M_R_qqb_ZZ(realVVKinematics R) const { // First the Born variables: Energy2 mZ2(R.k22r()); // Then the rest: Energy2 s(R.sr()); Energy2 tk(R.tkr()); Energy2 uk(R.ukr()); Energy2 q1(R.q1r()); Energy2 q2(R.q2r()); Energy2 q1h(R.q1hatr()); Energy2 q2h(R.q2hatr()); double cosThetaW(sqrt(1.-sin2ThetaW_)); double gV2,gA2,gX,gY,gZ; gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_); gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_); gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_); gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_); gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.; gZ = gX; if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY; Energy2 t_u_qqb(0.*GeV2); t_u_qqb = (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2. * ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk - 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s) )/q1h/q1/q2h/s*tk + 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s + ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk) + 2.*mZ2*mZ2*(uk+tk+2.*s) )/q1h/q1/q2/s*tk + ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s) )/q1h/q2/s - ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk + q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s + 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s - 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk + (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s + q1*(uk+s)*(uk+tk)/q1h/q2h/s + (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk + (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk + (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk - (q1*q1+q2*q2)/q1/q2 - 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk ); swap(tk ,uk ); swap(q1 ,q2 ); swap(q1h,q2h); t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2. * ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk - 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s) )/q1h/q1/q2h/s*tk + 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s + ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk) + 2.*mZ2*mZ2*(uk+tk+2.*s) )/q1h/q1/q2/s*tk + ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s) )/q1h/q2/s - ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk + q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s + 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s - 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk + (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s + q1*(uk+s)*(uk+tk)/q1h/q2h/s + (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk + (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk + (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk - (q1*q1+q2*q2)/q1/q2 - 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk ); swap(tk ,uk ); swap(q1 ,q2 ); swap(q1h,q2h); swap(q1 ,q1h); swap(q2 ,q2h); t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2. * ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk - 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s) )/q1h/q1/q2h/s*tk + 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s + ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk) + 2.*mZ2*mZ2*(uk+tk+2.*s) )/q1h/q1/q2/s*tk + ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s) )/q1h/q2/s - ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk + q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s + 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s - 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk + (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s + q1*(uk+s)*(uk+tk)/q1h/q2h/s + (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk + (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk + (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk - (q1*q1+q2*q2)/q1/q2 - 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk ); swap(q1 ,q1h); swap(q2 ,q2h); swap(tk ,uk ); swap(q1 ,q2h); swap(q2 ,q1h); t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2. * ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk - 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s) )/q1h/q1/q2h/s*tk + 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s + ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk) + 2.*mZ2*mZ2*(uk+tk+2.*s) )/q1h/q1/q2/s*tk + ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s) )/q1h/q2/s - ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk + q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s + 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s - 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk + (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s + q1*(uk+s)*(uk+tk)/q1h/q2h/s + (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk + (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk + (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk - (q1*q1+q2*q2)/q1/q2 - 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk ); swap(tk ,uk ); swap(q1 ,q2h); swap(q2 ,q1h); return t_u_qqb; } /***************************************************************************/ // M_B_WW is the Born matrix element exactly as defined in Eqs. 3.2-3.8 // of of NPB 410(1993)280-384. double MEPP2VVPowheg::M_Born_WW(bornVVKinematics B) const { Energy2 s(B.sb()); Energy2 t(B.tb()); Energy2 u(B.ub()); Energy2 mW2(B.k12b()); // N.B. the diboson masses are preserved in getting bool up_type = abs(quark_->id())%2==0 ? true : false; double Qi = up_type ? 2./3. : -1./3. ; double giL = up_type ? guL_/2. : gdL_/2.; double giR = up_type ? guR_/2. : gdR_/2.; double e2 = sqr(gW_)*sin2ThetaW_; double cos2ThetaW(1.-sin2ThetaW_); double ctt_i(gW_*gW_*gW_*gW_/16.); InvEnergy2 cts_i(gW_*gW_*e2/4./s *(Qi+2.*eZ_*giL/e2*s/(s-mW2/cos2ThetaW))); InvEnergy4 css_i(e2*e2/s/s*(sqr(Qi+eZ_*(giL+giR)/e2*s/(s-mW2/cos2ThetaW)) +sqr( eZ_*(giL-giR)/e2*s/(s-mW2/cos2ThetaW))) ); ctt_i *= 8.*Fij2_/gW_/gW_; cts_i *= sqrt(8.*Fij2_/gW_/gW_); if(quark_->id()!=-antiquark_->id()) { cts_i = 0./GeV2; css_i = 0./GeV2/GeV2; } if(!up_type) swap(t,u); double signf = up_type ? 1. : -1.; return 1./4./NC_ * ( ctt_i*( 16.*(u*t/mW2/mW2-1.)*(1./4.+mW2*mW2/t/t)+16.*s/mW2) - cts_i*( 16.*(u*t/mW2/mW2-1.)*(s/4.-mW2/2.-mW2*mW2/t) + 16.*s*(s/mW2-2.+2.*mW2/t) ) *signf + css_i*( 8.*(u*t/mW2/mW2-1.)*(s*s/4.-s*mW2+3.*mW2*mW2) + 8.*s*s*(s/mW2-4.) ) ); } /***************************************************************************/ // M_V_regular_WW is the regular part of the one-loop WW matrix element // exactly as defined in Eqs. C.1 - C.7 of of NPB 410(1993)280-324 *** // modulo a factor 1/(2s) ***, which is a flux factor that those authors // absorb in the matrix element. double MEPP2VVPowheg::M_V_regular_WW(realVVKinematics S) const { Energy2 s(S.bornVariables().sb()); Energy2 t(S.bornVariables().tb()); Energy2 u(S.bornVariables().ub()); Energy2 mW2(S.k12r()); // N.B. the diboson masses are preserved in getting double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44. bool up_type = abs(quark_->id())%2==0 ? true : false; double Qi = up_type ? 2./3. : -1./3.; double giL = up_type ? guL_/2. : gdL_/2.; double giR = up_type ? guR_/2. : gdR_/2.; double e2 = sqr(gW_)*sin2ThetaW_; double cos2ThetaW(1.-sin2ThetaW_); double ctt_i(gW_*gW_*gW_*gW_/16.); InvEnergy2 cts_i(gW_*gW_*e2/4./s *(Qi+2.*eZ_*giL/e2*s/(s-mW2/cos2ThetaW))); InvEnergy4 css_i(e2*e2/s/s*(sqr(Qi+eZ_*(giL+giR)/e2*s/(s-mW2/cos2ThetaW)) +sqr( eZ_*(giL-giR)/e2*s/(s-mW2/cos2ThetaW))) ); ctt_i *= 8.*Fij2_/gW_/gW_; cts_i *= sqrt(8.*Fij2_/gW_/gW_); if(quark_->id()!=-antiquark_->id()) { cts_i = 0./GeV2; css_i = 0./GeV2/GeV2; } if(!up_type) swap(t,u); double signf = up_type ? 1. : -1.; InvEnergy4 TildeI4 = ( 2.*sqr(log(-t/mW2))-4.*log((mW2-t)/mW2)*log(-t/mW2) - 4.*ReLi2(t/mW2) )/s/t; InvEnergy2 TildeI3t = 1./(mW2-t) *(sqr(log(mW2/s))/2.-sqr(log(-t/s))/2.-pi*pi/2.); InvEnergy2 TildeI3l = 1./s/beta*( 4.*ReLi2((beta-1.)/(beta+1.)) + sqr(log((1.-beta)/(1.+beta))) + pi*pi/3.); double Fup1_st(0.); Fup1_st = 4.*(80.*t*t+73.*s*t-140.*mW2*t+72.*mW2*mW2)/t/t - 4.*sqr(4.*t+s)/s/beta/beta/t - 128.*(t+2.*s)/mW2 + 64.*t*(t+s)/mW2/mW2 - (32.*(t*t-3.*s*t-3.*mW2*mW2)/t/t+128.*s/(t-mW2))*log(-t/mW2) + ( 8.*(6.*t*t+8.*s*t-19.*mW2*t+12.*mW2*mW2)/t/t - (32.*t*t-128.*s*t-26.*s*s)/s/beta/beta/t + 6.*sqr(4.*t+s)/s/sqr(sqr(beta))/t )*log(s/mW2) + 32.*s*(2.*mW2*mW2/t-u)*TildeI4 - 64.*(t-mW2)*(2.*mW2*mW2/t/t-u/t)*TildeI3t + ( (16.*t*(4.*mW2-u)-49.*s*s+72.*mW2*s-48.*mW2*mW2)/2./t + 2.*(8.*t*t-14.*s*t-3.*s*s)/beta/beta/t - 3.*sqr(4.*t+s)/2./sqr(sqr(beta))/t )*TildeI3l + 32./3.*( 2.*(t+2.*s)/mW2 - (3.*t+2.*s-4.*mW2)/t - t*(t+s)/mW2/mW2 )*pi*pi; Energy2 Jup1_st(0.*GeV2); Jup1_st = -128.*(t*t+2.*s*t+2.*s*s)/mW2 - 16.*(t*t-21.*s*t-26.*mW2*t+34.*mW2*s+17.*mW2*mW2)/t + 64.*s*t*(t+s)/mW2/mW2 +32.*s*s/(t-mW2) + ( 16.*(t-5.*s+2.*mW2)-48.*mW2*(2.*s+mW2)/t + 64.*s*(2.*t+s)/(t-mW2) - 32.*s*s*t/sqr(t-mW2) )*log(-t/mW2) + ( 16.*(4.*t+s)/beta/beta - 16.*(3.*t-2.*s) + 48.*mW2*(2.*t-2.*s-mW2)/t )*log(s/mW2) + 16.*s*(t*(2.*s+u)-2.*mW2*(2.*s+mW2))*TildeI4 + 32.*(t-mW2)*(2.*mW2*(2.*s+mW2)/t-2.*s-u)*TildeI3t + ( 32.*s*t-12.*s*s+32.*mW2*mW2 - 16.*mW2*(2.*t+7.*s)-4.*s*(4.*t+s)/beta/beta )*TildeI3l + 32./3.*( 2.*(t*t+2.*s*t+2.*s*s)/mW2 - s*t*(t+s)/mW2/mW2-2.*mW2*(2.*t-2.*s-mW2)/t-t-4.*s )*pi*pi; Energy4 Kup1_st(0.*GeV2*GeV2); Kup1_st = 16.*( 12.*t*t+20.*s*t-24.*mW2*t+17.*s*s-4.*mW2*s+12.*mW2*mW2 + s*s*t*(t+s)/mW2/mW2-2.*s*(2.*t*t+3.*s*t+2.*s*s)/mW2) *(2.-pi*pi/3.); return pi*alphaS_*CF_/NC_/(sqr(4.*pi)) * ( ctt_i*Fup1_st - cts_i*Jup1_st*signf + css_i*Kup1_st ); } /***************************************************************************/ // t_u_M_R_qqb is the real emission q + qb -> n + g matrix element // exactly as defined in Eqs. C.1 of NPB 383(1992)3-44, multiplied by // tk * uk! Energy2 MEPP2VVPowheg::t_u_M_R_qqb_WW(realVVKinematics R) const { // First the Born variables: Energy2 s2(R.s2r()); Energy2 mW2(R.k12r()); // Then the rest: Energy2 s(R.sr()); Energy2 tk(R.tkr()); Energy2 uk(R.ukr()); Energy2 q1(R.q1r()); Energy2 q2(R.q2r()); Energy2 q1h(R.q1hatr()); Energy2 q2h(R.q2hatr()); bool up_type = abs(quark_->id())%2==0 ? true : false; double Qi = up_type ? 2./3. : -1./3.; double giL = up_type ? guL_/2. : gdL_/2.; double giR = up_type ? guR_/2. : gdR_/2.; double e2 = sqr(gW_)*sin2ThetaW_; double cos2ThetaW(1.-sin2ThetaW_); double ctt_i(gW_*gW_*gW_*gW_/16.); InvEnergy2 cts_i(gW_*gW_*e2/4./s2*(Qi+2.*eZ_*giL/e2*s2/(s2-mW2/cos2ThetaW))); InvEnergy4 css_i(e2*e2/s2/s2*(sqr(Qi+eZ_*(giL+giR)/e2*s2/(s2-mW2/cos2ThetaW)) +sqr( eZ_*(giL-giR)/e2*s2/(s2-mW2/cos2ThetaW))) ); ctt_i *= 8.*Fij2_/gW_/gW_; cts_i *= sqrt(8.*Fij2_/gW_/gW_); if(quark_->id()!=-antiquark_->id()) { cts_i = 0./GeV2; css_i = 0./GeV2/GeV2; } if(!up_type) { swap(q1,q1h); swap(q2,q2h); } double signf = up_type ? 1. : -1.; Energy2 t_u_Xup(0.*GeV2); Energy4 t_u_Yup(0.*GeV2*GeV2); Energy6 t_u_Zup(0.*GeV2*GeV2*GeV2); t_u_Xup = 32.*mW2*(tk*uk+3.*q2*uk+q2*s+q1*q2)/q1/q2/q2*tk + 32.*mW2*q1/q2/q2*uk - 64.*mW2*s/q2 - 32.*tk*(uk-q2)/q1/q2*tk + 64.*mW2*mW2*mW2/q1/q1/q2*tk - 16.*(2.*tk-2.*s-q2)/q2*uk + 16.*s*(2.*s+2.*q1+q2/2.)/q2 - 8.*(4.*tk+uk+9.*s+2.*q2+2.*q1)/mW2*tk - 16.*s*(2.*s+q1)/mW2 - 64.*mW2*mW2*(tk*uk+q2*tk+q1*uk-q2*s/2.)/q1/q2/q2 + 8.*s2*q1*(tk+s+q1)/mW2/mW2; swap(tk,uk); swap(q1,q2); t_u_Xup += 32.*mW2*(tk*uk+3.*q2*uk+q2*s+q1*q2)/q1/q2/q2*tk + 32.*mW2*q1/q2/q2*uk - 64.*mW2*s/q2 - 32.*tk*(uk-q2)/q1/q2*tk + 64.*mW2*mW2*mW2/q1/q1/q2*tk - 16.*(2.*tk-2.*s-q2)/q2*uk + 16.*s*(2.*s+2.*q1+q2/2.)/q2 - 8.*(4.*tk+uk+9.*s+2.*q2+2.*q1)/mW2*tk - 16.*s*(2.*s+q1)/mW2 - 64.*mW2*mW2*(tk*uk+q2*tk+q1*uk-q2*s/2.)/q1/q2/q2 + 8.*s2*q1*(tk+s+q1)/mW2/mW2; swap(tk,uk); swap(q1,q2); t_u_Yup = - 16.*tk*(uk*(uk+s+q1)+q2*(s-2.*q1))/q1/q2*tk - 32.*mW2*mW2*s/q2 - 32.*mW2*mW2*mW2/q1/q2*tk + 16.*(2.*q2*uk+s*s+q1*s+5.*q2*s+q1*q2+2.*q2*q2)/q2*tk - 16.*(q2*q2+s*s-q2*s)/q1*tk + 16.*s*(q1*s+3./2.*q2*s+q1*q2-q1*q1)/q2 + 16.*mW2*tk*(4.*uk+s+q1-2.*q2)/q1/q2*tk + 16.*mW2*(3.*s*uk+q1*uk-q1*s-3.*q2*s-q1*q1+q2*q2)/q1/q2*tk + 16.*mW2*s*(q2-4.*s+2.*q1)/q2 - 8.*s2*(4.*tk+uk+9.*s+4.*q1+2.*q2)/mW2*tk - 16.*s2*(2.*s*s+2.*q1*s+q1*q1)/mW2 - 32.*mW2*mW2*(tk+uk/2.+2.*s-q1)/q1/q2*tk + 8.*s2*s2*q1*(tk+s+q1)/mW2/mW2; swap(tk,uk); swap(q1,q2); t_u_Yup += - 16.*tk*(uk*(uk+s+q1)+q2*(s-2.*q1))/q1/q2*tk - 32.*mW2*mW2*s/q2 - 32.*mW2*mW2*mW2/q1/q2*tk + 16.*(2.*q2*uk+s*s+q1*s+5.*q2*s+q1*q2+2.*q2*q2)/q2*tk - 16.*(q2*q2+s*s-q2*s)/q1*tk + 16.*s*(q1*s+3./2.*q2*s+q1*q2-q1*q1)/q2 + 16.*mW2*tk*(4.*uk+s+q1-2.*q2)/q1/q2*tk + 16.*mW2*(3.*s*uk+q1*uk-q1*s-3.*q2*s-q1*q1+q2*q2)/q1/q2*tk + 16.*mW2*s*(q2-4.*s+2.*q1)/q2 - 8.*s2*(4.*tk+uk+9.*s+4.*q1+2.*q2)/mW2*tk - 16.*s2*(2.*s*s+2.*q1*s+q1*q1)/mW2 - 32.*mW2*mW2*(tk+uk/2.+2.*s-q1)/q1/q2*tk + 8.*s2*s2*q1*(tk+s+q1)/mW2/mW2; swap(tk,uk); swap(q1,q2); t_u_Zup = 8.*s2*(9.*tk+3.*uk+20.*s+10.*q1+4.*q2)*tk + 8.*s2*(17./2.*s*s+10.*q1*s+6.*q1*q1) - 4.*s2*s2*(4.*tk+uk+9.*s+6.*q1+2.*q2)/mW2*tk - 8.*s2*s2*(2.*s*s+3.*q1*s+2.*q1*q1)/mW2 - 16.*mW2*(2.*tk+5.*uk+7.*s+6.*q1+6.*q2)*tk - 16.*mW2*s*(s+6.*q1) + 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mW2 + 48.*mW2*mW2*s2; swap(tk,uk); swap(q1,q2); t_u_Zup += 8.*s2*(9.*tk+3.*uk+20.*s+10.*q1+4.*q2)*tk + 8.*s2*(17./2.*s*s+10.*q1*s+6.*q1*q1) - 4.*s2*s2*(4.*tk+uk+9.*s+6.*q1+2.*q2)/mW2*tk - 8.*s2*s2*(2.*s*s+3.*q1*s+2.*q1*q1)/mW2 - 16.*mW2*(2.*tk+5.*uk+7.*s+6.*q1+6.*q2)*tk - 16.*mW2*s*(s+6.*q1) + 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mW2 + 48.*mW2*mW2*s2; swap(tk,uk); swap(q1,q2); return -pi*alphaS_*CF_/NC_ * ( ctt_i*t_u_Xup - cts_i*t_u_Yup*signf + css_i*t_u_Zup ); } /***************************************************************************/ // The game here is to get this helicity amplitude squared to return all the // same values as t_u_M_R_qqb above, TIMES a further factor tk*uk! Energy2 MEPP2VVPowheg::t_u_M_R_qqb_hel_amp(realVVKinematics R) const { using namespace ThePEG::Helicity; // qqb_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half, // PDT::Spin1,PDT::Spin1, // PDT::Spin1)); double sum_hel_amps_sqr(0.); tcPDPtr p1data(quark_); tcPDPtr p2data(antiquark_); tcPDPtr k1data(mePartonData()[2]); tcPDPtr k2data(mePartonData()[3]); tcPDPtr kdata(getParticleData(ParticleID::g)); if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); SpinorWaveFunction qSpinor(R.p1r(),p1data,incoming); SpinorBarWaveFunction qbSpinor(R.p2r(),p2data,incoming); vector q; vector qb; for(unsigned int ix=0;ix<2;ix++) { qSpinor.reset(ix); qbSpinor.reset(ix); q.push_back(qSpinor); qb.push_back(qbSpinor); } VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing); VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing); vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } VectorWaveFunction gPolarization(R.kr(),kdata,outgoing); vector g; for(unsigned int ix=0;ix<3;ix+=2) { gPolarization.reset(ix); g.push_back(gPolarization); } AbstractFFVVertexPtr ffg = FFGvertex_; AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_; // Collecting information for intermediate fermions vector tc; if(abs(k1data->id())==24&&abs(k2data->id())==24) { if(abs(p1data->id())%2==0) for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix)); else for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix)); } else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data); else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data); // Loop over helicities summing the relevant diagrams for(unsigned int p1hel=0;p1hel<2;++p1hel) { for(unsigned int p2hel=0;p2hel<2;++p2hel) { for(unsigned int khel=0;khel<2;++khel) { SpinorWaveFunction p1_k = ffg->evaluate(mu_UV2(),5,p1data,q[p1hel],g[khel]); SpinorBarWaveFunction p2_k = ffg->evaluate(mu_UV2(),5,p2data,qb[p2hel],g[khel]); for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { // If helicity is exactly conserved (massless quarks) skip if p1hel=p2hel // but if the production ME is required first fill it with (0.,0.). if((p1hel==p2hel)&&helicityConservation_) { // if(getMatrix) { // if(khel==0) // qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,0) = Complex(0.,0.); // else // qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,2) = Complex(0.,0.); // } continue; } vector diagrams; // Get all t-channel diagram contributions tcPDPtr intermediate_t; for(unsigned int ix=0;ixid()==24&&k2data->id()==-24)) ? p2data : tc[ix]; SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_t,q[p1hel],v1[k1hel]); SpinorBarWaveFunction p2_v2 = ffv2->evaluate(scale(),5,intermediate_t,qb[p2hel],v2[k2hel]); // First calculate all the off-shell fermion currents // Now calculate the 6 t-channel diagrams // q+qb->g+v1+v2, q+qb->v1+g+v2, q+qb->v1+v2+g if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) { diagrams.push_back(ffv1->evaluate(scale(),p1_k,p2_v2,v1[k1hel])); diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v1,p2_v2,g[khel])); diagrams.push_back(ffv2->evaluate(scale(),p1_v1,p2_k,v2[k2hel])); } intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix]; SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_t,q[p1hel],v2[k2hel]); SpinorBarWaveFunction p2_v1 = ffv1->evaluate(scale(),5,intermediate_t,qb[p2hel],v1[k1hel]); // q+qb->g+v2+v1, q+qb->v2+g+v1, q+qb->v2+v1+g if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) { diagrams.push_back(ffv2->evaluate(scale(),p1_k,p2_v1,v2[k2hel])); diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v2,p2_v1,g[khel])); diagrams.push_back(ffv1->evaluate(scale(),p1_v2,p2_k,v1[k1hel])); } } // Note: choosing 3 as the second argument in WWWvertex_->evaluate() // sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which // means the propagator does not contain a width factor (which is // good re. gauge invariance). // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams if(abs(k1data->id())==24&&k2data->id()==23) { // The off-shell s-channel boson current VectorWaveFunction k1_k2 = WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]); // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g diagrams.push_back(ffv1->evaluate(scale(),p1_k,qb[p2hel],k1_k2)); diagrams.push_back(ffv1->evaluate(scale(),q[p1hel],p2_k,k1_k2)); } // If W+W- calculate the four V+jet-like s-channel diagrams if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) { // The off-shell s-channel boson current VectorWaveFunction k1_k2; // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g, tcPDPtr Z0 = getParticleData(ParticleID::Z0); k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]); diagrams.push_back(FFZvertex_->evaluate(scale(),p1_k,qb[p2hel],k1_k2)); diagrams.push_back(FFZvertex_->evaluate(scale(),q[p1hel],p2_k,k1_k2)); // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g, tcPDPtr gamma = getParticleData(ParticleID::gamma); k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]); diagrams.push_back(FFPvertex_->evaluate(scale(),p1_k,qb[p2hel],k1_k2)); diagrams.push_back(FFPvertex_->evaluate(scale(),q[p1hel],p2_k,k1_k2)); } // Add up all diagrams to get the total amplitude: Complex hel_amp(0.); for(unsigned int ix=0;ixid()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.; return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2; } /***************************************************************************/ // The game here is to get this helicity amplitude squared to return all the // same values as t_u_M_R_qg above, TIMES a further factor tk*uk! Energy2 MEPP2VVPowheg::t_u_M_R_qg_hel_amp(realVVKinematics R) const { using namespace ThePEG::Helicity; // qg_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1, // PDT::Spin1,PDT::Spin1, // PDT::Spin1Half)); double sum_hel_amps_sqr(0.); tcPDPtr p1data(quark_); tcPDPtr p2data(getParticleData(ParticleID::g)); tcPDPtr k1data(mePartonData()[2]); tcPDPtr k2data(mePartonData()[3]); tcPDPtr kdata (antiquark_->CC()); if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); SpinorWaveFunction qinSpinor(R.p1r(),p1data,incoming); SpinorBarWaveFunction qoutSpinor(R.kr(),kdata,outgoing); vector qin; vector qout; for(unsigned int ix=0;ix<2;ix++) { qinSpinor.reset(ix); qoutSpinor.reset(ix); qin.push_back(qinSpinor); qout.push_back(qoutSpinor); } VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing); VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing); vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } VectorWaveFunction gPolarization(R.p2r(),p2data,incoming); vector g; for(unsigned int ix=0;ix<3;ix+=2) { gPolarization.reset(ix); g.push_back(gPolarization); } AbstractFFVVertexPtr ffg = FFGvertex_; AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_; // Collecting information for intermediate fermions vector tc; if(abs(k1data->id())==24&&abs(k2data->id())==24) { if(abs(p1data->id())%2==0) for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix)); else for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix)); } else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data); else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC()); // Loop over helicities summing the relevant diagrams for(unsigned int p1hel=0;p1hel<2;++p1hel) { for(unsigned int p2hel=0;p2hel<2;++p2hel) { for(unsigned int khel=0;khel<2;++khel) { SpinorWaveFunction p1_p2 = ffg->evaluate(mu_UV2(),5,p1data,qin[p1hel],g[p2hel]); SpinorBarWaveFunction p2_k = ffg->evaluate(mu_UV2(),5,kdata->CC(),qout[khel],g[p2hel]); for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { // If helicity is exactly conserved (massless quarks) skip if p1hel!=khel // but if the production ME is required first fill it with (0.,0.). if((p1hel!=khel)&&helicityConservation_) { // if(getMatrix) { // if(p2hel==0) // qg_hel_amps_(p1hel,0,k1hel,k2hel,khel) = Complex(0.,0.); // else // qg_hel_amps_(p1hel,2,k1hel,k2hel,khel) = Complex(0.,0.); // } continue; } vector diagrams; // Get all t-channel diagram contributions tcPDPtr intermediate_q; for(unsigned int ix=0;ixid()==24&&k2data->id()==-24)) ? antiquark_ : tc[ix]; SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_q,qin[p1hel],v1[k1hel]); SpinorBarWaveFunction k_v2 = ffv2->evaluate(scale(),5,intermediate_q,qout[khel],v2[k2hel]); // First calculate all the off-shell fermion currents // Now calculate the 6 abelian diagrams // q+g->v1+v2+q with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones. if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) { diagrams.push_back(ffv2->evaluate(scale(),p1_v1,p2_k,v2[k2hel])); diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v1,k_v2,g[p2hel])); diagrams.push_back(ffv1->evaluate(scale(),p1_p2,k_v2,v1[k1hel])); } intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix]; SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_q,qin[p1hel],v2[k2hel]); SpinorBarWaveFunction k_v1 = ffv1->evaluate(scale(),5,intermediate_q,qout[khel],v1[k1hel]); // q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones. if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) { diagrams.push_back(ffv1->evaluate(scale(),p1_v2,p2_k,v1[k1hel])); diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v2,k_v1,g[p2hel])); diagrams.push_back(ffv2->evaluate(scale(),p1_p2,k_v1,v2[k2hel])); } } // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams if(abs(k1data->id())==24&&k2data->id()==23) { // The off-shell s-channel boson current VectorWaveFunction k1_k2 = WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]); // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g diagrams.push_back(ffv1->evaluate(scale(),p1_p2,qout[khel],k1_k2)); diagrams.push_back(ffv1->evaluate(scale(),qin[p1hel],p2_k,k1_k2)); } // If W+W- calculate the four V+jet-like s-channel diagrams if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==kdata->id())) { // The off-shell s-channel boson current VectorWaveFunction k1_k2; // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g, tcPDPtr Z0 = getParticleData(ParticleID::Z0); k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]); diagrams.push_back(FFZvertex_->evaluate(scale(),p1_p2,qout[khel],k1_k2)); diagrams.push_back(FFZvertex_->evaluate(scale(),qin[p1hel],p2_k,k1_k2)); // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g, tcPDPtr gamma = getParticleData(ParticleID::gamma); k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]); diagrams.push_back(FFPvertex_->evaluate(scale(),p1_p2,qout[khel],k1_k2)); diagrams.push_back(FFPvertex_->evaluate(scale(),qin[p1hel],p2_k,k1_k2)); } // Add up all diagrams to get the total amplitude: Complex hel_amp(0.); for(unsigned int ix=0;ixid()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.; return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2; } /***************************************************************************/ // The game here is to get this helicity amplitude squared to return all the // same values as t_u_M_R_gqb above, TIMES a further factor tk*uk! Energy2 MEPP2VVPowheg::t_u_M_R_gqb_hel_amp(realVVKinematics R) const { using namespace ThePEG::Helicity; // gqb_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1Half, // PDT::Spin1,PDT::Spin1, // PDT::Spin1Half)); double sum_hel_amps_sqr(0.); tcPDPtr p1data(getParticleData(ParticleID::g)); tcPDPtr p2data(antiquark_); tcPDPtr k1data(mePartonData()[2]); tcPDPtr k2data(mePartonData()[3]); tcPDPtr kdata (quark_->CC()); if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); SpinorBarWaveFunction qbinSpinor(R.p2r(),p2data,incoming); SpinorWaveFunction qboutSpinor(R.kr(),kdata,outgoing); vector qbin; vector qbout; for(unsigned int ix=0;ix<2;ix++) { qbinSpinor.reset(ix); qboutSpinor.reset(ix); qbin.push_back(qbinSpinor); qbout.push_back(qboutSpinor); } VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing); VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing); vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } VectorWaveFunction gPolarization(R.p1r(),p1data,incoming); vector g; for(unsigned int ix=0;ix<3;ix+=2) { gPolarization.reset(ix); g.push_back(gPolarization); } AbstractFFVVertexPtr ffg = FFGvertex_; AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_; // Collecting information for intermediate fermions vector tc; if(abs(k1data->id())==24&&abs(k2data->id())==24) { if(abs(p2data->id())%2==0) for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix)); else for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix)); } else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p2data); else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC()); // Loop over helicities summing the relevant diagrams for(unsigned int p1hel=0;p1hel<2;++p1hel) { for(unsigned int p2hel=0;p2hel<2;++p2hel) { for(unsigned int khel=0;khel<2;++khel) { SpinorBarWaveFunction p1_p2 = ffg->evaluate(mu_UV2(),5,p2data,qbin[p2hel],g[p1hel]); SpinorWaveFunction p1_k = ffg->evaluate(mu_UV2(),5,kdata->CC(),qbout[khel],g[p1hel]); for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { // If helicity is exactly conserved (massless quarks) skip if p2hel!=khel // but if the production ME is required first fill it with (0.,0.). if((p2hel!=khel)&&helicityConservation_) { // if(getMatrix) { // if(p1hel==0) // gqb_hel_amps_(0,p2hel,k1hel,k2hel,khel) = Complex(0.,0.); // else // gqb_hel_amps_(2,p2hel,k1hel,k2hel,khel) = Complex(0.,0.); // } continue; } vector diagrams; // Get all t-channel diagram contributions tcPDPtr intermediate_q; for(unsigned int ix=0;ixid()==24&&k2data->id()==-24)) ? quark_ : tc[ix]; SpinorBarWaveFunction p2_v1 = ffv1->evaluate(scale(),5,intermediate_q,qbin[p2hel],v1[k1hel]); SpinorWaveFunction k_v2 = ffv2->evaluate(scale(),5,intermediate_q,qbout[khel],v2[k2hel]); // First calculate all the off-shell fermion currents // Now calculate the 6 abelian diagrams q+g->v1+v2+q // with 2 t-channel propagators, 1 s- and 1 t-channel // and 2 t-channel ones. if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==0))) { diagrams.push_back(ffv2->evaluate(scale(),p1_k,p2_v1,v2[k2hel])); diagrams.push_back(ffg->evaluate(mu_UV2(),k_v2,p2_v1,g[p1hel])); diagrams.push_back(ffv1->evaluate(scale(),k_v2,p1_p2,v1[k1hel])); } intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix]; SpinorBarWaveFunction p2_v2 = ffv2->evaluate(scale(),5,intermediate_q,qbin[p2hel],v2[k2hel]); SpinorWaveFunction k_v1 = ffv1->evaluate(scale(),5,intermediate_q,qbout[khel],v1[k1hel]); // q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones. if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==1))) { diagrams.push_back(ffv1->evaluate(scale(),p1_k,p2_v2,v1[k1hel])); diagrams.push_back(ffg->evaluate(mu_UV2(),k_v1,p2_v2,g[p1hel])); diagrams.push_back(ffv2->evaluate(scale(),k_v1,p1_p2,v2[k2hel])); } } // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams if(abs(k1data->id())==24&&k2data->id()==23) { // The off-shell s-channel boson current VectorWaveFunction k1_k2 = WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]); // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g diagrams.push_back(ffv1->evaluate(scale(),qbout[khel],p1_p2,k1_k2)); diagrams.push_back(ffv1->evaluate(scale(),p1_k,qbin[p2hel],k1_k2)); } // If W+W- calculate the four V+jet-like s-channel diagrams if((k1data->id()==24&&k2data->id()==-24)&&(p2data->id()==kdata->id())) { // The off-shell s-channel boson current VectorWaveFunction k1_k2; // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g, tcPDPtr Z0 = getParticleData(ParticleID::Z0); k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]); diagrams.push_back(FFZvertex_->evaluate(scale(),qbout[khel],p1_p2,k1_k2)); diagrams.push_back(FFZvertex_->evaluate(scale(),p1_k,qbin[p2hel],k1_k2)); // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g, tcPDPtr gamma = getParticleData(ParticleID::gamma); k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]); diagrams.push_back(FFPvertex_->evaluate(scale(),qbout[khel],p1_p2,k1_k2)); diagrams.push_back(FFPvertex_->evaluate(scale(),p1_k,qbin[p2hel],k1_k2)); } // Add up all diagrams to get the total amplitude: Complex hel_amp(0.); for(unsigned int ix=0;ixid()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.; return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2; } double MEPP2VVPowheg::lo_me() const { using namespace ThePEG::Helicity; double sum_hel_amps_sqr(0.); tcPDPtr p1data(quark_); tcPDPtr p2data(antiquark_); tcPDPtr k1data(mePartonData()[2]); tcPDPtr k2data(mePartonData()[3]); if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); // Should never actually occur. SpinorWaveFunction qSpinor(B_.p1b(),p1data,incoming); SpinorBarWaveFunction qbSpinor(B_.p2b(),p2data,incoming); vector q; vector qb; for(unsigned int ix=0;ix<2;ix++) { qSpinor.reset(ix); qbSpinor.reset(ix); q.push_back(qSpinor); qb.push_back(qbSpinor); } VectorWaveFunction v1Polarization(B_.k1b(),k1data,outgoing); VectorWaveFunction v2Polarization(B_.k2b(),k2data,outgoing); vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_; // Collecting information for intermediate fermions vector tc; if(abs(k1data->id())==24&&abs(k2data->id())==24) { if(abs(p1data->id())%2==0) for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix)); else for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix)); } else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data); else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data); // Loop over helicities summing the relevant diagrams for(unsigned int p1hel=0;p1hel<2;++p1hel) { for(unsigned int p2hel=0;p2hel<2;++p2hel) { if((p1hel==p2hel)&&helicityConservation_) continue; for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { vector diagrams; // Get all t-channel diagram contributions tcPDPtr intermediate_t; for(unsigned int ix=0;ixid()==24&&k2data->id()==-24)) ? p2data : tc[ix]; SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_t,q[p1hel],v1[k1hel]); // First calculate all the off-shell fermion currents // Now calculate the 6 t-channel diagrams // q+qb->v1+v2 if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) diagrams.push_back(ffv2->evaluate(scale(),p1_v1,qb[p2hel],v2[k2hel])); intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix]; SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_t,q[p1hel],v2[k2hel]); // q+qb->v2+v1 if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) diagrams.push_back(ffv1->evaluate(scale(),p1_v2,qb[p2hel],v1[k1hel])); } // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams if(abs(k1data->id())==24&&k2data->id()==23) { // The off-shell s-channel boson current VectorWaveFunction k1_k2 = WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]); // q+qb->v1*->v1+v2 diagrams.push_back(ffv1->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2)); } // If W+W- calculate the four V+jet-like s-channel diagrams if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) { // The off-shell s-channel boson current VectorWaveFunction k1_k2; // q+qb->Z0*->v1+v2 tcPDPtr Z0 = getParticleData(ParticleID::Z0); k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]); diagrams.push_back(FFZvertex_->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2)); // q+qb->gamma*->v1+v2 tcPDPtr gamma = getParticleData(ParticleID::gamma); k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]); diagrams.push_back(FFPvertex_->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2)); } // Add up all diagrams to get the total amplitude: Complex hel_amp(0.); for(unsigned int ix=0;ixid()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.; return sum_hel_amps_sqr; } -HardTreePtr MEPP2VVPowheg::generateHardest(ShowerTreePtr tree, - ShowerInteraction::Type inter) { +RealEmissionProcessPtr MEPP2VVPowheg::generateHardest(RealEmissionProcessPtr born, + ShowerInteraction::Type inter) { // check if generating QCD radiation if(inter!=ShowerInteraction::QCD && inter!=ShowerInteraction::QEDQCD && inter!=ShowerInteraction::ALL) - return HardTreePtr(); + return RealEmissionProcessPtr(); // Now we want to set these data vectors according to the particles we've // received from the current 2->2 hard collision: - vector particlesToShower; - for(map::const_iterator - cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit ) - particlesToShower.push_back(cit->first); + vector particlesToShower; + for(unsigned int ix=0;ixbornIncoming().size();++ix) + particlesToShower.push_back(born->bornIncoming()[ix]); qProgenitor_ = particlesToShower[0]; qbProgenitor_ = particlesToShower[1]; - showerQuark_ = particlesToShower[0]->progenitor(); - showerAntiquark_ = particlesToShower[1]->progenitor(); - qHadron_ = particlesToShower[0]->beam(); - qbHadron_ = particlesToShower[1]->beam(); + showerQuark_ = particlesToShower[0]; + showerAntiquark_ = particlesToShower[1]; + qHadron_ = dynamic_ptr_cast(born->hadrons()[0]->dataPtr()); + qbHadron_ = dynamic_ptr_cast(born->hadrons()[1]->dataPtr()); if(showerQuark_->id()<0) { swap(qProgenitor_,qbProgenitor_); swap(showerQuark_,showerAntiquark_); swap(qHadron_,qbHadron_); } // In _our_ calculation we basically define the +z axis as being given // by the direction of the incoming quark for q+qb & q+g processes and // the incoming gluon for g+qbar processes. So now we might need to flip // the beams, bjorken x values, colliding partons accordingly: flipped_ = showerQuark_->momentum().z()outgoingLines().size()==2); - for(map::const_iterator - cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit ) - particlesToShower.push_back(cit->first); - - V1_ = particlesToShower[2]->progenitor(); - V2_ = particlesToShower[3]->progenitor(); + vector cmap; + // undecayed gauge bosons + if(born->bornOutgoing().size()==2) { + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + particlesToShower.push_back(born->bornOutgoing()[ix]); + } + V1_ = particlesToShower[2]; + V2_ = particlesToShower[3]; + } + else if(born->bornOutgoing().size()==4) { + // If the vector bosons have decayed already then we may want to + // to get the children_ (and any associated photons) to correct + // spin correlations: + children_.clear(); + map clines; + for(unsigned int ix=0;ixbornOutgoing().size();++ix) { + tPPtr original = born->bornOutgoing()[ix]; + PPtr copy = original->dataPtr()->produceParticle(original->momentum()); + children_.push_back(copy); + cmap.push_back(ix); + // sort out colour + if(original->colourLine()) { + map::iterator cit = clines.find(original->colourLine()); + if(cit!=clines.end()) { + cit->second->addColoured(copy); + } + else { + ColinePtr newline = new_ptr(ColourLine()); + clines[original->colourLine()] = newline; + newline->addColoured(copy); + } + } + // and anticolour + else if(original->antiColourLine()) { + map::iterator cit = clines.find(original->antiColourLine()); + if(cit!=clines.end()) { + cit->second->addAntiColoured(copy); + } + else { + ColinePtr newline = new_ptr(ColourLine()); + clines[original->antiColourLine()] = newline; + newline->addAntiColoured(copy); + } + } + } + assert(children_.size()==4); + PPtr V[2]; + for(unsigned int ix=0;ix<2;++ix) { + int charge = + children_[0+2*ix]->dataPtr()->iCharge()+ + children_[1+2*ix]->dataPtr()->iCharge(); + Lorentz5Momentum psum =children_[0+2*ix]->momentum()+ + children_[1+2*ix]->momentum(); + psum.rescaleMass(); + if(charge==-3) + V[ix] = getParticleData(ParticleID::Wminus)->produceParticle(psum); + else if(charge==0) + V[ix] = getParticleData(ParticleID::Z0)->produceParticle(psum); + else if(charge==3) + V[ix] = getParticleData(ParticleID::Wplus)->produceParticle(psum); + else + assert(false); + } + V1_ = V[0]; + V2_ = V[1]; + if(children_[0]->id()<0) { + swap(children_[0],children_[1]); + swap(cmap[0],cmap[1]); + } + if(children_[2]->id()<0) { + swap(children_[2],children_[3]); + swap(cmap[2],cmap[3]); + } + } + else + assert(false); gluon_ = getParticleData(ParticleID::g)->produceParticle(); - // Abort the run if V1_ and V2_ are not just pointers to different gauge bosons if(!V1_||!V2_) throw Exception() << "MEPP2VVPowheg::generateHardest()\n" << "one or both of the gauge boson pointers is null." << Exception::abortnow; if(!(abs(V1_->id())==24||V1_->id()==23)||!(abs(V2_->id())==24||V2_->id()==23)) throw Exception() << "MEPP2VVPowheg::generateHardest()\nmisidentified gauge bosons" << "V1_ = " << V1_->PDGName() << "\n" << "V2_ = " << V2_->PDGName() << "\n" << Exception::abortnow; - // Order the gauge bosons in the same way as in the NLO calculation // (the same way as in the NLO matrix element): // W+(->e+,nu_e) W-(->e-,nu_ebar) (MCFM: 61 [nproc]) - if(V1_->id()==-24&&V2_->id()== 24) swap(V1_,V2_); - // W+/-(mu+,nu_mu / mu-,nu_mubar) Z(nu_e,nu_ebar) (MCFM: 72+77 [nproc]) - if(V1_->id()== 23&&abs(V2_->id())== 24) swap(V1_,V2_); + bool order = false; + if((V1_->id()==-24&&V2_->id()== 24) || + // W+/-(mu+,nu_mu / mu-,nu_mubar) Z(nu_e,nu_ebar) (MCFM: 72+77 [nproc]) + (V1_->id()== 23&&abs(V2_->id())== 24) ) { + swap(V1_,V2_); + order = true; + swap(cmap[0],cmap[2]); + swap(cmap[1],cmap[3]); + swap(children_[0],children_[2]); + swap(children_[1],children_[3]); + } // *** N.B. *** // We should not have to do a swap in the ZZ case, even if the different // (off-shell) masses of the Z's are taken into account by generating // the Born variables using the WZ LO/NLO matrix element(s), because // those transformed matrix elements are, according to mathematica, // symmetric in the momenta (and therefore also the masses) of the 2 Z's. - // If the vector bosons have decayed already then we may want to - // to get the children_ (and any associated photons) to correct - // spin correlations: - StepPtr theSubProcess = generator()->eventHandler()->currentStep(); - tPVector outgoing = theSubProcess->getFinalState(); - children_.clear(); - photons_.clear(); - if(outgoing.size()>=4) { - for(unsigned int ix=0;ixparents()[0]&& - (abs(outgoing[ix]->parents()[0]->id())==24|| - abs(outgoing[ix]->parents()[0]->id())==23)) { - if(outgoing[ix]->id()!=ParticleID::gamma) - children_.push_back(outgoing[ix]); - else - photons_.push_back(outgoing[ix]); - } - assert(children_.size()==4); - if(children_[0]->parents()[0]!=children_[1]->parents()[0]) - swap(children_[0],children_[2]); - if(children_[0]->parents()[0]!=children_[1]->parents()[0]) - swap(children_[0],children_[3]); - if(children_[0]->parents()[0]->id()!=V1_->id()) { - swap(children_[0],children_[2]); - swap(children_[1],children_[3]); - } - if(children_[0]->id()<0) swap(children_[0],children_[1]); - if(children_[2]->id()<0) swap(children_[2],children_[3]); - assert(children_[0]->parents()[0]==children_[1]->parents()[0]); - assert(children_[2]->parents()[0]==children_[3]->parents()[0]); - } // Now we want to construct a bornVVKinematics object. The // constructor for that needs all 4 momenta, q, qbar, V1_, V2_ // in that order, as well as the Bjorken xq and xqbar. // Get the momenta first: vector theBornMomenta; theBornMomenta.push_back(showerQuark_->momentum()); theBornMomenta.push_back(showerAntiquark_->momentum()); theBornMomenta.push_back(V1_->momentum()); theBornMomenta.push_back(V2_->momentum()); // N.B. if the showerQuark_ travels in the -z direction the born kinematics object // will detect this and rotate all particles by pi about the y axis! // Leading order momentum fractions: tcPPtr qHadron = generator()->currentEvent()->primaryCollision()->incoming().first; tcPPtr qbHadron = generator()->currentEvent()->primaryCollision()->incoming().second; assert(qHadron->children().size()>0&&qbHadron->children().size()>0); if(qHadron->children()[0]->id()<0) swap(qHadron,qbHadron); // quark and antiquark momentum fractions respectively double xa = showerQuark_ ->momentum().z()/qHadron ->momentum().z(); double xb = showerAntiquark_->momentum().z()/qbHadron->momentum().z(); // Create the object containing all 2->2 __kinematic__ information: B_ = bornVVKinematics(theBornMomenta,xa,xb); // lo_me_ is the colour & spin averaged n-body matrix element squared: lo_me_ = lo_me(true); // Attempt to generate some radiative variables and their kinematics: vector theRealMomenta; channel_ = 999; - if(!getEvent(theRealMomenta,channel_)) return HardTreePtr(); + if(!getEvent(theRealMomenta,channel_)) { + born->pT()[ShowerInteraction::QCD] = min_pT_; + return born; + } // Set the maximum pT for subsequent emissions: - pT_ < min_pT_ ? qProgenitor_ ->maximumpT(min_pT_,ShowerInteraction::QCD) : - qProgenitor_ ->maximumpT(pT_ ,ShowerInteraction::QCD); - pT_ < min_pT_ ? qbProgenitor_->maximumpT(min_pT_,ShowerInteraction::QCD) : - qbProgenitor_->maximumpT(pT_ ,ShowerInteraction::QCD); + born->pT()[ShowerInteraction::QCD] = pT_ < min_pT_ ? min_pT_ : pT_; // Determine whether the quark or antiquark emitted: fermionNumberOfMother_=0; if((channel_==0&&theRealMomenta[0].z()/theRealMomenta[4].z()>=ZERO)|| channel_==2) fermionNumberOfMother_ = 1; else if((channel_==0&&theRealMomenta[0].z()/theRealMomenta[4].z()0.1*GeV||inMinusOut.x()>0.1*GeV|| inMinusOut.y()>0.1*GeV||inMinusOut.z()>0.1*GeV) cout << "MEPP2VVPowheg::generateHardest\n" << "Momentum imbalance in V1 V2 rest frame\n" << "P_in minus P_out = " << inMinusOut/GeV << endl; // From the radiative kinematics we now have to form ShowerParticle objects: - ShowerParticlePtr p1; - ShowerParticlePtr p2; - ShowerParticlePtr k1(new_ptr(ShowerParticle(V1_->dataPtr(),true ))); - ShowerParticlePtr k2(new_ptr(ShowerParticle(V2_->dataPtr(),true ))); - ShowerParticlePtr k ; + PPtr p1,p2,k; + PPtr k1 = V1_->dataPtr()->produceParticle(theRealMomenta[2]); + PPtr k2 = V2_->dataPtr()->produceParticle(theRealMomenta[3]); // q+qbar -> V1+V2+g if(channel_==0) { - p1 = new_ptr(ShowerParticle(showerQuark_->dataPtr() ,false)); - p2 = new_ptr(ShowerParticle(showerAntiquark_->dataPtr() ,false)); - k = new_ptr(ShowerParticle(gluon_->dataPtr() ,true )); + p1 = showerQuark_ ->dataPtr()->produceParticle(theRealMomenta[0]); + p2 = showerAntiquark_->dataPtr()->produceParticle(theRealMomenta[1]); + k = gluon_ ->dataPtr()->produceParticle(theRealMomenta[4]); + k->incomingColour(p1); + k->incomingColour(p2,true); } // q+g -> V1+V2+q else if(channel_==1) { - p1 = new_ptr(ShowerParticle(showerQuark_->dataPtr() ,false)); - p2 = new_ptr(ShowerParticle(gluon_->dataPtr() ,false)); - k = new_ptr(ShowerParticle(showerAntiquark_->dataPtr()->CC() ,true )); + p1 = showerQuark_ ->dataPtr() ->produceParticle(theRealMomenta[0]); + p2 = gluon_ ->dataPtr() ->produceParticle(theRealMomenta[1]); + k = showerAntiquark_->dataPtr()->CC()->produceParticle(theRealMomenta[4]); + k->incomingColour(p2); + p2->colourConnect(p1); } // g+qbar -> V1+V2+qbar else { - p1 = new_ptr(ShowerParticle(gluon_->dataPtr() ,false)); - p2 = new_ptr(ShowerParticle(showerAntiquark_->dataPtr() ,false)); - k = new_ptr(ShowerParticle(showerQuark_->dataPtr()->CC() ,true )); + p1 = gluon_ ->dataPtr() ->produceParticle(theRealMomenta[0]); + p2 = showerAntiquark_->dataPtr() ->produceParticle(theRealMomenta[1]); + k = showerQuark_ ->dataPtr()->CC()->produceParticle(theRealMomenta[4]); + k->incomingColour(p1,true); + p1->colourConnect(p2,true); } - // Set the momenta of the ShowerParticlePtr's: - p1->set5Momentum(theRealMomenta[0]); - p2->set5Momentum(theRealMomenta[1]); - k1->set5Momentum(theRealMomenta[2]); - k2->set5Momentum(theRealMomenta[3]); - k ->set5Momentum(theRealMomenta[4]); - // Then construct another set of ShowerPointers that will be - // useful in creating the hardTree, using this information: - ShowerParticlePtr mother; - ShowerParticlePtr spacelikeSon; - ShowerParticlePtr timelikeSon; - ShowerParticlePtr spectator; + Lorentz5Momentum pmother,pspect; if(fermionNumberOfMother_==1) { - mother = new_ptr(ShowerParticle(showerQuark_->dataPtr() ,false)); - spacelikeSon = p1; - timelikeSon = k; - spectator = p2; - } else if(fermionNumberOfMother_==-1) { - mother = new_ptr(ShowerParticle(showerAntiquark_->dataPtr(),false)); - spacelikeSon = p2; - timelikeSon = k; - spectator = p1; - } else { - throw Exception() << "MEPP2VVPowheg::generateHardest()" - << "Failed to determine whether the q or qbar branched" - << Exception::runerror; + pmother = theRealMomenta[0]-theRealMomenta[4]; + pspect = theRealMomenta[1]; } - Lorentz5Momentum motherMomentum(spacelikeSon->momentum()-timelikeSon->momentum()); - motherMomentum.rescaleMass(); - mother->set5Momentum(motherMomentum); - // Create HardBranchingPtrs for the particles - HardBranchingPtr spacelikeSonBranching = - new_ptr(HardBranching(spacelikeSon,SudakovPtr(),HardBranchingPtr() ,HardBranching::Incoming )); - HardBranchingPtr timelikeSonBranching = - new_ptr(HardBranching(timelikeSon ,SudakovPtr(),spacelikeSonBranching,HardBranching::Outgoing)); - HardBranchingPtr spectatorBranching = - new_ptr(HardBranching(spectator ,SudakovPtr(),HardBranchingPtr() ,HardBranching::Incoming )); - HardBranchingPtr motherBranching = - new_ptr(HardBranching(mother ,SudakovPtr(),spacelikeSonBranching,HardBranching::Incoming )); - HardBranchingPtr V1_Branching = - new_ptr(HardBranching(k1 ,SudakovPtr(),HardBranchingPtr() ,HardBranching::Outgoing)); - HardBranchingPtr V2_Branching = - new_ptr(HardBranching(k2 ,SudakovPtr(),HardBranchingPtr() ,HardBranching::Outgoing)); - - // N.B. The DrellYanHardGenerator first adds the timelikeSonBranching as a child - // child of the spacelikeSonBranching before adding the motherBranching. We do - // it the other way round in accordance with PowhegEvolver::checkShowerMomentum. - spacelikeSonBranching->addChild(motherBranching); - spacelikeSonBranching->addChild(timelikeSonBranching); - spacelikeSonBranching->type(motherBranching->branchingParticle()->id()>0 ? - ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine); - motherBranching->colourPartner(spectatorBranching); - spectatorBranching->colourPartner(motherBranching); - - vector spacelikeBranchings,hardBranchings; - spacelikeBranchings.push_back(fermionNumberOfMother_ == 1 ? - spacelikeSonBranching : spectatorBranching); - spacelikeBranchings.push_back(fermionNumberOfMother_ == -1 ? - spacelikeSonBranching : spectatorBranching); - hardBranchings.push_back(motherBranching); - hardBranchings.push_back(spectatorBranching); - hardBranchings.push_back(V1_Branching); - hardBranchings.push_back(V2_Branching); - + else { + pmother = theRealMomenta[1]-theRealMomenta[4]; + pspect = theRealMomenta[0]; + } + + unsigned int iemit = fermionNumberOfMother_==1 ? 0 : 1; + unsigned int ispect = fermionNumberOfMother_==1 ? 1 : 0; + // fill the output + if(showerQuark_ !=born->bornIncoming()[0]) { + born->incoming().push_back(p2); + born->incoming().push_back(p1); + swap(iemit,ispect); + } + else { + born->incoming().push_back(p1); + born->incoming().push_back(p2); + } + born->emitter (iemit); + born->spectator(ispect); + pair xnew; + for(unsigned int ix=0;ixincoming().size();++ix) { + double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); + if(ix==0) xnew.first = x; + else if (ix==1) xnew.second = x; + } + born->x(xnew); + born->interaction(ShowerInteraction::QCD); + // if gauge bosons not decayed, we're done + if(born->bornOutgoing().size()==2) { + born->emitted(4); + if(!order) { + born->outgoing().push_back(k1); + born->outgoing().push_back(k2); + } + else { + born->outgoing().push_back(k2); + born->outgoing().push_back(k1); + } + born->outgoing().push_back(k); + return born; + } // Recalculate the hard vertex for this event: // For spin correlations, if an emission occurs go calculate the relevant // combination of amplitudes for the ProductionMatrixElement. if(realMESpinCorrelations_) { // Here we reset the realVVKinematics n+1 momenta to be those // of the lab frame in order to calculate the spin correlations. // Note that these momenta are not used for anything else after // this. R_.p1r(theRealMomenta[0]); R_.p2r(theRealMomenta[1]); R_.k1r(theRealMomenta[2]); R_.k2r(theRealMomenta[3]); R_.kr (theRealMomenta[4]); if(channel_==0) t_u_M_R_qqb_hel_amp(R_,true); else if(channel_==1) t_u_M_R_qg_hel_amp (R_,true); else if(channel_==2) t_u_M_R_gqb_hel_amp(R_,true); recalculateVertex(); } - // Construct the HardTree object needed to perform the showers - HardTreePtr hardTree=new_ptr(HardTree(hardBranchings,spacelikeBranchings, - ShowerInteraction::QCD)); - - if(hardTree->branchings().size()!=4) throw Exception() - << "MEPP2VVPowheg::generateHardest()\n" - << "The hardTree has " << hardTree->branchings().size() << "branchings\n" - << hardTree << "\n" << Exception::runerror; - if((motherBranching->parent()!=spacelikeSonBranching)&& - spacelikeSonBranching->parent()!=HardBranchingPtr()&& - spectatorBranching->parent()!=HardBranchingPtr()) throw Exception() - << "MEPP2VVPowheg::generateHardest()\n" - << "The parent-child relationships are not valid.\n" - << "motherBranching->parent() = " << motherBranching->parent() << "\n" - << "spacelikeSonBranching = " << spacelikeSonBranching << "\n" - << "spectatorBranching->parent() = " << spectatorBranching->parent() << "\n" - << "spacelikeSonBranching->parent() = " << spacelikeSonBranching->parent() << "\n" - << Exception::runerror; - - if(fermionNumberOfMother_== 1) { - hardTree->connect(showerQuark_ ,motherBranching ); - hardTree->connect(showerAntiquark_,spectatorBranching); - spacelikeSonBranching->beam(qProgenitor_ ->original()->parents()[0]); - motherBranching ->beam(qProgenitor_ ->original()->parents()[0]); - spectatorBranching ->beam(qbProgenitor_->original()->parents()[0]); - } else if(fermionNumberOfMother_==-1) { - hardTree->connect(showerAntiquark_,motherBranching ); - hardTree->connect(showerQuark_ ,spectatorBranching); - spacelikeSonBranching->beam(qbProgenitor_->original()->parents()[0]); - motherBranching ->beam(qbProgenitor_->original()->parents()[0]); - spectatorBranching ->beam(qProgenitor_ ->original()->parents()[0]); - } -// hardTree->connect(V1_ ,V1_Branching ); -// hardTree->connect(V2_ ,V2_Branching ); - - // This if {...} else if {...} puts the mother and spectator on the same colour - // line. If we don't do this, then when reconstructFinalStateShower calls - // setInitialEvolutionScales it says it failed to set the colour partners, so - // it can't set the scale and it just forgets the emission / event. This seems - // like an unintrusive work-around until reconstructFinalStateShower is sorted. - ColinePtr bornColourLine=new_ptr(ColourLine()); - if(fermionNumberOfMother_== 1) { - bornColourLine->addColoured(mother); - bornColourLine->addAntiColoured(spectator); - if(timelikeSon->id()==ParticleID::g) { - bornColourLine->addAntiColoured(timelikeSon); - ColinePtr newLine=new_ptr(ColourLine()); - newLine->addColoured(timelikeSon); - newLine->addColoured(spacelikeSon); - } - else { - bornColourLine->addColoured(spacelikeSon); - ColinePtr newLine=new_ptr(ColourLine()); - newLine->addAntiColoured(timelikeSon); - newLine->addAntiColoured(spacelikeSon); - } - } else if(fermionNumberOfMother_==-1) { - bornColourLine->addAntiColoured(mother); - bornColourLine->addColoured(spectator); - if(timelikeSon->id()==ParticleID::g) { - bornColourLine->addColoured(timelikeSon); - ColinePtr newLine=new_ptr(ColourLine()); - newLine->addAntiColoured(timelikeSon); - newLine->addAntiColoured(spacelikeSon); - } - else { - bornColourLine->addAntiColoured(spacelikeSon); - ColinePtr newLine=new_ptr(ColourLine()); - newLine->addColoured(timelikeSon); - newLine->addColoured(spacelikeSon); - } - } - // this is a pain but we need the boost, which we don't have yet here!! - vector pin(2); - vector pq (2); - vector::iterator cit; - pin[0] = motherBranching ->branchingParticle()->momentum(); - pin[1] = spectatorBranching->branchingParticle()->momentum(); - Energy etemp = motherBranching ->beam()->momentum().z(); - pq[0] = Lorentz5Momentum(ZERO, ZERO,etemp, abs(etemp)); - etemp = spectatorBranching->beam()->momentum().z(); - pq[1] = Lorentz5Momentum(ZERO, ZERO,etemp, abs(etemp)); - // decompose the momenta - double alpha[2],beta[2]; - Energy2 p12=pq[0]*pq[1]; - Lorentz5Momentum pt[2]; - for(unsigned int ix=0;ix<2;++ix) { - alpha[ix] = pin[ix]*pq[1]/p12; - beta [ix] = pin[ix]*pq[0]/p12; - pt[ix] = pin[ix]-alpha[ix]*pq[0]-beta[ix]*pq[1]; - } - // parton level centre-of-mass - Lorentz5Momentum pcm=pin[0]+pin[1]; - pcm.rescaleMass(); - double rap=pcm.rapidity(); - // hadron level cmf - Energy2 s = (pq[0] +pq[1] ).m2(); - // calculate the x values - double x[2]={sqrt(pcm.mass2()/s*exp(2.*rap)),pcm.mass2()/s/x[0]}; - if(pq[0].z()branchingParticle()->momentum(), - fromRest*toRest*V2_Branching->branchingParticle()->momentum()}; - LorentzRotation R(-(mother->momentum()+spectator ->momentum()).boostVector()); - R.boost((showerQuark_->momentum()+showerAntiquark_->momentum()).boostVector()); - for(map >::const_iterator - tit = tree->treelinks().begin(); - tit != tree->treelinks().end();++tit) { - ShowerTreePtr decayTree = tit->first; - map::const_iterator - cit = decayTree->incomingLines().begin(); - // reset the momentum of the decay particle - Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum(); - Lorentz5Momentum newMomentum = tit->second.second == V1_ ? pv[0] : pv[1]; - map::const_iterator cjt; - // reset the momenta of the decay products, - LorentzRotation boostToORF(newMomentum.findBoostToCM(), - newMomentum.e()/newMomentum.mass()); - tPPtr children[2]; - if(children_[0]->parents()[0]==cit->first->original()) { - children[0] = children_[0]; - children[1] = children_[1]; - } - else { - children[0] = children_[2]; - children[1] = children_[3]; - } - if(UseRandom::rndbool()) swap(children[0],children[1]); - double originalTheta0 = (boostToORF*R*children[0]->momentum()).theta(); - double originalPhi0 = (boostToORF*R*children[0]->momentum()).phi(); - boostToORF.rotateZ(-originalPhi0); - boostToORF.rotateY(-originalTheta0); - double originalPhi1 = (boostToORF*children[1]->momentum()).phi(); - LorentzRotation boost(oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); - tPPtr newChildren[2]; - for(cjt=decayTree->outgoingLines().begin(); - cjt!=decayTree->outgoingLines().end();++cjt) { - if(cjt->first->progenitor()->id()==children[0]->id()) - newChildren[0] = cjt->first->progenitor(); - else if(cjt->first->progenitor()->id()==children[1]->id()) - newChildren[1] = cjt->first->progenitor(); - } - boost.rotateZ(-(boost*newChildren[0]->momentum()).phi()); - boost.rotateY(-(boost*newChildren[0]->momentum()).theta()); - boost.rotateZ(-(boost*newChildren[1]->momentum()).phi()); - boost.rotateZ( originalPhi1); - boost.rotateY( originalTheta0); - boost.rotateZ( originalPhi0); - boost.boost(-oldMomentum.findBoostToCM(), - oldMomentum.e()/oldMomentum.mass()); - for(cjt=decayTree->outgoingLines().begin(); - cjt!=decayTree->outgoingLines().end();++cjt) { - cjt->first->original() ->set5Momentum(cjt->first->progenitor()->momentum()); - cjt->first->progenitor()->deepTransform(boost); - cjt->first->original() ->deepTransform(boost); - cjt->first->copy() ->deepTransform(boost); - } - } - return hardTree; + born->emitted(6); + for(unsigned int ix=0;ixoutgoing().push_back(children_[cmap[ix]]); + born->outgoing().push_back(k); + // return the result + return born; } double MEPP2VVPowheg::getResult(int channel, realVVKinematics R, Energy pT) { // This routine should return the integrand of the exact Sudakov form factor, // defined precisely as // KH 19th August - next 2 lines changed for phi in 0->pi not 0->2pi // \Delta(pT) = exp[ - \int_{pT}^{pTmax} dpT dYk d\phi/pi * getResult(...) ] // (Where phi is in 0->pi NOT 0->2*pi !) // Get pi for the prefactor: using Constants::pi; // Get the VV invariant mass^2: Energy2 p2 = B_.sb(); // Get the momentum fractions for the n+1 body event: double x1 = R.x1r(); double x2 = R.x2r(); // Reject the event if the x1 and x2 values are outside the phase space: if(x1<0.||x1>1.||x2<0.||x2>1.||x1*x2maximumCMEnergy())) return 0.; // Get the momentum fractions for the n body event: double x1b = B_.x1b(); double x2b = B_.x2b(); // Get the mandelstam variables needed to calculate the n+1 body matrix element: Energy2 s = R.sr() ; Energy2 t_u_MR_o_MB; double lo_lumi, nlo_lumi; // The luminosity function for the leading order n-body process: lo_lumi = qHadron_ ->pdf()->xfx(qHadron_ ,showerQuark_ ->dataPtr(),PDFScale_,x1b)* qbHadron_->pdf()->xfx(qbHadron_,showerAntiquark_->dataPtr(),PDFScale_,x2b); // Now we calculate the luminosity functions (product of the two pdfs) for the // real emission process(es) and also their matrix elements: // q + qbar -> V + V + g if(channel==0) { nlo_lumi = qHadron_ ->pdf()->xfx(qHadron_ ,showerQuark_ ->dataPtr() ,PDFScale_,x1) * qbHadron_->pdf()->xfx(qbHadron_,showerAntiquark_->dataPtr() ,PDFScale_,x2); t_u_MR_o_MB = t_u_M_R_qqb_hel_amp(R,false)/lo_me_; } // q + g -> V + V + q else if(channel==1) { nlo_lumi = qHadron_ ->pdf()->xfx(qHadron_ ,showerQuark_->dataPtr() ,PDFScale_,x1) * qbHadron_->pdf()->xfx(qbHadron_,getParticleData(ParticleID::g),PDFScale_,x2); t_u_MR_o_MB = t_u_M_R_qg_hel_amp(R,false)/lo_me_; } // g + qbar -> V + V + qbar else { nlo_lumi = qHadron_ ->pdf()->xfx(qHadron_ ,getParticleData(ParticleID::g),PDFScale_,x1) * qbHadron_->pdf()->xfx(qbHadron_,showerAntiquark_->dataPtr() ,PDFScale_,x2); t_u_MR_o_MB = t_u_M_R_gqb_hel_amp(R,false)/lo_me_; } // Multiply ratio of the real emission matrix elements to the Born matrix element // by the ratio of the pdfs for the real emission and born processes to get theWeight if(lo_lumi<=0.||nlo_lumi<=0.) return 0.; else return t_u_MR_o_MB * ( nlo_lumi/lo_lumi * p2/s ) * sqr(p2/s)/8./pi/pi / pT / p2 * GeV; } bool MEPP2VVPowheg::getEvent(vector & theRealMomenta, unsigned int & channel) { // Invariant mass of the colliding hadrons: Energy2 S = sqr(generator()->maximumCMEnergy()); // Born variables which are preserved (mass and rapidity of the diboson system): Energy2 p2 = B_.sb(); double Yb = B_.Yb(); // Born variables which are not preserved but are needed (the momentum fractions): double x1b(B_.x1b()), x2b(B_.x2b()); double x12b(x1b*x1b), x22b(x2b*x2b); // Maximum jet pT (half of the hadronic C.O.M. energy. N.B. this is overestimated a lot): Energy starting_pT = sqrt(S)/2.; // Initialize the pT_ *integration limit* i.e. the pT of the generated emission: pT_ = ZERO; // The pT *integration variable*: Energy pT; // The x_1 & x_2 momentum fractions corresponding to incoming momenta p1 & p2: double x1_(-999.), x2_(-999.); double x1 (-999.), x2 (-999.); // The jet rapidity *integration variable* and its limits: double Yk, minYk(-8.0), maxYk(8.0); // The theta2 integration variable (the azimuthal angle of the gluon w.r.t // V1 in the V1 & V2 rest frame: double theta2; // The realVVKinematics object corresponding to the current integration // set of integration variables: realVVKinematics R; // The veto algorithm rejection weight and a corresponding flag: double rejectionWeight; bool rejectEmission ; // Initialize the flag indicating the selected radiation channel: channel=999; // Some product of constants used for the crude distribution: double a(0.); for(int j=0;j<3;j++) { pT=starting_pT; a =(maxYk-minYk)*prefactor_[j]/2./b0_; do { // Generate next pT according to exp[- \int^{pTold}_{pT} dpT a*(power-1)/(pT^power)] // pT = GeV/pow( pow(GeV/pT,power_-1.) - log(UseRandom::rnd())/a // , 1./(power_-1.) ); // Generate next pT according to exp[- \int^{pTold}_{pT} dpT alpha1loop*prefactor/pT ] pT = LambdaQCD_*exp( 0.5*exp( log(log(sqr(pT/LambdaQCD_)))+log(UseRandom::rnd())/a ) ); // Generate rapidity of the jet: Yk = minYk + UseRandom::rnd()*(maxYk - minYk); // Generate the theta2 radiative variable: // KH 19th August - next line changed for phi in 0->pi not 0->2pi // theta2 = UseRandom::rnd() * 2.*Constants::pi; theta2 = UseRandom::rnd() * Constants::pi; // eT of the diboson system: Energy eT = sqrt(pT*pT+p2); // Calculate the eT and then solve for x_{\oplus} & x_{\ominus}: x1 = (pT*exp( Yk)+eT*exp( Yb))/sqrt(S); x2 = (pT*exp(-Yk)+eT*exp(-Yb))/sqrt(S); // Calculate the xr radiative variable: double xr(p2/(x1*x2*S)); // Then use this to calculate the y radiative variable: double y(-((xr+1.)/(xr-1.))*(xr*sqr(x1/x1b)-1.)/(xr*sqr(x1/x1b)+1.)); // The y value above should equal the one commented out below this line: // double y( ((xr+1.)/(xr-1.))*(xr*sqr(x2/x2b)-1.)/(xr*sqr(x2/x2b)+1.)); // Now we get the lower limit on the x integration, xbar: double omy(1.-y), opy(1.+y); double xbar1 = 2.*opy*x12b/(sqrt(sqr(1.+x12b)*sqr(omy)+16.*y*x12b)+omy*(1.-x1b)*(1.+x1b)); double xbar2 = 2.*omy*x22b/(sqrt(sqr(1.+x22b)*sqr(opy)-16.*y*x22b)+opy*(1.-x2b)*(1.+x2b)); double xbar = max(xbar1,xbar2); // Now we can calculate xtilde: double xt = (xr-xbar)/(1.-xbar); // Finally we can make the realVVKinematics object: R = realVVKinematics(B_,xt,y,theta2); // The next thing we have to do is set the QCD, EW and PDF scales using R: setTheScales(pT); // ... and so calculate rejection weight: rejectionWeight = getResult(j,R,pT); // If generating according to exp[- \int^{pTold}_{pT} dpT a*(power-1)/(pT^power)] // rejectionWeight/= showerAlphaS_->overestimateValue()*prefactor_[j]*pow(GeV/pT,power_); // If generating according to exp[- \int^{pTold}_{pT} dpT alpha1loop*prefactor/pT ] rejectionWeight/= 1./b0_/log(sqr(pT/LambdaQCD_))*prefactor_[j]*GeV/pT; rejectEmission = UseRandom::rnd()>rejectionWeight; // The event is a no-emission event if pT goes past min_pT_ - basically set to // outside the histogram bounds (hopefully histogram objects just ignore it then). if(pT1.) { ostringstream stream; stream << "MEPP2VVPowheg::getEvent weight for channel " << j << " is greater than one: " << rejectionWeight << endl; generator()->logWarning( Exception(stream.str(), Exception::warning) ); } } while(rejectEmission); // set pT of emission etc if(pT>pT_) { channel = j; pT_ = pT; Yk_ = Yk; R_ = R ; x1_ = x1; x2_ = x2; } } // Was this an (overall) no emission event? if(pT_3) throw Exception() << "MEPP2VVPowheg::getEvent() channel = " << channel << " pT = " << pT/GeV << " pT_ = " << pT_/GeV << Exception::abortnow; // Work out the momenta in the lab frame, reserving the mass and rapidity // of the VV system: LorentzRotation yzRotation; yzRotation.setRotateX(-atan2(pT_/GeV,sqrt(p2)/GeV)); LorentzRotation boostFrompTisZero; boostFrompTisZero.setBoostY(-pT_/sqrt(p2+pT_*pT_)); LorentzRotation boostFromYisZero; boostFromYisZero.setBoostZ(tanh(Yb)); theRealMomenta.resize(5); theRealMomenta[0] = Lorentz5Momentum(ZERO,ZERO, x1_*sqrt(S)/2., x1_*sqrt(S)/2.,ZERO); theRealMomenta[1] = Lorentz5Momentum(ZERO,ZERO,-x2_*sqrt(S)/2., x2_*sqrt(S)/2.,ZERO); theRealMomenta[2] = boostFromYisZero*boostFrompTisZero*yzRotation*(R_.k1r()); theRealMomenta[3] = boostFromYisZero*boostFrompTisZero*yzRotation*(R_.k2r()); theRealMomenta[4] = Lorentz5Momentum(ZERO, pT_, pT_*sinh(Yk_), pT_*cosh(Yk_),ZERO); return true; } void MEPP2VVPowheg::setTheScales(Energy pT) { // Work out the scales we want to use in the matrix elements and the pdfs: // Scale for alpha_S: pT^2 of the diboson system. QCDScale_ = max(pT*pT,sqr(min_pT_)); // Scale for real emission PDF: // pT^2+mVV^2 - as mcfm does in the case of a single W/Z boson). // Energy2 PDFScale_ = max(R.pT2_in_lab(),sqr(min_pT_))+R.s2r(); // pT^2 - as advocated by Nason & Ridolfi for ZZ production & Alioli et al for gg->h: PDFScale_ = max(pT*pT,sqr(min_pT_)); // Scale of electroweak vertices: mVV^2 the invariant mass of the diboson system. // EWScale_ = B_.sb(); // ... And this choice is more like what can be seen in mcatnlo_vbmain.f (weird). EWScale_ = 0.5*(B_.k12b()+B_.k22b()); return; } /***************************************************************************/ // This is identical to the code in the Powheg matrix element. It should // equal t_u_M_R_qqb in there, which is supposed to be the real emission ME // times tk*uk. Energy2 MEPP2VVPowheg::t_u_M_R_qqb_hel_amp(realVVKinematics R, bool getMatrix) const { using namespace ThePEG::Helicity; ProductionMatrixElement qqb_hel_amps(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1 ,PDT::Spin1 , PDT::Spin1); double sum_hel_amps_sqr(0.); tcPDPtr p1data(showerQuark_->dataPtr()); tcPDPtr p2data(showerAntiquark_->dataPtr()); tcPDPtr k1data(V1_->dataPtr()); tcPDPtr k2data(V2_->dataPtr()); tcPDPtr kdata(getParticleData(ParticleID::g)); if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); SpinorWaveFunction qSpinor(R.p1r(),p1data,incoming); SpinorBarWaveFunction qbSpinor(R.p2r(),p2data,incoming); vector q; vector qb; for(unsigned int ix=0;ix<2;ix++) { qSpinor.reset(ix); qbSpinor.reset(ix); q.push_back(qSpinor); qb.push_back(qbSpinor); } VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing); VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing); vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } VectorWaveFunction gPolarization(R.kr(),kdata,outgoing); vector g; for(unsigned int ix=0;ix<3;ix+=2) { gPolarization.reset(ix); g.push_back(gPolarization); } AbstractFFVVertexPtr ffg = FFGvertex_; AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_; // Collecting information for intermediate fermions vector tc; if(abs(k1data->id())==24&&abs(k2data->id())==24) { if(abs(p1data->id())%2==0) for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix)); else for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix)); } else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data); else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data); // Loop over helicities summing the relevant diagrams for(unsigned int p1hel=0;p1hel<2;++p1hel) { for(unsigned int p2hel=0;p2hel<2;++p2hel) { for(unsigned int khel=0;khel<2;++khel) { SpinorWaveFunction p1_k = ffg->evaluate(QCDScale_,5,p1data,q[p1hel],g[khel]); SpinorBarWaveFunction p2_k = ffg->evaluate(QCDScale_,5,p2data,qb[p2hel],g[khel]); for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { // If helicity is exactly conserved (massless quarks) skip if p1hel=p2hel // but if the production ME is required first fill it with (0.,0.). if((p1hel==p2hel)&&helicityConservation_) { if(getMatrix) { if(khel==0) qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,0) = Complex(0.,0.); else qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,2) = Complex(0.,0.); } continue; } vector diagrams; // Get all t-channel diagram contributions tcPDPtr intermediate_t; for(unsigned int ix=0;ixid()==24&&k2data->id()==-24)) ? p2data : tc[ix]; // Note: choosing 5 as the second argument ffvX_->evaluate() sets // option 5 in thepeg/Helicity/Vertex/VertexBase.cc, which makes // the (fermion) propagator denominator massless: 1/p^2. // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams SpinorWaveFunction p1_v1 = ffv1->evaluate(EWScale_,5,intermediate_t,q[p1hel],v1[k1hel]); SpinorBarWaveFunction p2_v2 = ffv2->evaluate(EWScale_,5,intermediate_t,qb[p2hel],v2[k2hel]); // First calculate all the off-shell fermion currents // Now calculate the 6 t-channel diagrams // q+qb->g+v1+v2, q+qb->v1+g+v2, q+qb->v1+v2+g if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) { diagrams.push_back(ffv1->evaluate(EWScale_,p1_k,p2_v2,v1[k1hel])); diagrams.push_back(ffg->evaluate(QCDScale_,p1_v1,p2_v2,g[khel])); diagrams.push_back(ffv2->evaluate(EWScale_,p1_v1,p2_k,v2[k2hel])); } intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix]; SpinorWaveFunction p1_v2 = ffv2->evaluate(EWScale_,5,intermediate_t,q[p1hel],v2[k2hel]); SpinorBarWaveFunction p2_v1 = ffv1->evaluate(EWScale_,5,intermediate_t,qb[p2hel],v1[k1hel]); // q+qb->g+v2+v1, q+qb->v2+g+v1, q+qb->v2+v1+g if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) { diagrams.push_back(ffv2->evaluate(EWScale_,p1_k,p2_v1,v2[k2hel])); diagrams.push_back(ffg->evaluate(QCDScale_,p1_v2,p2_v1,g[khel])); diagrams.push_back(ffv1->evaluate(EWScale_,p1_v2,p2_k,v1[k1hel])); } } // Note: choosing 3 as the second argument in WWWvertex_->evaluate() // sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which // means the propagator does not contain a width factor (which is // good re. gauge invariance). // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams if(abs(k1data->id())==24&&k2data->id()==23) { // The off-shell s-channel boson current VectorWaveFunction k1_k2 = WWWvertex_->evaluate(EWScale_,3,k1data->CC(),v2[k2hel],v1[k1hel]); // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g diagrams.push_back(ffv1->evaluate(EWScale_,p1_k,qb[p2hel],k1_k2)); diagrams.push_back(ffv1->evaluate(EWScale_,q[p1hel],p2_k,k1_k2)); } // If W+W- calculate the four V+jet-like s-channel diagrams if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) { // The off-shell s-channel boson current VectorWaveFunction k1_k2; // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g, tcPDPtr Z0 = getParticleData(ParticleID::Z0); k1_k2 = WWWvertex_->evaluate(EWScale_,3,Z0,v2[k2hel],v1[k1hel]); diagrams.push_back(FFZvertex_->evaluate(EWScale_,p1_k,qb[p2hel],k1_k2)); diagrams.push_back(FFZvertex_->evaluate(EWScale_,q[p1hel],p2_k,k1_k2)); // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g, tcPDPtr gamma = getParticleData(ParticleID::gamma); k1_k2 = WWWvertex_->evaluate(EWScale_,3,gamma,v2[k2hel],v1[k1hel]); diagrams.push_back(FFPvertex_->evaluate(EWScale_,p1_k,qb[p2hel],k1_k2)); diagrams.push_back(FFPvertex_->evaluate(EWScale_,q[p1hel],p2_k,k1_k2)); } // Add up all diagrams to get the total amplitude: Complex hel_amp(0.); for(unsigned int ix=0;ixid()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.; return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2; } /***************************************************************************/ // This is identical to the code in the Powheg matrix element. It should // equal t_u_M_R_qg in there, which is supposed to be the real emission ME // times tk*uk. Energy2 MEPP2VVPowheg::t_u_M_R_qg_hel_amp(realVVKinematics R, bool getMatrix) const { using namespace ThePEG::Helicity; ProductionMatrixElement qg_hel_amps(PDT::Spin1Half,PDT::Spin1, PDT::Spin1,PDT::Spin1, PDT::Spin1Half); double sum_hel_amps_sqr(0.); tcPDPtr p1data(showerQuark_->dataPtr()); tcPDPtr p2data(getParticleData(ParticleID::g)); tcPDPtr k1data(V1_->dataPtr()); tcPDPtr k2data(V2_->dataPtr()); tcPDPtr kdata (showerAntiquark_->dataPtr()->CC()); if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); SpinorWaveFunction qinSpinor(R.p1r(),p1data,incoming); SpinorBarWaveFunction qoutSpinor(R.kr(),kdata,outgoing); vector qin; vector qout; for(unsigned int ix=0;ix<2;ix++) { qinSpinor.reset(ix); qoutSpinor.reset(ix); qin.push_back(qinSpinor); qout.push_back(qoutSpinor); } VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing); VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing); vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } VectorWaveFunction gPolarization(R.p2r(),p2data,incoming); vector g; for(unsigned int ix=0;ix<3;ix+=2) { gPolarization.reset(ix); g.push_back(gPolarization); } AbstractFFVVertexPtr ffg = FFGvertex_; AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_; // Collecting information for intermediate fermions vector tc; if(abs(k1data->id())==24&&abs(k2data->id())==24) { if(abs(p1data->id())%2==0) for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix)); else for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix)); } else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data); else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC()); // Loop over helicities summing the relevant diagrams for(unsigned int p1hel=0;p1hel<2;++p1hel) { for(unsigned int p2hel=0;p2hel<2;++p2hel) { for(unsigned int khel=0;khel<2;++khel) { SpinorWaveFunction p1_p2 = ffg->evaluate(QCDScale_,5,p1data,qin[p1hel],g[p2hel]); SpinorBarWaveFunction p2_k = ffg->evaluate(QCDScale_,5,kdata->CC(),qout[khel],g[p2hel]); for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { // If helicity is exactly conserved (massless quarks) skip if p1hel!=khel // but if the production ME is required first fill it with (0.,0.). if((p1hel!=khel)&&helicityConservation_) { if(getMatrix) { if(p2hel==0) qg_hel_amps(p1hel,0,k1hel,k2hel,khel) = Complex(0.,0.); else qg_hel_amps(p1hel,2,k1hel,k2hel,khel) = Complex(0.,0.); } continue; } vector diagrams; // Get all t-channel diagram contributions tcPDPtr intermediate_q; for(unsigned int ix=0;ixid()==24&&k2data->id()==-24)) ? showerAntiquark_->dataPtr() : tc[ix]; SpinorWaveFunction p1_v1 = ffv1->evaluate(EWScale_,5,intermediate_q,qin[p1hel],v1[k1hel]); SpinorBarWaveFunction k_v2 = ffv2->evaluate(EWScale_,5,intermediate_q,qout[khel],v2[k2hel]); // First calculate all the off-shell fermion currents // Now calculate the 6 abelian diagrams // q+g->v1+v2+q with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones. if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) { diagrams.push_back(ffv2->evaluate(EWScale_,p1_v1,p2_k,v2[k2hel])); diagrams.push_back(ffg->evaluate(QCDScale_,p1_v1,k_v2,g[p2hel])); diagrams.push_back(ffv1->evaluate(EWScale_,p1_p2,k_v2,v1[k1hel])); } intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix]; SpinorWaveFunction p1_v2 = ffv2->evaluate(EWScale_,5,intermediate_q,qin[p1hel],v2[k2hel]); SpinorBarWaveFunction k_v1 = ffv1->evaluate(EWScale_,5,intermediate_q,qout[khel],v1[k1hel]); // q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones. if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) { diagrams.push_back(ffv1->evaluate(EWScale_,p1_v2,p2_k,v1[k1hel])); diagrams.push_back(ffg->evaluate(QCDScale_,p1_v2,k_v1,g[p2hel])); diagrams.push_back(ffv2->evaluate(EWScale_,p1_p2,k_v1,v2[k2hel])); } } // Note: choosing 3 as the second argument in WWWvertex_->evaluate() // sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which // means the propagator does not contain a width factor (which is // good re. gauge invariance). // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams if(abs(k1data->id())==24&&k2data->id()==23) { // The off-shell s-channel boson current VectorWaveFunction k1_k2 = WWWvertex_->evaluate(EWScale_,3,k1data->CC(),v2[k2hel],v1[k1hel]); // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g diagrams.push_back(ffv1->evaluate(EWScale_,p1_p2,qout[khel],k1_k2)); diagrams.push_back(ffv1->evaluate(EWScale_,qin[p1hel],p2_k,k1_k2)); } // If W+W- calculate the four V+jet-like s-channel diagrams if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==kdata->id())) { // The off-shell s-channel boson current VectorWaveFunction k1_k2; // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g, tcPDPtr Z0 = getParticleData(ParticleID::Z0); k1_k2 = WWWvertex_->evaluate(EWScale_,3,Z0,v2[k2hel],v1[k1hel]); diagrams.push_back(FFZvertex_->evaluate(EWScale_,p1_p2,qout[khel],k1_k2)); diagrams.push_back(FFZvertex_->evaluate(EWScale_,qin[p1hel],p2_k,k1_k2)); // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g, tcPDPtr gamma = getParticleData(ParticleID::gamma); k1_k2 = WWWvertex_->evaluate(EWScale_,3,gamma,v2[k2hel],v1[k1hel]); diagrams.push_back(FFPvertex_->evaluate(EWScale_,p1_p2,qout[khel],k1_k2)); diagrams.push_back(FFPvertex_->evaluate(EWScale_,qin[p1hel],p2_k,k1_k2)); } // Add up all diagrams to get the total amplitude: Complex hel_amp(0.); for(unsigned int ix=0;ixid()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.; return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2; } /***************************************************************************/ // This is identical to the code in the Powheg matrix element. It should // equal t_u_M_R_gqb in there, which is supposed to be the real emission ME // times tk*uk. Energy2 MEPP2VVPowheg::t_u_M_R_gqb_hel_amp(realVVKinematics R, bool getMatrix) const { using namespace ThePEG::Helicity; ProductionMatrixElement gqb_hel_amps(PDT::Spin1,PDT::Spin1Half, PDT::Spin1,PDT::Spin1, PDT::Spin1Half); double sum_hel_amps_sqr(0.); tcPDPtr p1data(getParticleData(ParticleID::g)); tcPDPtr p2data(showerAntiquark_->dataPtr()); tcPDPtr k1data(V1_->dataPtr()); tcPDPtr k2data(V2_->dataPtr()); tcPDPtr kdata (showerQuark_->dataPtr()->CC()); if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); SpinorBarWaveFunction qbinSpinor(R.p2r(),p2data,incoming); SpinorWaveFunction qboutSpinor(R.kr(),kdata,outgoing); vector qbin; vector qbout; for(unsigned int ix=0;ix<2;ix++) { qbinSpinor.reset(ix); qboutSpinor.reset(ix); qbin.push_back(qbinSpinor); qbout.push_back(qboutSpinor); } VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing); VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing); vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } VectorWaveFunction gPolarization(R.p1r(),p1data,incoming); vector g; for(unsigned int ix=0;ix<3;ix+=2) { gPolarization.reset(ix); g.push_back(gPolarization); } AbstractFFVVertexPtr ffg = FFGvertex_; AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_; // Collecting information for intermediate fermions vector tc; if(abs(k1data->id())==24&&abs(k2data->id())==24) { if(abs(p2data->id())%2==0) for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix)); else for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix)); } else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p2data); else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC()); // Loop over helicities summing the relevant diagrams for(unsigned int p1hel=0;p1hel<2;++p1hel) { for(unsigned int p2hel=0;p2hel<2;++p2hel) { for(unsigned int khel=0;khel<2;++khel) { SpinorBarWaveFunction p1_p2 = ffg->evaluate(QCDScale_,5,p2data,qbin[p2hel],g[p1hel]); SpinorWaveFunction p1_k = ffg->evaluate(QCDScale_,5,kdata->CC(),qbout[khel],g[p1hel]); for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { // If helicity is exactly conserved (massless quarks) skip if p2hel!=khel // but if the production ME is required first fill it with (0.,0.). if((p2hel!=khel)&&helicityConservation_) { if(getMatrix) { if(p1hel==0) gqb_hel_amps(0,p2hel,k1hel,k2hel,khel) = Complex(0.,0.); else gqb_hel_amps(2,p2hel,k1hel,k2hel,khel) = Complex(0.,0.); } continue; } vector diagrams; // Get all t-channel diagram contributions tcPDPtr intermediate_q; for(unsigned int ix=0;ixid()==24&&k2data->id()==-24)) ? showerQuark_->dataPtr() : tc[ix]; SpinorBarWaveFunction p2_v1 = ffv1->evaluate(EWScale_,5,intermediate_q,qbin[p2hel],v1[k1hel]); SpinorWaveFunction k_v2 = ffv2->evaluate(EWScale_,5,intermediate_q,qbout[khel],v2[k2hel]); // First calculate all the off-shell fermion currents // Now calculate the 6 abelian diagrams q+g->v1+v2+q // with 2 t-channel propagators, 1 s- and 1 t-channel // and 2 t-channel ones. if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==0))) { diagrams.push_back(ffv2->evaluate(EWScale_,p1_k,p2_v1,v2[k2hel])); diagrams.push_back(ffg->evaluate(QCDScale_,k_v2,p2_v1,g[p1hel])); diagrams.push_back(ffv1->evaluate(EWScale_,k_v2,p1_p2,v1[k1hel])); } intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix]; SpinorBarWaveFunction p2_v2 = ffv2->evaluate(EWScale_,5,intermediate_q,qbin[p2hel],v2[k2hel]); SpinorWaveFunction k_v1 = ffv1->evaluate(EWScale_,5,intermediate_q,qbout[khel],v1[k1hel]); // q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones. if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==1))) { diagrams.push_back(ffv1->evaluate(EWScale_,p1_k,p2_v2,v1[k1hel])); diagrams.push_back(ffg->evaluate(QCDScale_,k_v1,p2_v2,g[p1hel])); diagrams.push_back(ffv2->evaluate(EWScale_,k_v1,p1_p2,v2[k2hel])); } } // Note: choosing 3 as the second argument in WWWvertex_->evaluate() // sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which // means the propagator does not contain a width factor (which is // good re. gauge invariance). // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams if(abs(k1data->id())==24&&k2data->id()==23) { // The off-shell s-channel boson current VectorWaveFunction k1_k2 = WWWvertex_->evaluate(EWScale_,3,k1data->CC(),v2[k2hel],v1[k1hel]); // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g diagrams.push_back(ffv1->evaluate(EWScale_,qbout[khel],p1_p2,k1_k2)); diagrams.push_back(ffv1->evaluate(EWScale_,p1_k,qbin[p2hel],k1_k2)); } // If W+W- calculate the four V+jet-like s-channel diagrams if((k1data->id()==24&&k2data->id()==-24)&&(p2data->id()==kdata->id())) { // The off-shell s-channel boson current VectorWaveFunction k1_k2; // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g, tcPDPtr Z0 = getParticleData(ParticleID::Z0); k1_k2 = WWWvertex_->evaluate(EWScale_,3,Z0,v2[k2hel],v1[k1hel]); diagrams.push_back(FFZvertex_->evaluate(EWScale_,qbout[khel],p1_p2,k1_k2)); diagrams.push_back(FFZvertex_->evaluate(EWScale_,p1_k,qbin[p2hel],k1_k2)); // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g, tcPDPtr gamma = getParticleData(ParticleID::gamma); k1_k2 = WWWvertex_->evaluate(EWScale_,3,gamma,v2[k2hel],v1[k1hel]); diagrams.push_back(FFPvertex_->evaluate(EWScale_,qbout[khel],p1_p2,k1_k2)); diagrams.push_back(FFPvertex_->evaluate(EWScale_,p1_k,qbin[p2hel],k1_k2)); } // Add up all diagrams to get the total amplitude: Complex hel_amp(0.); for(unsigned int ix=0;ixid()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.; return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2; } /***************************************************************************/ // This returns exactly the same value as lo_me2_ when you put it in MEPP2VVPowheg.cc double MEPP2VVPowheg::lo_me(bool getMatrix) const { using namespace ThePEG::Helicity; ProductionMatrixElement lo_hel_amps(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1 ,PDT::Spin1); double sum_hel_amps_sqr(0.); tcPDPtr p1data(showerQuark_->dataPtr()); tcPDPtr p2data(showerAntiquark_->dataPtr()); tcPDPtr k1data(V1_->dataPtr()); tcPDPtr k2data(V2_->dataPtr()); if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); // Should never actually occur. // If you want to reproduce the spin correlations of MEPP2VV // you should evaluate this ME using the lab frame momenta // instead of the bornVVKinematics ones (partonic C.O.M. frame). SpinorWaveFunction qSpinor; SpinorBarWaveFunction qbSpinor; if(!getMatrix) { qSpinor=SpinorWaveFunction(B_.p1b(),p1data,incoming); qbSpinor=SpinorBarWaveFunction(B_.p2b(),p2data,incoming); } else { qSpinor=SpinorWaveFunction(showerQuark_->momentum(),p1data,incoming); qbSpinor=SpinorBarWaveFunction(showerAntiquark_->momentum(),p2data,incoming); } vector q; vector qb; for(unsigned int ix=0;ix<2;ix++) { qSpinor.reset(ix); qbSpinor.reset(ix); q.push_back(qSpinor); qb.push_back(qbSpinor); } // If you want to reproduce the spin correlations of MEPP2VV // you should evaluate this ME using the lab frame momenta // instead of the bornVVKinematics ones (partonic C.O.M. frame). VectorWaveFunction v1Polarization; VectorWaveFunction v2Polarization; if(!getMatrix) { v1Polarization=VectorWaveFunction(B_.k1b(),k1data,outgoing); v2Polarization=VectorWaveFunction(B_.k2b(),k2data,outgoing); } else { v1Polarization=VectorWaveFunction(V1_->momentum(),k1data,outgoing); v2Polarization=VectorWaveFunction(V2_->momentum(),k2data,outgoing); } vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_; // Collecting information for intermediate fermions vector tc; if(abs(k1data->id())==24&&abs(k2data->id())==24) { if(abs(p1data->id())%2==0) for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix)); else for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix)); } else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data); else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data); // Loop over helicities summing the relevant diagrams for(unsigned int p1hel=0;p1hel<2;++p1hel) { for(unsigned int p2hel=0;p2hel<2;++p2hel) { for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { if((p1hel==p2hel)&&helicityConservation_) { lo_hel_amps(p1hel,p2hel,k1hel,k2hel) = Complex(0.,0.); continue; } vector diagrams; // Get all t-channel diagram contributions tcPDPtr intermediate_t; for(unsigned int ix=0;ixid()==24&&k2data->id()==-24)) ? p2data : tc[ix]; SpinorWaveFunction p1_v1 = ffv1->evaluate(EWScale_,5,intermediate_t,q[p1hel],v1[k1hel]); // First calculate all the off-shell fermion currents // Now calculate the 6 t-channel diagrams // q+qb->v1+v2 if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) diagrams.push_back(ffv2->evaluate(EWScale_,p1_v1,qb[p2hel],v2[k2hel])); intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix]; SpinorWaveFunction p1_v2 = ffv2->evaluate(EWScale_,5,intermediate_t,q[p1hel],v2[k2hel]); // q+qb->v2+v1 if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) diagrams.push_back(ffv1->evaluate(EWScale_,p1_v2,qb[p2hel],v1[k1hel])); } // Note: choosing 3 as the second argument in WWWvertex_->evaluate() // sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which // means the propagator does not contain a width factor (which is // good re. gauge invariance). // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams if(abs(k1data->id())==24&&k2data->id()==23) { // The off-shell s-channel boson current VectorWaveFunction k1_k2 = WWWvertex_->evaluate(EWScale_,3,k1data->CC(),v2[k2hel],v1[k1hel]); // q+qb->v1*->v1+v2 diagrams.push_back(ffv1->evaluate(EWScale_,q[p1hel],qb[p2hel],k1_k2)); } // If W+W- calculate the four V+jet-like s-channel diagrams if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) { // The off-shell s-channel boson current VectorWaveFunction k1_k2; // q+qb->Z0*->v1+v2 tcPDPtr Z0 = getParticleData(ParticleID::Z0); k1_k2 = WWWvertex_->evaluate(EWScale_,3,Z0,v2[k2hel],v1[k1hel]); diagrams.push_back(FFZvertex_->evaluate(EWScale_,q[p1hel],qb[p2hel],k1_k2)); // q+qb->gamma*->v1+v2 tcPDPtr gamma = getParticleData(ParticleID::gamma); k1_k2 = WWWvertex_->evaluate(EWScale_,3,gamma,v2[k2hel],v1[k1hel]); diagrams.push_back(FFPvertex_->evaluate(EWScale_,q[p1hel],qb[p2hel],k1_k2)); } // Add up all diagrams to get the total amplitude: Complex hel_amp(0.); for(unsigned int ix=0;ixid()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.; return sum_hel_amps_sqr; } /***************************************************************************/ // This member selects a [2-body] decay mode and assigns children to the // vector bosons with momenta which are isotropic in their rest frames. bool MEPP2VVPowheg::isotropicDecayer() { using namespace ThePEG::Helicity; // Generate the children's momenta isotropically in // the rest frames of V1 and V2: double cth,phi; // First V1's children: cth = UseRandom::rnd()*2.-1.; phi = UseRandom::rnd()*2.*Constants::pi; Energy m1(V1_->momentum().m()); Energy m3(children_[0]->data().constituentMass()); Energy m4(children_[1]->data().constituentMass()); Energy p34(triangleFn(sqr(m1),sqr(m3),sqr(m4)) /2./m1); if(isnan(p34/GeV)||cth>1.||cth<-1.) return false; Energy pT34(p34*sqrt(1.-cth)*sqrt(1.+cth)); Lorentz5Momentum k3(pT34*sin(phi),pT34*cos(phi),p34 *cth, sqrt(p34*p34+sqr(m3)),m3); Lorentz5Momentum k4(-k3); k4.setE(sqrt(p34*p34+sqr(m4))); k4.setTau(m4); Boost boostToV1RF(R_.k1r().boostVector()); k3.boost(boostToV1RF); k3.rescaleRho(); k4.boost(boostToV1RF); k4.rescaleRho(); // Second V2's children: cth = UseRandom::rnd()*2.-1.; phi = UseRandom::rnd()*2.*Constants::pi; Energy m2(V2_->momentum().m()); Energy m5(children_[2]->data().constituentMass()); Energy m6(children_[3]->data().constituentMass()); Energy p56(triangleFn(sqr(m2),sqr(m5),sqr(m6)) /2./m2); if(isnan(p56/GeV)||cth>1.||cth<-1.) return false; Energy pT56(p56*sqrt(1.-cth)*sqrt(1.+cth)); Lorentz5Momentum k5(pT56*sin(phi),pT56*cos(phi),p56*cth, sqrt(p56*p56+sqr(m5)),m5); Lorentz5Momentum k6(-k5); k6.setE(sqrt(p56*p56+sqr(m6))); k6.setTau(m6); Boost boostToV2RF(R_.k2r().boostVector()); k5.boost(boostToV2RF); k5.rescaleRho(); k6.boost(boostToV2RF); k6.rescaleRho(); // Assign the momenta to the children: children_[0]->set5Momentum(k3); children_[1]->set5Momentum(k4); children_[2]->set5Momentum(k5); children_[3]->set5Momentum(k6); return true; } // Override 2->2 production matrix here: void MEPP2VVPowheg::recalculateVertex() { // Zero the squared amplitude; this equals sum_hel_amps_sqr if all // is working as it should: Complex productionMatrix2(0.,0.); for(unsigned int k1hel=0;k1hel<3;++k1hel) for(unsigned int k2hel=0;k2hel<3;++k2hel) productionMatrix2 += productionMatrix_[k1hel][k1hel][k2hel][k2hel]; // Get the vector wavefunctions: VectorWaveFunction v1Polarization; VectorWaveFunction v2Polarization; v1Polarization=VectorWaveFunction(R_.k1r(),V1_->dataPtr(),outgoing); v2Polarization=VectorWaveFunction(R_.k2r(),V2_->dataPtr(),outgoing); vector v1; vector v2; for(unsigned int ix=0;ix<3;ix++) { v1Polarization.reset(ix); v2Polarization.reset(ix); v1.push_back(v1Polarization); v2.push_back(v2Polarization); } AbstractFFVVertexPtr ffv1 = V1_->id()==23 ? FFZvertex_ : FFWvertex_; AbstractFFVVertexPtr ffv2 = V2_->id()==23 ? FFZvertex_ : FFWvertex_; bool vetoed(true); while(vetoed) { // Decay the bosons isotropically in their rest frames: isotropicDecayer(); // Get the spinor wavefunctions: SpinorWaveFunction k3Spinor(children_[0]->momentum(),children_[0]->dataPtr(),outgoing); SpinorBarWaveFunction k4Spinor(children_[1]->momentum(),children_[1]->dataPtr(),outgoing); SpinorWaveFunction k5Spinor(children_[2]->momentum(),children_[2]->dataPtr(),outgoing); SpinorBarWaveFunction k6Spinor(children_[3]->momentum(),children_[3]->dataPtr(),outgoing); vector k3,k5; vector k4,k6; for(unsigned int ix=0;ix<2;ix++) { k3Spinor.reset(ix); k4Spinor.reset(ix); k3.push_back(k3Spinor); k4.push_back(k4Spinor); k5Spinor.reset(ix); k6Spinor.reset(ix); k5.push_back(k5Spinor); k6.push_back(k6Spinor); } DecayMEPtr decayAmps(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k3hel=0;k3hel<2;++k3hel) { for(unsigned int k4hel=0;k4hel<2;++k4hel) { (*decayAmps)(k1hel,k3hel,k4hel) = ffv1->evaluate(EWScale_,k3[k3hel],k4[k4hel],v1[k1hel]); } } } Complex V1decayMatrix[3][3]; for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k1helpr=0;k1helpr<3;++k1helpr) { Complex theElement(0.,0.); for(unsigned int k3hel=0;k3hel<2;++k3hel) { for(unsigned int k4hel=0;k4hel<2;++k4hel) { theElement += (*decayAmps)(k1hel,k3hel,k4hel) *conj((*decayAmps)(k1helpr,k3hel,k4hel)); } } V1decayMatrix[k1hel][k1helpr] = theElement; } } Complex V1decayMatrix2(0.,0.); for(unsigned int k1hel=0;k1hel<3;++k1hel) V1decayMatrix2 += V1decayMatrix[k1hel][k1hel]; for(unsigned int k2hel=0;k2hel<3;++k2hel) { for(unsigned int k5hel=0;k5hel<2;++k5hel) { for(unsigned int k6hel=0;k6hel<2;++k6hel) { (*decayAmps)(k2hel,k5hel,k6hel) = ffv2->evaluate(EWScale_,k5[k5hel],k6[k6hel],v2[k2hel]); } } } Complex V2decayMatrix[3][3]; for(unsigned int k2hel=0;k2hel<3;++k2hel) { for(unsigned int k2helpr=0;k2helpr<3;++k2helpr) { Complex theElement(0.,0.); for(unsigned int k5hel=0;k5hel<2;++k5hel) { for(unsigned int k6hel=0;k6hel<2;++k6hel) { theElement += (*decayAmps)(k2hel,k5hel,k6hel) *conj((*decayAmps)(k2helpr,k5hel,k6hel)); } } V2decayMatrix[k2hel][k2helpr] = theElement; } } Complex V2decayMatrix2(0.,0.); for(unsigned int k2hel=0;k2hel<3;++k2hel) V2decayMatrix2 += V2decayMatrix[k2hel][k2hel]; // Contract the production matrix and the decay matrices: Complex meTimesV1V2denominators(0.,0.); for(unsigned int k1hel=0;k1hel<3;++k1hel) { for(unsigned int k1helpr=0;k1helpr<3;++k1helpr) { for(unsigned int k2hel=0;k2hel<3;++k2hel) { for(unsigned int k2helpr=0;k2helpr<3;++k2helpr) { meTimesV1V2denominators += productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] *V1decayMatrix[k1hel][k1helpr] *V2decayMatrix[k2hel][k2helpr]; } } } } if(imag(meTimesV1V2denominators)/real(meTimesV1V2denominators)>1.e-7) cout << "MEPP2VVPowheg warning\n" << "the matrix element's imaginary part is large " << meTimesV1V2denominators << endl; if(imag(productionMatrix2)/real(productionMatrix2)>1.e-7) cout << "MEPP2VVPowheg warning\n" << "the production matrix element's imaginary part is large " << productionMatrix2 << endl; if(imag(V1decayMatrix2)/real(V1decayMatrix2)>1.e-7) cout << "MEPP2VVPowheg warning\n" << "the V1 decay matrix element's imaginary part is large " << V1decayMatrix2 << endl; if(imag(V2decayMatrix2)/real(V2decayMatrix2)>1.e-7) cout << "MEPP2VVPowheg warning\n" << "the V2 decay matrix element's imaginary part is large " << V2decayMatrix2 << endl; // Need branching ratio at least in here I would think ---> double decayWeight( real(meTimesV1V2denominators) / real(productionMatrix2*V1decayMatrix2*V2decayMatrix2)); if(decayWeight>1.) cout << "MEPP2VVPowheg::recalculateVertex decayWeight > 1., decayWeight = " << decayWeight << endl; if(decayWeight<0.) cout << "MEPP2VVPowheg::recalculateVertex decayWeight < 0., decayWeight = " << decayWeight << endl; if(UseRandom::rnd()=ZERO) { return sqrt(lambda2); } else { generator()->log() << "MEPP2VVPowheg::triangleFn " << "kinematic instability, imaginary triangle function\n"; return -999999.*GeV2; } } diff --git a/MatrixElement/Powheg/MEPP2VVPowheg.h b/MatrixElement/Powheg/MEPP2VVPowheg.h --- a/MatrixElement/Powheg/MEPP2VVPowheg.h +++ b/MatrixElement/Powheg/MEPP2VVPowheg.h @@ -1,874 +1,873 @@ // -*- C++ -*- #ifndef HERWIG_MEPP2VVPowheg_H #define HERWIG_MEPP2VVPowheg_H // // This is the declaration of the MEPP2VVPowheg class. // #include "Herwig/MatrixElement/Hadron/MEPP2VV.h" #include "Herwig/MatrixElement/Powheg/VVKinematics.h" #include "Herwig/Utilities/Maths.h" #include "Herwig/Models/StandardModel/StandardCKM.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; using Math::ReLi2; using Constants::pi; /** * Here is the documentation of the MEPP2VVPowheg class. * * @see \ref MEPP2VVPowhegInterfaces "The interfaces" * defined for MEPP2VVPowheg. */ class MEPP2VVPowheg: public MEPP2VV { public: /** * The default constructor. */ MEPP2VVPowheg(); /** @name Member functions for the generation of hard QCD radiation */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return ISR;} /** * Apply the POWHEG style correction */ - virtual HardTreePtr generateHardest(ShowerTreePtr, - ShowerInteraction::Type inter); + virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, + ShowerInteraction::Type inter); //@} public: /** * Generate internal degrees of freedom given nDim() uniform * random numbers in the interval \f$ ]0,1[ \f$. To help the phase space * generator, the dSigHatDR should be a smooth function of these * numbers, although this is not strictly necessary. * @param r a pointer to the first of nDim() consecutive random numbers. * @return true if the generation succeeded, otherwise false. */ virtual bool generateKinematics(const double * r); /** * The number of internal degrees of freedom used in the matrix * element. */ virtual int nDim() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * This member check the collinear limits of the * real emission matrix elements are equal to the * appropriate combinations of Born ME's multiplied * by the splitting functions. */ bool sanityCheck() const; /** * Return the CKM matrix elements. */ Complex CKM(int ix,int iy) const { return ckm_[ix][iy]; } 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(); //@} public: /** * Function to set the born variables. */ void getKinematics(double xt, double y, double theta2); /** * Calculate the correction weight with which leading-order * configurations are re-weighted. */ double NLOweight() const; /** * Calculate the ratio of the NLO luminosity to the LO * luminosity function for the \f$q\bar{q}\f$ initiated channel. */ double Lhat_ab(tcPDPtr a, tcPDPtr b, realVVKinematics Kinematics) const; /** * Calculate the universal soft-virtual contribution to the NLO weight. */ double Vtilde_universal(realVVKinematics S) const; /** * Function for calculation of the \f$q\bar{q}\f$ initiated real * contribution. */ double Ctilde_Ltilde_qq_on_x(tcPDPtr a,tcPDPtr b,realVVKinematics C) const; /** * Function for calculation of the \f$gq\f$ initiated real * contribution. */ double Ctilde_Ltilde_gq_on_x(tcPDPtr a,tcPDPtr b,realVVKinematics C) const; /** * Function for calculation of the \f$q\bar{q}\f$ initiated real * contribution. */ double Rtilde_Ltilde_qqb_on_x(tcPDPtr a,tcPDPtr b) const; /** * Function for calculation of the \f$qg\f$ initiated real * contribution. */ double Rtilde_Ltilde_qg_on_x(tcPDPtr a,tcPDPtr b) const; /** * Function for calculation of the \f$gqb\f$ initiated real * contribution. */ double Rtilde_Ltilde_gqb_on_x(tcPDPtr a,tcPDPtr b) const; /** * The regular part of the virtual correction matrix element(s). * For WZ production this is given by Equation B.2 in NPB 383 (1992) * 3-44 *** modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ double M_V_regular(realVVKinematics S) const; /** * Member variable to store the * regular part of the virtual correction matrix element(s). * For WZ production this is given by Equation B.2 in NPB 383 (1992) * 3-44 *** modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ mutable double M_V_regular_; /** * The matrix element q + qb -> n + g times tk*uk */ Energy2 t_u_M_R_qqb(realVVKinematics R) const; /** * Member variable to store the matrix element q + qb -> n + g times tk*uk */ mutable Energy2 t_u_M_R_qqb_; /** * The matrix element q + g -> n + q times tk*uk */ Energy2 t_u_M_R_qg(realVVKinematics R) const; /** * Member variable to store the matrix element q + g -> n + q times tk*uk */ mutable Energy2 t_u_M_R_qg_; /** * The matrix element g + qb -> n + q times tk*uk */ Energy2 t_u_M_R_gqb(realVVKinematics R) const; /** * Member variable to store the matrix element g + qb -> n + q times tk*uk */ mutable Energy2 t_u_M_R_gqb_; /** * The matrix element q + qb -> n + g times (tk*uk)^2 - using helicity amplitudes */ Energy2 t_u_M_R_qqb_hel_amp(realVVKinematics R) const; /** * Member variable to store the * matrix element q + qb -> n + g times (tk*uk)^2 - using helicity amplitudes */ mutable Energy2 t_u_M_R_qqb_hel_amp_; /** * The matrix element q + g -> n + q times (tk*uk)^2 - using helicity amplitudes */ Energy2 t_u_M_R_qg_hel_amp(realVVKinematics R) const; /** * Member variable to store the * matrix element q + g -> n + q times (tk*uk)^2 - using helicity amplitudes */ mutable Energy2 t_u_M_R_qg_hel_amp_; /** * The matrix element g + qb -> n + qb times (tk*uk)^2 - using helicity amplitudes */ Energy2 t_u_M_R_gqb_hel_amp(realVVKinematics R) const; /** * Member variable to store the * matrix element g + qb -> n + qb times (tk*uk)^2 - using helicity amplitudes */ mutable Energy2 t_u_M_R_gqb_hel_amp_; /** * The leading order matrix element - using helicity amplitudes */ double lo_me() const; /** * The Born matrix element as given in Equation 3.1 - 3.3 in NPB 383 * (1992) *** modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ double M_Born_WZ(bornVVKinematics B) const; /** * Member variable to store the * Born matrix element as given in Equation 3.1 - 3.3 in NPB 383 * (1992) *** modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ mutable double M_Born_; /** * The Born matrix element as given in Equation 2.18 - 2.19 in NPB 357 * (1991) *** modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ double M_Born_ZZ(bornVVKinematics B) const; /** * M_V_regular_ZZ is the regular part of the one-loop ZZ matrix element * exactly as defined in Eqs. B.1 & B.2 of NPB 357(1991)409-438 *** * modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ double M_V_regular_ZZ(realVVKinematics S) const; /** * t_u_M_R_qqb_ZZ is the q + qb -> n + g times tk*uk real emission * matrix element as defined in Eq. C.1 of NPB 357(1991)409-438 *** * modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ Energy2 t_u_M_R_qqb_ZZ(realVVKinematics R) const; /** * The Born matrix element as given in Equation 3.2 - 3.8 in NPB 410 * (1993) *** modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ double M_Born_WW(bornVVKinematics B) const; /** * M_V_regular_WW is the regular part of the one-loop WW matrix element * exactly as defined in Eqs. C.1 - C.7 of of NPB 410(1993)280-324 *** * modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ double M_V_regular_WW(realVVKinematics S) const; /** * t_u_M_R_qqb_WW is the q + qb -> n + g times tk*uk real emission * matrix element as defined in Eq. D.1-D.5 of NPB 410(1993)280-324 *** * modulo a factor 1/(2s) ***, which is a flux factor that * those authors absorb in the matrix element. */ Energy2 t_u_M_R_qqb_WW(realVVKinematics R) const; /** * Return the factorion scale squared. */ Energy2 mu_F2() const; /** * Return the renormalisation scale squared. */ Energy2 mu_UV2() const; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ inline virtual IBPtr clone() const { return new_ptr(*this); } /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ inline virtual IBPtr fullclone() const { return new_ptr(*this); } //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initMEPP2VVPowheg; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEPP2VVPowheg & operator=(const MEPP2VVPowheg &); private: /** * Parameters for the NLO weight */ //@{ /** * Parameter to determine when to use limiting value of real emission * matrix elements, to avoid rounding error issues. */ double tiny; /** * The BeamParticleData object for the plus and minus direction hadrons */ tcBeamPtr hadron_A_; tcBeamPtr hadron_B_; /** * Born / virtual 2->2 kinematics. */ bornVVKinematics B_; /** * Soft limit of the 2->3 real emission kinematics. */ realVVKinematics S_; /** * Soft-collinear limit of the 2->3 kinematics (emission in +z direction). */ realVVKinematics SCp_; /** * The collinear limit of the 2->3 kinematics (emission in -z direction). */ realVVKinematics SCm_; /** * The collinear limit of the 2->3 kinematics (emission in +z direction). */ realVVKinematics Cp_; /** * The collinear limit of the 2->3 kinematics (emission in -z direction). */ realVVKinematics Cm_; /** * The resolved 2->3 real emission kinematics: */ realVVKinematics H_; /** * The ParticleData object for the plus and minus lo partons */ tcPDPtr ab_, bb_; /** * The ParticleData object for the quark and antiquark * (which can be in a different order to ab_ and bb_). */ tcPDPtr quark_, antiquark_; /** * Values of the PDF's before radiation */ double lo_lumi_; /** * The value of the leading order qqbar->VV matrix element */ mutable double lo_me2_; /** * The CF_ colour factor */ double CF_; /** * The TR_ colour factor */ double TR_; /** * The number of colours */ double NC_; /** * The weak coupling and the sin (squared) of the Weinberg angle */ mutable double gW_, sin2ThetaW_; /** * The up and down, left handed, quark-boson couplings */ mutable double guL_, gdL_; /** * The up and down, right handed, quark-boson couplings (for WW & ZZ) */ mutable double guR_, gdR_; /** * The TGC coupling */ mutable double eZ_; /** * The TGC coupling squared. This is useful for debugging purposes * when one wants to turn of t-channel * TGC interference contributions * but leave the pure TGC contributions intact. It is also needed in * order to transform WZ matrix elements into WW ones. */ mutable double eZ2_; /** * The CKM factor (Fij^2) */ mutable double Fij2_; /** * Whether to generate the positive, negative or leading order contribution */ unsigned int contrib_; /** * Whether to generate all channels contributions or just qqb or just * qg+gqb contributions */ unsigned int channels_; /** * Whether to use a fixed or a running QCD coupling for the NLO weight */ unsigned int nlo_alphaS_opt_; /** * The value of alphaS to use for the nlo weight if nlo_alphaS_opt_=1 */ double fixed_alphaS_; /** * Flag to remove or multiply in MCFM branching fractions for testing */ unsigned int removebr_; /** * Selects a dynamic (sHat) or fixed factorization scale */ unsigned int scaleopt_; /** * The factorization scale */ Energy mu_F_; /** * The renormalization scale */ Energy mu_UV_; /** * The pT of V1 in a radiative event in the lab frame (for scale setting only) */ Energy2 k1r_perp2_lab_; /** * The pT of V2 in a radiative event in the lab frame (for scale setting only) */ Energy2 k2r_perp2_lab_; /** * The ckm matrix elements (unsquared, to allow interference) */ vector< vector > ckm_; /** * Option to impose helicity conservation on the real NLO ME's (greatly improves evaluation time). */ bool helicityConservation_; /** * The q + qb -> v1 + v2 + g helicity amplitudes */ mutable ProductionMatrixElement qqb_hel_amps_; /** * The q + g -> v1 + v2 + q helicity amplitudes */ mutable ProductionMatrixElement qg_hel_amps_; /** * The g + qb -> v1 + v2 + qb helicity amplitudes */ mutable ProductionMatrixElement gqb_hel_amps_; //@} /** * The vertices */ //@{ /** * The photon fermion-antifermion vertex */ AbstractFFVVertexPtr FFPvertex_; /** * The W fermion-antifermion vertex */ AbstractFFVVertexPtr FFWvertex_; /** * The Z fermion-antifermionvertex */ AbstractFFVVertexPtr FFZvertex_; /** * The triple electroweak gauge boson vertex */ AbstractVVVVertexPtr WWWvertex_; /** * The quark-antiquark gluon vertex */ AbstractFFVVertexPtr FFGvertex_; //@} /** * The value of \f$\alpha_S\f$ used for the calculation */ mutable double alphaS_; protected: /** * Returns the matrix element for a given type of process, * rapidity of the jet \f$y_j\f$ and transverse momentum \f$p_T\f$ * @param emis_type the type of emission, * (0 is \f$q\bar{q}\to Vg\f$, 1 is \f$qg\to Vq\f$ and 2 is \f$g\bar{q}\to V\bar{q}\f$) * @param pT The transverse momentum of the jet * @param R The object containing the kinematics */ double getResult(int emis_type, realVVKinematics R, Energy pT); /** * generates the hardest emission (yj,p) * @param pnew The momenta of the new particles * @param emissiontype The type of emission, as for getResult * @return Whether not an emission was generated */ bool getEvent(vector & pnew,unsigned int & emissiontype); /** * sets the QCD, EW and PDF scales * @param pT The pT of the current step in the veto algorithm */ void setTheScales(Energy pT); /** * The matrix element q + qb -> n + g times tk*uk */ Energy2 t_u_M_R_qqb_hel_amp(realVVKinematics R, bool getMatrix) const; /** * The matrix element q + g -> n + q times tk*uk */ Energy2 t_u_M_R_qg_hel_amp(realVVKinematics R, bool getMatrix) const; /** * The matrix element g + qb -> n + q times tk*uk */ Energy2 t_u_M_R_gqb_hel_amp(realVVKinematics R, bool getMatrix) const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ double lo_me(bool getMatrix) const; /** * Recalculate hard vertex to include spin correlations for radiative events. */ void recalculateVertex(); /** * Member which selects a two body decay mode for each vector * boson and distributes decay products isotropically */ bool isotropicDecayer(); /** * The triangle function lambda(x,y,z)=sqrt(x^2+y^2+z^2-2*x*y-2*y*z-2*x*z) */ Energy2 triangleFn(Energy2,Energy2,Energy2); private: /** * If this boolean is true the n+1 body helicity amplitudes will be * used to calculate a hard vertex based on those kinematics for spin * correlations in the decays. */ bool realMESpinCorrelations_; /** * The colour & spin averaged n-body (leading order) matrix element squared. */ double lo_me_; /** * The resolved 2->3 real emission kinematics. */ realVVKinematics R_; /** * This specifies the emitting configuration: * 1: q + qbar -> V1 + V2 + g * 2: q + g -> V1 + V2 + q * 3: g + qbar -> V1 + V2 + qbar. */ unsigned int channel_; /** * Identifies the space-like mother of the branching * as quark (+1) or antiquark (-1): */ int fermionNumberOfMother_; /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr showerAlphaS_; /** * Constants for the sampling. The distribution is assumed to have the * form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$ */ //@{ /** * The power, \f$n\f$, for the sampling */ double power_; /** * The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel */ double preqqbar_; /** * The prefactor, \f$c\f$ for the \f$qg\f$ channel */ double preqg_; /** * The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel */ double pregqbar_; /** * The QCD beta function divided by 4pi, (11-2/3*nf)/4/pi, with nf = 5. */ double b0_; /** * The fundamental QCD scale in the one-loop alpha_{S} used for the crude * (not the very crude) overestimate of the Sudakov exponent. The default * value is set so such that alphaS(MZ), neglecting all flavour threshold * effects i.e. MZ*exp(-1/2/b0_/alphaS(MZ)). */ Energy LambdaQCD_; /** * The prefactors as a vector for easy use */ vector prefactor_; //@} /** * Properties of the incoming particles */ //@{ /** * Pointers to the ShowerProgenitor objects for the partons */ - ShowerProgenitorPtr qProgenitor_; - ShowerProgenitorPtr qbProgenitor_; + PPtr qProgenitor_; + PPtr qbProgenitor_; /** * Pointers to the Shower particle objects for the partons */ - ShowerParticlePtr showerQuark_; - ShowerParticlePtr showerAntiquark_; + PPtr showerQuark_; + PPtr showerAntiquark_; /** * Pointers to the BeamParticleData objects */ tcBeamPtr qHadron_; tcBeamPtr qbHadron_; //@} /** * Properties of the boson and jets */ //@{ /** * Pointers to the Shower particle objects for the partons */ PPtr gluon_; - ShowerParticlePtr V1_; - ShowerParticlePtr V2_; + PPtr V1_; + PPtr V2_; vector children_; - vector photons_; /** * Flag indicating if the q & qbar are flipped or not i.e. this * is true if q enters from the -z direction in the lab frame. */ bool flipped_; /** * the rapidity of the jet */ double Yk_; /** * The transverse momentum of the jet */ Energy pT_; //@} /** * The transverse momentum of the jet */ Energy min_pT_; // Work out the scales we want to use in the matrix elements and the pdfs: /** * Scale for alpha_S: pT^2 of the diboson system. */ Energy2 QCDScale_; /** * Scale for real emission PDF: */ Energy2 PDFScale_; /** * Scale of electroweak vertices: mVV^2 the invariant mass of the diboson system. */ Energy2 EWScale_; /** * A matrix to hold the home-grown production matrix element */ mutable Complex productionMatrix_[3][3][3][3]; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEPP2VVPowheg. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MEPP2VVPowheg. */ typedef Herwig::MEPP2VV NthBase; }; /** This template specialization informs ThePEG about the name of * the MEPP2VVPowheg 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::MEPP2VVPowheg"; } /** * The name of a file containing the dynamic library where the class * MEPP2VVPowheg is implemented. It may also include several, space-separated, * libraries if the class MEPP2VVPowheg 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 "HwMEHadron.so HwPowhegMEHadron.so"; } }; /** @endcond */ } #endif /* HERWIG_MEPP2VVPowheg_H */ diff --git a/MatrixElement/Reweighters/ReweightEW.cc b/MatrixElement/Reweighters/ReweightEW.cc --- a/MatrixElement/Reweighters/ReweightEW.cc +++ b/MatrixElement/Reweighters/ReweightEW.cc @@ -1,175 +1,175 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the ReweightEW class. // #include "ReweightEW.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; ReweightEW::ReweightEW() : filename() {} ReweightEW::~ReweightEW() {} IBPtr ReweightEW::clone() const { return new_ptr(*this); } IBPtr ReweightEW::fullclone() const { return new_ptr(*this); } double ReweightEW::weight() const{ int N = subProcess()->outgoing().size(); if (N != 2) { std::cerr << "< 2 particles in FS!\n"; return 1.0; } else { Energy2 s = (subProcess()->outgoing()[0]->momentum() +subProcess()->outgoing()[1]->momentum()).m2(); Energy2 t = (subProcess()->incoming().first->momentum() -subProcess()->outgoing()[0]->momentum()).m2(); double sg = s/(1.0*GeV2), tg = t/(1.0*GeV2); int f1, f2; f1 = subProcess()->incoming().first->id(); f2 = subProcess()->incoming().second->id(); // Flavour of incoming quarks: there's only one correction factor // for all flavours in WZ production, so call with u quark. ZZ, WW, // AA: always same and opposite flavours. Value of f1 matters. if (f1 != -f2) { f1 = 2; } double val = EWKFac(abs(f1), sg, tg); thelasts = sg; thelastt = tg; thelastk = val; return val; } } -void ReweightEW::setSTK(const double &s, const double &t, const double &K) { +void ReweightEW::setSTK(double s, double t, double K) { thelasts = s; thelastt = t; thelastk = K; } void ReweightEW::inittable() { int n = 200; // int n = 500; FILE *fp; // initialize table, n^2 rows in file fp = fopen(filename.c_str(),"r"); if (!fp) { cerr << "ReweightEW: Can't open EW file "+filename+". \n" << "You can download EW grid files from\n" << "http://www.hepforge.org/archive/herwig/ewgrids\n"; // put files to login.hepforge.org:herwig/downloads/ewgrids/ } else { for (int i = 0; i < n*n; ++i) { int out = fscanf(fp,"%lf %lf %lf %lf %lf",&tab[i][1],&tab[i][2],&tab[i][3],&tab[i][4],&tab[i][5]); if (!out) cerr << "Problems reading EW file " << filename << ".\n"; } fclose(fp); } } void ReweightEW::doinitrun() { inittable(); } void ReweightEW::doinit() { inittable(); } double ReweightEW::EWKFac(unsigned int f, double s, double t) const { int kmin, i, imin, j, jmin, n = 200; //n = 500; double tmin, smin, delsmin, deltmin; // initialization delsmin=1E30; deltmin=1E30; imin=0; jmin=0; smin=0E0; tmin=0E0; // Find best values for s,t for (i=1; i<=n; i++) { if (fabs(s-pow(tab[n*i-1][1],2)) < delsmin) { smin = pow(tab[n*i-1][1],2); delsmin = fabs(s-smin); imin = i; } } for (j=1; j<=n; j++) { if (fabs(fabs(t)-fabs(tab[n*(imin-1)+j-1][2])) < deltmin) { tmin = tab[n*(imin-1)+j-1][2]; deltmin = fabs(fabs(t)-fabs(tmin)); jmin = j; } } // Compute correct column kmin=n*(imin-1)+jmin-1; // return K-factor = 1 + (value delta from table). double val = tab[kmin][5]; if (f > 0 && f < 6) { if (f == 2 || f == 4) val = tab[kmin][3]; // u, c if (f == 1 || f == 3) val = tab[kmin][4]; // d, s if (f == 5) val = tab[kmin][5]; // b } else val = 0.0; // don't reweight. return 1.+val; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ReweightEW::persistentOutput(PersistentOStream & os) const { os << filename; } void ReweightEW::persistentInput(PersistentIStream & is, int) { is >> filename; } // *** 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 describeHerwigReweightEW("Herwig::ReweightEW", "Herwig.so"); void ReweightEW::Init() { static ClassDocumentation documentation ("There is no documentation for the ReweightEW class"); static Parameter interfaceFilename ("Filename", "Name of the EW K factor file", &ReweightEW::filename, ""); } diff --git a/MatrixElement/Reweighters/ReweightEW.h b/MatrixElement/Reweighters/ReweightEW.h --- a/MatrixElement/Reweighters/ReweightEW.h +++ b/MatrixElement/Reweighters/ReweightEW.h @@ -1,178 +1,178 @@ // -*- C++ -*- #ifndef Herwig_ReweightEW_H #define Herwig_ReweightEW_H // // This is the declaration of the ReweightEW class. // #include "ThePEG/MatrixElement/ReweightBase.h" #include namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the ReweightEW class. * * @see \ref ReweightEWInterfaces "The interfaces" * defined for ReweightEW. */ class ReweightEW: public ReweightBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ ReweightEW(); /** * The destructor. */ virtual ~ReweightEW(); //@} public: /** * Return the weight for the kinematical configuation provided by * the assigned XComb object (in the LastXCombInfo base class). */ virtual double weight() const; /** * Return values of the last evaluation (double/doubles in GeV2) */ double lastS() const {return thelasts;} double lastT() const {return thelastt;} double lastK() const {return thelastk;} - void setSTK(const double &s, const double &t, const double &K); + void setSTK(double s, double t, double K); /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The last s */ mutable double thelasts; /** * The last t */ mutable double thelastt; /** * The last K-factor */ mutable double thelastk; /** * The table of K factors to be read from file */ // tab[40000][5]; boost::array,40001> tab; // boost::array,250001> tab; /** * EW K factor filename */ string filename; public: /** * Computation of K factors from table (s and t in GeV) */ double EWKFac(unsigned int f, double s, double t) const; private: /** * initialize tables */ void inittable(); private: /** * Describe a concrete base class with persistent data. */ static ClassDescription initReweightEW; protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ReweightEW & operator=(const ReweightEW &); }; } #endif /* Herwig_ReweightEW_H */ diff --git a/Models/General/HiggsVectorBosonProcessConstructor.h b/Models/General/HiggsVectorBosonProcessConstructor.h --- a/Models/General/HiggsVectorBosonProcessConstructor.h +++ b/Models/General/HiggsVectorBosonProcessConstructor.h @@ -1,152 +1,152 @@ // -*- C++ -*- #ifndef HERWIG_HiggsVectorBosonProcessConstructor_H #define HERWIG_HiggsVectorBosonProcessConstructor_H // // This is the declaration of the HiggsVectorBosonProcessConstructor class. // #include "HardProcessConstructor.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the HiggsVectorBosonProcessConstructor class. * * @see \ref HiggsVectorBosonProcessConstructorInterfaces "The interfaces" * defined for HiggsVectorBosonProcessConstructor. */ class HiggsVectorBosonProcessConstructor: public HardProcessConstructor { public: /** * The default constructor. */ HiggsVectorBosonProcessConstructor(); /** * Main function called to start constructing the diagrams for * the 2->2 process */ void constructDiagrams(); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initHiggsVectorBosonProcessConstructor; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HiggsVectorBosonProcessConstructor & operator=(const HiggsVectorBosonProcessConstructor &); private: /** * The allowed outgoing vector bosons */ PDVector _vector; /** * The outgoing higgs bosons */ PDVector _higgs; /** * Collision Type */ bool _type; /** * Treatment of the Higgs width */ unsigned int _shapeOpt; /** * The shower coupling for the Matrix Element corrections */ ShowerAlphaPtr _alpha; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of HiggsVectorBosonProcessConstructor. */ template <> struct BaseClassTrait { /** Typedef of the first base class of HiggsVectorBosonProcessConstructor. */ typedef Herwig::HardProcessConstructor NthBase; }; /** This template specialization informs ThePEG about the name of * the HiggsVectorBosonProcessConstructor 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::HiggsVectorBosonProcessConstructor"; } }; /** @endcond */ } #endif /* HERWIG_HiggsVectorBosonProcessConstructor_H */ diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -1,1565 +1,1569 @@ Herwig News -*- outline -*- ================================================================================ -* Herwig 7.0.3 release: 2016-xx-xx +* Herwig 7.0.3 release: 2016-07-21 + +** subprocess generation filters + A number of filters has been implemented to speed up process and diagram + generation for the case of Standard Model like processes; this is + particularly helpful for processes involving a large number of electroweak + combinatorics. See the documentation for more details. + +** fix to directory hierarchy + A bug in the Herwig-scratch directory hierarchy when integrating with + different seeds has been fixed. ** fix for relocating MadGraph generated amplitudes The directory and symbolic link structure for MadGraph-built amplitudes has been changed to allow for relocation of a run directory to a different file system hierarchy. ** z* variable added to LeptonsJetsAnalysis The builtin LeptonsJetsAnalysis has been extented to include the normalized relative rapidity z* -** fix to directory hierarchy - A bug in the Herwig-scratch directory hierarchy when integrating with - different seeds has been fixed. - ** detuning parameter for shower reweighting An efficiency tweak when using the shower reweighting facilities has been introduced for the veto algorithms in both the QTilde and the Dipole shower. See the documentation for more details. -** subprocess generation filters - A number of filters has been implemented to speed up process and diagram - generation for the case of Standard Model like processes; this is - particularly helpful for processes involving a large number of electroweak - combinatorics. See the documentation for more details. +** BaryonThreeQuarkModelFormFactor + A scaling bug in the form factor series expansion was fixed. + * 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. The method is described in arXiv:1605.08256 ** mergegrids mode A main mode for the Herwig executable has been added which merges the integration grids from parallel runs. ** 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/PDF/HwRemDecayer.h b/PDF/HwRemDecayer.h --- a/PDF/HwRemDecayer.h +++ b/PDF/HwRemDecayer.h @@ -1,638 +1,638 @@ // -*- C++ -*- // // HwRemDecayer.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_HwRemDecayer_H #define HERWIG_HwRemDecayer_H // // This is the declaration of the HwRemDecayer class. // #include "ThePEG/PDT/RemnantDecayer.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/PDF/BeamParticleData.h" -#include "Herwig/Shower/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" #include "Herwig/PDT/StandardMatchers.h" #include "ThePEG/PDT/StandardMatchers.h" #include "HwRemDecayer.fh" namespace Herwig { using namespace ThePEG; /** * The HwRemDecayer class is responsible for the decay of the remnants. Additional * secondary scatters have to be evolved backwards to a gluon, the * first/hard interaction has to be evolved back to a valence quark. * This is all generated inside this class, * which main methods are then called by the ShowerHandler. * * A simple forced splitting algorithm is used. * This takes the Remnant object produced from the PDF and backward * evolution (hadron - parton) and produce partons with the remaining * flavours and with the correct colour connections. * * The algorithim operates by starting with the parton which enters the hard process. * If this is from the sea there is a forced branching to produce the antiparticle * from a gluon branching. If the parton entering the hard process was a gluon, or * a gluon was produced from the first step of the algorithm, there is then a further * branching back to a valence parton. After these partons have been produced a quark or * diquark is produced to give the remaining valence content of the incoming hadron. * * The forced branching are generated using a scale between QSpac and EmissionRange times * the minimum scale. The energy fractions are then distributed using * \f[\frac{\alpha_S}{2\pi}\frac{P(z)}{z}f(x/z,\tilde{q})\f] * with the massless splitting functions. * * \author Manuel B\"ahr * * @see \ref HwRemDecayerInterfaces "The interfaces" * defined for HwRemDecayer. */ class HwRemDecayer: public RemnantDecayer { public: /** Typedef to store information about colour partners */ typedef vector > PartnerMap; public: /** * The default constructor. */ HwRemDecayer() : allowTop_(false),ptmin_(-1.*GeV), beta_(ZERO), maxtrySoft_(10), colourDisrupt_(1.0), _kinCutoff(0.75*GeV), _forcedSplitScale(2.5*GeV), _range(1.1), _zbin(0.05),_ybin(0.), _nbinmax(100), DISRemnantOpt_(0), pomeronStructure_(0), mg_(ZERO) {} /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode &) const { return true; } /** * Return true if this decayer can handle the extraction of the \a * extracted parton from the given \a particle. */ virtual bool canHandle(tcPDPtr particle, tcPDPtr parton) const; /** * Return true if this decayed can extract more than one parton from * a particle. */ virtual bool multiCapable() const { return true; } /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @param step the step we are working on. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p, Step & step) const; //@} public: /** * struct that is used to catch exceptions which are thrown * due to energy conservation issues of additional soft scatters */ struct ExtraSoftScatterVeto {}; /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); /** * Do several checks and initialization, for remnantdecay inside ShowerHandler. */ void initialize(pair rems, tPPair beam, Step & step, Energy forcedSplitScale); /** * Initialize the soft scattering machinery. * @param ptmin = the pt cutoff used in the UE model * @param beta = slope of the soft pt-spectrum */ void initSoftInteractions(Energy ptmin, InvEnergy2 beta); /** * Perform the acual forced splitting. * @param partons is a pair of ThePEG::Particle pointers which store the final * partons on which the shower ends. * @param pdfs are pointers to the pdf objects for both beams * @param first is a flage wether or not this is the first or a secondary interation */ void doSplit(pair partons, pair pdfs, bool first); /** * Perform the final creation of the diquarks. Set the remnant masses and do * all colour connections. * @param colourDisrupt = variable to control how many "hard" scatters * are colour isolated * @param softInt = parameter for the number of soft scatters */ void finalize(double colourDisrupt=0.0, unsigned int softInt=0); /** * Find the children */ void findChildren(tPPtr,vector &) const; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit() { Interfaced::doinit(); _ybin=0.25/_zbin; mg_ = getParticleData(ParticleID::g)->constituentMass(); } //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initHwRemDecayer; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HwRemDecayer & operator=(const HwRemDecayer &); public: /** * Simple struct to store info about baryon quark and di-quark * constituents. */ struct HadronContent { /** * manually extract the valence flavour \a id. */ inline void extract(int id) { for(unsigned int i=0; iid() == ParticleID::gamma || (hadron->id() == ParticleID::pomeron && pomeronStructure==1) || hadron->id() == ParticleID::reggeon) { flav[0] = id; flav[1] = -id; extracted = 0; flav.resize(2); } else if (hadron->id() == ParticleID::pomeron && pomeronStructure==0) { extracted = 0; } else { extracted = i; } break; } } } /** * Return a proper particle ID assuming that \a id has been removed * from the hadron. */ long RemID() const; /** * Method to determine whether \a parton is a quark from the sea. * @return TRUE if \a parton is neither a valence quark nor a gluon. */ bool isSeaQuark(tcPPtr parton) const { return ((parton->id() != ParticleID::g) && ( !isValenceQuark(parton) ) ); } /** * Method to determine whether \a parton is a valence quark. */ bool isValenceQuark(tcPPtr parton) const { return isValenceQuark(parton->id()); } /** * Method to determine whether \a parton is a quark from the sea. * @return TRUE if \a parton is neither a valence quark nor a gluon. */ bool isSeaQuarkData(tcPDPtr partonData) const { return ((partonData->id() != ParticleID::g) && ( !isValenceQuarkData(partonData) ) ); } /** * Method to determine whether \a parton is a valence quark. */ bool isValenceQuarkData(tcPDPtr partonData) const { int id(sign*partonData->id()); return find(flav.begin(),flav.end(),id) != flav.end(); } /** * Method to determine whether \a parton is a valence quark. */ bool isValenceQuark(int id) const { return find(flav.begin(),flav.end(),sign*id) != flav.end(); } /** The valence flavours of the corresponding baryon. */ vector flav; /** The array index of the extracted particle. */ int extracted; /** -1 if the particle is an anti-particle. +1 otherwise. */ int sign; /** The ParticleData objects of the hadron */ tcPDPtr hadron; /** Pomeron treatment */ unsigned int pomeronStructure; }; /** * Return the hadron content objects for the incoming particles. */ const pair& content() const { return theContent; } /** * Return a HadronContent struct from a PPtr to a hadron. */ HadronContent getHadronContent(tcPPtr hadron) const; /** * Set the hadron contents. */ void setHadronContent(tPPair beam) { theContent.first = getHadronContent(beam.first); theContent.second = getHadronContent(beam.second); } private: /** * Do the forced Splitting of the Remnant with respect to the * extracted parton \a parton. * @param parton = PPtr to the parton going into the subprocess. * @param content = HadronContent struct to keep track of flavours. * @param rem = Pointer to the ThePEG::RemnantParticle. * @param used = Momentum vector to keep track of remaining momenta. * @param partners = Vector of pairs filled with tPPtr to the particles * which should be colour connected. * @param pdf pointer to the PDF Object which is used for this particle * @param first = Flag for the first interaction. */ void split(tPPtr parton, HadronContent & content, tRemPPtr rem, Lorentz5Momentum & used, PartnerMap & partners, tcPDFPtr pdf, bool first); /** * Merge the colour lines of two particles * @param p1 = Pointer to particle 1 * @param p2 = Pointer to particle 2 * @param anti = flag to indicate, if (anti)colour was extracted as first parton. */ void mergeColour(tPPtr p1, tPPtr p2, bool anti) const; /** * Set the colour connections. * @param partners = Object that holds the information which particles to connect. * @param anti = flag to indicate, if (anti)colour was extracted as first parton. * @param disrupt parameter for disruption of the colour structure */ void fixColours(PartnerMap partners, bool anti, double disrupt) const; /** * Set the momenta of the Remnants properly and boost the decay particles. */ void setRemMasses() const; /** * This creates a parton from the remaining flavours of the hadron. The * last parton used was a valance parton, so only 2 (or 1, if meson) flavours * remain to be used. */ PPtr finalSplit(const tRemPPtr rem, long remID, Lorentz5Momentum usedMomentum) const { // Create the remnant and set its momentum, also reset all of the decay // products from the hadron PPtr remnant = new_ptr(Particle(getParticleData(remID))); Lorentz5Momentum prem(rem->momentum()-usedMomentum); prem.setMass(getParticleData(remID)->constituentMass()); prem.rescaleEnergy(); remnant->set5Momentum(prem); // Add the remnant to the step, but don't do colour connections thestep->addDecayProduct(rem,remnant,false); return remnant; } /** * This takes the particle and find a splitting for np -> p + child and * creates the correct kinematics and connects for such a split. This * Splitting has an upper bound on qtilde given by the energy argument * @param rem The Remnant * @param child The PDG code for the outgoing particle * @param oldQ The maximum scale for the evolution * @param oldx The fraction of the hadron's momentum carried by the last parton * @param pf The momentum of the last parton at input and after branching at output * @param p The total emitted momentum * @param content The content of the hadron */ PPtr forceSplit(const tRemPPtr rem, long child, Energy &oldQ, double &oldx, Lorentz5Momentum &pf, Lorentz5Momentum &p, HadronContent & content) const; /** * Check if a particle is a parton from a hadron or not * @param parton The parton to be tested */ bool isPartonic(tPPtr parton) const; /** @name Soft interaction methods. */ //@{ /** * Produce pt values according to dN/dp_T = N p_T exp(-beta_*p_T^2) */ Energy softPt() const; /** * Get the 2 pairs of 5Momenta for the scattering. Needs calling of * initSoftInteractions. */ void softKinematics(Lorentz5Momentum &r1, Lorentz5Momentum &r2, Lorentz5Momentum &g1, Lorentz5Momentum &g2) const; /** * Create N soft gluon interactions */ void doSoftInteractions(unsigned int N); /** * Method to add a particle to the step * @param parent = pointer to the parent particle * @param id = Particle ID of the newly created particle * @param p = Lorentz5Momentum of the new particle */ tPPtr addParticle(tcPPtr parent, long id, Lorentz5Momentum p) const; //@} /** * A flag which indicates, whether the extracted valence quark was a * anti particle. */ pair theanti; /** * variable to sum up the x values of the extracted particles */ pair theX; /**Pair of HadronContent structs to know about the quark content of the beams*/ pair theContent; /**Pair of Lorentz5Momentum to keep track of the forced splitting product momenta*/ pair theUsed; /** * Pair of PartnerMap's to store the particles, which will be colour * connected in the end. */ pair theMaps; /** * Variable to hold a pointer to the current step. The variable is used to * determine, wether decay(const DecayMode & dm, const Particle & p, Step & step) * has been called in this event or not. */ StepPtr thestep; /** * Pair of Remnant pointers. This is needed to boost * in the Remnant-Remnant CMF after all have been decayed. */ pair theRems; /** * The beam particle data for the current incoming hadron */ mutable tcPPtr theBeam; /** * the beam data */ mutable Ptr::const_pointer theBeamData; /** * The PDF for the current initial-state shower */ mutable tcPDFPtr _pdf; private: /** * Switch to control handling of top quarks in proton */ bool allowTop_; /** @name Soft interaction variables. */ //@{ /** * Pair of soft Remnant pointers, i.e. Diquarks. */ tPPair softRems_; /** * ptcut of the UE model */ Energy ptmin_; /** * slope of the soft pt-spectrum: dN/dp_T = N p_T exp(-beta*p_T^2) */ InvEnergy2 beta_; /** * Maximum number of attempts for the regeneration of an additional * soft scattering, before the number of scatters is reduced. */ unsigned int maxtrySoft_; /** * Variable to store the relative number of colour disrupted * connections to additional soft subprocesses. */ double colourDisrupt_; //@} /** @name Forced splitting variables. */ //@{ /** * The kinematic cut-off */ Energy _kinCutoff; /** * The PDF freezing scale as set in ShowerHandler */ Energy _forcedSplitScale; /** * Range for emission */ double _range; /** * Size of the bins in z for the interpolation */ double _zbin; /** * Size of the bins in y for the interpolation */ double _ybin; /** * Maximum number of bins for the z interpolation */ int _nbinmax; /** * Pointer to the object calculating the QCD coupling */ ShowerAlphaPtr _alphaS; /** * Pointer to the object calculating the QED coupling */ ShowerAlphaPtr _alphaEM; /** * Option for the DIS remnant */ unsigned int DISRemnantOpt_; /** * Option for the treatment of the pomeron structure */ unsigned int pomeronStructure_; //@} /** * The gluon constituent mass. */ Energy mg_; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of HwRemDecayer. */ template <> struct BaseClassTrait { /** Typedef of the first base class of HwRemDecayer. */ typedef RemnantDecayer NthBase; }; /** This template specialization informs ThePEG about the name of * the HwRemDecayer 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::HwRemDecayer"; } /** * The name of a file containing the dynamic library where the class * HwRemDecayer is implemented. It may also include several, space-separated, * libraries if the class HwRemDecayer 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_HwRemDecayer_H */ diff --git a/PDT/ThreeBodyAllOnCalculator.h b/PDT/ThreeBodyAllOnCalculator.h --- a/PDT/ThreeBodyAllOnCalculator.h +++ b/PDT/ThreeBodyAllOnCalculator.h @@ -1,279 +1,279 @@ // -*- C++ -*- // // ThreeBodyAllOnCalculator.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_ThreeBodyAllOnCalculator_H #define HERWIG_ThreeBodyAllOnCalculator_H // This is the declaration of the ThreeBodyAllOnCalculator class. #include "WidthCalculatorBase.h" #include "Herwig/Utilities/GSLIntegrator.h" #include "Herwig/Decay/DecayIntegrator.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" namespace Herwig { using namespace ThePEG; template class ThreeBodyAllOnCalculator; /** \ingroup PDT * * The ThreeBodyAllOnCalculator class is designed to integrate * a three-body matrix element in which all the outgoing particles are * on-shell to give the partial width. A multi-channel type approach is * used together with a GSL integration subroutine. * * @see GSLIntegrator * @see ThreeBodyAllOnOuter * @see ThreeBodyAllOnIner * */ template class ThreeBodyAllOnCalculator: public WidthCalculatorBase { /** \ingroup PDT * The class for the outer integrand of the integral of a three body decay matrix * element. This class is used by the ThreeBodyAllOnCalculator * to perform the outer integral. * * @see ThreeBodyAllOnCalculator * @see ThreeBodyAllOnInner */ struct Outer { /** * Constructor with a pointer to the ThreeBodyAllOnCalculator */ Outer(typename Ptr >::const_pointer in, double relerr) : _integrand(in), _integrator(1e-35,relerr,1000) {} /** * Retreive function value */ Energy4 operator ()(double x) const { Energy2 low, upp; _integrand->outerVariables(x,low,upp); return _integrator.value(*_integrand,low,upp); } /** Argument type for the GSLIntegrator */ typedef double ArgType; /** Return type for the GSLIntegrator */ typedef Energy4 ValType; /** * pointer to the decay integrator */ typename Ptr >::const_pointer _integrand; /** * GSL integration class */ GSLIntegrator _integrator; }; public: /** * The ThreeBodyAllOnOuter class is a friend so it can access the private * members and perform the integral. */ friend struct ThreeBodyAllOnOuter; public: /** * Constructor with all the parameters * @param inweights The weights for the different integration channels * @param intype The types of the different integration channels. * @param inmass The mass for the Jacobian for the different channels. * @param inwidth The width for the Jacobian for the different channels. * @param inpow the power for power-law smoothing for a given channel * @param inme The pointer to the function which gives the matrix element. * @param mode The mode to be integrated * @param m1 The mass of the first particle. * @param m2 The mass of the second particle. * @param m3 The mass of the third particle. */ ThreeBodyAllOnCalculator(vector inweights, vector intype, vector inmass, vector inwidth, vector inpow, T inme, int mode, Energy m1,Energy m2,Energy m3, double relerr=1e-3) : _channelweights(inweights),_channeltype(intype),_channelmass(inmass), _channelwidth(inwidth),_channelpower(inpow),_theME(inme),_mode(mode), _thechannel(0),_mapping(inweights.size(),0),_souter(ZERO), _integrator(1e-35,relerr,1000),_relerr(relerr) { _m.resize(4); _m[1]=m1;_m[2]=m2;_m[3]=m3; _m2.resize(4); for(int ix=1;ix<4;++ix) { _m2[ix]=sqr(_m[ix]); } } /** * calculate the width for a given mass * @param q2 The mass squared of the decaying particle. * @return The partial width. */ Energy partialWidth(Energy2 q2) const; /** * Get the mass of one of the decay products. This must be * implemented in classes inheriting from this one. * @param imass The mass required. * @param mass The new value. * @return The mass required. */ void resetMass(int imass,Energy mass) { assert(imass<4); _m[imass]=mass; _m2[imass]=mass*mass; } /** * Get the mass of one of the decay products. This must be * implemented in classes inheriting from this one. * @param imass The mass required. * @return The mass required. */ Energy getMass(const int imass) const { assert(imass>=0&&imass<4); return _m[imass]; } /** * Get the masses of all bar the one specified. Used to get the limits * for integration. * @param imass The particle not needed * @return The sum of the other masses. */ Energy otherMass(const int imass) const { assert(imass>0&&imass<4); if(imass==1) return _m[2]+_m[3]; else if(imass==2) return _m[1]+_m[3]; else return _m[1]+_m[2]; } /** * The integrand for the inner integrand. * @param argument The mass squared for the inner integral * @return The value of the inner integrand. */ Energy2 operator ()(Energy2 argument) const; /** Argument type for the GSLIntegrator */ typedef Energy2 ArgType; /** Return type for the GSLIntegrator */ typedef Energy2 ValType; protected: /** * shift the variables for the outer integrand and give limits for the inner one. * This member sets the value of the _souter member for the mass squared of the * outer integral and calculates the limits on the mass squared of the inner * integral. * @param x The integration variable * @param low The lower limit for the inner integral. * @param upp The upper limit for the inner integral. */ - void outerVariables(const double & x, Energy2 & low, Energy2 & upp) const; + void outerVariables(double x, Energy2 & low, Energy2 & upp) const; private: /** * Private and non-existent assignment operator. */ ThreeBodyAllOnCalculator & operator=(const ThreeBodyAllOnCalculator &); private: /** * weights for the different channels */ vector _channelweights; /** * the types for the different channels */ vector _channeltype; /** * the mass of the resonance for a given channel */ vector _channelmass; /** * the width of the resonance for a given channel */ vector _channelwidth; /** * the power for power-law smoothing for a given channel */ vector _channelpower; /** * Function giving the matrix element as a function of s12,s13,s23 */ T _theME; /** * The mode */ int _mode; /** * the channel currently being integrated */ mutable int _thechannel; /** * The mapping currently in used */ mutable vector _mapping; /** * the value of s for the outer integral */ mutable Energy2 _souter; /** * masses of the external particles */ mutable vector _m; /** * mass squareds of the external particles */ mutable vector _m2; /** * member to do the integration */ GSLIntegrator _integrator; /** * Relative error for the integration */ double _relerr; }; } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "ThreeBodyAllOnCalculator.tcc" #endif #endif /* HERWIG_ThreeBodyAllOnCalculator_H */ diff --git a/PDT/ThreeBodyAllOnCalculator.tcc b/PDT/ThreeBodyAllOnCalculator.tcc --- a/PDT/ThreeBodyAllOnCalculator.tcc +++ b/PDT/ThreeBodyAllOnCalculator.tcc @@ -1,198 +1,198 @@ // -*- C++ -*- // // ThreeBodyAllOnCalculator.tcc 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 templated member // functions of the ThreeBodyAllOnCalculator class. // using namespace Herwig; // shift the variables for the outer integrand and give limits for the inner one template -void ThreeBodyAllOnCalculator::outerVariables(const double & x, Energy2 & low, +void ThreeBodyAllOnCalculator::outerVariables(double x, Energy2 & low, Energy2 & upp) const { // first convert the value of x into the value of souter if(_mapping[_thechannel]==0) { _souter = _channelmass[_thechannel]*(_channelmass[_thechannel]+ _channelwidth[_thechannel]*tan(x)); } else if(_mapping[_thechannel]==1) { _souter = sqr(_channelmass[_thechannel])*(1.+1./x); } else { _souter = UnitRemoval::E2 * pow(x,1./(_channelpower[_thechannel]+1.)); } // now the limits of the inner integral Energy ea(ZERO),eb(ZERO); Energy rs=sqrt(_souter); Energy2 eam2(ZERO),ebm2(ZERO); switch(_channeltype[_thechannel]) { case 1: ea = 0.5*(_souter-_m2[1]+_m2[2])/rs; eam2 = sqr(ea)-_m2[2]; eb = 0.5*(_m2[0]-_souter-_m2[3])/rs; ebm2 = sqr(eb)-_m2[3]; break; case 2: ea = 0.5*(_souter-_m2[1]+_m2[3])/rs; eam2 = sqr(ea)-_m2[3]; eb = 0.5*(_m2[0]-_souter-_m2[2])/rs; ebm2 = sqr(eb)-_m2[2]; break; case 3: ea = 0.5*(_souter-_m2[2]+_m2[3])/rs; eam2 = sqr(ea)-_m2[3]; eb = 0.5*(_m2[0]-_souter-_m2[1])/rs; ebm2 = sqr(eb)-_m2[1]; break; default: assert(false); } Energy eam = sqrt(max(ZERO,eam2)); Energy ebm = sqrt(max(ZERO,ebm2)); Energy2 sum = sqr(ea+eb); // calculate the limits low = sum - sqr(eam+ebm); upp = sum - sqr(eam-ebm); } template Energy2 ThreeBodyAllOnCalculator::operator ()(Energy2 y) const { assert(!isnan(y/MeV2)); // set up the values of the s variables Energy2 s12(ZERO),s23(ZERO),s13(ZERO), m2sum(_m2[0]+_m2[1]+_m2[2]+_m2[3]); switch(_channeltype[_thechannel]) { case 1: s12 = _souter; s23 = y; s13 = m2sum-s12-s23; break; case 2: s23 = y; s13 = _souter; s12 = m2sum-s23-s13; break; case 3: s23 = _souter; s13 = y; s12 = m2sum-s23-s13; break; } // compute the jacobian // computer the denominator for the jacobian InvEnergy2 jacdem = ZERO; Energy2 sjac(ZERO); Energy2 rm2,rw2; for(unsigned int ix=0,N=_channeltype.size(); ix Energy ThreeBodyAllOnCalculator::partialWidth(Energy2 q2) const { Outer outer(this,_relerr); _m[0] = sqrt(q2); _m2[0]=q2; // check the decay is kinematically allowed if(_m[0]<_m[1]+_m[2]+_m[3]) return ZERO; // set up for the different channels unsigned int N = _channeltype.size(); vector rupp(N,0.),rlow(N,0.); for(unsigned int ix=0; ix ZERO) { if(_channelwidth[ix] > 1e-8*MeV) { rupp[ix] = atan2((upp-_channelmass[ix]*_channelmass[ix]), _channelmass[ix]*_channelwidth[ix]); rlow[ix] = atan2((low-_channelmass[ix]*_channelmass[ix]), _channelmass[ix]*_channelwidth[ix]); _mapping[ix] = 0; if(rupp[ix]/rlow[ix]>0.&&_channelwidth[ix]/_channelmass[ix]<1e-6) { _mapping[ix] = 1; Energy2 m2=sqr(_channelmass[ix]); rupp[ix] = m2/(low-m2); rlow[ix] = m2/(upp-m2); } } else { _mapping[ix] = 1; Energy2 m2=sqr(_channelmass[ix]); rupp[ix] = m2/(low-m2); rlow[ix] = m2/(upp-m2); } } else { _mapping[ix] = 2; rupp[ix] = pow(upp*UnitRemoval::InvE2, _channelpower[ix]+1.); rlow[ix] = pow(low*UnitRemoval::InvE2, _channelpower[ix]+1.); } } // perform the integrals for all the different channels Energy4 sum(ZERO); for(unsigned int ix=0,N=_channeltype.size(); ix(Constants::twopi * _m[0]); return sum/fact/32.; } diff --git a/README b/README --- a/README +++ b/README @@ -1,18 +1,14 @@ ======== Herwig 7 ======== -This is the release of Herwig 7.0.2, a multi purpose event +This is the release of Herwig 7.0.3, 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. +Please refer to https://herwig.hepforge.org/tutorials/ 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 3:0:0 +HwSampling_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4: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/Shower/Base/Branching.h b/Shower/Base/Branching.h deleted file mode 100644 --- a/Shower/Base/Branching.h +++ /dev/null @@ -1,69 +0,0 @@ -// -*- C++ -*- -#ifndef HERWIG_Branching_H -#define HERWIG_Branching_H -// -// This is the declaration of the Branching struct. -// -#include "Herwig/Shower/ShowerConfig.h" -#include "Herwig/Shower/Base/ShowerKinematics.h" - -namespace Herwig { - -using namespace ThePEG; - - /** \ingroup Shower - * The branching struct is used to store information on the branching. - * The kinematics variable is a pointer to the ShowerKinematics for the branching - * The sudakov variable is a pointer to the SudakovFormFactor for the branching - * The ids variable is the list of particles in the branching - */ - struct Branching { - - /** - * Pointer to the ShowerKinematics object for the branching - */ - ShoKinPtr kinematics; - - /** - * PDG codes of the particles in the branching - */ - IdList ids; - - /** - * The SudakovFormFactor for the branching - */ - tSudakovPtr sudakov; - - /** - * The type of radiation line - */ - ShowerPartnerType::Type type; - - /** - * Whether or not it keep from forced hard emisson - */ - bool hard; - - /** - * Which of the children is same as incoming - */ - unsigned int iout; - - /** - * Constructor for the struct - * @param a pointer to the ShowerKinematics object for the branching - * @param c PDG codes of the particles in the branching - * @param d The SudakovFormFactor for the branching - */ - Branching(ShoKinPtr a, IdList c,tSudakovPtr d,ShowerPartnerType::Type t) - : kinematics(a), ids(c), sudakov(d), type(t), hard(false), iout(0) {} - - /** - * Default constructor - */ - Branching() : hard(false), iout(0) {} - }; - -} - -#endif /* HERWIG_Branching_H */ diff --git a/Shower/Base/Evolver.cc b/Shower/Base/Evolver.cc --- a/Shower/Base/Evolver.cc +++ b/Shower/Base/Evolver.cc @@ -1,3196 +1,3280 @@ // -*- C++ -*- // // Evolver.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 Evolver class. // #include "Evolver.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Shower/Base/ShowerParticle.h" #include "ThePEG/Utilities/EnumIO.h" #include "ShowerKinematics.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/EventHandler.h" +#include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Utilities/Throw.h" #include "ShowerTree.h" #include "ShowerProgenitor.h" #include "KinematicsReconstructor.h" #include "PartnerFinder.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Shower/ShowerHandler.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ShowerVertex.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "ThePEG/Handlers/StandardXComb.h" using namespace Herwig; namespace { /** * A struct to order the particles in the same way as in the DecayMode's */ struct ParticleOrdering { /** * Operator for the ordering * @param p1 The first ParticleData object * @param p2 The second ParticleData object */ bool operator() (tcPDPtr p1, tcPDPtr p2) { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; typedef multiset OrderedParticles; /** * Cached lookup of decay modes. * Generator::findDecayMode() is not efficient. */ tDMPtr findDecayMode(const string & tag) { static map cache; map::const_iterator pos = cache.find(tag); if ( pos != cache.end() ) return pos->second; tDMPtr dm = CurrentGenerator::current().findDecayMode(tag); cache[tag] = dm; return dm; } } DescribeClass describeEvolver ("Herwig::Evolver","HwShower.so"); bool Evolver::_hardEmissionModeWarn = true; bool Evolver::_missingTruncWarn = true; IBPtr Evolver::clone() const { return new_ptr(*this); } IBPtr Evolver::fullclone() const { return new_ptr(*this); } void Evolver::persistentOutput(PersistentOStream & os) const { os << _model << _splittingGenerator << _maxtry << _meCorrMode << _hardVetoMode << _hardVetoRead << _hardVetoReadOption << _limitEmissions << _spinOpt << _softOpt << _hardPOWHEG << ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV) - << _vetoes << _trunc_Mode << _hardEmissionMode << _reconOpt + << _vetoes << _fullShowerVetoes << _nReWeight << _reWeight + << _trunc_Mode << _hardEmissionMode << _reconOpt << isMCatNLOSEvent << isMCatNLOHEvent << isPowhegSEvent << isPowhegHEvent << theFactorizationScaleFactor << theRenormalizationScaleFactor << ounit(muPt,GeV) << oenum(interaction_) << _maxTryFSR << _maxFailFSR << _fracFSR; } void Evolver::persistentInput(PersistentIStream & is, int) { is >> _model >> _splittingGenerator >> _maxtry >> _meCorrMode >> _hardVetoMode >> _hardVetoRead >> _hardVetoReadOption >> _limitEmissions >> _spinOpt >> _softOpt >> _hardPOWHEG >> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV) - >> _vetoes >> _trunc_Mode >> _hardEmissionMode >> _reconOpt + >> _vetoes >> _fullShowerVetoes >> _nReWeight >> _reWeight + >> _trunc_Mode >> _hardEmissionMode >> _reconOpt >> isMCatNLOSEvent >> isMCatNLOHEvent >> isPowhegSEvent >> isPowhegHEvent >> theFactorizationScaleFactor >> theRenormalizationScaleFactor >> iunit(muPt,GeV) >> ienum(interaction_) >> _maxTryFSR >> _maxFailFSR >> _fracFSR; } void Evolver::doinit() { Interfaced::doinit(); // calculate max no of FSR vetos _maxFailFSR = max(int(_maxFailFSR), int(_fracFSR*double(generator()->N()))); + // check on the reweighting + for(unsigned int ix=0;ix<_fullShowerVetoes.size();++ix) { + if(_fullShowerVetoes[ix]->behaviour()==1) { + _reWeight = true; + break; + } + } + if(_reWeight && maximumTries()<_nReWeight) { + throw Exception() << "Reweight being performed in the shower but the number of attempts for the" + << "shower is less than that for the reweighting.\n" + << "Maximum number of attempt for the shower " + << fullName() << ":MaxTry is " << maximumTries() << "\nand for reweighting is " + << fullName() << ":NReWeight is " << _nReWeight << "\n" + << "we recommend the number of attempts is 10 times the number for reweighting\n" + << Exception::runerror; + } } void Evolver::Init() { static ClassDocumentation documentation ("This class is responsible for carrying out the showering,", "including the kinematics reconstruction, in a given scale range," "including the option of the POWHEG approach to simulated next-to-leading order" " radiation\\cite{Nason:2004rx}.", "%\\cite{Nason:2004rx}\n" "\\bibitem{Nason:2004rx}\n" " P.~Nason,\n" " ``A new method for combining NLO QCD with shower Monte Carlo algorithms,''\n" " JHEP {\\bf 0411} (2004) 040\n" " [arXiv:hep-ph/0409146].\n" " %%CITATION = JHEPA,0411,040;%%\n"); static Reference interfaceSplitGen("SplittingGenerator", "A reference to the SplittingGenerator object", &Herwig::Evolver::_splittingGenerator, false, false, true, false); static Reference interfaceShowerModel ("ShowerModel", "The pointer to the object which defines the shower evolution model.", &Evolver::_model, false, false, true, false, false); static Parameter interfaceMaxTry ("MaxTry", "The maximum number of attempts to generate the shower from a" " particular ShowerTree", - &Evolver::_maxtry, 100, 1, 1000, + &Evolver::_maxtry, 100, 1, 100000, + false, false, Interface::limited); + + static Parameter interfaceNReWeight + ("NReWeight", + "The number of attempts for the shower when reweighting", + &Evolver::_nReWeight, 100, 10, 10000, false, false, Interface::limited); static Switch ifaceMECorrMode ("MECorrMode", "Choice of the ME Correction Mode", &Evolver::_meCorrMode, 1, false, false); static SwitchOption off (ifaceMECorrMode,"No","MECorrections off", 0); static SwitchOption on (ifaceMECorrMode,"Yes","hard+soft on", 1); static SwitchOption hard (ifaceMECorrMode,"Hard","only hard on", 2); static SwitchOption soft (ifaceMECorrMode,"Soft","only soft on", 3); static Switch ifaceHardVetoMode ("HardVetoMode", "Choice of the Hard Veto Mode", &Evolver::_hardVetoMode, 1, false, false); static SwitchOption HVoff (ifaceHardVetoMode,"No","hard vetos off", 0); static SwitchOption HVon (ifaceHardVetoMode,"Yes","hard vetos on", 1); static SwitchOption HVIS (ifaceHardVetoMode,"Initial", "only IS emissions vetoed", 2); static SwitchOption HVFS (ifaceHardVetoMode,"Final","only FS emissions vetoed", 3); static Switch ifaceHardVetoRead ("HardVetoScaleSource", "If hard veto scale is to be read", &Evolver::_hardVetoRead, 0, false, false); static SwitchOption HVRcalc (ifaceHardVetoRead,"Calculate","Calculate from hard process", 0); static SwitchOption HVRread (ifaceHardVetoRead,"Read","Read from XComb->lastScale", 1); static Switch ifaceHardVetoReadOption ("HardVetoReadOption", "Apply read-in scale veto to all collisions or just the primary one?", &Evolver::_hardVetoReadOption, false, false, false); static SwitchOption AllCollisions (ifaceHardVetoReadOption, "AllCollisions", "Read-in pT veto applied to primary and secondary collisions.", false); static SwitchOption PrimaryCollision (ifaceHardVetoReadOption, "PrimaryCollision", "Read-in pT veto applied to primary but not secondary collisions.", true); static Parameter ifaceiptrms ("IntrinsicPtGaussian", "RMS of intrinsic pT of Gaussian distribution:\n" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &Evolver::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV, false, false, Interface::limited); static Parameter ifacebeta ("IntrinsicPtBeta", "Proportion of inverse quadratic distribution in generating intrinsic pT.\n" "(1-Beta) is the proportion of Gaussian distribution", &Evolver::_beta, 0, 0, 1, false, false, Interface::limited); static Parameter ifacegamma ("IntrinsicPtGamma", "Parameter for inverse quadratic:\n" "2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))", &Evolver::_gamma,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static Parameter ifaceiptmax ("IntrinsicPtIptmax", "Upper bound on intrinsic pT for inverse quadratic", &Evolver::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV, false, false, Interface::limited); static RefVector ifaceVetoes ("Vetoes", "The vetoes to be checked during showering", &Evolver::_vetoes, -1, false,false,true,true,false); + static RefVector interfaceFullShowerVetoes + ("FullShowerVetoes", + "The vetos to be appliede on the full final state of the shower", + &Evolver::_fullShowerVetoes, -1, false, false, true, false, false); + static Switch interfaceLimitEmissions ("LimitEmissions", "Limit the number and type of emissions for testing", &Evolver::_limitEmissions, 0, false, false); static SwitchOption interfaceLimitEmissionsNoLimit (interfaceLimitEmissions, "NoLimit", "Allow an arbitrary number of emissions", 0); static SwitchOption interfaceLimitEmissionsOneInitialStateEmission (interfaceLimitEmissions, "OneInitialStateEmission", "Allow one emission in the initial state and none in the final state", 1); static SwitchOption interfaceLimitEmissionsOneFinalStateEmission (interfaceLimitEmissions, "OneFinalStateEmission", "Allow one emission in the final state and none in the initial state", 2); static SwitchOption interfaceLimitEmissionsHardOnly (interfaceLimitEmissions, "HardOnly", "Only allow radiation from the hard ME correction", 3); static SwitchOption interfaceLimitEmissionsOneEmission (interfaceLimitEmissions, "OneEmission", "Allow one emission in either the final state or initial state, but not both", 4); static Switch interfaceTruncMode ("TruncatedShower", "Include the truncated shower?", &Evolver::_trunc_Mode, 1, false, false); static SwitchOption interfaceTruncMode0 (interfaceTruncMode,"No","Truncated Shower is OFF", 0); static SwitchOption interfaceTruncMode1 (interfaceTruncMode,"Yes","Truncated Shower is ON", 1); static Switch interfaceHardEmissionMode ("HardEmissionMode", "Whether to use ME corrections or POWHEG for the hardest emission", &Evolver::_hardEmissionMode, 0, false, false); static SwitchOption interfaceHardEmissionModeDecayMECorrection (interfaceHardEmissionMode, "DecayMECorrection", "Old fashioned ME correction for decays only", -1); static SwitchOption interfaceHardEmissionModeMECorrection (interfaceHardEmissionMode, "MECorrection", "Old fashioned ME correction", 0); static SwitchOption interfaceHardEmissionModePOWHEG (interfaceHardEmissionMode, "POWHEG", "Powheg style hard emission using internal matrix elements", 1); static SwitchOption interfaceHardEmissionModeMatchboxPOWHEG (interfaceHardEmissionMode, "MatchboxPOWHEG", "Powheg style emission for the hard process using Matchbox", 2); static SwitchOption interfaceHardEmissionModeFullPOWHEG (interfaceHardEmissionMode, "FullPOWHEG", "Powheg style emission for the hard process using Matchbox " "and decays using internal matrix elements", 3); static Switch interfaceInteraction ("Interaction", "The interactions to be used in the shower", &Evolver::interaction_, ShowerInteraction::QEDQCD, false, false); static SwitchOption interfaceInteractionQCD (interfaceInteraction, "QCDOnly", "Only QCD", ShowerInteraction::QCD); static SwitchOption interfaceInteractionQEDOnly (interfaceInteraction, "QEDOnly", "Only QED", ShowerInteraction::QED); static SwitchOption interfaceInteractionEWOnly (interfaceInteraction, "EWOnly", "Only EW", ShowerInteraction::EW); static SwitchOption interfaceInteractionQEDQCD (interfaceInteraction, "QEDQCD", "QED and QCD", ShowerInteraction::QEDQCD); static SwitchOption interfaceInteractionALL (interfaceInteraction, "ALL", "QED, QCD and EW", ShowerInteraction::ALL); static Switch interfaceReconstructionOption ("ReconstructionOption", "Treatment of the reconstruction of the transverse momentum of " "a branching from the evolution scale.", &Evolver::_reconOpt, 0, false, false); static SwitchOption interfaceReconstructionOptionCutOff (interfaceReconstructionOption, "CutOff", "Use the cut-off masses in the calculation", 0); static SwitchOption interfaceReconstructionOptionOffShell (interfaceReconstructionOption, "OffShell", "Use the off-shell masses in the calculation veto the emission of the parent," " no veto in generation of emissions from children", 1); static SwitchOption interfaceReconstructionOptionOffShell2 (interfaceReconstructionOption, "OffShell2", "Use the off-shell masses in the calculation veto the emissions from the children." " no veto in generation of emissions from children", 2); static SwitchOption interfaceReconstructionOptionOffShell3 (interfaceReconstructionOption, "OffShell3", "Use the off-shell masses in the calculation veto the emissions from the children." " veto in generation of emissions from children using cut-off for second parton", 3); static SwitchOption interfaceReconstructionOptionOffShell4 (interfaceReconstructionOption, "OffShell4", "Ass OffShell3 but with a restriction on the mass of final-state" " jets produced via backward evolution.", 4); static Switch interfaceSpinCorrelations ("SpinCorrelations", "Treatment of spin correlations in the parton shower", &Evolver::_spinOpt, 1, false, false); static SwitchOption interfaceSpinCorrelationsOff (interfaceSpinCorrelations, "No", "No spin correlations", 0); static SwitchOption interfaceSpinCorrelationsSpin (interfaceSpinCorrelations, "Yes", "Include the azimuthal spin correlations only", 1); static Switch interfaceSoftCorrelations ("SoftCorrelations", "Option for the treatment of soft correlations in the parton shower", &Evolver::_softOpt, 2, false, false); static SwitchOption interfaceSoftCorrelationsNone (interfaceSoftCorrelations, "No", "No soft correlations", 0); static SwitchOption interfaceSoftCorrelationsFull (interfaceSoftCorrelations, "Full", "Use the full eikonal", 1); static SwitchOption interfaceSoftCorrelationsSingular (interfaceSoftCorrelations, "Singular", "Use original Webber-Marchisini form", 2); static Switch interfaceHardPOWHEG ("HardPOWHEG", "Treatment of powheg emissions which are too hard to have a shower interpretation", &Evolver::_hardPOWHEG, false, false, false); static SwitchOption interfaceHardPOWHEGAsShower (interfaceHardPOWHEG, "AsShower", "Still interpret as shower emissions", false); static SwitchOption interfaceHardPOWHEGRealEmission (interfaceHardPOWHEG, "RealEmission", "Generate shower from the real emmission configuration", true); static Parameter interfaceMaxTryFSR ("MaxTryFSR", "The maximum number of attempted FSR emissions in" " the generation of the FSR", &Evolver::_maxTryFSR, 100000, 10, 100000000, false, false, Interface::limited); static Parameter interfaceMaxFailFSR ("MaxFailFSR", "Maximum number of failures generating the FSR", &Evolver::_maxFailFSR, 100, 1, 100000000, false, false, Interface::limited); static Parameter interfaceFSRFailureFraction ("FSRFailureFraction", "Maximum fraction of events allowed to fail due to too many FSR emissions", &Evolver::_fracFSR, 0.001, 1e-10, 1, false, false, Interface::limited); } void Evolver::generateIntrinsicpT(vector particlesToShower) { _intrinsic.clear(); if ( !ipTon() || !isISRadiationON() ) return; // don't do anything for the moment for secondary scatters if( !ShowerHandler::currentHandler()->firstInteraction() ) return; // generate intrinsic pT for(unsigned int ix=0;ixprogenitor()->isFinalState()) continue; if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue; Energy ipt; if(UseRandom::rnd() > _beta) { ipt=_iptrms*sqrt(-log(UseRandom::rnd())); } else { ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.); } pair pt = make_pair(ipt,UseRandom::rnd(Constants::twopi)); _intrinsic[particlesToShower[ix]] = pt; } } void Evolver::setupMaximumScales(const vector & p, XCPtr xcomb) { // let POWHEG events radiate freely if(_hardEmissionMode>0&&hardTree()) { vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy); return; } // return if no vetos if (!hardVetoOn()) return; // find out if hard partonic subprocess. bool isPartonic(false); map::const_iterator cit = _currenttree->incomingLines().begin(); Lorentz5Momentum pcm; for(; cit!=currentTree()->incomingLines().end(); ++cit) { pcm += cit->first->progenitor()->momentum(); isPartonic |= cit->first->progenitor()->coloured(); } // find minimum pt from hard process, the maximum pt from all outgoing // coloured lines (this is simpler and more general than // 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will // be transverse mass. Energy ptmax = generator()->maximumCMEnergy(); // general case calculate the scale if (!hardVetoXComb()|| (hardVetoReadOption()&& !ShowerHandler::currentHandler()->firstInteraction())) { // scattering process if(currentTree()->isHard()) { assert(xcomb); // coloured incoming particles if (isPartonic) { map::const_iterator cjt = currentTree()->outgoingLines().begin(); for(; cjt!=currentTree()->outgoingLines().end(); ++cjt) { if (cjt->first->progenitor()->coloured()) ptmax = min(ptmax,cjt->first->progenitor()->momentum().mt()); } } if (ptmax == generator()->maximumCMEnergy() ) ptmax = pcm.m(); if(hardVetoXComb()&&hardVetoReadOption()&& !ShowerHandler::currentHandler()->firstInteraction()) { ptmax=min(ptmax,sqrt(xcomb->lastShowerScale())); } } // decay, incoming() is the decaying particle. else { ptmax = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } // hepeup.SCALUP is written into the lastXComb by the // LesHouchesReader itself - use this by user's choice. // Can be more general than this. else { if(currentTree()->isHard()) { assert(xcomb); ptmax = sqrt( xcomb->lastShowerScale() ); } else { ptmax = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } } ptmax *= ShowerHandler::currentHandler()->hardScaleFactor(); // set maxHardPt for all progenitors. For partonic processes this // is now the max pt in the FS, for non-partonic processes or // processes with no coloured FS the invariant mass of the IS vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax); } void Evolver::setupHardScales(const vector & p, XCPtr xcomb) { if ( hardVetoXComb() && (!hardVetoReadOption() || ShowerHandler::currentHandler()->firstInteraction()) ) { Energy hardScale = ZERO; if(currentTree()->isHard()) { assert(xcomb); hardScale = sqrt( xcomb->lastShowerScale() ); } else { hardScale = currentTree()->incomingLines().begin()->first ->progenitor()->momentum().mass(); } hardScale *= ShowerHandler::currentHandler()->hardScaleFactor(); vector::const_iterator ckt = p.begin(); for (; ckt != p.end(); ckt++) (*ckt)->hardScale(hardScale); muPt = hardScale; } } void Evolver::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) { isMCatNLOSEvent = false; isMCatNLOHEvent = false; isPowhegSEvent = false; isPowhegHEvent = false; Ptr::tptr subme; Ptr::tptr me; Ptr::tptr dipme; Ptr::ptr sxc = dynamic_ptr_cast::ptr>(xcomb); if ( sxc ) { subme = dynamic_ptr_cast::tptr>(sxc->matrixElement()); me = dynamic_ptr_cast::tptr>(sxc->matrixElement()); dipme = dynamic_ptr_cast::tptr>(sxc->matrixElement()); } if ( subme ) { if ( subme->showerApproximation() ) { theShowerApproximation = subme->showerApproximation(); // separate MCatNLO and POWHEG-type corrections if ( !subme->showerApproximation()->needsSplittingGenerator() ) { if ( subme->realShowerSubtraction() ) isMCatNLOHEvent = true; else if ( subme->virtualShowerSubtraction() ) isMCatNLOSEvent = true; } else { if ( subme->realShowerSubtraction() ) isPowhegHEvent = true; else if ( subme->virtualShowerSubtraction() || subme->loopSimSubtraction() ) isPowhegSEvent = true; } } } else if ( me ) { if ( me->factory()->showerApproximation() ) { theShowerApproximation = me->factory()->showerApproximation(); if ( !me->factory()->showerApproximation()->needsSplittingGenerator() ) isMCatNLOSEvent = true; else isPowhegSEvent = true; } } string error = "Inconsistent hard emission set-up in Evolver::showerHardProcess(). "; if ( ( isMCatNLOSEvent || isMCatNLOHEvent ) ){ if (_hardEmissionMode > 1) throw Exception() << error << "Cannot generate POWHEG matching with MC@NLO shower " << "approximation. Add 'set Evolver:HardEmissionMode 0' to input file." << Exception::runerror; if ( ShowerHandler::currentHandler()->canHandleMatchboxTrunc()) throw Exception() << error << "Cannot use truncated qtilde shower with MC@NLO shower " << "approximation. Set LHCGenerator:EventHandler" << ":CascadeHandler to '/Herwig/Shower/ShowerHandler' or " << "'/Herwig/DipoleShower/DipoleShowerHandler'." << Exception::runerror; } else if ( ((isPowhegSEvent || isPowhegHEvent) || dipme) && _hardEmissionMode < 2){ if ( ShowerHandler::currentHandler()->canHandleMatchboxTrunc()) throw Exception() << error << "Unmatched events requested for POWHEG shower " << "approximation. Set Evolver:HardEmissionMode to " << "'MatchboxPOWHEG' or 'FullPOWHEG'." << Exception::runerror; else if (_hardEmissionModeWarn){ _hardEmissionModeWarn = false; _hardEmissionMode+=2; throw Exception() << error << "Unmatched events requested for POWHEG shower " << "approximation. Changing Evolver:HardEmissionMode from " << _hardEmissionMode-2 << " to " << _hardEmissionMode << Exception::warning; } } if ( isPowhegSEvent || isPowhegHEvent) { if (theShowerApproximation->needsTruncatedShower() && !ShowerHandler::currentHandler()->canHandleMatchboxTrunc() ) throw Exception() << error << "Current shower handler cannot generate truncated shower. " << "Set Generator:EventHandler:CascadeHandler to " << "'/Herwig/Shower/PowhegShowerHandler'." << Exception::runerror; } else if ( dipme && _missingTruncWarn){ _missingTruncWarn=false; throw Exception() << "Warning: POWHEG shower approximation used without " << "truncated shower. Set Generator:EventHandler:" << "CascadeHandler to '/Herwig/Shower/PowhegShowerHandler' and " << "'MEMatching:TruncatedShower Yes'." << Exception::warning; } else if ( !dipme && _hardEmissionMode > 1 && ShowerHandler::currentHandler()->firstInteraction()) throw Exception() << error << "POWHEG matching requested for LO events. Include " << "'set Factory:ShowerApproximation MEMatching' in input file." << Exception::runerror; _hardme = HwMEBasePtr(); // extract the matrix element tStdXCombPtr lastXC = dynamic_ptr_cast(xcomb); if(lastXC) { _hardme = dynamic_ptr_cast(lastXC->matrixElement()); } _decayme = HwDecayerBasePtr(); // set the current tree currentTree(hard); hardTree(HardTreePtr()); // number of attempts if more than one interaction switched on unsigned int interactionTry=0; do { try { // generate the showering doShowering(true,xcomb); // if no vetos return return; } catch (InteractionVeto) { currentTree()->clear(); ++interactionTry; } } while(interactionTry<=5); throw Exception() << "Too many tries for shower in " << "Evolver::showerHardProcess()" << Exception::eventerror; } void Evolver::hardMatrixElementCorrection(bool hard) { // set the initial enhancement factors for the soft correction _initialenhance = 1.; _finalenhance = 1.; // if hard matrix element switched off return if(!MECOn(hard)) return; // see if we can get the correction from the matrix element // or decayer if(hard) { if(_hardme&&_hardme->hasMECorrection()) { _hardme->initializeMECorrection(_currenttree, _initialenhance,_finalenhance); if(hardMEC(hard)) _hardme->applyHardMatrixElementCorrection(_currenttree); } } else { if(_decayme&&_decayme->hasMECorrection()) { _decayme->initializeMECorrection(_currenttree, _initialenhance,_finalenhance); if(hardMEC(hard)) _decayme->applyHardMatrixElementCorrection(_currenttree); } } } ShowerParticleVector Evolver::createTimeLikeChildren(tShowerParticlePtr, IdList ids) { // Create the ShowerParticle objects for the two children of // the emitting particle; set the parent/child relationship // if same as definition create particles, otherwise create cc ShowerParticleVector children; for(unsigned int ix=0;ix<2;++ix) { children.push_back(new_ptr(ShowerParticle(ids[ix+1],true))); if(children[ix]->id()==_progenitor->id()&&!ids[ix+1]->stable()) children[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass())); else children[ix]->set5Momentum(Lorentz5Momentum(ids[ix+1]->mass())); } return children; } bool Evolver::timeLikeShower(tShowerParticlePtr particle, ShowerInteraction::Type type, Branching fb, bool first) { // don't do anything if not needed if(_limitEmissions == 1 || hardOnly() || ( _limitEmissions == 2 && _nfs != 0) || ( _limitEmissions == 4 && _nfs + _nis != 0) ) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } // too many tries if(_nFSR>=_maxTryFSR) { ++_nFailedFSR; // too many failed events if(_nFailedFSR>=_maxFailFSR) throw Exception() << "Too many events have failed due to too many shower emissions, in\n" << "Evolver::timeLikeShower(). Terminating run\n" << Exception::runerror; throw Exception() << "Too many attempted emissions in Evolver::timeLikeShower()\n" << Exception::eventerror; } // generate the emission ShowerParticleVector children; int ntry=0; // generate the emission if(!fb.kinematics) fb = selectTimeLikeBranching(particle,type,HardBranchingPtr()); // no emission, return if(!fb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } Branching fc[2]; bool setupChildren = true; while (ntry<50) { fc[0] = Branching(); fc[1] = Branching(); ++ntry; assert(fb.kinematics); // has emitted // Assign the shower kinematics to the emitting particle. if(setupChildren) { ++_nFSR; particle->showerKinematics(fb.kinematics); // check highest pT if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the children children = createTimeLikeChildren(particle,fb.ids); // update the children particle->showerKinematics()-> updateChildren(particle, children,fb.type,_reconOpt>=3); // update number of emissions ++_nfs; if(_limitEmissions!=0) { if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } setupChildren = false; } // select branchings for children fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); // old default if(_reconOpt==0) { // shower the first particle if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); break; } // Herwig default else if(_reconOpt==1) { // shower the first particle if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); // clean up the vetoed emission if(particle->virtualMass()==ZERO) { particle->showerKinematics(ShoKinPtr()); for(unsigned int ix=0;ixabandonChild(children[ix]); children.clear(); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); particle->vetoEmission(fb.type,fb.kinematics->scale()); // generate the new emission fb = selectTimeLikeBranching(particle,type,HardBranchingPtr()); // no emission, return if(!fb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } setupChildren = true; continue; } else break; } // veto children else if(_reconOpt>=2) { // cut-off masses for the branching const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); // compute the masses of the children Energy masses[3]; for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) { const vector & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids); Energy2 q2 = fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale()); if(fc[ix].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); masses[ix+1] = sqrt(q2); } else { masses[ix+1] = virtualMasses[ix+1]; } } masses[0] = fb.ids[0]->id()!=ParticleID::g ? virtualMasses[0] : ZERO; double z = fb.kinematics->z(); Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale()) + sqr(masses[0])) - sqr(masses[1])*(1.-z) - sqr(masses[2])*z; if(pt2>=ZERO) { break; } else { // reset the scales for the children for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); else children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); children[ix]->virtualMass(ZERO); } } } }; if(_reconOpt>=2) { // shower the first particle if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); } if(first&&!children.empty()) particle->showerKinematics()->resetChildren(particle,children); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } bool Evolver::spaceLikeShower(tShowerParticlePtr particle, PPtr beam, ShowerInteraction::Type type) { //using the pdf's associated with the ShowerHandler assures, that //modified pdf's are used for the secondary interactions via //CascadeHandler::resetPDFs(...) tcPDFPtr pdf; if(ShowerHandler::currentHandler()->firstPDF().particle() == _beam) pdf = ShowerHandler::currentHandler()->firstPDF().pdf(); if(ShowerHandler::currentHandler()->secondPDF().particle() == _beam) pdf = ShowerHandler::currentHandler()->secondPDF().pdf(); Energy freeze = ShowerHandler::currentHandler()->pdfFreezingScale(); // don't do anything if not needed if(_limitEmissions == 2 || hardOnly() || ( _limitEmissions == 1 && _nis != 0 ) || ( _limitEmissions == 4 && _nis + _nfs != 0 ) ) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } Branching bb; // generate branching while (true) { bb=_splittingGenerator->chooseBackwardBranching(*particle,beam, _initialenhance, _beam,type, pdf,freeze); // return if no emission if(!bb.kinematics) { if(particle->spinInfo()) particle->spinInfo()->develop(); return false; } // if not vetoed break if(!spaceLikeVetoed(bb,particle)) break; // otherwise reset scale and continue particle->vetoEmission(bb.type,bb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); } // assign the splitting function and shower kinematics particle->showerKinematics(bb.kinematics); if(bb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(bb.kinematics->pT()); // For the time being we are considering only 1->2 branching // particles as in Sudakov form factor tcPDPtr part[2]={bb.ids[0],bb.ids[2]}; // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr(ShowerParticle(part[0],false)); ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true)); ShowerParticleVector theChildren; theChildren.push_back(particle); theChildren.push_back(otherChild); //this updates the evolution scale particle->showerKinematics()-> updateParent(newParent, theChildren,bb.type); // update the history if needed _currenttree->updateInitialStateShowerProduct(_progenitor,newParent); _currenttree->addInitialStateBranching(particle,newParent,otherChild); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower ++_nis; bool emitted = _limitEmissions==0 ? spaceLikeShower(newParent,beam,type) : false; if(newParent->spinInfo()) newParent->spinInfo()->develop(); // now reconstruct the momentum if(!emitted) { if(_intrinsic.find(_progenitor)==_intrinsic.end()) { bb.kinematics->updateLast(newParent,ZERO,ZERO); } else { pair kt=_intrinsic[_progenitor]; bb.kinematics->updateLast(newParent, kt.first*cos(kt.second), kt.first*sin(kt.second)); } } particle->showerKinematics()-> updateChildren(newParent, theChildren,bb.type,_reconOpt>=4); if(_limitEmissions!=0) { if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } // perform the shower of the final-state particle timeLikeShower(otherChild,type,Branching(),true); updateHistory(otherChild); if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop(); // return the emitted if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } void Evolver::showerDecay(ShowerTreePtr decay) { _decayme = HwDecayerBasePtr(); _hardme = HwMEBasePtr(); // find the decayer // try the normal way if possible tDMPtr dm = decay->incomingLines().begin()->first->original() ->decayMode(); if(!dm) dm = decay->incomingLines().begin()->first->copy() ->decayMode(); if(!dm) dm = decay->incomingLines().begin()->first->progenitor()->decayMode(); // otherwise make a string and look it up if(!dm) { string tag = decay->incomingLines().begin()->first->original()->dataPtr()->name() + "->"; OrderedParticles outgoing; for(map::const_iterator it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) { if(abs(decay->incomingLines().begin()->first->original()->id()) == ParticleID::t && abs(it->first->original()->id())==ParticleID::Wplus && decay->treelinks().size() == 1) { ShowerTreePtr Wtree = decay->treelinks().begin()->first; for(map::const_iterator it2=Wtree->outgoingLines().begin();it2!=Wtree->outgoingLines().end();++it2) { outgoing.insert(it2->first->original()->dataPtr()); } } else { outgoing.insert(it->first->original()->dataPtr()); } } for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) { if(it!=outgoing.begin()) tag += ","; tag +=(**it).name(); } tag += ";"; dm = findDecayMode(tag); } if(dm) _decayme = dynamic_ptr_cast(dm->decayer()); // set the ShowerTree to be showered currentTree(decay); decay->applyTransforms(); hardTree(HardTreePtr()); unsigned int interactionTry=0; do { try { // generate the showering doShowering(false,XCPtr()); // if no vetos // force calculation of spin correlations SpinPtr spInfo = decay->incomingLines().begin()->first->progenitor()->spinInfo(); if(spInfo) { if(!spInfo->developed()) spInfo->needsUpdate(); spInfo->develop(); } // and then return return; } catch (InteractionVeto) { currentTree()->clear(); ++interactionTry; } } while(interactionTry<=5); throw Exception() << "Too many tries for QED shower in Evolver::showerDecay()" << Exception::eventerror; } bool Evolver::spaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction::Type type, Branching fb) { // too many tries if(_nFSR>=_maxTryFSR) { ++_nFailedFSR; // too many failed events if(_nFailedFSR>=_maxFailFSR) throw Exception() << "Too many events have failed due to too many shower emissions, in\n" << "Evolver::timeLikeShower(). Terminating run\n" << Exception::runerror; throw Exception() << "Too many attempted emissions in Evolver::timeLikeShower()\n" << Exception::eventerror; } // generate the emission ShowerParticleVector children; int ntry=0; // generate the emission if(!fb.kinematics) fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type, HardBranchingPtr()); // no emission, return if(!fb.kinematics) return false; Branching fc[2]; bool setupChildren = true; while (ntry<50) { if(particle->virtualMass()==ZERO) particle->virtualMass(_progenitor->progenitor()->mass()); fc[0] = Branching(); fc[1] = Branching(); ++ntry; assert(fb.kinematics); // has emitted // Assign the shower kinematics to the emitting particle. if(setupChildren) { ++_nFSR; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the ShowerParticle objects for the two children children = createTimeLikeChildren(particle,fb.ids); // updateChildren the children particle->showerKinematics()-> updateChildren(particle, children, fb.type,_reconOpt>=3); setupChildren = false; } // select branchings for children fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass, type,HardBranchingPtr()); fc[1] = selectTimeLikeBranching (children[1],type,HardBranchingPtr()); // old default if(_reconOpt==0) { // shower the first particle _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); _currenttree->addInitialStateBranching(particle,children[0],children[1]); if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); updateHistory(children[1]); // branching has happened break; } // Herwig default else if(_reconOpt==1) { // shower the first particle _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); _currenttree->addInitialStateBranching(particle,children[0],children[1]); if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); updateHistory(children[1]); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); // clean up the vetoed emission if(particle->virtualMass()==ZERO) { particle->showerKinematics(ShoKinPtr()); for(unsigned int ix=0;ixabandonChild(children[ix]); children.clear(); particle->vetoEmission(fb.type,fb.kinematics->scale()); // generate the new emission fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type, HardBranchingPtr()); // no emission, return if(!fb.kinematics) { return false; } setupChildren = true; continue; } else break; } else if(_reconOpt>=2) { // cut-off masses for the branching const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); // compute the masses of the children Energy masses[3]; // space-like children masses[1] = children[0]->virtualMass(); // time-like child if(fc[1].kinematics) { const vector & vm = fc[1].sudakov->virtualMasses(fc[1].ids); Energy2 q2 = fc[1].kinematics->z()*(1.-fc[1].kinematics->z())*sqr(fc[1].kinematics->scale()); if(fc[1].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); masses[2] = sqrt(q2); } else { masses[2] = virtualMasses[2]; } masses[0]=particle->virtualMass(); double z = fb.kinematics->z(); Energy2 pt2 = (1.-z)*(z*sqr(masses[0])-sqr(masses[1])-z/(1.-z)*sqr(masses[2])); if(pt2>=ZERO) { break; } else { // reset the scales for the children for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); else { if(ix==0) children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,Constants::MaxEnergy); else children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); } } children[0]->virtualMass(_progenitor->progenitor()->mass()); children[1]->virtualMass(ZERO); } } }; if(_reconOpt>=2) { // In the case of splittings which involves coloured particles, // set properly the colour flow of the branching. // update the history if needed _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); _currenttree->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); // shower the second particle if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); updateHistory(children[1]); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); } // branching has happened return true; } vector Evolver::setupShower(bool hard) { // generate POWHEG hard emission if needed if(_hardEmissionMode>0) hardestEmission(hard); ShowerInteraction::Type inter = interaction_; if(_hardtree&&inter!=ShowerInteraction::QEDQCD && inter!=ShowerInteraction::ALL) { inter = _hardtree->interaction(); } // set the initial colour partners setEvolutionPartners(hard,inter,false); // generate hard me if needed if(_hardEmissionMode==0 || (!hard && _hardEmissionMode==-1)) hardMatrixElementCorrection(hard); // get the particles to be showered vector particlesToShower = currentTree()->extractProgenitors(); // remake the colour partners if needed if(_currenttree->hardMatrixElementCorrection()) { setEvolutionPartners(hard,interaction_,true); _currenttree->resetShowerProducts(); } // return the answer return particlesToShower; } void Evolver::setEvolutionPartners(bool hard,ShowerInteraction::Type type, bool clear) { // match the particles in the ShowerTree and hardTree if(hardTree() && !hardTree()->connect(currentTree())) throw Exception() << "Can't match trees in " << "Evolver::setEvolutionPartners()" << Exception::eventerror; // extract the progenitors vector particles = currentTree()->extractProgenitorParticles(); // clear the partners if needed if(clear) { for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); particles[ix]->clearPartners(); } } // sort out the colour partners if(hardTree()) { // find the partner for(unsigned int ix=0;ixparticles()[particles[ix]]->colourPartner(); if(!partner) continue; for(map::const_iterator it=hardTree()->particles().begin(); it!=hardTree()->particles().end();++it) { if(it->second==partner) particles[ix]->partner(it->first); } if(!particles[ix]->partner()) throw Exception() << "Can't match partners in " << "Evolver::setEvolutionPartners()" << Exception::eventerror; } } // Set the initial evolution scales showerModel()->partnerFinder()-> setInitialEvolutionScales(particles,!hard,type,!_hardtree); if(hardTree() && _hardPOWHEG) { bool tooHard=false; map::const_iterator eit=hardTree()->particles().end(); for(unsigned int ix=0;ix::const_iterator mit = hardTree()->particles().find(particles[ix]); Energy hardScale(ZERO); ShowerPartnerType::Type type(ShowerPartnerType::Undefined); // final-state if(particles[ix]->isFinalState()) { if(mit!= eit && !mit->second->children().empty()) { hardScale = mit->second->scale(); type = mit->second->type(); } } // initial-state else { if(mit!= eit && mit->second->parent()) { hardScale = mit->second->parent()->scale(); type = mit->second->parent()->type(); } } if(type!=ShowerPartnerType::Undefined) { if(type==ShowerPartnerType::QED) { tooHard |= particles[ix]->scales().QED_noAOscales().QCD_c_noAOscales().QCD_ac_noAOscales().EWchildren().empty()) { ShowerParticleVector theChildren; for(unsigned int ix=0;ixchildren().size();++ix) { ShowerParticlePtr part = dynamic_ptr_cast (particle->children()[ix]); theChildren.push_back(part); } // update the history if needed if(particle==_currenttree->getFinalStateShowerProduct(_progenitor)) _currenttree->updateFinalStateShowerProduct(_progenitor, particle,theChildren); _currenttree->addFinalStateBranching(particle,theChildren); for(unsigned int ix=0;ixprogenitor()->initializeFinalState(); if(hardTree()) { map::const_iterator eit=hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && !mit->second->children().empty() ) { bool output=truncatedTimeLikeShower(progenitor()->progenitor(), mit->second ,type,Branching(),true); if(output) updateHistory(progenitor()->progenitor()); return output; } } // do the shower bool output = hardOnly() ? false : timeLikeShower(progenitor()->progenitor() ,type,Branching(),true) ; if(output) updateHistory(progenitor()->progenitor()); return output; } bool Evolver::startSpaceLikeShower(PPtr parent, ShowerInteraction::Type type) { // initialise the basis vectors progenitor()->progenitor()->initializeInitialState(parent); if(hardTree()) { map::const_iterator eit =hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && mit->second->parent() ) { return truncatedSpaceLikeShower( progenitor()->progenitor(), parent, mit->second->parent(), type ); } } // perform the shower return hardOnly() ? false : spaceLikeShower(progenitor()->progenitor(),parent,type); } bool Evolver:: startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction::Type type) { _nFSR = 0; // set up the particle basis vectors progenitor()->progenitor()->initializeDecay(); if(hardTree()) { map::const_iterator eit =hardTree()->particles().end(), mit = hardTree()->particles().find(progenitor()->progenitor()); if( mit != eit && mit->second->parent() ) { HardBranchingPtr branch=mit->second; while(branch->parent()) branch=branch->parent(); return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxScales, minimumMass, branch ,type, Branching()); } } // perform the shower return hardOnly() ? false : spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type,Branching()); } bool Evolver::timeLikeVetoed(const Branching & fb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction::Type type = convertInteraction(fb.type); // check whether emission was harder than largest pt of hard subprocess if ( hardVetoFS() && fb.kinematics->pT() > _progenitor->maxHardPt() ) return true; // soft matrix element correction veto if( softMEC()) { if(_hardme && _hardme->hasMECorrection()) { if(_hardme->softMatrixElementVeto(_progenitor,particle,fb)) return true; } else if(_decayme && _decayme->hasMECorrection()) { if(_decayme->softMatrixElementVeto(_progenitor,particle,fb)) return true; } } // veto on maximum pt if(fb.kinematics->pT()>_progenitor->maximumpT(type)) return true; // general vetos if (fb.kinematics && !_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoTimeLike(_progenitor,particle,fb); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if(vetoed) return true; } if ( ShowerHandler::currentHandler()->firstInteraction() && ShowerHandler::currentHandler()->profileScales() ) { double weight = ShowerHandler::currentHandler()->profileScales()-> hardScaleProfile(_progenitor->hardScale(),fb.kinematics->pT()); if ( UseRandom::rnd() > weight ) return true; } return false; } bool Evolver::spaceLikeVetoed(const Branching & bb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction::Type type = convertInteraction(bb.type); // check whether emission was harder than largest pt of hard subprocess if (hardVetoIS() && bb.kinematics->pT() > _progenitor->maxHardPt()) return true; // apply the soft correction if( softMEC() && _hardme && _hardme->hasMECorrection() ) { if(_hardme->softMatrixElementVeto(_progenitor,particle,bb)) return true; } // the more general vetos // check vs max pt for the shower if(bb.kinematics->pT()>_progenitor->maximumpT(type)) return true; if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,bb); switch ((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } } if (vetoed) return true; } if ( ShowerHandler::currentHandler()->firstInteraction() && ShowerHandler::currentHandler()->profileScales() ) { double weight = ShowerHandler::currentHandler()->profileScales()-> hardScaleProfile(_progenitor->hardScale(),bb.kinematics->pT()); if ( UseRandom::rnd() > weight ) return true; } return false; } bool Evolver::spaceLikeDecayVetoed( const Branching & fb, ShowerParticlePtr particle) { // work out type of interaction ShowerInteraction::Type type = convertInteraction(fb.type); // apply the soft correction if( softMEC() && _decayme && _decayme->hasMECorrection() ) { if(_decayme->softMatrixElementVeto(_progenitor,particle,fb)) return true; } // veto on hardest pt in the shower if(fb.kinematics->pT()> _progenitor->maximumpT(type)) return true; // general vetos if (!_vetoes.empty()) { bool vetoed=false; for (vector::iterator v = _vetoes.begin(); v != _vetoes.end(); ++v) { bool test = (**v).vetoSpaceLike(_progenitor,particle,fb); switch((**v).vetoType()) { case ShowerVeto::Emission: vetoed |= test; break; case ShowerVeto::Shower: if(test) throw VetoShower(); break; case ShowerVeto::Event: if(test) throw Veto(); break; } if (vetoed) return true; } } return false; } void Evolver::hardestEmission(bool hard) { HardTreePtr ISRTree; if( ( _hardme && _hardme->hasPOWHEGCorrection()!=0 && _hardEmissionMode< 2) || ( _decayme && _decayme->hasPOWHEGCorrection()!=0 && _hardEmissionMode!=2) ) { if(_hardme) { assert(hard); _hardtree = _hardme->generateHardest( currentTree(),interaction_); } else { assert(!hard); _hardtree = _decayme->generateHardest( currentTree() ); } // store initial state POWHEG radiation if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1) ISRTree=_hardtree; } else if (_hardEmissionMode>1 && hard) { // Get minimum pT cutoff used in shower approximation Energy maxpt = 1.*GeV; int colouredIn = 0; int colouredOut = 0; for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if( it->second->coloured() ) colouredOut+=1; } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = currentTree()->incomingLines().begin(); it != currentTree()->incomingLines().end(); ++it ) { if( ! it->second->coloured() ) colouredIn+=1; } if ( theShowerApproximation ){ if ( theShowerApproximation->ffPtCut() == theShowerApproximation->fiPtCut() && theShowerApproximation->ffPtCut() == theShowerApproximation->iiPtCut() ) maxpt = theShowerApproximation->ffPtCut(); else if ( colouredIn == 2 && colouredOut == 0 ) maxpt = theShowerApproximation->iiPtCut(); else if ( colouredIn == 0 && colouredOut > 1 ) maxpt = theShowerApproximation->ffPtCut(); else if ( colouredIn == 2 && colouredOut == 1 ) maxpt = min(theShowerApproximation->iiPtCut(), theShowerApproximation->fiPtCut()); else if ( colouredIn == 1 && colouredOut > 1 ) maxpt = min(theShowerApproximation->ffPtCut(), theShowerApproximation->fiPtCut()); else maxpt = min(min(theShowerApproximation->iiPtCut(), theShowerApproximation->fiPtCut()), theShowerApproximation->ffPtCut()); } // Generate hardtree from born and real emission subprocesses _hardtree = ShowerHandler::currentHandler()->generateCKKW(currentTree()); // Find transverse momentum of hardest emission if (_hardtree){ for(set::iterator it=_hardtree->branchings().begin(); it!=_hardtree->branchings().end();++it) { if ((*it)->parent() && (*it)->status()==HardBranching::Incoming) maxpt=(*it)->branchingParticle()->momentum().perp(); if ((*it)->children().size()==2 && (*it)->status()==HardBranching::Outgoing){ if ((*it)->branchingParticle()->id()!=21 && abs((*it)->branchingParticle()->id())>5 ){ if ((*it)->children()[0]->branchingParticle()->id()==21 || abs((*it)->children()[0]->branchingParticle()->id())<6) maxpt=(*it)->children()[0]->branchingParticle()->momentum().perp(); else if ((*it)->children()[1]->branchingParticle()->id()==21 || abs((*it)->children()[1]->branchingParticle()->id())<6) maxpt=(*it)->children()[1]->branchingParticle()->momentum().perp(); } else { if ( abs((*it)->branchingParticle()->id())<6){ if (abs((*it)->children()[0]->branchingParticle()->id())<6) maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); else maxpt = (*it)->children()[0]->branchingParticle()->momentum().perp(); } else maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); } } } } // Hardest (pt) emission should be the first powheg emission. maxpt=min(sqrt(ShowerHandler::currentHandler()->lastXCombPtr()->lastShowerScale()),maxpt); // Set maxpt to pT of emission when showering POWHEG real-emission subprocesses if (!isPowhegSEvent && !isPowhegHEvent){ vector outGluon; vector outQuark; map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it; for( it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if ( abs(it->second->id())< 6) outQuark.push_back(it->second->id()); if ( it->second->id()==21 ) outGluon.push_back(it->second->id()); } if (outGluon.size() + outQuark.size() == 1){ for( it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if ( abs(it->second->id())< 6 || it->second->id()==21 ) maxpt = it->second->momentum().perp(); } } else if (outGluon.size() + outQuark.size() > 1){ // assume qqbar pair from a Z/gamma if (outGluon.size()==1 && outQuark.size() == 2 && outQuark[0]==-outQuark[1]){ for( it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if ( it->second->id()==21 ) maxpt = it->second->momentum().perp(); } } // otherwise take the lowest pT avoiding born DY events else { maxpt = generator()->maximumCMEnergy(); for( it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if ( abs(it->second->id())< 6 || it->second->id()==21 ) maxpt = min(maxpt,it->second->momentum().perp()); } } } } // set maximum pT for subsequent emissions from S events if ( isPowhegSEvent || (!isPowhegSEvent && !isPowhegHEvent)){ for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it = currentTree()->outgoingLines().begin(); it != currentTree()->outgoingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT(maxpt, ShowerInteraction::QCD ); } for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it = currentTree()->incomingLines().begin(); it != currentTree()->incomingLines().end(); ++it ) { if( ! it->second->coloured() ) continue; it->first->maximumpT(maxpt, ShowerInteraction::QCD ); } } } else _hardtree = ShowerHandler::currentHandler()->generateCKKW(currentTree()); // if hard me doesn't have a FSR powheg // correction use decay powheg correction if (_hardme && _hardme->hasPOWHEGCorrection()<2) { // check for intermediate colour singlet resonance const ParticleVector inter = _hardme->subProcess()->intermediates(); if (inter.size()!=1 || inter[0]->momentum().m2()/GeV2 < 0 || inter[0]->dataPtr()->iColour()!=PDT::Colour0){ if(_hardtree) connectTrees(currentTree(),_hardtree,hard); return; } map out = currentTree()->outgoingLines(); // ignore cases where outgoing particles are not coloured if (out.size()!=2 || out. begin()->second->dataPtr()->iColour()==PDT::Colour0 || out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) { if(_hardtree) connectTrees(currentTree(),_hardtree,hard); return; } // look up decay mode tDMPtr dm; string tag; string inParticle = inter[0]->dataPtr()->name() + "->"; vector outParticles; outParticles.push_back(out.begin ()->first->progenitor()->dataPtr()->name()); outParticles.push_back(out.rbegin()->first->progenitor()->dataPtr()->name()); for (int it=0; it<2; ++it){ tag = inParticle + outParticles[it] + "," + outParticles[(it+1)%2] + ";"; dm = generator()->findDecayMode(tag); if(dm) break; } // get the decayer HwDecayerBasePtr decayer; if(dm) decayer = dynamic_ptr_cast(dm->decayer()); // check if decayer has a FSR POWHEG correction if (!decayer || decayer->hasPOWHEGCorrection()<2){ if(_hardtree) connectTrees(currentTree(),_hardtree,hard); return; } // generate the hardest emission ShowerDecayMap decay; PPtr in = new_ptr(*inter[0]); ShowerTreePtr decayTree = new_ptr(ShowerTree(in, decay)); HardTreePtr FSRTree = decayer->generateHardest(decayTree); if (!FSRTree) { if(_hardtree) connectTrees(currentTree(),_hardtree,hard); return; } // if there is no ISRTree make _hardtree from FSRTree if (!ISRTree){ vector inBranch,hardBranch; for(map::const_iterator cit =currentTree()->incomingLines().begin(); cit!=currentTree()->incomingLines().end();++cit ) { inBranch.push_back(new_ptr(HardBranching(cit->second,SudakovPtr(), HardBranchingPtr(), HardBranching::Incoming))); inBranch.back()->beam(cit->first->original()->parents()[0]); hardBranch.push_back(inBranch.back()); } if(inBranch[0]->branchingParticle()->dataPtr()->coloured()) { inBranch[0]->colourPartner(inBranch[1]); inBranch[1]->colourPartner(inBranch[0]); } for(set::iterator it=FSRTree->branchings().begin(); it!=FSRTree->branchings().end();++it) { if((**it).branchingParticle()->id()!=in->id()) hardBranch.push_back(*it); } hardBranch[2]->colourPartner(hardBranch[3]); hardBranch[3]->colourPartner(hardBranch[2]); HardTreePtr newTree = new_ptr(HardTree(hardBranch,inBranch, ShowerInteraction::QCD)); _hardtree = newTree; } // Otherwise modify the ISRTree to include the emission in FSRTree else { vector FSROut, ISROut; set::iterator itFSR, itISR; // get outgoing particles for(itFSR =FSRTree->branchings().begin(); itFSR!=FSRTree->branchings().end();++itFSR){ if ((**itFSR).status()==HardBranching::Outgoing) FSROut.push_back((*itFSR)->branchingParticle()); } for(itISR =ISRTree->branchings().begin(); itISR!=ISRTree->branchings().end();++itISR){ if ((**itISR).status()==HardBranching::Outgoing) ISROut.push_back((*itISR)->branchingParticle()); } // find COM frame formed by outgoing particles LorentzRotation eventFrameFSR, eventFrameISR; eventFrameFSR = ((FSROut[0]->momentum()+FSROut[1]->momentum()).findBoostToCM()); eventFrameISR = ((ISROut[0]->momentum()+ISROut[1]->momentum()).findBoostToCM()); // find rotation between ISR and FSR frames int j=0; if (ISROut[0]->id()!=FSROut[0]->id()) j=1; eventFrameISR.rotateZ( (eventFrameFSR*FSROut[0]->momentum()).phi()- (eventFrameISR*ISROut[j]->momentum()).phi() ); eventFrameISR.rotateY( (eventFrameFSR*FSROut[0]->momentum()).theta()- (eventFrameISR*ISROut[j]->momentum()).theta() ); eventFrameISR.invert(); for (itFSR=FSRTree->branchings().begin(); itFSR!=FSRTree->branchings().end();++itFSR){ if ((**itFSR).branchingParticle()->id()==in->id()) continue; for (itISR =ISRTree->branchings().begin(); itISR!=ISRTree->branchings().end();++itISR){ if ((**itISR).status()==HardBranching::Incoming) continue; if ((**itFSR).branchingParticle()->id()== (**itISR).branchingParticle()->id()){ // rotate FSRTree particle to ISRTree event frame (**itISR).branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).branchingParticle()->momentum()); (**itISR).branchingParticle()->rescaleMass(); // add the children of the FSRTree particles to the ISRTree if(!(**itFSR).children().empty()){ (**itISR).addChild((**itFSR).children()[0]); (**itISR).addChild((**itFSR).children()[1]); // rotate momenta to ISRTree event frame (**itISR).children()[0]->branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).children()[0]->branchingParticle()->momentum()); (**itISR).children()[1]->branchingParticle()->setMomentum(eventFrameISR* eventFrameFSR* (**itFSR).children()[1]->branchingParticle()->momentum()); } } } } _hardtree = ISRTree; } } if(_hardtree){ connectTrees(currentTree(),_hardtree,hard); } } bool Evolver::truncatedTimeLikeShower(tShowerParticlePtr particle, HardBranchingPtr branch, ShowerInteraction::Type type, Branching fb, bool first) { // select a branching if we don't have one if(!fb.kinematics) fb = selectTimeLikeBranching(particle,type,branch); // must be an emission, the forced one it not a truncated one assert(fb.kinematics); ShowerParticleVector children; int ntry=0; Branching fc[2]; bool setupChildren = true; while (ntry<50) { if(!fc[0].hard) fc[0] = Branching(); if(!fc[1].hard) fc[1] = Branching(); ++ntry; // Assign the shower kinematics to the emitting particle. if(setupChildren) { ++_nFSR; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the children children = createTimeLikeChildren(particle,fb.ids); // update the children particle->showerKinematics()-> updateChildren(particle, children,fb.type,_reconOpt>=3); setupChildren = false; } // select branchings for children if(!fc[0].kinematics) { // select branching for first particle if(!fb.hard && fb.iout ==1 ) fc[0] = selectTimeLikeBranching(children[0],type,branch); else if(fb.hard && !branch->children()[0]->children().empty() ) fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); else fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); } // select branching for the second particle if(!fc[1].kinematics) { // select branching for first particle if(!fb.hard && fb.iout ==2 ) fc[1] = selectTimeLikeBranching(children[1],type,branch); else if(fb.hard && !branch->children()[1]->children().empty() ) fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); else fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); } // old default if(_reconOpt==0 || (_reconOpt==1 && fb.hard) ) { // shower the first particle if(fc[0].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 1) truncatedTimeLikeShower(children[0],branch,type,fc[0],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 2) truncatedTimeLikeShower(children[1],branch,type,fc[1],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[1]->children().empty() ) truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false); else timeLikeShower(children[1],type,fc[1],false); } if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); break; } // H7 default else if(_reconOpt==1) { // shower the first particle if(fc[0].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 1) truncatedTimeLikeShower(children[0],branch,type,fc[0],false); else timeLikeShower(children[0],type,fc[0],false); } if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 2) truncatedTimeLikeShower(children[1],branch,type,fc[1],false); else timeLikeShower(children[1],type,fc[1],false); } if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); // clean up the vetoed emission if(particle->virtualMass()==ZERO) { particle->showerKinematics(ShoKinPtr()); for(unsigned int ix=0;ixabandonChild(children[ix]); children.clear(); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); particle->vetoEmission(fb.type,fb.kinematics->scale()); // generate the new emission fb = selectTimeLikeBranching(particle,type,branch); // must be at least hard emission assert(fb.kinematics); setupChildren = true; continue; } else break; } else if(_reconOpt>=2) { // cut-off masses for the branching const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); // compute the masses of the children Energy masses[3]; for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) { const vector & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids); Energy2 q2 = fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale()); if(fc[ix].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); masses[ix+1] = sqrt(q2); } else { masses[ix+1] = virtualMasses[ix+1]; } } masses[0] = fb.ids[0]->id()!=ParticleID::g ? virtualMasses[0] : ZERO; double z = fb.kinematics->z(); Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale()) + sqr(masses[0])) - sqr(masses[1])*(1.-z) - sqr(masses[2])*z; if(pt2>=ZERO) { break; } // if only the hard emission have to accept it else if ((fc[0].hard && !fc[1].kinematics) || (fc[1].hard && !fc[0].kinematics) ) { break; } else { // reset the scales for the children for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].hard) continue; if(fc[ix].kinematics && ! fc[ix].hard ) children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); else children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); children[ix]->virtualMass(ZERO); } } } }; if(_reconOpt>=2) { // shower the first particle if(fc[0].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 1) truncatedTimeLikeShower(children[0],branch,type,fc[0],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); // shower the second particle if(fc[1].kinematics) { // the parent has truncated emission and following line if(!fb.hard && fb.iout == 2) truncatedTimeLikeShower(children[1],branch,type,fc[1],false); // hard emission and subsquent hard emissions else if(fb.hard && !branch->children()[1]->children().empty() ) truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false); else timeLikeShower(children[1],type,fc[1],false); } if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); // branching has happened particle->showerKinematics()->updateParent(particle, children,fb.type); } if(first&&!children.empty()) particle->showerKinematics()->resetChildren(particle,children); if(particle->spinInfo()) particle->spinInfo()->develop(); return true; } bool Evolver::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam, HardBranchingPtr branch, ShowerInteraction::Type type) { tcPDFPtr pdf; if(ShowerHandler::currentHandler()->firstPDF().particle() == beamParticle()) pdf = ShowerHandler::currentHandler()->firstPDF().pdf(); if(ShowerHandler::currentHandler()->secondPDF().particle() == beamParticle()) pdf = ShowerHandler::currentHandler()->secondPDF().pdf(); Energy freeze = ShowerHandler::currentHandler()->pdfFreezingScale(); Branching bb; // parameters of the force branching double z(0.); HardBranchingPtr timelike; for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) { if( branch->children()[ix]->status() ==HardBranching::Outgoing) { timelike = branch->children()[ix]; } if( branch->children()[ix]->status() ==HardBranching::Incoming ) z = branch->children()[ix]->z(); } // generate truncated branching tcPDPtr part[2]; if(z>=0.&&z<=1.) { while (true) { if( !isTruncatedShowerON() || hardOnly() ) break; bb = splittingGenerator()->chooseBackwardBranching( *particle, beam, 1., beamParticle(), type , pdf,freeze); if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) { bb = Branching(); break; } // particles as in Sudakov form factor part[0] = bb.ids[0]; part[1] = bb.ids[2]; double zsplit = bb.kinematics->z(); // apply the vetos for the truncated shower // if doesn't carry most of momentum ShowerInteraction::Type type2 = convertInteraction(bb.type); if(type2==branch->sudakov()->interactionType() && zsplit < 0.5) { particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } // others if( part[0]->id() != particle->id() || // if particle changes type bb.kinematics->pT() > progenitor()->maximumpT(type2) || // pt veto bb.kinematics->scale() < branch->scale()) { // angular ordering veto particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } // and those from the base class if(spaceLikeVetoed(bb,particle)) { particle->vetoEmission(bb.type,bb.kinematics->scale()); continue; } break; } } if( !bb.kinematics ) { //do the hard emission ShoKinPtr kinematics = branch->sudakov()->createInitialStateBranching( branch->scale(), z, branch->phi(), branch->children()[0]->pT() ); // assign the splitting function and shower kinematics particle->showerKinematics( kinematics ); if(kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(kinematics->pT()); // For the time being we are considering only 1->2 branching // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) ); ShowerParticlePtr otherChild = new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(), true, true ) ); ShowerParticleVector theChildren; theChildren.push_back( particle ); theChildren.push_back( otherChild ); particle->showerKinematics()-> updateParent( newParent, theChildren, branch->type()); // update the history if needed currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); currentTree()->addInitialStateBranching( particle, newParent, otherChild ); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower bool emitted=false; if(!hardOnly()) { if( branch->parent() ) { emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type); } else { emitted = spaceLikeShower( newParent, beam , type); } } if( !emitted ) { if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { kinematics->updateLast( newParent, ZERO, ZERO ); } else { pair kt = intrinsicpT()[progenitor()]; kinematics->updateLast( newParent, kt.first*cos( kt.second ), kt.first*sin( kt.second ) ); } } particle->showerKinematics()-> updateChildren( newParent, theChildren,bb.type,false); if(hardOnly()) return true; // perform the shower of the final-state particle if( timelike->children().empty() ) { timeLikeShower( otherChild , type,Branching(),true); } else { truncatedTimeLikeShower( otherChild, timelike , type,Branching(), true); } updateHistory(otherChild); // return the emitted return true; } // assign the splitting function and shower kinematics particle->showerKinematics( bb.kinematics ); if(bb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(bb.kinematics->pT()); // For the time being we are considering only 1->2 branching // Now create the actual particles, make the otherChild a final state // particle, while the newParent is not ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) ); ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) ); ShowerParticleVector theChildren; theChildren.push_back( particle ); theChildren.push_back( otherChild ); particle->showerKinematics()-> updateParent( newParent, theChildren, bb.type); // update the history if needed currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); currentTree()->addInitialStateBranching( particle, newParent, otherChild ); // for the reconstruction of kinematics, parent/child // relationships are according to the branching process: // now continue the shower bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type); // now reconstruct the momentum if( !emitted ) { if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { bb.kinematics->updateLast( newParent, ZERO, ZERO ); } else { pair kt = intrinsicpT()[ progenitor() ]; bb.kinematics->updateLast( newParent, kt.first*cos( kt.second ), kt.first*sin( kt.second ) ); } } particle->showerKinematics()-> updateChildren( newParent, theChildren, bb.type,false); // perform the shower of the final-state particle timeLikeShower( otherChild , type,Branching(),true); updateHistory(otherChild); // return the emitted return true; } bool Evolver:: truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass, HardBranchingPtr branch, ShowerInteraction::Type type, Branching fb) { // select a branching if we don't have one if(!fb.kinematics) fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch); // must be an emission, the forced one it not a truncated one assert(fb.kinematics); ShowerParticleVector children; int ntry=0; Branching fc[2]; bool setupChildren = true; while (ntry<50) { if(!fc[0].hard) fc[0] = Branching(); if(!fc[1].hard) fc[1] = Branching(); ++ntry; if(setupChildren) { ++_nFSR; // Assign the shower kinematics to the emitting particle. particle->showerKinematics(fb.kinematics); if(fb.kinematics->pT()>progenitor()->highestpT()) progenitor()->highestpT(fb.kinematics->pT()); // create the ShowerParticle objects for the two children children = createTimeLikeChildren(particle,fb.ids); // updateChildren the children particle->showerKinematics()-> updateChildren(particle, children, fb.type,_reconOpt>=3); setupChildren = false; } // select branchings for children if(!fc[0].kinematics) { if(children[0]->id()==particle->id()) { // select branching for first particle if(!fb.hard) fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type,branch); else if(fb.hard && ! branch->children()[0]->children().empty() ) fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, branch->children()[0]); else fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, HardBranchingPtr()); } else { // select branching for first particle if(fb.hard && !branch->children()[0]->children().empty() ) fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); else fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); } } // select branching for the second particle if(!fc[1].kinematics) { if(children[1]->id()==particle->id()) { // select branching for first particle if(!fb.hard) fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type,branch); else if(fb.hard && ! branch->children()[1]->children().empty() ) fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, branch->children()[1]); else fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, HardBranchingPtr()); } else { if(fb.hard && !branch->children()[1]->children().empty() ) fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); else fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); } } // old default if(_reconOpt==0 || (_reconOpt==1 && fb.hard) ) { // update the history if needed currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); currentTree()->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[0]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[0]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } } // shower the second particle if(fc[1].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[1]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[1]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); // normal shower else timeLikeShower(children[0],type,fc[1],false); } } updateHistory(children[1]); // branching has happened break; } // H7 default else if(_reconOpt==1) { // update the history if needed currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); currentTree()->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[0]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[0]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } } // shower the second particle if(fc[1].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[1]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[1]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); // normal shower else timeLikeShower(children[0],type,fc[1],false); } } // clean up the vetoed emission if(particle->virtualMass()==ZERO) { particle->showerKinematics(ShoKinPtr()); for(unsigned int ix=0;ixabandonChild(children[ix]); children.clear(); particle->vetoEmission(fb.type,fb.kinematics->scale()); // generate the new emission fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch); // must be at least hard emission assert(fb.kinematics); setupChildren = true; continue; } else { updateHistory(children[1]); break; } } else if(_reconOpt>=2) { // cut-off masses for the branching const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); // compute the masses of the children Energy masses[3]; // space-like children masses[1] = children[0]->virtualMass(); // time-like child if(fc[1].kinematics) { const vector & vm = fc[1].sudakov->virtualMasses(fc[1].ids); Energy2 q2 = fc[1].kinematics->z()*(1.-fc[1].kinematics->z())*sqr(fc[1].kinematics->scale()); if(fc[1].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); masses[2] = sqrt(q2); } else { masses[2] = virtualMasses[2]; } masses[0]=particle->virtualMass(); double z = fb.kinematics->z(); Energy2 pt2 = (1.-z)*(z*sqr(masses[0])-sqr(masses[1])-z/(1.-z)*sqr(masses[2])); if(pt2>=ZERO) { break; } else { // reset the scales for the children for(unsigned int ix=0;ix<2;++ix) { if(fc[ix].kinematics) children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); else { if(ix==0) children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,Constants::MaxEnergy); else children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); } } children[0]->virtualMass(_progenitor->progenitor()->mass()); children[1]->virtualMass(ZERO); } } }; if(_reconOpt>=2) { // update the history if needed currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); currentTree()->addInitialStateBranching(particle,children[0],children[1]); // shower the first particle if(fc[0].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[0]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[0]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); // normal shower else timeLikeShower(children[0],type,fc[0],false); } } // shower the second particle if(fc[1].kinematics) { if(children[0]->id()==particle->id()) { if(!fb.hard) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch,type,fc[1]); else if(fb.hard && ! branch->children()[0]->children().empty() ) truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, branch->children()[0],type,fc[1]); else spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); } else { if(fb.hard && !branch->children()[0]->children().empty() ) truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); // normal shower else timeLikeShower(children[0],type,fc[1],false); } } updateHistory(children[1]); } return true; } void Evolver::connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ) { ShowerParticleVector particles; // find the Sudakovs for(set::iterator cit=hardTree->branchings().begin(); cit!=hardTree->branchings().end();++cit) { // Sudakovs for ISR if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) { ++_nis; vector br(3); br[0] = (**cit).parent()->branchingParticle()->id(); br[1] = (**cit). branchingParticle()->id(); br[2] = (**cit).parent()->children()[0]==*cit ? (**cit).parent()->children()[1]->branchingParticle()->id() : (**cit).parent()->children()[0]->branchingParticle()->id(); BranchingList branchings = splittingGenerator()->initialStateBranchings(); if(br[1]<0&&br[0]==br[1]) { br[0] = abs(br[0]); br[1] = abs(br[1]); } else if(br[1]<0) { br[1] = -br[1]; br[2] = -br[2]; } long index = abs(br[1]); SudakovPtr sudakov; for(BranchingList::const_iterator cjt = branchings.lower_bound(index); cjt != branchings.upper_bound(index); ++cjt ) { IdList ids = cjt->second.particles; if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { sudakov=cjt->second.sudakov; break; } } if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in " << "Evolver::connectTrees() for ISR" << Exception::runerror; (**cit).parent()->sudakov(sudakov); } // Sudakovs for FSR else if(!(**cit).children().empty()) { ++_nfs; vector br(3); br[0] = (**cit) .branchingParticle()->id(); br[1] = (**cit).children()[0]->branchingParticle()->id(); br[2] = (**cit).children()[1]->branchingParticle()->id(); BranchingList branchings = splittingGenerator()->finalStateBranchings(); if(br[0]<0) { br[0] = abs(br[0]); br[1] = abs(br[1]); br[2] = abs(br[2]); } long index = br[0]; SudakovPtr sudakov; for(BranchingList::const_iterator cjt = branchings.lower_bound(index); cjt != branchings.upper_bound(index); ++cjt ) { IdList ids = cjt->second.particles; if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { sudakov=cjt->second.sudakov; break; } } if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in " << "Evolver::connectTrees()" << Exception::runerror; (**cit).sudakov(sudakov); } } // calculate the evolution scale for(set::iterator cit=hardTree->branchings().begin(); cit!=hardTree->branchings().end();++cit) { particles.push_back((*cit)->branchingParticle()); } showerModel()->partnerFinder()-> setInitialEvolutionScales(particles,!hard,hardTree->interaction(), !hardTree->partnersSet()); hardTree->partnersSet(true); // inverse reconstruction if(hard) { showerModel()->kinematicsReconstructor()-> deconstructHardJets(hardTree,ShowerHandler::currentHandler()->evolver(), hardTree->interaction()); } else showerModel()->kinematicsReconstructor()-> deconstructDecayJets(hardTree,ShowerHandler::currentHandler()->evolver(), hardTree->interaction()); // now reset the momenta of the showering particles vector particlesToShower; for(map::const_iterator cit=showerTree->incomingLines().begin(); cit!=showerTree->incomingLines().end();++cit ) particlesToShower.push_back(cit->first); // extract the showering particles for(map::const_iterator cit=showerTree->outgoingLines().begin(); cit!=showerTree->outgoingLines().end();++cit ) particlesToShower.push_back(cit->first); // match them map partners; for(set::const_iterator bit=hardTree->branchings().begin(); bit!=hardTree->branchings().end();++bit) { Energy2 dmin( 1e30*GeV2 ); ShowerProgenitorPtr partner; for(vector::const_iterator pit=particlesToShower.begin(); pit!=particlesToShower.end();++pit) { if(partners.find(*pit)!=partners.end()) continue; if( (**bit).branchingParticle()->id() != (**pit).progenitor()->id() ) continue; if( (**bit).branchingParticle()->isFinalState() != (**pit).progenitor()->isFinalState() ) continue; if( (**pit).progenitor()->isFinalState() ) { Energy2 dtest = sqr( (**pit).progenitor()->momentum().x() - (**bit).showerMomentum().x() ) + sqr( (**pit).progenitor()->momentum().y() - (**bit).showerMomentum().y() ) + sqr( (**pit).progenitor()->momentum().z() - (**bit).showerMomentum().z() ) + sqr( (**pit).progenitor()->momentum().t() - (**bit).showerMomentum().t() ); // add mass difference for identical particles (e.g. Z0 Z0 production) dtest += 1e10*sqr((**pit).progenitor()->momentum().m()-(**bit).showerMomentum().m()); if( dtest < dmin ) { partner = *pit; dmin = dtest; } } else { // ensure directions are right if((**pit).progenitor()->momentum().z()/(**bit).showerMomentum().z()>ZERO) { partner = *pit; break; } } } if(!partner) throw Exception() << "Failed to match shower and hard trees in Evolver::hardestEmission" << Exception::eventerror; partners[partner] = *bit; } for(vector::const_iterator pit=particlesToShower.begin(); pit!=particlesToShower.end();++pit) { HardBranchingPtr partner = partners[*pit]; if((**pit).progenitor()->dataPtr()->stable()) { (**pit).progenitor()->set5Momentum(partner->showerMomentum()); (**pit).copy()->set5Momentum(partner->showerMomentum()); } else { Lorentz5Momentum oldMomentum = (**pit).progenitor()->momentum(); Lorentz5Momentum newMomentum = partner->showerMomentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); (**pit).progenitor()->transform(boost); (**pit).copy() ->transform(boost); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); (**pit).progenitor()->transform(boost); (**pit).copy() ->transform(boost); } } // correction boosts for daughter trees for(map >::const_iterator tit = showerTree->treelinks().begin(); tit != showerTree->treelinks().end();++tit) { ShowerTreePtr decayTree = tit->first; map::const_iterator cit = decayTree->incomingLines().begin(); // reset the momentum of the decay particle Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum(); Lorentz5Momentum newMomentum = tit->second.second->momentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); decayTree->transform(boost,true); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); decayTree->transform(boost,true); } } void Evolver::doShowering(bool hard,XCPtr xcomb) { // zero number of emissions _nis = _nfs = 0; // if MC@NLO H event and limited emissions // indicate both final and initial state emission if ( isMCatNLOHEvent && _limitEmissions != 0 ) { _nis = _nfs = 1; } // extract particles to shower vector particlesToShower(setupShower(hard)); // setup the maximum scales for the shower if (hardVetoOn()) setupMaximumScales(particlesToShower,xcomb); // set the hard scales for the profiles setupHardScales(particlesToShower,xcomb); // specific stuff for hard processes and decays Energy minmass(ZERO), mIn(ZERO); // hard process generate the intrinsic p_T once and for all if(hard) { generateIntrinsicpT(particlesToShower); } // decay compute the minimum mass of the final-state else { for(unsigned int ix=0;ixprogenitor()->isFinalState()) { if(particlesToShower[ix]->progenitor()->dataPtr()->stable()) minmass += particlesToShower[ix]->progenitor()->dataPtr()->constituentMass(); else minmass += particlesToShower[ix]->progenitor()->mass(); } else { mIn = particlesToShower[ix]->progenitor()->mass(); } } // throw exception if decay can't happen if ( minmass > mIn ) { throw Exception() << "Evolver.cc: Mass of decaying particle is " << "below constituent masses of decay products." << Exception::eventerror; } } + bool reWeighting = _reWeight && hard && ShowerHandler::currentHandler()->firstInteraction(); + double eventWeight=0.; + unsigned int nTryReWeight(0); // create random particle vector vector tmp; unsigned int nColouredIncoming = 0; while(particlesToShower.size()>0){ unsigned int xx=UseRandom::irnd(particlesToShower.size()); tmp.push_back(particlesToShower[xx]); particlesToShower.erase(particlesToShower.begin()+xx); } particlesToShower=tmp; for(unsigned int ix=0;ixprogenitor()->isFinalState() && particlesToShower[ix]->progenitor()->coloured()) ++nColouredIncoming; } bool switchRecon = hard && nColouredIncoming !=1; // main shower loop unsigned int ntry(0); bool reconstructed = false; do { // clear results of last attempt if needed if(ntry!=0) { currentTree()->clear(); setEvolutionPartners(hard,interaction_,true); _nis = _nfs = 0; // if MC@NLO H event and limited emissions // indicate both final and initial state emission if ( isMCatNLOHEvent && _limitEmissions != 0 ) { _nis = _nfs = 1; } for(unsigned int ix=0; ixprogenitor()->spinInfo(); if(spin && spin->decayVertex() && dynamic_ptr_cast(spin->decayVertex())) { spin->decayVertex(VertexPtr()); } } } // loop over particles for(unsigned int ix=0;ixprogenitor()->isFinalState()) { if(!isFSRadiationON()) continue; // perform shower progenitor()->hasEmitted(startTimeLikeShower(interaction_)); } // initial-state radiation else { if(!isISRadiationON()) continue; // hard process if(hard) { // get the PDF setBeamParticle(_progenitor->beam()); assert(beamParticle()); // perform the shower // set the beam particle tPPtr beamparticle=progenitor()->original(); if(!beamparticle->parents().empty()) beamparticle=beamparticle->parents()[0]; // generate the shower progenitor()->hasEmitted(startSpaceLikeShower(beamparticle, interaction_)); } // decay else { // skip colour and electrically neutral particles if(!progenitor()->progenitor()->dataPtr()->coloured() && !progenitor()->progenitor()->dataPtr()->charged()) { progenitor()->hasEmitted(false); continue; } // perform shower // set the scales correctly. The current scale is the maximum scale for // emission not the starting scale ShowerParticle::EvolutionScales maxScales(progenitor()->progenitor()->scales()); progenitor()->progenitor()->scales() = ShowerParticle::EvolutionScales(); if(progenitor()->progenitor()->dataPtr()->charged()) { progenitor()->progenitor()->scales().QED = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QED_noAO = progenitor()->progenitor()->mass(); } if(progenitor()->progenitor()->hasColour()) { progenitor()->progenitor()->scales().QCD_c = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QCD_c_noAO = progenitor()->progenitor()->mass(); } if(progenitor()->progenitor()->hasAntiColour()) { progenitor()->progenitor()->scales().QCD_ac = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().QCD_ac_noAO = progenitor()->progenitor()->mass(); } progenitor()->progenitor()->scales().EW = progenitor()->progenitor()->mass(); progenitor()->progenitor()->scales().EW_noAO = progenitor()->progenitor()->mass(); // perform the shower progenitor()->hasEmitted(startSpaceLikeDecayShower(maxScales,minmass, interaction_)); } } + // do the kinematic reconstruction, checking if it worked + reconstructed = hard ? + showerModel()->kinematicsReconstructor()-> + reconstructHardJets (currentTree(),intrinsicpT(),interactions_[inter], + switchRecon && ntry>maximumTries()/2) : + showerModel()->kinematicsReconstructor()-> + reconstructDecayJets(currentTree(),interactions_[inter]); + if(!reconstructed) continue; + // apply vetos on the full shower + for(vector::const_iterator it=_fullShowerVetoes.begin(); + it!=_fullShowerVetoes.end();++it) { + int veto = (**it).applyVeto(currentTree()); + if(veto<0) continue; + // veto the shower + if(veto==0) { + reconstructed = false; + break; + } + // veto the shower and reweight + else if(veto==1) { + reconstructed = false; + break; + } + // veto the event + else if(veto==2) { + throw Veto(); + } + } + if(reWeighting) { + if(reconstructed) eventWeight += 1.; + reconstructed=false; + ++nTryReWeight; + if(nTryReWeight==_nReWeight) { + reWeighting = false; + if(eventWeight==0.) throw Veto(); + } + } } // do the kinematic reconstruction, checking if it worked reconstructed = hard ? showerModel()->kinematicsReconstructor()-> reconstructHardJets (currentTree(),intrinsicpT(),interaction_, switchRecon && ntry>maximumTries()/2) : showerModel()->kinematicsReconstructor()-> reconstructDecayJets(currentTree(),interaction_); } while(!reconstructed&&maximumTries()>++ntry); // check if failed to generate the shower if(ntry==maximumTries()) { if(hard) throw ShowerHandler::ShowerTriesVeto(ntry); else throw Exception() << "Failed to generate the shower after " << ntry << " attempts in Evolver::showerDecay()" << Exception::eventerror; } + // handle the weights and apply any reweighting required + if(nTryReWeight>0) { + tStdEHPtr seh = dynamic_ptr_cast(generator()->currentEventHandler()); + static bool first = true; + if(seh) { + seh->reweight(eventWeight/double(nTryReWeight)); + } + else if(first) { + generator()->log() << "Reweighting the shower only works with internal Herwig7 processes" + << "Presumably you are showering Les Houches Events. These will not be" + << "reweighted\n"; + first = false; + } + } // tree has now showered _currenttree->hasShowered(true); hardTree(HardTreePtr()); } void Evolver:: convertHardTree(bool hard,ShowerInteraction::Type type) { map cmap; // incoming particles for(map::const_iterator cit=currentTree()->incomingLines().begin();cit!=currentTree()->incomingLines().end();++cit) { map::const_iterator mit = hardTree()->particles().find(cit->first->progenitor()); // put the colour lines in the map ShowerParticlePtr oldParticle = cit->first->progenitor(); ShowerParticlePtr newParticle = mit->second->branchingParticle(); ColinePtr cLine = oldParticle-> colourLine(); ColinePtr aLine = oldParticle->antiColourLine(); if(newParticle->colourLine() && cmap.find(newParticle-> colourLine())==cmap.end()) cmap[newParticle-> colourLine()] = cLine; if(newParticle->antiColourLine() && cmap.find(newParticle->antiColourLine())==cmap.end()) cmap[newParticle->antiColourLine()] = aLine; // check whether or not particle emits bool emission = mit->second->parent(); if(emission) { if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); } if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); } newParticle = mit->second->parent()->branchingParticle(); } // get the new colour lines ColinePtr newCLine,newALine; // sort out colour lines if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newCLine = cmap[ctemp]; } else { newCLine = new_ptr(ColourLine()); cmap[ctemp] = newCLine; } } // and anticolour lines if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newALine = cmap[ctemp]; } else { newALine = new_ptr(ColourLine()); cmap[ctemp] = newALine; } } // remove colour lines from old particle if(aLine) { aLine->removeAntiColoured(cit->first->copy()); aLine->removeAntiColoured(cit->first->progenitor()); } if(cLine) { cLine->removeColoured(cit->first->copy()); cLine->removeColoured(cit->first->progenitor()); } // add particle to colour lines if(newCLine) newCLine->addColoured (newParticle); if(newALine) newALine->addAntiColoured(newParticle); // insert new particles cit->first->copy(newParticle); ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,false))); cit->first->progenitor(sp); currentTree()->incomingLines()[cit->first]=sp; cit->first->perturbative(!emission); // and the emitted particle if needed if(emission) { ShowerParticlePtr newOut = mit->second->parent()->children()[1]->branchingParticle(); if(newOut->colourLine()) { ColinePtr ctemp = newOut-> colourLine(); ctemp->removeColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addColoured (newOut); } if(newOut->antiColourLine()) { ColinePtr ctemp = newOut->antiColourLine(); ctemp->removeAntiColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addAntiColoured(newOut); } ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); out->perturbative(false); currentTree()->outgoingLines().insert(make_pair(out,sout)); } if(hard) { // sort out the value of x if(mit->second->beam()->momentum().z()>ZERO) { sp->x(newParticle->momentum(). plus()/mit->second->beam()->momentum(). plus()); } else { sp->x(newParticle->momentum().minus()/mit->second->beam()->momentum().minus()); } } } // outgoing particles for(map::const_iterator cit=currentTree()->outgoingLines().begin();cit!=currentTree()->outgoingLines().end();++cit) { map >::const_iterator tit; for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { if(tit->second.first && tit->second.second==cit->first->progenitor()) break; } map::const_iterator mit = hardTree()->particles().find(cit->first->progenitor()); if(mit==hardTree()->particles().end()) continue; // put the colour lines in the map ShowerParticlePtr oldParticle = cit->first->progenitor(); ShowerParticlePtr newParticle = mit->second->branchingParticle(); ShowerParticlePtr newOut; ColinePtr cLine = oldParticle-> colourLine(); ColinePtr aLine = oldParticle->antiColourLine(); if(newParticle->colourLine() && cmap.find(newParticle-> colourLine())==cmap.end()) cmap[newParticle-> colourLine()] = cLine; if(newParticle->antiColourLine() && cmap.find(newParticle->antiColourLine())==cmap.end()) cmap[newParticle->antiColourLine()] = aLine; // check whether or not particle emits bool emission = !mit->second->children().empty(); if(emission) { if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); } if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); } newParticle = mit->second->children()[0]->branchingParticle(); newOut = mit->second->children()[1]->branchingParticle(); if(newParticle->id()!=oldParticle->id()&&newParticle->id()==newOut->id()) swap(newParticle,newOut); } // get the new colour lines ColinePtr newCLine,newALine; // sort out colour lines if(newParticle->colourLine()) { ColinePtr ctemp = newParticle-> colourLine(); ctemp->removeColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newCLine = cmap[ctemp]; } else { newCLine = new_ptr(ColourLine()); cmap[ctemp] = newCLine; } } // and anticolour lines if(newParticle->antiColourLine()) { ColinePtr ctemp = newParticle->antiColourLine(); ctemp->removeAntiColoured(newParticle); if(cmap.find(ctemp)!=cmap.end()) { newALine = cmap[ctemp]; } else { newALine = new_ptr(ColourLine()); cmap[ctemp] = newALine; } } // remove colour lines from old particle if(aLine) { aLine->removeAntiColoured(cit->first->copy()); aLine->removeAntiColoured(cit->first->progenitor()); } if(cLine) { cLine->removeColoured(cit->first->copy()); cLine->removeColoured(cit->first->progenitor()); } // special for unstable particles if(newParticle->id()==oldParticle->id() && (tit!=currentTree()->treelinks().end()||!oldParticle->dataPtr()->stable())) { Lorentz5Momentum oldMomentum = oldParticle->momentum(); Lorentz5Momentum newMomentum = newParticle->momentum(); LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); oldParticle->transform(boost); boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); oldParticle->transform(boost); if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); newParticle=oldParticle; } // add particle to colour lines if(newCLine) newCLine->addColoured (newParticle); if(newALine) newALine->addAntiColoured(newParticle); // insert new particles cit->first->copy(newParticle); ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,true))); cit->first->progenitor(sp); currentTree()->outgoingLines()[cit->first]=sp; cit->first->perturbative(!emission); // and the emitted particle if needed if(emission) { if(newOut->colourLine()) { ColinePtr ctemp = newOut-> colourLine(); ctemp->removeColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addColoured (newOut); } if(newOut->antiColourLine()) { ColinePtr ctemp = newOut->antiColourLine(); ctemp->removeAntiColoured(newOut); assert(cmap.find(ctemp)!=cmap.end()); cmap[ctemp]->addAntiColoured(newOut); } ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); out->perturbative(false); currentTree()->outgoingLines().insert(make_pair(out,sout)); } // update any decay products if(tit!=currentTree()->treelinks().end()) currentTree()->updateLink(tit->first,make_pair(cit->first,sp)); } // reset the tree currentTree()->resetShowerProducts(); // reextract the particles and set the colour partners vector particles = currentTree()->extractProgenitorParticles(); // clear the partners for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); particles[ix]->clearPartners(); } // clear the tree hardTree(HardTreePtr()); // Set the initial evolution scales showerModel()->partnerFinder()-> setInitialEvolutionScales(particles,!hard,type,!_hardtree); } Branching Evolver::selectTimeLikeBranching(tShowerParticlePtr particle, ShowerInteraction::Type type, HardBranchingPtr branch) { Branching fb; unsigned int iout=0; while (true) { // break if doing truncated shower and no truncated shower needed if(branch && (!isTruncatedShowerON()||hardOnly())) break; fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type); // no emission break if(!fb.kinematics) break; // special for truncated shower if(branch) { // check haven't evolved too far if(fb.kinematics->scale() < branch->scale()) { fb=Branching(); break; } // find the truncated line iout=0; if(fb.ids[1]->id()!=fb.ids[2]->id()) { if(fb.ids[1]->id()==particle->id()) iout=1; else if (fb.ids[2]->id()==particle->id()) iout=2; } else if(fb.ids[1]->id()==particle->id()) { if(fb.kinematics->z()>0.5) iout=1; else iout=2; } // apply the vetos for the truncated shower // no flavour changing branchings if(iout==0) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); // only if same interaction for forced branching ShowerInteraction::Type type2 = convertInteraction(fb.type); // and evolution if(type2==branch->sudakov()->interactionType()) { if(zsplit < 0.5 || // hardest line veto fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // pt veto if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // standard vetos for all emissions if(timeLikeVetoed(fb,particle)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); continue; } break; } // normal case if(!branch) { if(fb.kinematics) fb.hard = false; return fb; } // truncated emission if(fb.kinematics) { fb.hard = false; fb.iout = iout; return fb; } // otherwise need to return the hard emission // construct the kinematics for the hard emission ShoKinPtr showerKin= branch->sudakov()->createFinalStateBranching(branch->scale(), branch->children()[0]->z(), branch->phi(), branch->children()[0]->pT()); IdList idlist(3); idlist[0] = particle->dataPtr(); idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() ); fb.hard = true; fb.iout=0; // return it return fb; } Branching Evolver::selectSpaceLikeDecayBranching(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction::Type type, HardBranchingPtr branch) { Branching fb; unsigned int iout=0; while (true) { // break if doing truncated shower and no truncated shower needed if(branch && (!isTruncatedShowerON()||hardOnly())) break; // select branching fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass, _initialenhance,type); // return if no radiation if(!fb.kinematics) break; // special for truncated shower if(branch) { // check haven't evolved too far if(fb.kinematics->scale() < branch->scale()) { fb=Branching(); break; } // find the truncated line iout=0; if(fb.ids[1]->id()!=fb.ids[2]->id()) { if(fb.ids[1]->id()==particle->id()) iout=1; else if (fb.ids[2]->id()==particle->id()) iout=2; } else if(fb.ids[1]->id()==particle->id()) { if(fb.kinematics->z()>0.5) iout=1; else iout=2; } // apply the vetos for the truncated shower // no flavour changing branchings if(iout==0) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } ShowerInteraction::Type type2 = convertInteraction(fb.type); double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); if(type2==branch->sudakov()->interactionType()) { if(zsplit < 0.5 || // hardest line veto fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // pt veto if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } } // if not vetoed break if(spaceLikeDecayVetoed(fb,particle)) { // otherwise reset scale and continue particle->vetoEmission(fb.type,fb.kinematics->scale()); continue; } break; } // normal case if(!branch) { if(fb.kinematics) fb.hard = false; return fb; } // truncated emission if(fb.kinematics) { fb.hard = false; fb.iout = iout; return fb; } // otherwise need to return the hard emission // construct the kinematics for the hard emission ShoKinPtr showerKin= branch->sudakov()->createDecayBranching(branch->scale(), branch->children()[0]->z(), branch->phi(), branch->children()[0]->pT()); IdList idlist(3); idlist[0] = particle->dataPtr(); idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); // create the branching fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine ); fb.hard=true; fb.iout=0; // return it return fb; } diff --git a/Shower/Base/Evolver.h b/Shower/Base/Evolver.h --- a/Shower/Base/Evolver.h +++ b/Shower/Base/Evolver.h @@ -1,917 +1,935 @@ // -*- C++ -*- // // Evolver.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_Evolver_H #define HERWIG_Evolver_H // // This is the declaration of the Evolver class. // #include "ThePEG/Interface/Interfaced.h" #include "Herwig/Shower/SplittingFunctions/SplittingGenerator.h" #include "ShowerModel.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ShowerTree.h" #include "ShowerProgenitor.fh" #include "Herwig/Shower/ShowerHandler.fh" #include "Branching.h" #include "ShowerVeto.h" +#include "FullShowerVeto.h" #include "HardTree.h" #include "ThePEG/Handlers/XComb.h" #include "Evolver.fh" #include "Herwig/MatrixElement/HwMEBase.h" #include "Herwig/Decay/HwDecayerBase.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" +#include "Herwig/Utilities/Statistic.h" namespace Herwig { using namespace ThePEG; /**\ingroup Shower * Exception class * used to communicate failure of QED shower */ struct InteractionVeto {}; /** \ingroup Shower * The Evolver class class performs the sohwer evolution of hard scattering * and decay processes in Herwig. * * @see \ref EvolverInterfaces "The interfaces" * defined for Evolver. */ class Evolver: public Interfaced { /** * The ShowerHandler is a friend to set some parameters at initialisation */ friend class ShowerHandler; public: /** * Pointer to an XComb object */ typedef Ptr::pointer XCPtr; public: /** * Default Constructor */ Evolver() : _maxtry(100), _meCorrMode(1), _hardVetoMode(1), _hardVetoRead(0), _reconOpt(0), _hardVetoReadOption(false), _iptrms(ZERO), _beta(0.), _gamma(ZERO), _iptmax(), _limitEmissions(0), _initialenhance(1.), _finalenhance(1.), + _nReWeight(100), _reWeight(false), interaction_(ShowerInteraction::QEDQCD), _trunc_Mode(true), _hardEmissionMode(0), _spinOpt(1), _softOpt(2), _hardPOWHEG(false), theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0), muPt(ZERO), _maxTryFSR(100000),_maxFailFSR(100),_fracFSR(0.001), _nFSR(0), _nFailedFSR(0) {} /** * Members to perform the shower */ //@{ /** * Perform the shower of the hard process */ virtual void showerHardProcess(ShowerTreePtr,XCPtr); /** * Perform the shower of a decay */ virtual void showerDecay(ShowerTreePtr); //@} /** * Access to the flags and shower variables */ //@{ /** * Is there any showering switched on */ bool showeringON() const { return isISRadiationON() || isFSRadiationON(); } /** * It returns true/false if the initial-state radiation is on/off. */ bool isISRadiationON() const { return _splittingGenerator->isISRadiationON(); } /** * It returns true/false if the final-state radiation is on/off. */ bool isFSRadiationON() const { return _splittingGenerator->isFSRadiationON(); } /** * Get the ShowerModel */ ShowerModelPtr showerModel() const {return _model;} /** * Get the SplittingGenerator */ tSplittingGeneratorPtr splittingGenerator() const { return _splittingGenerator; } /** * Mode for hard emissions */ int hardEmissionMode() const {return _hardEmissionMode;} /** * Switch on or off hard vetoes */ void restrictPhasespace(bool yes) { if ( yes ) _hardVetoMode = 1; else _hardVetoMode = 0; } /** * Switch on or off hard veto scale from muF */ void hardScaleIsMuF(bool yes) { if ( yes ) _hardVetoRead = 1; else _hardVetoRead = 0; } //@} /** * Connect the Hard and Shower trees */ virtual void connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ); /** * Access to switches for spin correlations */ //@{ /** * Spin Correlations */ unsigned int spinCorrelations() const { return _spinOpt; } /** * Soft correlations */ unsigned int softCorrelations() const { return _softOpt; } /** * Any correlations */ bool correlations() const { return _spinOpt!=0||_softOpt!=0; } //@} /** * Set the factorization scale factor */ void factorizationScaleFactor(double f) { if ( f == theFactorizationScaleFactor ) return; theFactorizationScaleFactor = f; splittingGenerator()->factorizationScaleFactor(f); } /** * Set the renormalization scale factor */ void renormalizationScaleFactor(double f) { if ( f == theRenormalizationScaleFactor ) return; theRenormalizationScaleFactor = f; splittingGenerator()->renormalizationScaleFactor(f); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * Perform the shower */ void doShowering(bool hard,XCPtr); /** * Generate the hard matrix element correction */ virtual void hardMatrixElementCorrection(bool); /** * Generate the hardest emission */ virtual void hardestEmission(bool hard); /** * Extract the particles to be showered, set the evolution scales * and apply the hard matrix element correction * @param hard Whether this is a hard process or decay * @return The particles to be showered */ virtual vector setupShower(bool hard); /** * set the colour partners */ virtual void setEvolutionPartners(bool hard,ShowerInteraction::Type, bool clear); /** * Methods to perform the evolution of an individual particle, including * recursive calling on the products */ //@{ /** * It does the forward evolution of the time-like input particle * (and recursively for all its radiation products). * accepting only emissions which conforms to the showerVariables * and soft matrix element correction. * If at least one emission has occurred then the method returns true. * @param particle The particle to be showered */ virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction::Type, Branching fb, bool first); /** * It does the backward evolution of the space-like input particle * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * If at least one emission has occurred then the method returns true * @param particle The particle to be showered * @param beam The beam particle */ virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam, ShowerInteraction::Type); /** * If does the forward evolution of the input on-shell particle * involved in a decay * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * @param particle The particle to be showered * @param maxscale The maximum scale for the shower. * @param minimumMass The minimum mass of the final-state system */ virtual bool spaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction::Type, Branching fb); /** * Truncated shower from a time-like particle */ virtual bool truncatedTimeLikeShower(tShowerParticlePtr particle, HardBranchingPtr branch, ShowerInteraction::Type type, Branching fb, bool first); /** * Truncated shower from a space-like particle */ virtual bool truncatedSpaceLikeShower(tShowerParticlePtr particle,PPtr beam, HardBranchingPtr branch, ShowerInteraction::Type type); /** * Truncated shower from a time-like particle */ virtual bool truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass, HardBranchingPtr branch, ShowerInteraction::Type type, Branching fb); //@} /** * Switches for matrix element corrections */ //@{ /** * Any ME correction? */ bool MECOn(bool hard) const { return ( _hardEmissionMode == 0 || (!hard && _hardEmissionMode ==-1) ) && _meCorrMode > 0; } /** * Any hard ME correction? */ bool hardMEC(bool hard) const { return ( _hardEmissionMode == 0 || (!hard && _hardEmissionMode ==-1) ) && (_meCorrMode == 1 || _meCorrMode == 2); } /** * Any soft ME correction? */ bool softMEC() const { return ( _hardEmissionMode == 0 || (_currenttree->isDecay() && _hardEmissionMode ==-1) ) && (_meCorrMode == 1 || _meCorrMode > 2); } //@} /** * Is the truncated shower on? */ bool isTruncatedShowerON() const {return _trunc_Mode;} /** * Switch for intrinsic pT */ //@{ /** * Any intrinsic pT? */ bool ipTon() const { return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO ); } //@} /**@name Additional shower vetoes */ //@{ /** * Insert a veto. */ void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); } /** * Remove a veto. */ void removeVeto (ShowerVetoPtr v) { vector::iterator vit = find(_vetoes.begin(),_vetoes.end(),v); if (vit != _vetoes.end()) _vetoes.erase(vit); } //@} /** * Switches for vetoing hard emissions */ //@{ /** * Vetos on? */ bool hardVetoOn() const { return _hardVetoMode > 0; } /** * veto hard emissions in IS shower? */ bool hardVetoIS() const { return _hardVetoMode == 1 || _hardVetoMode == 2; } /** * veto hard emissions in FS shower? */ bool hardVetoFS() const { return _hardVetoMode == 1 || _hardVetoMode > 2; } /** * veto hard emissions according to lastScale from XComb? */ bool hardVetoXComb() const {return (_hardVetoRead == 1);} /** * Returns true if the hard veto read-in is to be applied to only * the primary collision and false otherwise. */ bool hardVetoReadOption() const {return _hardVetoReadOption;} //@} /** * Enhancement factors for radiation needed to generate the soft matrix * element correction. */ //@{ /** * Access the enhancement factor for initial-state radiation */ double initialStateRadiationEnhancementFactor() const { return _initialenhance; } /** * Access the enhancement factor for final-state radiation */ double finalStateRadiationEnhancementFactor() const { return _finalenhance; } /** * Set the enhancement factor for initial-state radiation */ void initialStateRadiationEnhancementFactor(double in) { _initialenhance=in; } /** * Set the enhancement factor for final-state radiation */ void finalStateRadiationEnhancementFactor(double in) { _finalenhance=in; } //@} /** * Access to set/get the HardTree currently beinging showered */ //@{ /** * The HardTree currently being showered */ tHardTreePtr hardTree() {return _hardtree;} /** * The HardTree currently being showered */ void hardTree(tHardTreePtr in) {_hardtree = in;} //@} /** * Access/set the beam particle for the current initial-state shower */ //@{ /** * Get the beam particle data */ Ptr::const_pointer beamParticle() const { return _beam; } /** * Set the beam particle data */ void setBeamParticle(Ptr::const_pointer in) { _beam=in; } //@} /** * Set/Get the current tree being evolverd for inheriting classes */ //@{ /** * Get the tree */ tShowerTreePtr currentTree() { return _currenttree; } /** * Set the tree */ void currentTree(tShowerTreePtr tree) { _currenttree=tree; } //@} /** * Access the maximum number of attempts to generate the shower */ unsigned int maximumTries() const { return _maxtry; } /** * Set/Get the ShowerProgenitor for the current shower */ //@{ /** * Access the progenitor */ ShowerProgenitorPtr progenitor() { return _progenitor; } /** * Set the progenitor */ void progenitor(ShowerProgenitorPtr in) { _progenitor=in; } //@} /** * Calculate the intrinsic \f$p_T\f$. */ virtual void generateIntrinsicpT(vector); /** * Access to the intrinsic \f$p_T\f$ for inheriting classes */ map > & intrinsicpT() { return _intrinsic; } /** * find the maximally allowed pt acc to the hard process. */ void setupMaximumScales(const vector &,XCPtr); /** * find the relevant hard scales for profile scales. */ void setupHardScales(const vector &,XCPtr); /** * Return the relevant hard scale to be used in the profile scales */ Energy hardScale() const { return muPt; } /** * Convert the HardTree into an extra shower emission */ void convertHardTree(bool hard,ShowerInteraction::Type type); protected: /** * Start the shower of a timelike particle */ virtual bool startTimeLikeShower(ShowerInteraction::Type); /** * Update of the time-like stuff */ void updateHistory(tShowerParticlePtr particle); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeShower(PPtr,ShowerInteraction::Type); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction::Type); /** * Select the branching for the next time-like emission */ Branching selectTimeLikeBranching(tShowerParticlePtr particle, ShowerInteraction::Type type, HardBranchingPtr branch); /** * Select the branching for the next space-like emission in a decay */ Branching selectSpaceLikeDecayBranching(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction::Type type, HardBranchingPtr branch); /** * Create the timelike child of a branching */ ShowerParticleVector createTimeLikeChildren(tShowerParticlePtr particle, IdList ids); /** * Vetos for the timelike shower */ virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr); /** * Only generate the hard emission, for testing only. */ bool hardOnly() const {return _limitEmissions==3;} public: /** @name MC@NLO diagnostics */ //@{ /** * True, if Matchbox MC@NLO S-event */ bool wasMCatNLOSEvent() const { return isMCatNLOSEvent; } /** * True, if matchbox MC@NLO H-event */ bool wasMCatNLOHEvent() const { return isMCatNLOHEvent; } //@} 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Evolver & operator=(const Evolver &); private: /** * Pointer to the model for the shower evolution model */ ShowerModelPtr _model; /** * Pointer to the splitting generator */ SplittingGeneratorPtr _splittingGenerator; /** * Maximum number of tries to generate the shower of a particular tree */ unsigned int _maxtry; /** * Matrix element correction switch */ unsigned int _meCorrMode; /** * Hard emission veto switch */ unsigned int _hardVetoMode; /** * Hard veto to be read switch */ unsigned int _hardVetoRead; /** * Control of the reconstruction option */ unsigned int _reconOpt; /** * If hard veto pT scale is being read-in this determines * whether the read-in value is applied to primary and * secondary (MPI) scatters or just the primary one, with * the usual computation of the veto being performed for * the secondary (MPI) scatters. */ bool _hardVetoReadOption; /** * rms intrinsic pT of Gaussian distribution */ Energy _iptrms; /** * Proportion of inverse quadratic intrinsic pT distribution */ double _beta; /** * Parameter for inverse quadratic: 2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT)) */ Energy _gamma; /** * Upper bound on intrinsic pT for inverse quadratic */ Energy _iptmax; /** * Limit the number of emissions for testing */ unsigned int _limitEmissions; /** * The progenitor of the current shower */ ShowerProgenitorPtr _progenitor; /** * Matrix element */ HwMEBasePtr _hardme; /** * Decayer */ HwDecayerBasePtr _decayme; /** * The ShowerTree currently being showered */ ShowerTreePtr _currenttree; /** * The HardTree currently being showered */ HardTreePtr _hardtree; /** * Radiation enhancement factors for use with the veto algorithm * if needed by the soft matrix element correction */ //@{ /** * Enhancement factor for initial-state radiation */ double _initialenhance; /** * Enhancement factor for final-state radiation */ double _finalenhance; //@} /** * The beam particle data for the current initial-state shower */ Ptr::const_pointer _beam; /** * Storage of the intrinsic \f$p_t\f$ of the particles */ map > _intrinsic; /** * Vetoes */ vector _vetoes; /** + * Full Shower Vetoes + */ + vector _fullShowerVetoes; + + /** + * Number of iterations for reweighting + */ + unsigned int _nReWeight; + + /** + * Whether or not we are reweighting + */ + bool _reWeight; + + /** * number of IS emissions */ unsigned int _nis; /** * Number of FS emissions */ unsigned int _nfs; /** * The option for wqhich interactions to use */ ShowerInteraction::Type interaction_; /** * Truncated shower switch */ bool _trunc_Mode; /** * Count of the number of truncated emissions */ unsigned int _truncEmissions; /** * Mode for the hard emissions */ int _hardEmissionMode; /** * Option to include spin correlations */ unsigned int _spinOpt; /** * Option for the kernal for soft correlations */ unsigned int _softOpt; /** * Option for hard radiation in POWHEG events */ bool _hardPOWHEG; /** * True, if Matchbox MC@NLO S-event */ bool isMCatNLOSEvent; /** * True, if matchbox MC@NLO H-event */ bool isMCatNLOHEvent; /** * True, if Matchbox Powheg S-event */ bool isPowhegSEvent; /** * True, if matchbox Powheg H-event */ bool isPowhegHEvent; /** * The shower approximation to provide the hard scale profile */ Ptr::tptr theShowerApproximation; /** * The factorization scale factor. */ double theFactorizationScaleFactor; /** * The renormalization scale factor. */ double theRenormalizationScaleFactor; /** * True if no warnings about incorrect hard emission * mode setting have been issued yet */ static bool _hardEmissionModeWarn; /** * True if no warnings about missing truncated shower * have been issued yet */ static bool _missingTruncWarn; /** * The relevant hard scale to be used in the profile scales */ Energy muPt; /** * Maximum number of emission attempts for FSR */ unsigned int _maxTryFSR; /** * Maximum number of failures for FSR generation */ unsigned int _maxFailFSR; /** * Failure fraction for FSR generation */ double _fracFSR; /** * Counter for number of FSR emissions */ unsigned int _nFSR; /** * Counter for the number of failed events due to FSR emissions */ unsigned int _nFailedFSR; }; } #endif /* HERWIG_Evolver_H */ diff --git a/Shower/Base/HardTree.cc b/Shower/Base/HardTree.cc deleted file mode 100644 --- a/Shower/Base/HardTree.cc +++ /dev/null @@ -1,104 +0,0 @@ -// -*- C++ -*- -// -// This is the implementation of the non-inlined, non-templated member -// functions of the HardTree class. -// - -#include "HardTree.h" -#include "ThePEG/PDT/EnumParticles.h" -#include "ThePEG/Repository/CurrentGenerator.h" - -using namespace Herwig; - -HardTree::HardTree(vector branchings, - vector spacelike, - ShowerInteraction::Type type) - : interaction_(type), - branchings_(branchings.begin(),branchings.end()), - spacelike_ (spacelike .begin(),spacelike .end()), - partnersSet_(false) -{} - -bool HardTree::connect(ShowerTreePtr shower) { - particles_.clear(); - // extract the progenitors from the ShowerTree - vector progenitors = shower->extractProgenitors(); - vector connectedProgenitors(progenitors.size(),false); - // connect the trees up - for( set::iterator it = branchings().begin(); - it != branchings().end(); ++it) { - Energy2 dmin( 1e30*GeV2 ); - tShowerParticlePtr partner; - unsigned int progenitorsIndex(999); - for( unsigned int ix = 0; ix < progenitors.size(); ++ix ) { - if( connectedProgenitors[ix] ) continue; - if( (**it).branchingParticle()->id() != progenitors[ix]->progenitor()->id() ) continue; - if( (**it).branchingParticle()->isFinalState() != - progenitors[ix]->progenitor()->isFinalState() ) continue; - Energy2 dtest = - sqr( progenitors[ix]->progenitor()->momentum().x() - (**it).showerMomentum().x() ) + - sqr( progenitors[ix]->progenitor()->momentum().y() - (**it).showerMomentum().y() ) + - sqr( progenitors[ix]->progenitor()->momentum().z() - (**it).showerMomentum().z() ) + - sqr( progenitors[ix]->progenitor()->momentum().t() - (**it).showerMomentum().t() ); - if( dtest < dmin ) { - partner = progenitors[ix]->progenitor(); - progenitorsIndex = ix; - dmin = dtest; - } - } - if( !partner ) return false; - connectedProgenitors[progenitorsIndex] = true; - connect( partner, *it ); - if( (**it).status() == HardBranching::Incoming ) { - double z( (**it).z() ); - tHardBranchingPtr parent = (**it).parent(); - while (parent) { - z *= parent->z(); - parent = parent->parent(); - } - partner->x(z); - } - } - if( particles().size() == progenitors.size() ) return true; - else return false; -} - -ostream & Herwig::operator<<(ostream & os, const HardTree & x) { - os << "Output of HardTree " << &x << "\n"; - for(set::const_iterator it=x.branchings_.begin(); - it!=x.branchings_.end();++it) { - os << "Hard Particle: " << *(**it).branchingParticle() << " has Sudakov " - << (**it).sudakov() << " pT = " << (**it).pT()/GeV - << " scale = " << (**it).scale()/GeV << "\n"; - os << "Its colour lines are " << (**it).branchingParticle()->colourLine() << "\t" - << (**it).branchingParticle()->antiColourLine() << "\n"; - os << "Its basis vectors are " << (**it).pVector()/GeV - << " " << (**it).nVector()/GeV << "\n"; - os << "Its shower momentum is " << (**it).showerMomentum()/GeV << "\n"; - for(unsigned int iy=0;iy<(**it).children().size();++iy) { - os << "\t Children : " << *(**it).children()[iy]->branchingParticle() - << "\n"; - os << "It's colour lines are " - << (**it).children()[iy]->branchingParticle()->colourLine() << "\t" - << (**it).children()[iy]->branchingParticle()->antiColourLine() << "\n"; - } - } - for(set::const_iterator it=x.spacelike_.begin(); - it!=x.spacelike_.end();++it) { - os << "SpaceLike: " << *(**it).branchingParticle() << " has Sudakov" - << (**it).sudakov() << " pT = " << (**it).pT()/GeV - << " scale = " << (**it).scale()/GeV << "\n"; - os << "It's colour lines are " - << (**it).branchingParticle()->colourLine() << "\t" - << (**it).branchingParticle()->antiColourLine() << "\n"; - - for(unsigned int iy=0;iy<(**it).children().size();++iy) { - os << "\t Children: " << *(**it).children()[iy]->branchingParticle() - << "\n"; - os << "It's colour lines are " - << (**it).children()[iy]->branchingParticle()->colourLine() << "\t" - << (**it).children()[iy]->branchingParticle()->antiColourLine() << "\n"; - } - } - return os; -} diff --git a/Shower/Base/HardTree.h b/Shower/Base/HardTree.h deleted file mode 100644 --- a/Shower/Base/HardTree.h +++ /dev/null @@ -1,137 +0,0 @@ -// -*- C++ -*- -#ifndef HERWIG_HardTree_H -#define HERWIG_HardTree_H -// -// This is the declaration of the HardTree class. -// - -#include "ThePEG/Config/ThePEG.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/SudakovFormFactor.h" -#include "HardBranching.h" -#include "HardTree.fh" - -namespace Herwig { - -using namespace ThePEG; -/** - * The HardTree class is designed to contain the information required - * to implement the POWHEG approach for Monte Carlo at next-to-leading order. - */ -class HardTree : public Base { - - /** - * Output operator for testing - */ - friend ostream & operator << (ostream &, const HardTree & ); - -public: - - /** - * The default constructor. - */ - HardTree(vector, vector, ShowerInteraction::Type); - - /** - * Match particles in the ShowerTree to branchings in the HardTree - */ - bool connect(ShowerParticlePtr particle, HardBranchingPtr branching) { - if(branchings_.find(branching)==branchings_.end()) return false; - particles_[particle]=branching; - return true; - } - - /** - * Match the prticles in the ShowerTree to the branchings in the HardTree - */ - bool connect(ShowerTreePtr); - - /** - * Access the map between the ShowerParticle and the HardBranching - */ - map & particles() - {return particles_;} - - /** - * Access the set of branchings - */ - set & branchings() {return branchings_;} - - /** - * Access the incoming branchings - */ - set & incoming() {return spacelike_;} - - /** - * Type of interaction - */ - ShowerInteraction::Type interaction() {return interaction_;} - - /** - * Get the Rotation to be applied to the tree - */ - LorentzRotation showerRot() { return showerRot_; } - - /** - * Set the Rotation to be applied to the tree - */ - void showerRot( LorentzRotation r ) { showerRot_ = r; } - - /** - * Whether or not the evolution partners are set - */ - bool partnersSet() const {return partnersSet_;} - - /** - * Whether or not the evolution partners are set - */ - void partnersSet(bool in) {partnersSet_=in;} - -private: - - /** - * Type of interaction - */ - ShowerInteraction::Type interaction_; - - /** - * The ShowerTree - */ - ShowerTreePtr _tree; - - /** - * Map from the particles in the ShowerTree to the HardBranchings - */ - map particles_; - - /** - * The HardBranchings in the hard process - */ - set branchings_; - - /** - * The HardBranchings which initiate the space-like showers - */ - set spacelike_; - - /** - * Rotation to shower frame - */ - LorentzRotation showerRot_; - - /** - * Whether or not partners are set - */ - bool partnersSet_; - -}; - - /** - * Output operator for testing - */ - ostream & operator << (ostream &, const HardTree & ); - -} - -#endif /* HERWIG_HardTree_H */ diff --git a/Shower/Base/KinematicsReconstructor.h b/Shower/Base/KinematicsReconstructor.h deleted file mode 100644 --- a/Shower/Base/KinematicsReconstructor.h +++ /dev/null @@ -1,135 +0,0 @@ -// -*- C++ -*- -// -// KinematicsReconstructor.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_KinematicsReconstructor_H -#define HERWIG_KinematicsReconstructor_H -// -// This is the declaration of the KinematicsReconstructor class. -// - -#include "ThePEG/Interface/Interfaced.h" -#include "ShowerParticle.h" -#include "ShowerProgenitor.h" -#include "ShowerTree.h" -#include "HardTree.h" -#include "Evolver.fh" -#include "KinematicsReconstructor.fh" -#include - -namespace Herwig { - -using namespace ThePEG; - - /**\ingroup Shower - * Exception class - * used to communicate failure of kinematics - * reconstruction. - */ - struct KinematicsReconstructionVeto {}; - - -/** \ingroup Shower - * - * This class is responsible for the kinematical reconstruction - * after each showering step, and also for the necessary Lorentz boosts - * in order to preserve energy-momentum conservation in the overall collision, - * and also the invariant mass and the rapidity of the hard subprocess system. - * In the case of multi-step showering, there will be not unnecessary - * kinematical reconstructions. - * - * Notice: - * - although we often use the term "jet" in either methods or variables names, - * or in comments, which could appear applicable only for QCD showering, - * there is indeed no "dynamics" represented in this class: only kinematics - * is involved, as the name of this class remainds. Therefore it can be used - * for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung). - * - * @see \ref KinematicsReconstructorInterfaces "The interfaces" - * defined for KinematicsReconstructor. - */ -class KinematicsReconstructor: public Interfaced { - -public: - - /** - * Methods to reconstruct the kinematics of a scattering or decay process - */ - //@{ - /** - * Given the ShowerTree for the shower from a hard process - * the method does the reconstruction of the jets, - * including the appropriate boosts (kinematics reshufflings) - * needed to conserve the total energy-momentum of the collision - * and preserving the invariant mass and the rapidity of the - * hard subprocess system. - */ - virtual bool reconstructHardJets(ShowerTreePtr hard, - const map > & pt, - ShowerInteraction::Type type, - bool switchRecon) const=0; - - /** - * Given the ShowerTree for a decay shower - * the method does the reconstruction of the jets, - * including the appropriate boosts (kinematics reshufflings) - * needed to conserve the total energy-momentum of the collision - * and preserving the invariant mass and the rapidity of the - * hard subprocess system. - */ - virtual bool reconstructDecayJets(ShowerTreePtr decay, - ShowerInteraction::Type type) const=0; - //@} - - /** - * Methods to invert the reconstruction of the shower for - * a scattering or decay process and calculate - * the variables used to generate the - * shower given the particles produced. - * This is needed for the CKKW and POWHEG approaches - */ - //@{ - /** - * Given the particles, with a history which we wish to interpret - * as a shower reconstruct the variables used to generate the - * shower for a decay process - */ - virtual bool deconstructDecayJets(HardTreePtr decay,cEvolverPtr, - ShowerInteraction::Type) const=0; - - /** - * Given the particles, with a history which we wish to interpret - * as a shower reconstruct the variables used to generate the shower - * for a hard process - */ - virtual bool deconstructHardJets(HardTreePtr hard,cEvolverPtr, - ShowerInteraction::Type) const=0; - //@} - -public: - - /** - * The standard Init function used to initialize the interfaces. - * Called exactly once for each class by the class description system - * before the main function starts or - * when this class is dynamically loaded. - */ - static void Init(); - -private: - - /** - * The assignment operator is private and must never be called. - * In fact, it should not even be implemented. - */ - KinematicsReconstructor & operator=(const KinematicsReconstructor &); -}; - -} - -#endif /* HERWIG_KinematicsReconstructor_H */ diff --git a/Shower/Base/ShowerModel.cc b/Shower/Base/ShowerModel.cc deleted file mode 100644 --- a/Shower/Base/ShowerModel.cc +++ /dev/null @@ -1,66 +0,0 @@ -// -*- C++ -*- -// -// ShowerModel.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 ShowerModel class. -// - -#include "ShowerModel.h" -#include "ThePEG/Interface/ClassDocumentation.h" -#include "ThePEG/Interface/Reference.h" -#include "ThePEG/Interface/RefVector.h" -#include "ThePEG/Persistency/PersistentOStream.h" -#include "ThePEG/Persistency/PersistentIStream.h" -#include "KinematicsReconstructor.h" -#include "PartnerFinder.h" -#include "Evolver.h" -#include "SudakovFormFactor.h" -#include "ThePEG/Utilities/DescribeClass.h" - -using namespace Herwig; - -DescribeAbstractClass -describeShowerModel ("Herwig::ShowerModel","HwShower.so"); - -void ShowerModel::persistentOutput(PersistentOStream & os) const { - os << _reconstructor << _partnerfinder << _sudakovs; -} - -void ShowerModel::persistentInput(PersistentIStream & is, int) { - is >> _reconstructor >> _partnerfinder >> _sudakovs; -} - -void ShowerModel::doinit() { - Interfaced::doinit(); - checkConsistency(); -} - -void ShowerModel::Init() { - - static ClassDocumentation documentation - ("The ShowerModel class contains the references for the classes which" - " are specific to the shower evolution scheme."); - - static Reference interfaceKinematicsReconstructor - ("KinematicsReconstructor", - "Reference to the KinematicsReconstructor object", - &ShowerModel::_reconstructor, false, false, true, false, false); - - static Reference interfacePartnerFinder - ("PartnerFinder", - "Reference to the PartnerFinder object", - &ShowerModel::_partnerfinder, false, false, true, false, false); - - static RefVector interfaceSudakovFormFactors - ("SudakovFormFactors", - "Vector of references to the SudakovFormFactor objects", - &ShowerModel::_sudakovs, -1, false, false, true, false, false); - -} - diff --git a/Shower/Base/ShowerTree.cc b/Shower/Base/ShowerTree.cc deleted file mode 100644 --- a/Shower/Base/ShowerTree.cc +++ /dev/null @@ -1,1477 +0,0 @@ -// -*- C++ -*- -// -// ShowerTree.cc is a part of Herwig - A multi-purpose Monte Carlo event generator -// Copyright (C) 2002-2011 The Herwig Collaboration -// -// Herwig is licenced under version 2 of the GPL, see COPYING for details. -// Please respect the MCnet academic guidelines, see GUIDELINES for details. -// -#include "ShowerProgenitor.h" -#include "ThePEG/EventRecord/MultiColour.h" -#include "ThePEG/Repository/EventGenerator.h" -#include "ShowerTree.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/ShowerHandler.h" -#include "ThePEG/PDT/DecayMode.h" -#include "ThePEG/Handlers/EventHandler.h" -#include "ThePEG/Handlers/XComb.h" -#include "KinematicsReconstructor.h" -#include -#include "ThePEG/Repository/CurrentGenerator.h" -#include "ThePEG/PDT/StandardMatchers.h" - -using namespace Herwig; -using namespace ThePEG; - -set ShowerTree::_decayInShower = set(); - -bool ShowerTree::_spaceTime = false; - -Energy2 ShowerTree::_vmin2 = 0.1*GeV2; - -namespace { - void findBeam(tPPtr & beam, PPtr incoming) { - while(!beam->children().empty()) { - bool found=false; - for(unsigned int ix=0;ixchildren().size();++ix) { - if(beam->children()[ix]==incoming) { - found = true; - break; - } - } - if(found) break; - beam = beam->children()[0]; - } - } -} - -// constructor from hard process -ShowerTree::ShowerTree(const PPair incoming, const ParticleVector & out, - ShowerDecayMap& decay) - : _hardMECorrection(false), _wasHard(true), - _parent(), _hasShowered(false) { - tPPair beam = CurrentGenerator::current().currentEvent()->incoming(); - findBeam(beam.first ,incoming.first ); - findBeam(beam.second,incoming.second); - _incoming = incoming; - double x1(_incoming.first ->momentum().rho()/beam.first ->momentum().rho()); - double x2(_incoming.second->momentum().rho()/beam.second->momentum().rho()); - // must have two incoming particles - assert(_incoming.first && _incoming.second); - // set the parent tree - _parent=ShowerTreePtr(); - // temporary vectors to contain all the particles before insertion into - // the data structure - vector original,copy; - vector shower; - // create copies of ThePEG particles for the incoming particles - original.push_back(_incoming.first); - copy.push_back(new_ptr(Particle(*_incoming.first))); - original.push_back(_incoming.second); - copy.push_back(new_ptr(Particle(*_incoming.second))); - // and same for outgoing - map trees; - for (ParticleVector::const_iterator it = out.begin(); - it != out.end(); ++it) { - // if decayed or should be decayed in shower make the tree - PPtr orig = *it; - bool radiates = false; - if(!orig->children().empty()) { - // remove d,u,s,c,b quarks and leptons other than on-shell taus - if(StandardQCDPartonMatcher::Check(orig->id())|| - (LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())children().size();++iy) { - if(orig->children()[iy]->id()==orig->id()) { - foundParticle = true; - } - else if(orig->children()[iy]->id()==ParticleID::g || - orig->children()[iy]->id()==ParticleID::gamma) { - foundGauge = true; - } - } - radiates = foundParticle && foundGauge; - } - } - if(radiates) { - findDecayProducts(orig,original,copy,decay,trees); - } - else if(!orig->children().empty()|| - (decaysInShower(orig->id())&&!orig->dataPtr()->stable())) { - ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay)); - newtree->setParents(); - trees.insert(make_pair(orig,newtree)); - Energy width=orig->dataPtr()->generateWidth(orig->mass()); - decay.insert(make_pair(width,newtree)); - original.push_back(orig); - copy.push_back(new_ptr(Particle(*orig))); - } - else { - original.push_back(orig); - copy.push_back(new_ptr(Particle(*orig))); - } - } - // colour isolate the hard process - colourIsolate(original,copy); - // now create the Shower particles - // create ShowerParticles for the incoming particles - assert(original.size() == copy.size()); - for(unsigned int ix=0;ix=2)); - fixColour(temp); - // incoming - if(ix<2) { - temp->x(ix==0 ? x1 : x2); - _incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix], - copy[ix],temp)),temp)); - _backward.insert(temp); - } - // outgoing - else { - _outgoingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix], - copy[ix],temp)),temp)); - _forward.insert(temp); - } - } - // set up the map of daughter trees - map::const_iterator mit; - for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) { - map::const_iterator tit=trees.find(mit->first->original()); - if(tit!=trees.end()) - _treelinks.insert(make_pair(tit->second, - make_pair(mit->first,mit->first->progenitor()))); - } -} - -void ShowerTree::findDecayProducts(PPtr in, vector & original, vector & copy, - ShowerDecayMap& decay, map & trees) { - ParticleVector children=in->children(); - for(unsigned int ix=0;ixabandonChild(orig); - bool radiates = false; - if(!orig->children().empty()) { - // remove d,u,s,c,b quarks and leptons other than on-shell taus - if(StandardQCDPartonMatcher::Check(orig->id())|| - (LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())children().size();++iy) { - if(orig->children()[iy]->id()==orig->id()) { - foundParticle = true; - } - else if(orig->children()[iy]->id()==ParticleID::g || - orig->children()[iy]->id()==ParticleID::gamma) { - foundGauge = true; - } - } - radiates = foundParticle && foundGauge; - } - } - if(radiates) { - findDecayProducts(orig,original,copy,decay,trees); - } - else if(!orig->children().empty()|| - (decaysInShower(orig->id())&&!orig->dataPtr()->stable())) { - ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay)); - trees.insert(make_pair(orig,newtree)); - Energy width=orig->dataPtr()->generateWidth(orig->mass()); - decay.insert(make_pair(width,newtree)); - newtree->setParents(); - newtree->_parent=this; - original.push_back(orig); - copy.push_back(new_ptr(Particle(*orig))); - } - else { - original.push_back(orig); - copy.push_back(new_ptr(Particle(*orig))); - } - } -} - -ShowerTree::ShowerTree(PPtr in, - ShowerDecayMap& decay) - : _hardMECorrection(false), _wasHard(false), _hasShowered(false) { - // there must be an incoming particle - assert(in); - // temporary vectors to contain all the particles before insertion into - // the data structure - vector original,copy; - // insert place holder for incoming particle - original.push_back(in); - copy.push_back(PPtr()); - // we need to deal with the decay products if decayed - map trees; - if(!in->children().empty()) { - ParticleVector children=in->children(); - for(unsigned int ix=0;ixabandonChild(orig); - bool radiates = false; - if(!orig->children().empty()) { - if(StandardQCDPartonMatcher::Check(orig->id())|| - (LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())children().size();++iy) { - if(orig->children()[iy]->id()==orig->id()) { - foundParticle = true; - } - else if(orig->children()[iy]->id()==ParticleID::g || - orig->children()[iy]->id()==ParticleID::gamma) { - foundGauge = true; - } - } - radiates = foundParticle && foundGauge; - } - // finally assume all non-decaying particles are in this class - if(!radiates) { - radiates = !decaysInShower(orig->id()); - } - } - if(radiates) { - findDecayProducts(orig,original,copy,decay,trees); - } - else if(!orig->children().empty()|| - (decaysInShower(orig->id())&&!orig->dataPtr()->stable())) { - ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay)); - trees.insert(make_pair(orig,newtree)); - Energy width=orig->dataPtr()->generateWidth(orig->mass()); - decay.insert(make_pair(width,newtree)); - newtree->setParents(); - newtree->_parent=this; - original.push_back(orig); - copy.push_back(new_ptr(Particle(*orig))); - } - else { - original.push_back(orig); - copy.push_back(new_ptr(Particle(*orig))); - } - } - } - // create the incoming particle - copy[0] = new_ptr(Particle(*in)); - // isolate the colour - colourIsolate(original,copy); - // create the parent - ShowerParticlePtr sparent(new_ptr(ShowerParticle(*copy[0],2,false))); - fixColour(sparent); - _incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[0],copy[0],sparent)) - ,sparent)); - // return if not decayed - if(original.size()==1) return; - // create the children - assert(copy.size() == original.size()); - for (unsigned int ix=1;ix::const_iterator mit; - for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) { - map::const_iterator tit=trees.find(mit->first->original()); - if(tit!=trees.end()) - _treelinks.insert(make_pair(tit->second, - make_pair(mit->first,mit->first->progenitor()))); - } -} - -void ShowerTree::updateFinalStateShowerProduct(ShowerProgenitorPtr progenitor, - ShowerParticlePtr parent, - const ShowerParticleVector & children) { - assert(children.size()==2); - bool matches[2]; - for(unsigned int ix=0;ix<2;++ix) { - matches[ix] = children[ix]->id()==progenitor->id(); - } - ShowerParticlePtr newpart; - if(matches[0]&&matches[1]) { - if(parent->showerKinematics()->z()>0.5) newpart=children[0]; - else newpart=children[1]; - } - else if(matches[0]) newpart=children[0]; - else if(matches[1]) newpart=children[1]; - _outgoingLines[progenitor]=newpart; -} - -void ShowerTree::updateInitialStateShowerProduct(ShowerProgenitorPtr progenitor, - ShowerParticlePtr newParent) { - _incomingLines[progenitor]=newParent; -} - -void ShowerTree::isolateLine(vector::const_iterator cit, - vector & particles, - tcColinePtr oldline, - tColinePtr newline) { - // loop over particles - for(vector::const_iterator cjt=particles.begin(); - cjt!=particles.end();++cjt) { - if(cjt==cit) continue; - // if particle has colour line - if((*cjt).second->colourLine()) { - // if only one check if current line and reset - if(int((*cjt).second->colourInfo()->colourLines().size())==1) { - if((*cjt).second->colourLine()==oldline) - newline->addColoured((*cjt).first); - } - // if more than one check if each line current line and reset - else { - Ptr::pointer colour1 = - dynamic_ptr_cast::pointer> - ((*cjt).second->colourInfo()); - Ptr::pointer colour2 = - dynamic_ptr_cast::pointer> - ((*cjt).first ->colourInfo()); - for(unsigned int ix=0;ixcolourLines().size();++ix) { - if(colour1->colourLines()[ix]==oldline) - colour2->colourLine(newline,int(ix)+1); - } - } - } - // if particle has anticolour line - if((*cjt).second->antiColourLine()) { - // if only one check if current line and reset - if(int((*cjt).second->colourInfo()->antiColourLines().size())==1) { - if((*cjt).second->antiColourLine()==oldline) - newline->addColoured((*cjt).first,true); - } - // if more than one check if each line current line and reset - else { - Ptr::pointer colour1 = - dynamic_ptr_cast::pointer> - ((*cjt).second->colourInfo()); - Ptr::pointer colour2 = - dynamic_ptr_cast::pointer> - ((*cjt).first ->colourInfo()); - for(unsigned int ix=0;ixantiColourLines().size();++ix) { - if(colour1->antiColourLines()[ix]==oldline) - colour2->antiColourLine(newline, int(ix)+1); - } - } - } - } -} - -void ShowerTree::colourIsolate(const vector & original, - const vector & copy) { - // vectors must have same size - assert(original.size()==copy.size()); - // create a temporary map with all the particles to make looping easier - vector particles; - particles.reserve(original.size()); - for(unsigned int ix=0;ix::const_iterator cit; - // make the colour connections of the copies - for(cit=particles.begin();cit!=particles.end();++cit) { - if((*cit).first->colourInfo()) { - if((*cit).first->dataPtr()->iColour() == PDT::Colour6 || - (*cit).first->dataPtr()->iColour() == PDT::Colour6bar) - (*cit).first->colourInfo(new_ptr(MultiColour())); - else - (*cit).first->colourInfo(new_ptr(ColourBase())); - } - } - map cmap; - // make the colour connections of the copies - // loop over the particles - for(cit=particles.begin();cit!=particles.end();++cit) { - // if particle has at least one colour line - if((*cit).second->colourLine()) { - // one and only one line - if(int((*cit).second->colourInfo()->colourLines().size())==1) { - // if not already change - if(!(*cit).first->colourLine()) { - // make new line - tcColinePtr oldline=(*cit).second->colourLine(); - ColinePtr newline=ColourLine::create((*cit).first); - cmap[oldline]=newline; - isolateLine(cit,particles,oldline,newline); - } - } - // more than one line - else { - Ptr::pointer colour1 = - dynamic_ptr_cast::pointer> - ((*cit).second->colourInfo()); - vector lines1 = colour1->colourLines(); - Ptr::pointer colour2 = - dynamic_ptr_cast::pointer> - ((*cit).first->colourInfo()); - vector lines2 = colour2->colourLines(); - // loop over lines - for(unsigned int ix=0;ixix && !lines2[ix]) || - lines2.size()<=ix) { - tcColinePtr oldline = lines1[ix]; - ColinePtr newline = new_ptr(ColourLine()); - cmap[oldline]=newline; - colour2->colourLine(newline, int(ix)+1); - isolateLine(cit,particles,oldline,newline); - } - } - } - } - // if anticolour line - if((*cit).second->antiColourLine()) { - // one and only one line - if(int((*cit).second->colourInfo()->antiColourLines().size())==1) { - // if not already change - if(!(*cit).first->antiColourLine()) { - // make new line - tcColinePtr oldline=(*cit).second->antiColourLine(); - ColinePtr newline=ColourLine::create((*cit).first, true); - cmap[oldline]=newline; - isolateLine(cit,particles,oldline,newline); - } - } - // more than one line - else { - Ptr::pointer colour1 = - dynamic_ptr_cast::pointer> - ((*cit).second->colourInfo()); - vector lines1 = colour1->antiColourLines(); - Ptr::pointer colour2 = - dynamic_ptr_cast::pointer> - ((*cit).first->colourInfo()); - vector lines2 = colour2->antiColourLines(); - // loop over lines - for(unsigned int ix=0;ixix && !lines2[ix]) || - lines2.size()<=ix) { - tcColinePtr oldline = lines1[ix]; - ColinePtr newline = new_ptr(ColourLine()); - cmap[oldline]=newline; - colour2->antiColourLine(newline, int(ix)+1); - isolateLine(cit,particles,oldline,newline); - } - } - } - } - } - - // sort out sinks and sources - for(cit=particles.begin();cit!=particles.end();++cit) { - tColinePtr cline[2]; - tColinePair cpair; - for(unsigned int ix=0;ix<4;++ix) { - cline[0] = ix<2 ? cit->second->colourLine() : cit->second->antiColourLine(); - cline[1] = ix<2 ? cit->first ->colourLine() : cit->first ->antiColourLine(); - if(cline[0]) { - switch (ix) { - case 0: case 2: - cpair = cline[0]->sinkNeighbours(); - break; - case 1: case 3: - cpair = cline[0]->sourceNeighbours(); - break; - }; - } - else { - cpair = make_pair(tColinePtr(),tColinePtr()); - } - if(cline[0]&&cpair.first) { - map::const_iterator - mit[2] = {cmap.find(cpair.first),cmap.find(cpair.second)}; - if(mit[0]!=cmap.end()&&mit[1]!=cmap.end()) { - if(ix==0||ix==2) { - cline[1]->setSinkNeighbours(mit[0]->second,mit[1]->second); - } - else { - cline[1]->setSourceNeighbours(mit[0]->second,mit[1]->second); - } - } - } - } - } -} - -void ShowerTree::mapColour(PPtr original, - PPtr copy) { - // has colour line - if(copy->colourLine()) { - // one and only one - if(copy->colourInfo()->colourLines().size()==1) { - _colour.insert(make_pair(copy->colourLine(), - original->colourLine())); - } - // more than one - else { - Ptr::pointer colour1 = - dynamic_ptr_cast::pointer>(copy->colourInfo()); - vector lines1 = colour1->colourLines(); - Ptr::pointer colour2 = - dynamic_ptr_cast::pointer>(original->colourInfo()); - vector lines2 = colour2->colourLines(); - for(unsigned int ix=0;ix(lines1[ix]), - const_ptr_cast(lines2[ix]))); - } - } - // has anticolour line - if(copy->antiColourLine()) { - // one and only one - if(copy->colourInfo()->antiColourLines().size()==1) { - _colour.insert(make_pair(copy->antiColourLine(), - original->antiColourLine())); - } - // more than one - else { - Ptr::pointer colour1 = - dynamic_ptr_cast::pointer>(copy->colourInfo()); - vector lines1 = colour1->antiColourLines(); - - Ptr::pointer colour2 = - dynamic_ptr_cast::pointer>(original->colourInfo()); - vector lines2 = colour2->antiColourLines(); - - for(unsigned int ix=0;ix(lines1[ix]), - const_ptr_cast(lines2[ix]))); - } - } -} - -void ShowerTree::insertHard(StepPtr pstep, bool ISR, bool) { - assert(_incomingLines.size()==2); - _colour.clear(); - map::const_iterator cit; - // construct the map of colour lines for hard process - for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { - if(!cit->first->perturbative()) continue; - mapColour(cit->first->original(),cit->first->copy()); - } - map::const_iterator cjt; - for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { - if(!cjt->first->perturbative()) continue; - mapColour(cjt->first->original(),cjt->first->copy()); - } - // initial-state radiation - if(ISR) { - for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) { - ShowerParticlePtr init=(*cit).first->progenitor(); - assert(init->thePEGBase()); - PPtr original = (*cit).first->original(); - if(original->parents().empty()) continue; - PPtr hadron= original->parents()[0]; - assert(!original->children().empty()); - PPtr copy=cit->first->copy(); - ParticleVector intermediates=original->children(); - for(unsigned int ix=0;ixabandonChild(intermediates[ix]); - copy->abandonChild(intermediates[ix]); - } - // if not from a matrix element correction - if(cit->first->perturbative()) { - // break mother/daugther relations - init->addChild(original); - hadron->abandonChild(original); - // if particle showers add shower - if(cit->first->hasEmitted()) { - addInitialStateShower(init,hadron,pstep,false); - } - // no showering for this particle - else { - updateColour(init); - hadron->addChild(init); - pstep->addIntermediate(init); - init->setLifeLength(Lorentz5Distance()); - init->setVertex(LorentzPoint()); - } - } - // from matrix element correction - else { - // break mother/daugther relations - hadron->abandonChild(original); - copy->addChild(original); - updateColour(copy); - init->addChild(copy); - pstep->addIntermediate(copy); - copy->setLifeLength(Lorentz5Distance()); - copy->setVertex(LorentzPoint()); - // if particle showers add shower - if(cit->first->hasEmitted()) { - addInitialStateShower(init,hadron,pstep,false); - } - // no showering for this particle - else { - updateColour(init); - hadron->addChild(init); - pstep->addIntermediate(init); - init->setLifeLength(Lorentz5Distance()); - init->setVertex(LorentzPoint()); - } - } - } - } - else { - for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) { - ShowerParticlePtr init=(*cit).first->progenitor(); - assert(init->thePEGBase()); - PPtr original = (*cit).first->original(); - if(original->parents().empty()) continue; - PPtr hadron= original->parents()[0]; - assert(!original->children().empty()); - PPtr copy=cit->first->copy(); - ParticleVector intermediates=original->children(); - for(unsigned int ix=0;ixabandonChild(intermediates[ix]); - copy->abandonChild(intermediates[ix]); - } - // break mother/daugther relations - init->addChild(original); - hadron->abandonChild(original); - // no showering for this particle - updateColour(init); - hadron->addChild(init); - pstep->addIntermediate(init); - init->setLifeLength(Lorentz5Distance()); - init->setVertex(LorentzPoint()); - original->setLifeLength(Lorentz5Distance()); - original->setVertex(LorentzPoint()); - } - } - // final-state radiation - for(cjt=outgoingLines().begin();cjt!=outgoingLines().end();++cjt) { - ShowerParticlePtr init=(*cjt).first->progenitor(); - assert(init->thePEGBase()); - // ZERO the distance of original - (*cjt).first->original()->setLifeLength(Lorentz5Distance()); - (*cjt).first->original()->setVertex(LorentzPoint()); - // if not from a matrix element correction - if(cjt->first->perturbative()) { - // register the shower particle as a - // copy of the one from the hard process - tParticleVector parents=init->parents(); - for(unsigned int ix=0;ixabandonChild(init); - (*cjt).first->original()->addChild(init); - pstep->addDecayProduct(init); - } - // from a matrix element correction - else { - if(cjt->first->original()==_incoming.first|| - cjt->first->original()==_incoming.second) { - updateColour((*cjt).first->copy()); - (*cjt).first->original()->parents()[0]-> - addChild((*cjt).first->copy()); - pstep->addDecayProduct((*cjt).first->copy()); - (*cjt).first->copy()->addChild(init); - pstep->addDecayProduct(init); - } - else { - updateColour((*cjt).first->copy()); - (*cjt).first->original()->addChild((*cjt).first->copy()); - pstep->addDecayProduct((*cjt).first->copy()); - (*cjt).first->copy()->addChild(init); - pstep->addDecayProduct(init); - } - // ZERO the distance of copy ??? \todo change if add space-time - (*cjt).first->copy()->setLifeLength(Lorentz5Distance()); - (*cjt).first->copy()->setVertex(LorentzPoint()); - } - // copy so travels no distance - init->setLifeLength(Lorentz5Distance()); - init->setVertex(init->parents()[0]->decayVertex()); - // sort out the colour - updateColour(init); - // insert shower products - addFinalStateShower(init,pstep); - } - _colour.clear(); -} - -void ShowerTree::addFinalStateShower(PPtr p, StepPtr s) { - // if endpoint assume doesn't travel - if(p->children().empty()) { - if(p->dataPtr()->stable()||decaysInShower(p->id())) - p->setLifeLength(Lorentz5Distance()); - else { - Length ctau = p->dataPtr()->generateLifeTime(p->mass(), p->dataPtr()->width()); - Lorentz5Distance lifeLength(ctau,p->momentum().vect()*(ctau/p->mass())); - p->setLifeLength(lifeLength); - } - return; - } - // set the space-time distance - else { - p->setLifeLength(spaceTimeDistance(p)); - } - ParticleVector::const_iterator child; - for(child=p->children().begin(); child != p->children().end(); ++child) { - updateColour(*child); - s->addDecayProduct(*child); - (**child).setVertex(p->decayVertex()); - addFinalStateShower(*child,s); - } -} - -void ShowerTree::updateColour(PPtr particle) { - // if attached to a colour line - if(particle->colourLine()) { - // one and only one - if(particle->colourInfo()->colourLines().size()==1) { - bool reset=false; - // if colour line from hard process reconnect - ColinePtr c1=particle->colourLine(); - if(_colour.find(c1)!=_colour.end()) { - c1->removeColoured(particle); - _colour[c1]->addColoured(particle); - reset=true; - } - // ensure properly connected to the line - if(!reset) { - ColinePtr c1=particle->colourLine(); - c1->removeColoured(particle); - c1->addColoured(particle); - } - } - else { - Ptr::pointer colour = - dynamic_ptr_cast::pointer>(particle->colourInfo()); - vector lines = colour->colourLines(); - for(unsigned int ix=0;ix(lines[ix]); - if(_colour.find(c1)!=_colour.end()) { - colour->colourLine(_colour[c1],int(ix)+1); - c1->removeColoured(particle); - } - } - } - } - // if attached to an anticolour line - if(particle->antiColourLine()) { - bool reset=false; - // one and only one - if(particle->colourInfo()->antiColourLines().size()==1) { - // if anti colour line from hard process reconnect - ColinePtr c1=particle->antiColourLine(); - if(_colour.find(c1)!=_colour.end()) { - c1->removeColoured(particle,true); - _colour[c1]->addColoured(particle,true); - reset=true; - } - if(!reset) { - ColinePtr c1=particle->antiColourLine(); - c1->removeColoured(particle,true); - c1->addColoured(particle,true); - } - } - else { - Ptr::pointer colour = - dynamic_ptr_cast::pointer>(particle->colourInfo()); - vector lines = colour->antiColourLines(); - for(unsigned int ix=0;ix(lines[ix]); - if(_colour.find(c1)!=_colour.end()) { - colour->antiColourLine(_colour[c1],int(ix)+1); - c1->removeColoured(particle,true); - } - } - } - } -} - -void ShowerTree::addInitialStateShower(PPtr p, PPtr hadron, - StepPtr s, bool addchildren) { - // Each parton here should only have one parent - if(!p->parents().empty()) { - if(p->parents().size()!=1) - throw Exception() << "Particle must only have one parent in ShowerTree" - << "::addInitialStateShower" << Exception::runerror; - // set the space-time distances - if(addchildren) { - p->setLifeLength(spaceTimeDistance(p)); - p->setVertex(p->children()[0]->vertex()-p->lifeLength()); - } - else { - p->setLifeLength(spaceTimeDistance(p)); - p->setVertex(-p->lifeLength()); - } - // recurse - addInitialStateShower(p->parents()[0],hadron,s); - } - else { - hadron->addChild(p); - s->addIntermediate(p); - p->setVertex(p->children()[0]->vertex()); - p->setLifeLength(Lorentz5Distance()); - } - updateColour(p); - // if not adding children return - if(!addchildren) return; - // add children - ParticleVector::const_iterator child; - for(child = p->children().begin(); child != p->children().end(); ++child) { - // if a final-state particle update the colour - ShowerParticlePtr schild = - dynamic_ptr_cast(*child); - (**child).setVertex(p->decayVertex()); - if(schild && schild->isFinalState()) updateColour(*child); - // if there are grandchildren of p - if(!(*child)->children().empty()) { - // Add child as intermediate - s->addIntermediate(*child); - // If child is shower particle and final-state, add children - if(schild && schild->isFinalState()) addFinalStateShower(schild,s); - } - else - s->addDecayProduct(*child); - } -} - -void ShowerTree::decay(ShowerDecayMap & decay) { - // must be one incoming particle - assert(_incomingLines.size()==1); - // otherwise decay it - applyTransforms(); - // if already decayed return - if(!_outgoingLines.empty()) return; - // now we need to replace the particle with a new copy after the shower - // find particle after the shower - ShowerParticlePtr newparent=_parent->_treelinks[this].second; - // now make the new progenitor - vector original,copy; - original.push_back(newparent); - copy.push_back(new_ptr(Particle(*newparent))); - // reisolate the colour - colourIsolate(original,copy); - // make the new progenitor - ShowerParticlePtr stemp=new_ptr(ShowerParticle(*copy[0],2,false)); - fixColour(stemp); - ShowerProgenitorPtr newprog=new_ptr(ShowerProgenitor(original[0],copy[0],stemp)); - _incomingLines.clear(); - _incomingLines.insert(make_pair(newprog,stemp)); - // now we need to decay the copy - PPtr parent=copy[0]; - if(parent->spinInfo()) parent->spinInfo()->decay(true); - unsigned int ntry = 0; - while (true) { - // exit if fails - if (++ntry>=200) - throw Exception() << "Failed to perform decay in ShowerTree::decay()" - << " after " << 200 - << " attempts for " << parent->PDGName() - << Exception::eventerror; - // select decay mode - tDMPtr dm(parent->data().selectMode(*parent)); - if(!dm) - throw Exception() << "Failed to select decay mode in ShowerTree::decay()" - << "for " << newparent->PDGName() - << Exception::eventerror; - if(!dm->decayer()) - throw Exception() << "No Decayer for selected decay mode " - << " in ShowerTree::decay()" - << Exception::runerror; - // start of try block - try { - ParticleVector children = dm->decayer()->decay(*dm, *parent); - // if no children have another go - if(children.empty()) continue; - // set up parent - parent->decayMode(dm); - // add children - for (unsigned int i = 0, N = children.size(); i < N; ++i ) { - children[i]->setLabVertex(parent->labDecayVertex()); - parent->addChild(children[i]); - parent->scale(ZERO); - } - // if succeeded break out of loop - break; - } - catch(KinematicsReconstructionVeto) {} - } - // insert the trees from the children - ParticleVector children=parent->children(); - map trees; - for(unsigned int ix=0;ixabandonChild(orig); - // if particle has children or decays in shower - if(!orig->children().empty()|| - (decaysInShower(orig->id())&&!orig->dataPtr()->stable())) { - ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay)); - trees.insert(make_pair(orig,newtree)); - Energy width=orig->dataPtr()->generateWidth(orig->mass()); - decay.insert(make_pair(width,newtree)); - } - // now create the shower progenitors - PPtr ncopy=new_ptr(Particle(*orig)); - //copy[0]->addChild(ncopy); - ShowerParticlePtr nshow=new_ptr(ShowerParticle(*ncopy,2,true)); - fixColour(nshow); - ShowerProgenitorPtr prog=new_ptr(ShowerProgenitor(children[ix], - ncopy,nshow)); - _outgoingLines.insert(make_pair(prog,nshow)); - } - // set up the map of daughter trees - map::const_iterator mit; - for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) { - map::const_iterator tit=trees.find(mit->first->original()); - if(tit!=trees.end()) { - _treelinks.insert(make_pair(tit->second, - make_pair(mit->first, - mit->first->progenitor()))); - tit->second->_parent=this; - } - } -} - -void ShowerTree::insertDecay(StepPtr pstep,bool ISR, bool) { - assert(_incomingLines.size()==1); - _colour.clear(); - // find final particle from previous tree - PPtr final; - if(_parent&&!_parent->_treelinks.empty()) - final = _parent->_treelinks[this].second; - else - final=_incomingLines.begin()->first->original(); - // construct the map of colour lines - PPtr copy=_incomingLines.begin()->first->copy(); - mapColour(final,copy); - // now this is the ONE instance of the particle which should have a life length - // \todo change if space-time picture added - // set the lifelength, need this so that still in right direction after - // any ISR recoils - Length ctau = copy->lifeTime(); - Lorentz5Distance lifeLength(ctau,final->momentum().vect()*(ctau/final->mass())); - final->setLifeLength(lifeLength); - // initial-state radiation - if(ISR&&!_incomingLines.begin()->first->progenitor()->children().empty()) { - ShowerParticlePtr init=_incomingLines.begin()->first->progenitor(); - updateColour(init); - final->addChild(init); - pstep->addDecayProduct(init); - // just a copy doesn't travel - init->setLifeLength(Lorentz5Distance()); - init->setVertex(final->decayVertex()); - // insert shower products - addFinalStateShower(init,pstep); - // sort out colour - final=_incomingLines.begin()->second; - _colour.clear(); - mapColour(final,copy); - } - // get the decaying particles - // make the copy - tColinePair cline=make_pair(copy->colourLine(),copy->antiColourLine()); - updateColour(copy); - // sort out sinks and sources if needed - if(cline.first) { - if(cline.first->sourceNeighbours().first) { - copy->colourLine()->setSourceNeighbours(cline.first->sourceNeighbours().first, - cline.first->sourceNeighbours().second); - } - else if (cline.first->sinkNeighbours().first) { - copy->colourLine()->setSinkNeighbours(cline.first->sinkNeighbours().first, - cline.first->sinkNeighbours().second); - } - } - if(cline.second) { - if(cline.second->sourceNeighbours().first) { - copy->antiColourLine()->setSourceNeighbours(cline.second->sourceNeighbours().first, - cline.second->sourceNeighbours().second); - } - else if (cline.second->sinkNeighbours().first) { - copy->antiColourLine()->setSinkNeighbours(cline.second->sinkNeighbours().first, - cline.second->sinkNeighbours().second); - } - } - // copy of the one from the hard process - tParticleVector dpar=copy->parents(); - for(unsigned int ix=0;ixabandonChild(copy); - final->addChild(copy); - pstep->addDecayProduct(copy); - // just a copy does not move - copy->setLifeLength(Lorentz5Distance()); - copy->setVertex(final->decayVertex()); - // final-state radiation - map::const_iterator cit; - for(cit=outgoingLines().begin();cit!=outgoingLines().end();++cit) { - ShowerParticlePtr init=cit->first->progenitor(); - // ZERO the distance - init->setLifeLength(Lorentz5Distance()); - if(!init->thePEGBase()) - throw Exception() << "Final-state particle must have a ThePEGBase" - << " in ShowerTree::insertDecay()" - << Exception::runerror; - // if not from matrix element correction - if(cit->first->perturbative()) { - // add the child - updateColour(cit->first->copy()); - PPtr orig=cit->first->original(); - orig->setLifeLength(Lorentz5Distance()); - orig->setVertex(copy->decayVertex()); - copy->addChild(orig); - pstep->addDecayProduct(orig); - orig->addChild(cit->first->copy()); - pstep->addDecayProduct(cit->first->copy()); - // register the shower particle as a - // copy of the one from the hard process - tParticleVector parents=init->parents(); - for(unsigned int ix=0;ixabandonChild(init);} - (*cit).first->copy()->addChild(init); - pstep->addDecayProduct(init); - updateColour(init); - } - // from a matrix element correction - else { - if(copy->children().end()== - find(copy->children().begin(),copy->children().end(), - cit->first->original())) { - updateColour(cit->first->original()); - copy->addChild(cit->first->original()); - pstep->addDecayProduct(cit->first->original()); - } - updateColour(cit->first->copy()); - cit->first->original()->addChild(cit->first->copy()); - pstep->addDecayProduct(cit->first->copy()); - // register the shower particle as a - // copy of the one from the hard process - tParticleVector parents=init->parents(); - for(unsigned int ix=0;ixabandonChild(init);} - (*cit).first->copy()->addChild(init); - pstep->addDecayProduct(init); - updateColour(init); - } - // ZERO the distances as just copies - cit->first->copy()->setLifeLength(Lorentz5Distance()); - init->setLifeLength(Lorentz5Distance()); - cit->first->copy()->setVertex(copy->decayVertex()); - init->setVertex(copy->decayVertex()); - // insert shower products - addFinalStateShower(init,pstep); - } - _colour.clear(); -} - -void ShowerTree::clear() { - // reset the has showered flag - _hasShowered=false; - // clear the colour map - _colour.clear(); - map::const_iterator cit; - map::const_iterator cjt; - // abandon the children of the outgoing particles - for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit) { - ShowerParticlePtr orig=cit->first->progenitor(); - orig->set5Momentum(cit->first->copy()->momentum()); - ParticleVector children=orig->children(); - for(unsigned int ix=0;ixabandonChild(children[ix]); - _outgoingLines[cit->first]=orig; - cit->first->hasEmitted(false); - cit->first->reconstructed(ShowerProgenitor::notReconstructed); - } - // forward products - _forward.clear(); - for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit) - _forward.insert(cit->first->progenitor()); - // if a decay - if(!_wasHard) { - ShowerParticlePtr orig=_incomingLines.begin()->first->progenitor(); - orig->set5Momentum(_incomingLines.begin()->first->copy()->momentum()); - ParticleVector children=orig->children(); - for(unsigned int ix=0;ixabandonChild(children[ix]); - _incomingLines.begin()->first->reconstructed(ShowerProgenitor::notReconstructed); - } - // if a hard process - else { - for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt) { - tPPtr parent = cjt->first->original()->parents().empty() ? - tPPtr() : cjt->first->original()->parents()[0]; - ShowerParticlePtr temp= - new_ptr(ShowerParticle(*cjt->first->copy(), - cjt->first->progenitor()->perturbative(), - cjt->first->progenitor()->isFinalState())); - fixColour(temp); - temp->x(cjt->first->progenitor()->x()); - cjt->first->hasEmitted(false); - if(!(cjt->first->progenitor()==cjt->second)&&cjt->second&&parent) - parent->abandonChild(cjt->second); - cjt->first->progenitor(temp); - _incomingLines[cjt->first]=temp; - cjt->first->reconstructed(ShowerProgenitor::notReconstructed); - } - } - // reset the particles at the end of the shower - _backward.clear(); - // if hard process backward products - if(_wasHard) - for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt) - _backward.insert(cjt->first->progenitor()); - clearTransforms(); -} - -void ShowerTree::resetShowerProducts() { - map::const_iterator cit; - map::const_iterator cjt; - _backward.clear(); - _forward.clear(); - for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) - _backward.insert(cit->second); - for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) - _forward.insert(cjt->second); -} - -void ShowerTree::updateAfterShower(ShowerDecayMap & decay) { - // update the links - map::const_iterator mit; - map >::iterator tit; - for(tit=_treelinks.begin();tit!=_treelinks.end();++tit) { - if(tit->second.first) { - mit=_outgoingLines.find(tit->second.first); - if(mit!=_outgoingLines.end()) tit->second.second=mit->second; - } - } - // get the particles coming from those in the hard process - set hard; - for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) - hard.insert(mit->second); - // find the shower particles which should be decayed in the - // shower but didn't come from the hard process - set::const_iterator cit; - for(cit=_forward.begin();cit!=_forward.end();++cit) { - if((decaysInShower((**cit).id())&&!(**cit).dataPtr()->stable())&& - hard.find(*cit)==hard.end()) { - ShowerTreePtr newtree=new_ptr(ShowerTree(*cit,decay)); - newtree->setParents(); - newtree->_parent=this; - Energy width=(**cit).dataPtr()->generateWidth((**cit).mass()); - decay.insert(make_pair(width,newtree)); - _treelinks.insert(make_pair(newtree, - make_pair(tShowerProgenitorPtr(),*cit))); - } - } -} - -void ShowerTree::addFinalStateBranching(ShowerParticlePtr parent, - const ShowerParticleVector & children) { - assert(children.size()==2); - _forward.erase(parent); - for(unsigned int ix=0; ix >::const_iterator tit; - for(tit=_treelinks.begin();tit!=_treelinks.end();++tit) - tit->first->_parent=this; -} - -vector ShowerTree::extractProgenitors() { - // extract the particles from the ShowerTree - map::const_iterator mit; - vector ShowerHardJets; - for(mit=incomingLines().begin();mit!=incomingLines().end();++mit) - ShowerHardJets.push_back((*mit).first); - map::const_iterator mjt; - for(mjt=outgoingLines().begin();mjt!=outgoingLines().end();++mjt) - ShowerHardJets.push_back((*mjt).first); - return ShowerHardJets; -} - -void ShowerTree::transform(const LorentzRotation & boost, bool applyNow) { - if(applyNow) { - // now boost all the particles - map::const_iterator cit; - // incoming - for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { - cit->first->progenitor()->deepTransform(boost); - cit->first->copy()->deepTransform(boost); - } - // outgoing - map::const_iterator cjt; - for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { - cjt->first->progenitor()->deepTransform(boost); - cjt->first->copy()->deepTransform(boost); - } - } - else { - _transforms.transform(boost); - } - // child trees - for(map >::const_iterator - tit=_treelinks.begin();tit!=_treelinks.end();++tit) - tit->first->transform(boost,applyNow); -} - -void ShowerTree::applyTransforms() { - // now boost all the particles - map::const_iterator cit; - // incoming - for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { - cit->first->progenitor()->deepTransform(_transforms); - cit->first->copy()->deepTransform(_transforms); - } - // outgoing - map::const_iterator cjt; - for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { - cjt->first->progenitor()->deepTransform(_transforms); - cjt->first->copy()->deepTransform(_transforms); - } - // child trees - for(map >::const_iterator - tit=_treelinks.begin();tit!=_treelinks.end();++tit) - tit->first->applyTransforms(); - _transforms = LorentzRotation(); -} - -void ShowerTree::clearTransforms() { - _transforms = LorentzRotation(); - // // child trees - // for(map >::const_iterator - // tit=_treelinks.begin();tit!=_treelinks.end();++tit) - // tit->first->clearTransforms(); -} - -void ShowerTree::fixColour(tShowerParticlePtr part) { - if(!part->colourInfo()->colourLines().empty()) { - if(part->colourInfo()->colourLines().size()==1) { - ColinePtr line=part->colourLine(); - if(line) { - line->removeColoured(part); - line->addColoured(part); - } - } - else { - Ptr::pointer colour = - dynamic_ptr_cast::pointer>(part->colourInfo()); - vector lines = colour->colourLines(); - for(unsigned int ix=0;ix(lines[ix]); - if(line) { - line->removeColoured(part); - line->addColoured(part); - } - } - } - } - if(!part->colourInfo()->antiColourLines().empty()) { - if(part->colourInfo()->antiColourLines().size()==1) { - ColinePtr line=part->antiColourLine(); - if(line) { - line->removeAntiColoured(part); - line->addAntiColoured(part); - } - } - else { - Ptr::pointer colour = - dynamic_ptr_cast::pointer>(part->colourInfo()); - vector lines = colour->antiColourLines(); - for(unsigned int ix=0;ix(lines[ix]); - if(line) { - line->removeAntiColoured(part); - line->addAntiColoured(part); - } - } - } - } -} - -vector ShowerTree::extractProgenitorParticles() { - vector particles; - // incoming particles - for(map::const_iterator - cit=incomingLines().begin(); cit!=incomingLines().end();++cit) - particles.push_back(cit->first->progenitor()); - // outgoing particles - for(map::const_iterator - cjt=outgoingLines().begin(); cjt!=outgoingLines().end();++cjt) - particles.push_back(cjt->first->progenitor()); - return particles; -} - -Lorentz5Distance ShowerTree::spaceTimeDistance(tPPtr particle) { - if(!_spaceTime) return Lorentz5Distance(); - Energy2 q2 = particle->mass() > ZERO ? sqr(particle->mass()) : -sqr(particle->mass()); - const tcPDPtr data = particle->dataPtr(); - // calculate width imposing min value - Energy conMass = max(data->constituentMass(),200*MeV); - Energy width = max(data->generateWidth(particle->mass()),_vmin2/conMass); - // offshellness - Energy2 offShell = q2-sqr(data->constituentMass()); - if(abs(offShell)<1e-10*GeV2) offShell = ZERO; - InvEnergy2 fact = UseRandom::rndExp(1./sqrt((sqr(offShell)+sqr(q2*width/conMass)))); - Lorentz5Distance output = (hbarc*fact)*particle->momentum(); - return output; -} - -namespace { - -bool decayProduct(tSubProPtr subProcess, - tPPtr particle) { - // must be time-like and not incoming - if(particle->momentum().m2()<=ZERO|| - particle == subProcess->incoming().first|| - particle == subProcess->incoming().second) return false; - // if only 1 outgoing and this is it - if(subProcess->outgoing().size()==1 && - subProcess->outgoing()[0]==particle) return true; - // must not be the s-channel intermediate otherwise - if(find(subProcess->incoming().first->children().begin(), - subProcess->incoming().first->children().end(),particle)!= - subProcess->incoming().first->children().end()&& - find(subProcess->incoming().second->children().begin(), - subProcess->incoming().second->children().end(),particle)!= - subProcess->incoming().second->children().end()&& - subProcess->incoming().first ->children().size()==1&& - subProcess->incoming().second->children().size()==1) - return false; - // if non-coloured this is enough - if(!particle->dataPtr()->coloured()) return true; - // if coloured must be unstable - if(particle->dataPtr()->stable()) return false; - // must not have same particle type as a child - int id = particle->id(); - for(unsigned int ix=0;ixchildren().size();++ix) - if(particle->children()[ix]->id()==id) return false; - // otherwise its a decaying particle - return true; -} - -PPtr findParent(PPtr original, bool & isHard, - set outgoingset, - tSubProPtr subProcess) { - PPtr parent=original; - isHard |=(outgoingset.find(original) != outgoingset.end()); - if(!original->parents().empty()) { - PPtr orig=original->parents()[0]; - if(CurrentGenerator::current().currentEventHandler()->currentStep()-> - find(orig)&&decayProduct(subProcess,orig)) { - parent=findParent(orig,isHard,outgoingset,subProcess); - } - } - return parent; -} - -} - -void ShowerTree::constructTrees(tSubProPtr subProcess, ShowerTreePtr & hard, - ShowerDecayMap & decay, tPVector tagged, - bool splitTrees) { - // temporary storage of the particles - set hardParticles; - // loop over the tagged particles - bool isHard=false; - set outgoingset(tagged.begin(),tagged.end()); - for (tParticleVector::const_iterator taggedP = tagged.begin(); - taggedP != tagged.end(); ++taggedP) { - // if a remnant don't consider - if(CurrentGenerator::current().currentEventHandler()->currentCollision()->isRemnant(*taggedP)) - continue; - // find the parent and whether its a colourless s-channel resonance - bool isDecayProd=false; - // check if hard - isHard |=(outgoingset.find(*taggedP) != outgoingset.end()); - if(splitTrees) { - tPPtr parent = *taggedP; - // check if from s channel decaying colourless particle - while(parent&&!parent->parents().empty()&&!isDecayProd) { - parent = parent->parents()[0]; - if(parent == subProcess->incoming().first || - parent == subProcess->incoming().second ) break; - isDecayProd = decayProduct(subProcess,parent); - } - if (isDecayProd) - hardParticles.insert(findParent(parent,isHard,outgoingset,subProcess)); - } - if (!isDecayProd) - hardParticles.insert(*taggedP); - } - // there must be something to shower - if(hardParticles.empty()) - throw Exception() << "No particles to shower in " - << "ShowerTree::constructTrees()" - << Exception::eventerror; - if(!isHard) - throw Exception() << "Starting on decay not yet implemented in " - << "ShowerTree::constructTrees()" - << Exception::runerror; - // create the hard process ShowerTree - ParticleVector out(hardParticles.begin(),hardParticles.end()); - hard=new_ptr(ShowerTree(subProcess->incoming(),out, decay)); - hard->setParents(); -} - -namespace { - -Lorentz5Momentum sumMomenta(tPPtr particle) { - if(particle->children().empty()) - return particle->momentum(); - Lorentz5Momentum output; - for(unsigned int ix=0;ixchildren().size();++ix) { - output += sumMomenta(particle->children()[ix]); - } - return output; -} - -} - -void ShowerTree::checkMomenta() { - vector pin; - for(map::const_iterator it=_incomingLines.begin(); - it!=_incomingLines.end();++it) { - if(isDecay()) { - tPPtr parent = it->first->progenitor(); - pin.push_back(parent->momentum()); - while(!parent->children().empty()) { - pin.back() -= sumMomenta(parent->children()[1]); - parent = parent->children()[0]; - } - } - else { - tPPtr parent = it->second; - pin.push_back(parent->momentum()); - while(!parent->children().empty()&&parent->children().size()==2) { - pin.back() -= sumMomenta(parent->children()[1]); - parent = parent->children()[0]; - if(parent==it->first->progenitor()) break; - } - } - } - vector pout; - for(map::const_iterator it= _outgoingLines.begin(); - it!=_outgoingLines.end();++it) { - pout.push_back(sumMomenta(it->first->progenitor())); - } - Lorentz5Momentum psum; - for(unsigned int ix=0;ix< pin.size();++ix) { - CurrentGenerator::log() << "pin " << ix << pin[ix]/GeV << "\n"; - psum +=pin[ix]; - } - CurrentGenerator::log() << "In total " << psum/GeV << " " << psum.m()/GeV << "\n"; - Lorentz5Momentum psum2; - for(unsigned int ix=0;ix< pout.size();++ix) { - CurrentGenerator::log() << "pout " << ix << pout[ix]/GeV << "\n"; - psum2 +=pout[ix]; - } - CurrentGenerator::log() << "Out total " << psum2/GeV << " " << psum2.m()/GeV << "\n"; - CurrentGenerator::log() << "Total " << (psum-psum2)/GeV << "\n"; -} diff --git a/Shower/Base/ShowerTree.h b/Shower/Base/ShowerTree.h deleted file mode 100644 --- a/Shower/Base/ShowerTree.h +++ /dev/null @@ -1,467 +0,0 @@ -// -*- C++ -*- -// -// ShowerTree.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_ShowerTree_H -#define HERWIG_ShowerTree_H - -#include "ThePEG/Config/ThePEG.h" -#include "Herwig/Shower/ShowerHandler.fh" -#include "Herwig/Shower/ShowerConfig.h" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "ShowerProgenitor.h" -#include "ThePEG/EventRecord/Step.h" -#include -#include "ShowerTree.fh" - -namespace Herwig { - -/** - * Typedef for map of ShowerTrees for decays - */ -typedef multimap > ShowerDecayMap; - -using namespace ThePEG; - -/** \ingroup Shower - * - * The ShowerTree class stores the basic information needed for - * each hard interaction, either a scattering process or decay, which - * needs to be showered. - * - */ -class ShowerTree : public Base { - - friend class ShowerHandler; - -public: - - /** - * Constructors and Destructors - */ - //@{ - /** - * Constructor for a scattering process - * @param incoming The incoming particles - * @param out The outgoing particles - * @param decay Map into which the trees for any unstable particles are inserted - */ - ShowerTree(const PPair incoming, const ParticleVector & out, - ShowerDecayMap & decay); - - /** - * Constructor for a decay - * @param in The decaying particle - * @param decay Map into which the trees for any unstable particles are inserted - */ - ShowerTree(PPtr in, ShowerDecayMap & decay); - //@} - - /** - * Calculate the space-time displacement - * @param particle The particle for which to calculate the displacement - */ - static Lorentz5Distance spaceTimeDistance(tPPtr particle); - - /** - * Construct the trees from the hard process - * @param hard The output ShowerTree for the hard process - * @param decay The output ShowerTrees for any decays. - * @param decay Map for the decay trees - * @param tagged The tagged particles - * @param splitTrees Whether or not to split the process - */ - static void constructTrees(tSubProPtr subProcess, ShowerTreePtr & hard, - ShowerDecayMap & decay, tPVector tagged, - bool splitTrees); - -public: - - /** - * Insert the tree into the event record - * @param pstep The step into which the particles should be inserted - * @param ISR Whether or not ISR is switched on - * @param FSR Whether or not FSR is switched on - */ - void fillEventRecord(StepPtr pstep,bool ISR,bool FSR) { - if(_wasHard) - insertHard (pstep,ISR,FSR); - else - insertDecay(pstep,ISR,FSR); - } - - - /** - * Set the parent tree to this tree for trees which come from this one. - * This needs to be run after the constructor. - */ - void setParents(); - - /** - * Perform the decay for a tree starting with an unstable particle - * @param decay The map of widths and ShowerTrees for the decays so that - * any unstable decay products can be added. - */ - void decay(ShowerDecayMap & decay); - - /** - * Access methods for the type of interaction - */ - //@{ - /** - * Whether or not this is a scattering process - */ - bool isHard() const { return _wasHard; } - - - /** - * Whether or not this is a decay. - */ - bool isDecay() const { return !_wasHard; } - //@} - - /** - * Flags relating to the application of the hard matrix element correction - */ - //@{ - /** - * Was the hard matrix element correction applied - */ - bool hardMatrixElementCorrection() const { return _hardMECorrection; } - - /** - * Set whether or not the hard matrix element correction was applied - */ - void hardMatrixElementCorrection(bool in) { _hardMECorrection=in; } - //@} - - /** - * Get the incoming shower particles - */ - map & incomingLines() { - return _incomingLines; - } - - /** - * Get the outgoing shower particles - */ - map & outgoingLines() { - return _outgoingLines; - } - - /** - * Update the shower product for a final-state particle - */ - void updateFinalStateShowerProduct(ShowerProgenitorPtr progenitor, - ShowerParticlePtr parent, - const ShowerParticleVector & children); - - /** - * Update the shower product for an initial-state particle - */ - void updateInitialStateShowerProduct(ShowerProgenitorPtr progenitor, - ShowerParticlePtr newParent); - - /** - * Get the current final shower product for a final-state particle - */ - tShowerParticlePtr getFinalStateShowerProduct(ShowerProgenitorPtr progenitor) { - return _outgoingLines.find(progenitor)==_outgoingLines.end() - ? tShowerParticlePtr() : _outgoingLines[progenitor]; - } - - /** - * Add a final-state branching. This method removes the parent of the branching - * from the list of particles at the end of the shower and inserts the children - * @param parent The parent for the branching - * @param children The outgoing particles in the branching - */ - void addFinalStateBranching(ShowerParticlePtr parent, - const ShowerParticleVector & children); - - /** - * Add an initial-state branching. This method removes the oldParent of the - * branching and inserts the result of the backward evolution and the - * outgoing particle into the relevant lists. - * @param oldParent The particle being backward evolved - * @param newParent The initial-state particle resulting from the backward evolution - * @param otherChild The final-state particle produced in the evolution. - */ - void addInitialStateBranching(ShowerParticlePtr oldParent, - ShowerParticlePtr newParent, - ShowerParticlePtr otherChild); - - /** - * Member called at the end of the shower of a tree to perform a number of - * updates. - * @param decay The map of widths and ShowerTrees for the decays so that - * any unstable decay products can be added. - */ - void updateAfterShower(ShowerDecayMap & decay); - - /** - * Access and set the flag for whether this tree has been showered - */ - //@{ - /** - * Access the flag - */ - bool hasShowered() const { return _hasShowered; } - - /** - * Set the flag - */ - void hasShowered(bool in) { _hasShowered=in; } - //@} - - /** - * Access the parent tree - */ - ShowerTreePtr parent() const { return _parent; } - - /** - * Clear all the shower products so that the event can be reshowered - * if the first attempt fail - */ - void clear(); - - /** - * Reset the particles resulting from the shower to those which started - * the shower - */ - void resetShowerProducts(); - - /** - * Extract the progenitors for the reconstruction - */ - vector extractProgenitors(); - - /** - * Access to the outgoing particles - */ - const set & forwardParticles() const { return _forward; } - - /** - * Map of particles in this Tree which are the initial particles in other - * trees - */ - const map > & - treelinks() const {return _treelinks;} - - /** - * Update the link between shower particle and tree - */ - void updateLink(tShowerTreePtr tree, - pair in) { - _treelinks[tree] = in; - } - - /** - * Transform the tree - */ - void transform(const LorentzRotation & rot, bool applyNow); - - /** - * Apply any postphoned transformations - */ - void applyTransforms(); - - /** - * Clear any postphoned transformations - */ - void clearTransforms(); - - /** - * Transform which needs to be applied - */ - const LorentzRotation & transform() {return _transforms;} - - /** - * Get all the progenitors - */ - vector extractProgenitorParticles(); - - /** - * Check the momentum conservation in the tree - */ - void checkMomenta(); - -protected: - - /** - * Functions to add the shower to the event record. - */ - //@{ - /** - * Insert a hard process - * @param pstep The step into which the particles should be inserted - * @param ISR Whether or not ISR is switched on - * @param FSR Whether or not FSR is switched on - */ - void insertHard(StepPtr pstep,bool ISR,bool FSR); - - /** - * Insert a decay process - * @param pstep The step into which the particles should be inserted - * @param ISR Whether or not ISR is switched on - * @param FSR Whether or not FSR is switched on - */ - void insertDecay(StepPtr pstep,bool ISR,bool FSR); - - /** - * Recursively add the final-state shower from the particle to the event record. - * @param particle The final-state particle - * @param step The step - */ - void addFinalStateShower(PPtr particle, StepPtr step); - - /** - * Add the initial-state shwoer from the particle to the step - * @param particle The final-state particle - * @param hadron The incoming hadron - * @param step The step - * @param addchildren Add the children of the particle - */ - void addInitialStateShower(PPtr particle, PPtr hadron, - StepPtr step, bool addchildren=true); - - /** - * Update the colour information of a particle prior to insertion into the - * event record. - * @param particle The particle for which the colour is updated. - */ - void updateColour(PPtr particle); - - /** - * Map the colours for a given particle - */ - void mapColour(PPtr original, PPtr copy); - //@} - - /** - * Isolate the colour of the process from the rest of the event. - * Called in the constructor - * @param original The original particles - * @param copy The colour isolated copies - */ - void colourIsolate(const vector & original, const vector & copy); - - /** - * Isolate a specific colour line - */ - void isolateLine(vector::const_iterator cit, - vector & particles, - tcColinePtr oldline, - tColinePtr newline); - - /** - * After the creatation of a ShowerParticle make sure it is properly attached - * to its ColourLine - * @param part The particle - */ - void fixColour(tShowerParticlePtr part); - - void findDecayProducts(PPtr in, vector & original, vector & copy, - ShowerDecayMap& decay, map & trees); - -private: - - /** - * Incoming partons for the hard process - */ - PPair _incoming; - - /** - * The incoming ShowerParticles connected to the interaction - * as the index of a map with the particle the shower backward evolves - * them to as the value - */ - map _incomingLines; - - /** - * The outgoing ShowerParticles connected to the interaction - * as the index of a map with the particle the shower - * evolves them to as the value - */ - map _outgoingLines; - - /** - * The outgoing ShowerParticles at the end of the final-state shower - */ - set _forward; - - /** - * The incoming ShowerParticles at the end of the initial-state shower - */ - set _backward; - - /** - * Was the hard matrix element correction applied - */ - bool _hardMECorrection; - - /** - * Was this a scattering process or a decay - */ - bool _wasHard; - - /** - * Map of colour lines used to reset colours when inserted into the event - */ - map _colour; - - /** - * Map of particles in this Tree which are the initial particles in other - * trees - */ - map > _treelinks; - - /** - * The parent tree - */ - tShowerTreePtr _parent; - - /** - * Has this tree showered - */ - bool _hasShowered; - - /** - * The transforms which still need to be applied - */ - LorentzRotation _transforms; - -private: - - /** - * Copy of decay in shower from ShowerHandler - */ - static set _decayInShower; - - /** - * Whether or not to include space-time distances - */ - static bool _spaceTime; - - /** - * Minimum virtuality for the space-time model - */ - static Energy2 _vmin2; - - /** - * Check if a particle decays in the shower - * @param id The PDG code for the particle - */ - static bool decaysInShower(long id) { - return ( _decayInShower.find( abs(id) ) != - _decayInShower.end() ); - } - -}; -} - -#endif diff --git a/Shower/Base/ShowerVeto.h b/Shower/Base/ShowerVeto.h deleted file mode 100644 --- a/Shower/Base/ShowerVeto.h +++ /dev/null @@ -1,138 +0,0 @@ -// -*- C++ -*- -// -// ShowerVeto.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_ShowerVeto_H -#define HERWIG_ShowerVeto_H -// -// This is the declaration of the ShowerVeto class. -// - -#include "ThePEG/Interface/Interfaced.h" -#include "ShowerVeto.fh" -#include "Herwig/Shower/ShowerConfig.h" -#include "ShowerParticle.fh" -#include "ShowerProgenitor.fh" - -namespace Herwig { - -struct Branching; - -using namespace ThePEG; - -/**\ingroup Shower - * Exception class for vetoing a showering - */ -struct VetoShower { }; - -/**\ingroup Shower - * ShowerVeto is a general interface for performing - * vetoes during showering. - * - * @see \ref ShowerVetoInterfaces "The interfaces" - * defined for ShowerVeto. - */ -class ShowerVeto: public Interfaced { - -public: - - /** - * Define types of ShowerVetoes - */ - enum ShowerVetoType { - - /** - * Throw away emission, if veto encountered. Set the scale to - * the scale of vetoed emission. - */ - Emission = 1, - - /** - * Throw away showering - */ - Shower, - - /** - * Throw away event - */ - Event - }; - -public: - - /** - * Constructor giving the behaviour of this veto - */ - ShowerVeto (ShowerVetoType vetoType) : _vetoType(vetoType) {} - - /** - * Return the type of this veto - */ - ShowerVetoType vetoType () const {return _vetoType;} - -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: - - /** - * Return true, if the selected emission off the given - * particle and progenitor is vetoed. - */ - virtual bool vetoTimeLike (tcShowerProgenitorPtr, tcShowerParticlePtr, - const Branching&) = 0; - - /** - * Return true, if the selected emission off the given - * particle and progenitor is vetoed. - */ - virtual bool vetoSpaceLike (tcShowerProgenitorPtr, tcShowerParticlePtr, - const Branching&) = 0; - -private: - - /** - * The assignment operator is private and must never be called. - * In fact, it should not even be implemented. - */ - ShowerVeto & operator=(const ShowerVeto &); - -private: - - /** - * The type of this veto. - */ - ShowerVetoType _vetoType; - -}; - -} - -#endif /* HERWIG_ShowerVeto_H */ diff --git a/Shower/Default/QTildeFinder.h b/Shower/Default/QTildeFinder.h deleted file mode 100644 --- a/Shower/Default/QTildeFinder.h +++ /dev/null @@ -1,206 +0,0 @@ -// -*- C++ -*- -// -// QTildeFinder.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_QTildeFinder_H -#define HERWIG_QTildeFinder_H -// -// This is the declaration of the QTildeFinder class. -// - -#include "Herwig/Shower/Base/PartnerFinder.h" -#include "Herwig/Shower/ShowerConfig.h" -#include "ThePEG/Interface/Interfaced.h" - -namespace Herwig { -using namespace ThePEG; - -/** \ingroup Shower - * - * The QTildeFinder class is responsible for finding the partners and - * setting the initial evolution scales for the shower evolution described - * in JHEP 0312:045,2003. - * - * @see \ref QTildeFinderInterfaces "The interfaces" - * defined for QTildeFinder. - */ -class QTildeFinder: public PartnerFinder { - -public: - - /** - * The default constructor. - */ - QTildeFinder() : _finalFinalConditions(0), - _initialFinalDecayConditions(0), - _initialInitialConditions(0) {} - - /** @name Functions used by the persistent I/O system. */ - //@{ - /** - * Function used to write out object persistently. - * @param os the persistent output stream written to. - */ - void persistentOutput(PersistentOStream & os) const; - - /** - * Function used to read in object persistently. - * @param is the persistent input stream read from. - * @param version the version number of the object when written. - */ - void persistentInput(PersistentIStream & is, int version); - //@} - - /** - * The standard Init function used to initialize the interfaces. - * Called exactly once for each class by the class description system - * before the main function starts or - * when this class is dynamically loaded. - */ - static void Init(); - -public: - - /** - * Calculate the initial evolution scales given momenta - */ - pair calculateFinalFinalScales(Lorentz5Momentum p1, Lorentz5Momentum p2, - bool colouredfirst); - - /** - * Calculate the initial evolution scales given momenta - */ - pair calculateInitialInitialScales(const Lorentz5Momentum& p1, - const Lorentz5Momentum& p2); - - /** - * Calculate the initial evolution scales given momenta - */ - pair calculateInitialFinalScales(const Lorentz5Momentum& pb, const Lorentz5Momentum& pc, - const bool isDecayCase); - -protected: - - /** - * Given a pair of particles, supposedly partners w.r.t. an interaction, - * this method returns their initial evolution scales as a pair. - * If something wrong happens, it returns the null (ZERO,ZERO) pair. - * This method is used by the above setXXXInitialEvolutionScales - * methods. - */ - //@{ - /** - * Calculate the initial evolution scales for two final-state particles - */ - virtual pair calculateFinalFinalScales(const ShowerPPair &); - - /** - * Calculate the initial evolution scales for two initial-state particles - */ - virtual pair calculateInitialInitialScales(const ShowerPPair &); - - /** - * Calculate the initial evolution scales for one initial - * and one final-state particles - */ - virtual pair calculateInitialFinalScales(const ShowerPPair &, - const bool isDecayCase); - //@} - - /** - * Access function for the initial conditions for the shower - */ - //@{ - /** - * Initial conditions for the shower of a final-final colour connection - * - 0 is the symmetric choice - * - 1 is maximal emmision from the coloured particle - * - 2 is maximal emmision from the anticoloured particle - * - 3 is randomly selected maximal emmision - */ - unsigned int finalFinalConditions() const - {return _finalFinalConditions;} - - /** - * Initial conditions for the shower of an initial-final decay colour connection - * - 0 is the symmetric choice - * - 1 is maximal emission from the decay product - * - 2 is the smooth choice - */ - unsigned int initialFinalDecayConditions() const - {return _initialFinalDecayConditions;} - //@} - -protected: - - /** @name Clone Methods. */ - //@{ - /** - * Make a simple clone of this object. - * @return a pointer to the new object. - */ - virtual IBPtr clone() const {return new_ptr(*this);} - - /** Make a clone of this object, possibly modifying the cloned object - * to make it sane. - * @return a pointer to the new object. - */ - virtual IBPtr fullclone() const {return new_ptr(*this);} - //@} - -private: - - /** - * The assignment operator is private and must never be called. - * In fact, it should not even be implemented. - */ - QTildeFinder & operator=(const QTildeFinder &); - -private: - - /** - * Flags controlling the initial conditions for the shower - */ - //@{ - /** - * Initial conditions for the shower with a final-final colour - * connection - */ - unsigned int _finalFinalConditions; - - /** - * Initial conditions for the shower with an initial-final decay colour - * connection. This is done according to the top decay colour - * connection calculation in JHEP12(2003)_045. The options act as follows: - * 0: This is the default 'symmetric' choice which more or less divides - * the phase space evenly between the parent and its charged child. - * 1: This 'maximal' choice maximises the phase space available for - * gluons emitted from the charged child. - * 2: This (experimental) 'smooth' choice does not suffer from - * a discontinuity at the boundary between the region populated by - * emissions from the charged child and the region populated by emissions - * from the parent. This does, however, mean that the phase space - * available for emissions from the charged child is fairly minimal. - */ - unsigned int _initialFinalDecayConditions; - - /** - * Initial conditions for the shower with an initial-initial colour - * connection. This is done according to the colour connection - * calculation in JHEP12(2003)_045. The options act as follows: - * 0: This is the default 'symmetric' choice which more or less divides - * the phase space evenly between the two incoming partons. - * 1: This increases the phase space for emission from "parton b". - * 2: This increases the phase space for emission from "parton c". - */ - unsigned int _initialInitialConditions; - //@} -}; - -} - -#endif /* HERWIG_QTildeFinder_H */ diff --git a/Shower/Default/QTildeModel.cc b/Shower/Default/QTildeModel.cc deleted file mode 100644 --- a/Shower/Default/QTildeModel.cc +++ /dev/null @@ -1,62 +0,0 @@ -// -*- C++ -*- -// -// QTildeModel.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 QTildeModel class. -// - -#include "QTildeModel.h" -#include "ThePEG/Interface/ClassDocumentation.h" -#include "QTildeReconstructor.h" -#include "QTildeFinder.h" -#include "QTildeSudakov.h" -#include "ThePEG/Utilities/Throw.h" -#include "Herwig/Shower/Base/Evolver.h" -#include "ThePEG/Utilities/DescribeClass.h" - -using namespace Herwig; - -DescribeNoPIOClass -describeQTildeModel ("Herwig::QTildeModel","HwShower.so"); - -IBPtr QTildeModel::clone() const { - return new_ptr(*this); -} - -IBPtr QTildeModel::fullclone() const { - return new_ptr(*this); -} - -void QTildeModel::Init() { - - static ClassDocumentation documentation - ("The QTildeModel class is the ShowerModel object for the Herwig shower."); - -} - -void QTildeModel::checkConsistency() { - // check KinematicsReconstructor - if(!dynamic_ptr_cast::pointer>(kinematicsReconstructor())) - Throw() << "KinematicsReconstructor must be either " - << "QTildeKinematicsReconstructor or a class inheriting from it" - << "in QTildeModel::checkConsistency()"; - // check PartnerFinder - if(!dynamic_ptr_cast::pointer>(partnerFinder())) - Throw() << "PartnerFinder must be either " - << "QTildeFinder or a class inheriting from it" - << "in QTildeModel::checkConsistency()"; - // Sudakov form factors - vector::const_iterator sit; - for(sit=sudakovFormFactors().begin();sit!=sudakovFormFactors().end();++sit) { - if(!dynamic_ptr_cast::pointer>(*sit)) - Throw() << "SudakovFormFactors must be either " - << "QTildeSudakov or a class inheriting from it" - << "in QTildeModel::checkConsistency()"; - } -} diff --git a/Shower/Default/QTildeReconstructor.h b/Shower/Default/QTildeReconstructor.h deleted file mode 100644 --- a/Shower/Default/QTildeReconstructor.h +++ /dev/null @@ -1,646 +0,0 @@ -// -*- C++ -*- -// -// QTildeReconstructor.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_QTildeReconstructor_H -#define HERWIG_QTildeReconstructor_H -// -// This is the declaration of the QTildeReconstructor class. -// - -#include "Herwig/Shower/Base/KinematicsReconstructor.h" - -namespace Herwig { - -using namespace ThePEG; - -/** \ingroup Shower - * A simple struct to store the information we need on the - * showering - */ -struct JetKinStruct { - - /** - * Parent particle of the jet - */ - tShowerParticlePtr parent; - - /** - * Momentum of the particle before reconstruction - */ - Lorentz5Momentum p; - - /** - * Momentum of the particle after reconstruction - */ - Lorentz5Momentum q; -}; - -/** - * typedef for a vector of JetKinStruct - */ -typedef vector JetKinVect; - -/** - * Enum to identify types of colour singlet systems - */ -enum SystemType { UNDEFINED=-1, II, IF, F ,I }; - -/** - * Struct to store colour singlets - */ -template struct ColourSinglet { - - typedef vector > VecType; - - ColourSinglet() : type(UNDEFINED) {} - - ColourSinglet(SystemType intype,Value inpart) - : type(intype),jets(1,inpart) {} - - /** - * The type of system - */ - SystemType type; - - /** - * The jets in the system - */ - vector jets; - -}; - -/** - * Struct to store a colour singlet system of particles - */ -typedef ColourSinglet ColourSingletSystem; - -/** - * Struct to store a colour singlet shower - */ -typedef ColourSinglet ColourSingletShower; - -/** \ingroup Shower - * - * This class is responsible for the kinematical reconstruction - * after each showering step, and also for the necessary Lorentz boosts - * in order to preserve energy-momentum conservation in the overall collision, - * and also the invariant mass and the rapidity of the hard subprocess system. - * In the case of multi-step showering, there will be not unnecessary - * kinematical reconstructions. - * - * There is also the option of taking a set of momenta for the particles - * and inverting the reconstruction to give the evolution variables for the - * shower. - * - * Notice: - * - although we often use the term "jet" in either methods or variables names, - * or in comments, which could appear applicable only for QCD showering, - * there is indeed no "dynamics" represented in this class: only kinematics - * is involved, as the name of this class remainds. Therefore it can be used - * for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung). - * - * @see ShowerParticle - * @see ShowerKinematics - * @see \ref QTildeReconstructorInterfaces "The interfaces" - * defined for QTildeReconstructor. - */ -class QTildeReconstructor: public KinematicsReconstructor { - -public: - - /** - * Default constructor - */ - QTildeReconstructor() : _reconopt(0), _initialBoost(0), - _finalStateReconOption(0), - _initialStateReconOption(0), _minQ(MeV) {}; - - /** - * Methods to reconstruct the kinematics of a scattering or decay process - */ - //@{ - /** - * Given in input a vector of the particles which initiated the showers - * the method does the reconstruction of such jets, - * including the appropriate boosts (kinematics reshufflings) - * needed to conserve the total energy-momentum of the collision - * and preserving the invariant mass and the rapidity of the - * hard subprocess system. - */ - virtual bool reconstructHardJets(ShowerTreePtr hard, - const map > & pt, - ShowerInteraction::Type type, - bool switchRecon) const; - - /** - * Given in input a vector of the particles which initiated the showers - * the method does the reconstruction of such jets, - * including the appropriate boosts (kinematics reshufflings) - * needed to conserve the total energy-momentum of the collision - * and preserving the invariant mass and the rapidity of the - * hard subprocess system. - */ - virtual bool reconstructDecayJets(ShowerTreePtr decay, - ShowerInteraction::Type type) const; - //@} - - /** - * Methods to invert the reconstruction of the shower for - * a scattering or decay process and calculate - * the variables used to generate the - * shower given the particles produced. - * This is needed for the CKKW and POWHEG approaches - */ - //@{ - /** - * Given the particles, with a history which we wish to interpret - * as a shower reconstruct the variables used to generate the - * shower - */ - virtual bool deconstructDecayJets(HardTreePtr, cEvolverPtr, - ShowerInteraction::Type) const; - - /** - * Given the particles, with a history which we wish to interpret - * as a shower reconstruct the variables used to generate the shower - * for a hard process - */ - virtual bool deconstructHardJets(HardTreePtr, cEvolverPtr, - ShowerInteraction::Type) const; - //@} - -public: - - /** @name Functions used by the persistent I/O system. */ - //@{ - /** - * Function used to write out object persistently. - * @param os the persistent output stream written to. - */ - void persistentOutput(PersistentOStream & os) const; - - /** - * Function used to read in object persistently. - * @param is the persistent input stream read from. - * @param version the version number of the object when written. - */ - void persistentInput(PersistentIStream & is, int version); - //@} - - /** - * The standard Init function used to initialize the interfaces. - * Called exactly once for each class by the class description system - * before the main function starts or - * when this class is dynamically loaded. - */ - static void Init(); - -protected: - - /** - * Methods to reconstruct the kinematics of individual jets - */ - //@{ - /** - * Given the particle (ShowerParticle object) that - * originates a forward (time-like) jet, this method reconstructs the kinematics - * of the jet. That is, by starting from the final grand-children (which - * originates directly or indirectly from particleJetParent, - * and which don't have children), and moving "backwards" (in a physical - * time picture), towards the particleJetParent, the - * ShowerKinematics objects associated with the various particles, - * which have been created during the showering, are now completed. - * In particular, at the end, we get the mass of the jet, which is the - * main information we want. - * This methods returns false if there was no radiation or rescaling required - */ - virtual bool reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent) const; - - /** - * Exactly similar to the previous one, but for a space-like jet. - * Also in this case we start from the final grand-children (which - * are childless) of the particle which originates the jet, but in - * this case we proceed "forward" (in the physical time picture) - * towards the particleJetParent. - * This methods returns false if there was no radiation or rescaling required - */ - bool reconstructSpaceLikeJet(const tShowerParticlePtr particleJetParent) const; - - /** - * Exactly similar to the previous one, but for a decay jet - * This methods returns false if there was no radiation or rescaling required - */ - bool reconstructDecayJet(const tShowerParticlePtr particleJetParent) const; - //@} - - /** - * Methods to perform the reconstruction of various types of colour - * singlet systems - */ - //@{ - /** - * Perform the reconstruction of a system with one incoming and at least one - * outgoing particle - */ - void reconstructInitialFinalSystem(vector) const; - - /** - * Perform the reconstruction of a system with only final-state - * particles - */ - void reconstructFinalStateSystem(bool applyBoost, - const LorentzRotation & toRest, - const LorentzRotation & fromRest, - vector) const; - - /** - * Reconstruction of a general coloured system - */ - void reconstructGeneralSystem(vector & ShowerHardJets) const; - - /** - * Reconstruction of a general coloured system doing - * final-final, then initial-final and then initial-initial - */ - void reconstructFinalFirst(vector & ShowerHardJets) const; - - /** - * Reconstruction of a general coloured system doing - * colour parners - */ - void reconstructColourPartner(vector & ShowerHardJets) const; - - /** - * Reconstruction based on colour singlet systems - */ - void reconstructColourSinglets(vector & ShowerHardJets, - ShowerInteraction::Type type) const; - - /** - * Perform the reconstruction of a system with only final-state - * particles - */ - void reconstructInitialInitialSystem(bool & applyBoost, - LorentzRotation & toRest, - LorentzRotation & fromRest, - vector) const; - //@} - - /** - * Methods to perform the inverse reconstruction of various types of - * colour singlet systems - */ - //@{ - /** - * Perform the inverse reconstruction of a system with only final-state - * particles - */ - void deconstructFinalStateSystem(const LorentzRotation & toRest, - const LorentzRotation & fromRest, - HardTreePtr, - vector, - cEvolverPtr, - ShowerInteraction::Type) const; - - /** - * Perform the inverse reconstruction of a system with only initial-state - * particles - */ - void deconstructInitialInitialSystem(bool & applyBoost, - LorentzRotation & toRest, - LorentzRotation & fromRest, - HardTreePtr, - vector, - ShowerInteraction::Type ) const; - - /** - * Perform the inverse reconstruction of a system with only initial-state - * particles - */ - void deconstructInitialFinalSystem(HardTreePtr, - vector, - cEvolverPtr, - ShowerInteraction::Type ) const; - - bool deconstructGeneralSystem(HardTreePtr, cEvolverPtr, - ShowerInteraction::Type) const; - - bool deconstructColourSinglets(HardTreePtr, cEvolverPtr, - ShowerInteraction::Type) const; - - bool deconstructColourPartner(HardTreePtr, cEvolverPtr, - ShowerInteraction::Type) const; - //@} - - /** - * Recursively treat the most off-shell paricle seperately - * for final-final reconstruction - */ - void reconstructFinalFinalOffShell(JetKinVect orderedJets, Energy2 s, - bool recursive) const; - - /** - * Various methods for the Lorentz transforms needed to do the - * rescalings - */ - //@{ - /** - * Compute the boost to get from the the old momentum to the new - */ - LorentzRotation solveBoost(const double k, - const Lorentz5Momentum & newq, - const Lorentz5Momentum & oldp) const; - - /** - * Compute the boost to get from the the old momentum to the new - */ - LorentzRotation solveBoost(const Lorentz5Momentum & newq, - const Lorentz5Momentum & oldq) const; - - /** - * Compute the boost to get from the the old momentum to the new - */ - LorentzRotation solveBoostZ(const Lorentz5Momentum & newq, - const Lorentz5Momentum & oldq) const; - - /** - * Recursively boost the initial-state shower - * @param p The particle - * @param bv The boost - * @param parent The parent of the chain - */ - void boostChain(tPPtr p, const LorentzRotation & bv, tPPtr & parent) const; - - /** - * Given a 5-momentum and a scale factor, the method returns the - * Lorentz boost that transforms the 3-vector vec{momentum} ---> - * k*vec{momentum}. The method returns the null boost in the case no - * solution exists. This will only work in the case where the - * outgoing jet-momenta are parallel to the momenta of the particles - * leaving the hard subprocess. - */ - Boost solveBoostBeta( const double k, const Lorentz5Momentum & newq, - const Lorentz5Momentum & oldp); - - /** - * Compute boost parameter along z axis to get (Ep, any perp, qp) - * from (E, same perp, q). - */ - double getBeta(const double E, const double q, - const double Ep, const double qp) const - {return (q*E-qp*Ep)/(sqr(qp)+sqr(E));} - //@} - - /** - * Methods to calculate the various scaling factors - */ - //@{ - /** - * Given a vector of 5-momenta of jets, where the 3-momenta are the initial - * ones before showering and the masses are reconstructed after the showering, - * this method returns the overall scaling factor for the 3-momenta of the - * vector of particles, vec{P}_i -> k * vec{P}_i, such to preserve energy- - * momentum conservation, i.e. after the rescaling the center of mass 5-momentum - * is equal to the one specified in input, cmMomentum. - * The method returns 0 if such factor cannot be found. - * @param root_s Centre-of-mass energy - * @param jets The jets - */ - double solveKfactor( const Energy & root_s, const JetKinVect & jets ) const; - - /** - * Calculate the rescaling factors for the jets in a particle decay where - * there was initial-state radiation - * @param mb The mass of the decaying particle - * @param n The reference vector for the initial state radiation - * @param pjet The momentum of the initial-state jet - * @param jetKinematics The JetKinStruct objects for the jets - * @param partner The colour partner - * @param ppartner The momentum of the colour partner of the decaying particle - * before and after radiation - * @param k1 The rescaling parameter for the partner - * @param k2 The rescaling parameter for the outgoing singlet - * @param qt The transverse momentum vector - */ - bool solveDecayKFactor(Energy mb, - const Lorentz5Momentum & n, - const Lorentz5Momentum & pjet, - const JetKinVect & jetKinematics, - ShowerParticlePtr partner, - Lorentz5Momentum ppartner[2], - double & k1, - double & k2, - Lorentz5Momentum & qt) const; - - /** - * Compute the momentum rescaling factor needed to invert the shower - * @param pout The momenta of the outgoing particles - * @param mon The on-shell masses - * @param roots The mass of the decaying particle - */ - double inverseRescalingFactor(vector pout, - vector mon,Energy roots) const; - - /** - * Compute the momentum rescaling factor needed to invert the shower - * @param pout The momenta of the outgoing particles - * @param mon The on-shell masses - * @param roots The mass of the decaying particle - * @param ppartner The momentum of the colour partner - * @param mbar The mass of the decaying particle - * @param k1 The first scaling factor - * @param k2 The second scaling factor - */ - bool inverseDecayRescalingFactor(vector pout, - vector mon,Energy roots, - Lorentz5Momentum ppartner, Energy mbar, - double & k1, double & k2) const; - - /** - * Check the rescaling conserves momentum - * @param k The rescaling - * @param root_s The centre-of-mass energy - * @param jets The jets - */ - Energy momConsEq(const double & k, const Energy & root_s, - const JetKinVect & jets) const; - - - void findInitialBoost(const Lorentz5Momentum & pold, const Lorentz5Momentum & pnew, - LorentzRotation & toRest, LorentzRotation & fromRest) const; - //@} - - /** - * Find the colour partners of a particle to identify the colour singlet - * systems for the reconstruction. - */ - template void findPartners(Value branch,set & done, - const set & branchings, - vector & jets) const; - - /** - * Add the intrinsic \f$p_T\f$ to the system if needed - */ - bool addIntrinsicPt(vector) const; - - /** - * Apply a transform to the particle and any child, including child ShowerTree - * objects - * @param particle The particle - * @param r The Lorentz transformation - * @param match Whether or not to look at children etc - * @param original The original particle - */ - void deepTransform(PPtr particle,const LorentzRotation & r, - bool match=true,PPtr original=PPtr()) const; - - /** - * Find the mass of a particle in the hard branching - */ - Energy findMass(HardBranchingPtr) const; - - /** - * Calculate the initial-state rescaling factors - */ - vector initialStateRescaling(double x1, double x2, - const Lorentz5Momentum & pold, - const vector & p, - const vector & pq, - const vector& highespts) const; - - /** - * Calculate the inverse of the initial-state rescaling factor - */ - vector inverseInitialStateRescaling(double & x1, double & x2, - const Lorentz5Momentum & pold, - const vector & p, - const vector & pq) const; - - /** - * Find the colour singlet systems - */ - template - typename ColourSinglet::VecType identifySystems(set jets, - unsigned int & nnun,unsigned int & nnii, - unsigned int & nnif,unsigned int & nnf, - unsigned int & nni) const; - - /** - * Combine final-state colour systems - */ - template - void combineFinalState(vector > & systems) const; - -protected: - - /** @name Clone Methods. */ - //@{ - /** - * Make a simple clone of this object. - * @return a pointer to the new object. - */ - virtual IBPtr clone() const {return new_ptr(*this);} - - /** Make a clone of this object, possibly modifying the cloned object - * to make it sane. - * @return a pointer to the new object. - */ - virtual IBPtr fullclone() const {return new_ptr(*this);} - //@} - -protected: - - /** @name Standard Interfaced functions. */ - //@{ - /** - * Initialize this object after the setup phase before saving an - * EventGenerator to disk. - * @throws InitException if object could not be initialized properly. - */ - virtual void doinit(); - //@} - -private: - - /** - * The assignment operator is private and must never be called. - * In fact, it should not even be implemented. - */ - QTildeReconstructor & operator=(const QTildeReconstructor &); - -private: - - /** - * Option for handling the reconstruction - */ - unsigned int _reconopt; - - /** - * Option for the boost for initial-initial reconstruction - */ - unsigned int _initialBoost; - - /** - * Option for the reconstruction of final state systems - */ - unsigned int _finalStateReconOption; - - /** - * Option for the initial state reconstruction - */ - unsigned int _initialStateReconOption; - - /** - * Minimum invariant mass for initial-final dipoles to allow the - * reconstruction - */ - Energy _minQ; - - /** - * The progenitor of the jet currently being reconstructed - */ - mutable tShowerParticlePtr _progenitor; - - /** - * Storage of the intrinsic \f$p_T\f$ - */ - mutable map > _intrinsic; - - /** - * Current ShowerTree - */ - mutable tShowerTreePtr _currentTree; - - /** - * Particles which shouldn't have their masses rescaled as - * vector for the interface - */ - PDVector _noRescaleVector; - - /** - * Particles which shouldn't have their masses rescaled as - * set for quick access - */ - set _noRescale; - - /** - * Storage of the boosts applied to enable resetting after failure - */ - mutable map > _boosts; - - /** - * Storage of the boosts applied to enable resetting after failure - */ - mutable map > _treeBoosts; -}; - -} - -#include "QTildeReconstructor.tcc" -#endif /* HERWIG_QTildeReconstructor_H */ diff --git a/DipoleShower/AlphaS/Makefile.am b/Shower/Dipole/AlphaS/Makefile.am rename from DipoleShower/AlphaS/Makefile.am rename to Shower/Dipole/AlphaS/Makefile.am diff --git a/DipoleShower/AlphaS/alpha_s.cc b/Shower/Dipole/AlphaS/alpha_s.cc rename from DipoleShower/AlphaS/alpha_s.cc rename to Shower/Dipole/AlphaS/alpha_s.cc diff --git a/DipoleShower/AlphaS/alpha_s.h b/Shower/Dipole/AlphaS/alpha_s.h rename from DipoleShower/AlphaS/alpha_s.h rename to Shower/Dipole/AlphaS/alpha_s.h diff --git a/DipoleShower/AlphaS/gsl.cc b/Shower/Dipole/AlphaS/gsl.cc rename from DipoleShower/AlphaS/gsl.cc rename to Shower/Dipole/AlphaS/gsl.cc diff --git a/DipoleShower/AlphaS/gsl.h b/Shower/Dipole/AlphaS/gsl.h rename from DipoleShower/AlphaS/gsl.h rename to Shower/Dipole/AlphaS/gsl.h diff --git a/DipoleShower/AlphaS/gsl.tcc b/Shower/Dipole/AlphaS/gsl.tcc rename from DipoleShower/AlphaS/gsl.tcc rename to Shower/Dipole/AlphaS/gsl.tcc diff --git a/DipoleShower/AlphaS/lo_alpha_s.cc b/Shower/Dipole/AlphaS/lo_alpha_s.cc rename from DipoleShower/AlphaS/lo_alpha_s.cc rename to Shower/Dipole/AlphaS/lo_alpha_s.cc diff --git a/DipoleShower/AlphaS/lo_alpha_s.h b/Shower/Dipole/AlphaS/lo_alpha_s.h rename from DipoleShower/AlphaS/lo_alpha_s.h rename to Shower/Dipole/AlphaS/lo_alpha_s.h diff --git a/DipoleShower/AlphaS/nlo_alpha_s.cc b/Shower/Dipole/AlphaS/nlo_alpha_s.cc rename from DipoleShower/AlphaS/nlo_alpha_s.cc rename to Shower/Dipole/AlphaS/nlo_alpha_s.cc diff --git a/DipoleShower/AlphaS/nlo_alpha_s.h b/Shower/Dipole/AlphaS/nlo_alpha_s.h rename from DipoleShower/AlphaS/nlo_alpha_s.h rename to Shower/Dipole/AlphaS/nlo_alpha_s.h diff --git a/DipoleShower/Base/Dipole.cc b/Shower/Dipole/Base/Dipole.cc rename from DipoleShower/Base/Dipole.cc rename to Shower/Dipole/Base/Dipole.cc --- a/DipoleShower/Base/Dipole.cc +++ b/Shower/Dipole/Base/Dipole.cc @@ -1,296 +1,296 @@ // -*- C++ -*- // // Dipole.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 Dipole class. // #include "Dipole.h" -#include "Herwig/DipoleShower/Utility/DipolePartonSplitter.h" +#include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" using namespace Herwig; Dipole::Dipole() : theParticles(), thePDFs(), theFractions(1.0,1.0), theIndices(), theScales(0.0*GeV,0.0*GeV) {} Dipole::Dipole(const pair& newParticles, const pair& newPDFs, pair newFractions, pair newScales) : theParticles(newParticles), thePDFs(newPDFs), theFractions(newFractions), theIndices(), theScales(newScales) { theIndices.first = DipoleIndex(theParticles.first->dataPtr(), theParticles.second->dataPtr(), newPDFs.first,newPDFs.second); theIndices.second = theIndices.first; theIndices.second.swap(); } void Dipole::update() { theIndices.first = DipoleIndex(theParticles.first->dataPtr(), theParticles.second->dataPtr(), thePDFs.first,thePDFs.second); theIndices.second = theIndices.first; theIndices.second.swap(); assert(DipolePartonSplitter::colourConnected(theParticles.first,theParticles.second)); } pair Dipole::split(DipoleSplittingInfo& dsplit, bool colourSpectator) const { // check contracts assert(dsplit.splittingKinematics()); assert(dsplit.emitterData() && dsplit.emissionData() && dsplit.spectatorData()); if ( !colourSpectator ) { assert(index(dsplit.configuration()) == dsplit.index()); assert(emitterX(dsplit.configuration()) == dsplit.emitterX()); assert(spectatorX(dsplit.configuration()) == dsplit.spectatorX()); } else { assert(emitterX(dsplit.configuration()) == dsplit.emitterX()); assert(emitterPDF(dsplit.configuration()) == dsplit.index().emitterPDF()); assert((dsplit.configuration().first ? theParticles.first->dataPtr() : theParticles.second->dataPtr()) == dsplit.index().emitterData()); } // generate full kinematics dsplit.splittingKinematics()->generateKinematics(emitter(dsplit.configuration())->momentum(), spectator(dsplit.configuration())->momentum(), dsplit); tPPtr oldSpectator = spectator(dsplit.configuration()); PPtr newSpectator; // get a new spectator if ( !colourSpectator ) { newSpectator = dsplit.spectatorData()->produceParticle(dsplit.splittingKinematics()->lastSpectatorMomentum()); DipolePartonSplitter::change(oldSpectator,newSpectator,spectatorPDF(dsplit.configuration()).pdf()); dsplit.spectator(oldSpectator); dsplit.splitSpectator(newSpectator); } else { newSpectator = oldSpectator; } // perform the splitting tPPtr oldEmitter = emitter(dsplit.configuration()); PPtr newEmitter = dsplit.emitterData()->produceParticle(dsplit.splittingKinematics()->lastEmitterMomentum()); PPtr newEmission = dsplit.emissionData()->produceParticle(dsplit.splittingKinematics()->lastEmissionMomentum()); newEmitter->scale(sqr(dsplit.lastPt())); newEmission->scale(sqr(dsplit.lastPt())); newSpectator->scale(oldSpectator->scale()); DipolePartonSplitter::split(oldEmitter,newEmitter,newEmission, oldSpectator,emitterPDF(dsplit.configuration()).pdf()); dsplit.emitter(oldEmitter); dsplit.splitEmitter(newEmitter); dsplit.emission(newEmission); double emitter_x = emitterX(dsplit.configuration()) / dsplit.lastEmitterZ(); double spectator_x = spectatorX(dsplit.configuration()) / dsplit.lastSpectatorZ(); PDF emitter_pdf = emitterPDF(dsplit.configuration()); PDF spectator_pdf = spectatorPDF(dsplit.configuration()); // now check how we need to arrange the children // assignment is 0 = emitter, 1 = emission, 2 = spectator int left = 0; int middle = 1; int right = 2; if (dsplit.configuration().first) { // spectator is unique right = 2; // middle is the one connecting to the spectator if (DipolePartonSplitter::colourConnected(newSpectator,newEmission)) { middle = 1; left = 0; } else { assert(DipolePartonSplitter::colourConnected(newSpectator,newEmitter)); middle = 0; left = 1; } } else { // spectator is unique left = 2; // middle is the one connecting to the spectator if (DipolePartonSplitter::colourConnected(newSpectator,newEmission)) { middle = 1; right = 0; } else { assert(DipolePartonSplitter::colourConnected(newSpectator,newEmitter)); middle = 0; right = 1; } } pair left_particles; pair right_particles; pair left_pdfs; pair right_pdfs; pair left_fractions; pair right_fractions; switch (left) { case 0: left_particles.first = newEmitter; left_pdfs.first = emitter_pdf; left_fractions.first = emitter_x; break; case 1: left_particles.first = newEmission; left_pdfs.first = PDF(); left_fractions.first = 1.; break; case 2: left_particles.first = newSpectator; left_pdfs.first = spectator_pdf; left_fractions.first = spectator_x; break; } switch (middle) { case 0: left_particles.second = newEmitter; left_pdfs.second = emitter_pdf; left_fractions.second = emitter_x; break; case 1: left_particles.second = newEmission; left_pdfs.second = PDF(); left_fractions.second = 1.; break; case 2: left_particles.second = newSpectator; left_pdfs.second = spectator_pdf; left_fractions.second = spectator_x; break; } right_particles.first = left_particles.second; right_pdfs.first = left_pdfs.second; right_fractions.first = left_fractions.second; switch (right) { case 0: right_particles.second = newEmitter; right_pdfs.second = emitter_pdf; right_fractions.second = emitter_x; break; case 1: right_particles.second = newEmission; right_pdfs.second = PDF(); right_fractions.second = 1.; break; case 2: right_particles.second = newSpectator; right_pdfs.second = spectator_pdf; right_fractions.second = spectator_x; break; } Energy scale = dsplit.lastPt(); return make_pair(Dipole(left_particles,left_pdfs,left_fractions,pair(scale,scale)), Dipole(right_particles,right_pdfs,right_fractions,pair(scale,scale))); } void Dipole::recoil (DipoleSplittingInfo& dsplit) { // check contracts assert(dsplit.splittingKinematics()); assert(dsplit.spectatorData()); assert(spectatorX(dsplit.spectatorConfiguration()) == dsplit.spectatorX()); assert(spectatorPDF(dsplit.spectatorConfiguration()) == dsplit.index().spectatorPDF()); assert((dsplit.spectatorConfiguration().first ? theParticles.first->dataPtr() : theParticles.second->dataPtr()) == dsplit.index().spectatorData()); tPPtr oldSpectator = spectator(dsplit.spectatorConfiguration()); PPtr newSpectator = dsplit.spectatorData()->produceParticle(dsplit.splittingKinematics()->lastSpectatorMomentum()); DipolePartonSplitter::change(oldSpectator,newSpectator,spectatorPDF(dsplit.spectatorConfiguration()).pdf()); newSpectator->scale(sqr(dsplit.lastPt())); dsplit.spectator(oldSpectator); dsplit.splitSpectator(newSpectator); if ( dsplit.spectatorConfiguration().first ) { theParticles.second = newSpectator; theFractions.second /= dsplit.lastSpectatorZ(); } else { theParticles.first = newSpectator; theFractions.first /= dsplit.lastSpectatorZ(); } } void Dipole::print(ostream& os) const { os << "--- "; if ( !thePDFs.first.pdf() && !thePDFs.second.pdf() ) os << "FF"; else if ( thePDFs.first.pdf() && !thePDFs.second.pdf() ) os << "IF"; else if ( !thePDFs.first.pdf() && thePDFs.second.pdf() ) os << "FI"; else os << "II"; os << " Dipole ------------------------------------------------------------------\n"; if ( !theParticles.first || !theParticles.second ) { os << " *** This Dipole has not been setup properly. ***\n"; } else { os << " particles\n" << *theParticles.first << *theParticles.second; os << " scales/GeV = (" << (theScales.first/GeV) << "," << (theScales.second/GeV) << ") fractions = (" << theFractions.first << "," << theFractions.second << ")\n"; } os << "--------------------------------------------------------------------------------\n"; os << flush; } diff --git a/DipoleShower/Base/Dipole.h b/Shower/Dipole/Base/Dipole.h rename from DipoleShower/Base/Dipole.h rename to Shower/Dipole/Base/Dipole.h --- a/DipoleShower/Base/Dipole.h +++ b/Shower/Dipole/Base/Dipole.h @@ -1,270 +1,270 @@ // -*- C++ -*- // // Dipole.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_Dipole_H #define HERWIG_Dipole_H // // This is the declaration of the Dipole class. // -#include "Herwig/DipoleShower/Kinematics/DipoleSplittingKinematics.h" -#include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" +#include "Herwig/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief The Dipole class is used by the dipole shower to * represent a dipole of two coloured partons. * */ class Dipole { public: /** * The default constructor */ Dipole(); /** * The standard constructor */ Dipole(const pair& newParticles, const pair& newPDFs, pair newFractions, pair newScales = pair(ZERO,ZERO)); public: /** * Get the left particle. */ tPPtr leftParticle() const { return theParticles.first; } /** * Get the right particle. */ tPPtr rightParticle() const { return theParticles.second; } /** * Get the left PDF. */ const PDF& leftPDF() const { return thePDFs.first; } /** * Get the right PDF. */ const PDF& rightPDF() const { return thePDFs.second; } /** * Get the left fraction. */ double leftFraction() const { return theFractions.first; } /** * Get the right fraction. */ double rightFraction() const { return theFractions.second; } /** * Set the left particle. */ void leftParticle(PPtr p) { theParticles.first = p; } /** * Set the right particle. */ void rightParticle(PPtr p) { theParticles.second = p; } /** * Set the left PDF */ void leftPDF(const PDF& p) { thePDFs.first = p; } /** * Set the right PDF */ void rightPDF(const PDF& p) { thePDFs.second = p; } /** * Set the momentum fraction for the left particle. */ void leftFraction(double x) { theFractions.first = x; } /** * Set the momentum fraction for the right particle. */ void rightFraction(double x) { theFractions.second = x; } /** * Get the scale for the left particle. */ Energy leftScale() const { return theScales.first; } /** * Set the scale for the left particle. */ void leftScale(Energy s) { theScales.first = s; } /** * Get the scale for the right particle. */ Energy rightScale() const { return theScales.second; } /** * Set the scale for the right particle. */ void rightScale(Energy s) { theScales.second = s; } /** * Update information, if modified. */ void update(); public: /** * Return the dipole index for the selected * emitter-spectator assignment. */ const DipoleIndex& index(pair conf) const { return conf.first ? theIndices.first : theIndices.second; } /** * Return the emitter particle for the * selected configuration. */ tPPtr emitter(pair conf) const { return conf.first ? theParticles.first : theParticles.second; } /** * Return the spectator particle for the * selected configuration. */ tPPtr spectator(pair conf) const { return conf.first ? theParticles.second : theParticles.first; } /** * Return the scale associated to the emitter * for the selected configuration. */ Energy emitterScale(pair conf) const { return conf.first ? theScales.first : theScales.second; } /** * Set the scale associated to the emitter * for the selected configuration. */ void emitterScale(pair conf, Energy scale) { (conf.first ? theScales.first : theScales.second) = scale; } /** * Return the momentum fraction of the emitter * for the selected configuration. */ double emitterX(pair conf) const { return conf.first ? theFractions.first : theFractions.second; } /** * Return the PDF of the emitter * for the selected configuration. */ const PDF& emitterPDF(pair conf) const { return conf.first ? thePDFs.first : thePDFs.second; } /** * Return the momentum fraction of the spectator * for the selected configuration. */ double spectatorX(pair conf) const { return conf.first ? theFractions.second : theFractions.first; } /** * Return the PDF of the spectator * for the selected configuration. */ const PDF& spectatorPDF(pair conf) const { return conf.first ? thePDFs.second : thePDFs.first; } public: /** * Split this dipole according to the given splitting. * If colourSpectator is true, do not change the spectator. */ pair split (DipoleSplittingInfo& dsplit, bool colourSpectator) const; /** * Produce a new spectator according to the * given splitting. */ void recoil (DipoleSplittingInfo& dsplit); public: /** * Put information to ostream */ void print(ostream&) const; private: /** * The particles forming the dipole */ pair theParticles; /** * The PDF objects. */ pair thePDFs; /** * The momentum fractions associated * to the incoming particles */ pair theFractions; /** * The dipole indices, if the first or second particle * is considered as emitter. */ pair theIndices; /** * The scale associated to the first and second * particle, respectively. */ pair theScales; }; inline ostream& operator << (ostream& os, const Dipole& di) { di.print(os); return os; } } #endif /* HERWIG_Dipole_H */ diff --git a/DipoleShower/Base/DipoleChain.cc b/Shower/Dipole/Base/DipoleChain.cc rename from DipoleShower/Base/DipoleChain.cc rename to Shower/Dipole/Base/DipoleChain.cc --- a/DipoleShower/Base/DipoleChain.cc +++ b/Shower/Dipole/Base/DipoleChain.cc @@ -1,324 +1,324 @@ // -*- C++ -*- // // DipoleChain.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 DipoleChain class. // #include "DipoleChain.h" -#include "Herwig/DipoleShower/Utility/DipolePartonSplitter.h" +#include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" #include using namespace Herwig; DipoleChain::DipoleChain() : ggSingleDipole(false) {} bool DipoleChain::circular () const { return (theDipoles.front().leftParticle() == theDipoles.back().rightParticle()); } bool DipoleChain::hasLeftNeighbour (list::const_iterator dc) const { if ( dc == dipoles().begin() ) return circular(); return true; } Dipole& DipoleChain::leftNeighbour (list::iterator dc) { assert(hasLeftNeighbour(dc)); if ( dc == dipoles().begin() ) return dipoles().back(); return *(--dc); } const Dipole& DipoleChain::leftNeighbour (list::const_iterator dc) const { assert(hasLeftNeighbour(dc)); if ( dc == dipoles().begin() ) return dipoles().back(); return *(--dc); } list::iterator DipoleChain::leftNeighbourIterator(list::iterator dc) { assert(hasLeftNeighbour(dc)); if ( dc == dipoles().begin() ) return --dipoles().end(); return --dc; } bool DipoleChain::hasRightNeighbour (list::const_iterator dc) const { if (dc == --dipoles().end()) return circular(); return true; } Dipole& DipoleChain::rightNeighbour (list::iterator dc) { assert(hasRightNeighbour(dc)); if ( dc == --dipoles().end() ) return dipoles().front(); return *(++dc); } const Dipole& DipoleChain::rightNeighbour (list::const_iterator dc) const { assert(hasRightNeighbour(dc)); if ( dc == --dipoles().end() ) return dipoles().front(); return *(++dc); } list::iterator DipoleChain::rightNeighbourIterator(list::iterator dc) { assert(hasRightNeighbour(dc)); if ( dc == --dipoles().end() ) return dipoles().begin(); return ++dc; } void DipoleChain::check() { if ( theDipoles.begin() == boost::prior(theDipoles.end()) ) { if ( theDipoles.front().leftParticle()->hasColour() && theDipoles.front().leftParticle()->hasAntiColour() ) { assert(theDipoles.front().rightParticle()->hasColour() && theDipoles.front().rightParticle()->hasAntiColour()); ggSingleDipole = true; } } } list::iterator DipoleChain::insertSplitting(list::iterator emittingDipole, pair children, pair::iterator,list::iterator>& childIterators) { assert(DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle()) || DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle())); bool was_circular = circular(); if (hasLeftNeighbour(emittingDipole)) { list::iterator theLeftNeighbour = leftNeighbourIterator(emittingDipole); theLeftNeighbour->rightParticle(children.first.leftParticle()); if ( children.first.leftParticle()->scale() < sqr(theLeftNeighbour->rightScale()) ) theLeftNeighbour->rightScale(sqrt(children.first.leftParticle()->scale())); theLeftNeighbour->rightPDF(children.first.leftPDF()); theLeftNeighbour->rightFraction(children.first.leftFraction()); theLeftNeighbour->update(); } if (hasRightNeighbour(emittingDipole)) { list::iterator theRightNeighbour = rightNeighbourIterator(emittingDipole); theRightNeighbour->leftParticle(children.second.rightParticle()); if ( children.second.rightParticle()->scale() < sqr(theRightNeighbour->leftScale()) ) theRightNeighbour->leftScale(sqrt(children.second.rightParticle()->scale())); theRightNeighbour->leftPDF(children.second.rightPDF()); theRightNeighbour->leftFraction(children.second.rightFraction()); theRightNeighbour->update(); } if (DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle()) && DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle())) { // nothing special to do, just replace the emitting dipole // by the right one and insert the left one before it *emittingDipole = children.second; childIterators.second = emittingDipole; childIterators.first = dipoles().insert(emittingDipole,children.first); if ( ggSingleDipole ) { ggSingleDipole = false; Dipole miss; miss.leftParticle(dipoles().back().rightParticle()); miss.rightParticle(dipoles().front().leftParticle()); miss.leftScale(dipoles().back().rightScale()); miss.rightScale(dipoles().front().leftScale()); miss.leftPDF(dipoles().back().rightPDF()); miss.rightPDF(dipoles().front().leftPDF()); miss.leftFraction(dipoles().back().rightFraction()); miss.rightFraction(dipoles().front().leftFraction()); miss.update(); dipoles().push_back(miss); } return dipoles().end(); } if (!DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle())) { if ( !was_circular && !ggSingleDipole ) { *emittingDipole = children.second; childIterators.second = emittingDipole; assert(emittingDipole != dipoles().begin()); childIterators.first = boost::prior(emittingDipole); return emittingDipole; } *emittingDipole = children.second; if ( ggSingleDipole ) { ggSingleDipole = false; Dipole miss; miss.leftParticle(children.second.rightParticle()); miss.rightParticle(children.first.leftParticle()); miss.leftScale(children.second.rightScale()); miss.rightScale(children.first.leftScale()); miss.leftPDF(children.second.rightPDF()); miss.rightPDF(children.first.leftPDF()); miss.leftFraction(children.second.rightFraction()); miss.rightFraction(children.first.leftFraction()); miss.update(); dipoles().push_back(miss); childIterators.first = dipoles().begin(); childIterators.second = boost::prior(dipoles().end()); return dipoles().end(); } childIterators.second = emittingDipole; if ( emittingDipole == dipoles().begin() ) childIterators.first = --dipoles().end(); else childIterators.first = boost::prior(emittingDipole); if ( emittingDipole == dipoles().begin() ) return dipoles().end(); dipoles().splice(dipoles().begin(),dipoles(),emittingDipole,dipoles().end()); // explicitly fix iterators in case the splice implementation // at hand does invalidate iterators (the SGI docu says, it doesn't, // but it seems that this behaviour is not part of the standard) childIterators.second = dipoles().begin(); childIterators.first = --dipoles().end(); return dipoles().end(); } if (!DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle())) { if ( !was_circular && !ggSingleDipole ) { *emittingDipole = children.first; childIterators.first = emittingDipole; assert(emittingDipole != --dipoles().end()); childIterators.second = boost::next(emittingDipole); return boost::next(emittingDipole); } *emittingDipole = children.first; if ( ggSingleDipole ) { ggSingleDipole = false; Dipole miss; miss.leftParticle(children.second.rightParticle()); miss.rightParticle(children.first.leftParticle()); miss.leftScale(children.second.rightScale()); miss.rightScale(children.first.leftScale()); miss.leftPDF(children.second.rightPDF()); miss.rightPDF(children.first.leftPDF()); miss.leftFraction(children.second.rightFraction()); miss.rightFraction(children.first.leftFraction()); miss.update(); dipoles().push_front(miss); childIterators.first = dipoles().begin(); childIterators.second = boost::prior(dipoles().end()); return dipoles().end(); } childIterators.first = emittingDipole; if ( emittingDipole == --dipoles().end() ) childIterators.second = dipoles().begin(); else childIterators.second = boost::next(emittingDipole); if ( emittingDipole == --dipoles().end() ) return dipoles().end(); dipoles().splice(dipoles().begin(),dipoles(),boost::next(emittingDipole),dipoles().end()); // explicitly fix iterators in case the splice implementation // at hand does invalidate iterators (the SGI docu says, it doesn't, // but it seems that this behaviour is not part of the standard) childIterators.first = dipoles().begin(); childIterators.second = --dipoles().end(); return dipoles().end(); } return dipoles().end(); } void DipoleChain::updateDipole(list::iterator dip) { dip->update(); if (hasLeftNeighbour(dip)) { list::iterator theLeftNeighbour = leftNeighbourIterator(dip); theLeftNeighbour->rightParticle(dip->leftParticle()); theLeftNeighbour->rightPDF(dip->leftPDF()); theLeftNeighbour->rightFraction(dip->leftFraction()); theLeftNeighbour->update(); } if (hasRightNeighbour(dip)) { list::iterator theRightNeighbour = rightNeighbourIterator(dip); theRightNeighbour->leftParticle(dip->rightParticle()); theRightNeighbour->leftPDF(dip->rightPDF()); theRightNeighbour->leftFraction(dip->rightFraction()); theRightNeighbour->update(); } } void DipoleChain::print(ostream& os) const { os << "--- DipoleChain ----------------------------------------------------------------\n"; if ( theDipoles.empty() ) { os << " *** This DipoleChain is empty. ***\n"; } else { os << " " << (!circular() ? "non-" : "") << "circular with " << theDipoles.size() << " dipoles\n"; for (list::const_iterator dit = theDipoles.begin(); dit != theDipoles.end(); ++dit) { os << (*dit); } } os << "--------------------------------------------------------------------------------\n"; os << flush; } diff --git a/DipoleShower/Base/DipoleChain.h b/Shower/Dipole/Base/DipoleChain.h rename from DipoleShower/Base/DipoleChain.h rename to Shower/Dipole/Base/DipoleChain.h diff --git a/DipoleShower/Base/DipoleChainOrdering.cc b/Shower/Dipole/Base/DipoleChainOrdering.cc rename from DipoleShower/Base/DipoleChainOrdering.cc rename to Shower/Dipole/Base/DipoleChainOrdering.cc diff --git a/DipoleShower/Base/DipoleChainOrdering.h b/Shower/Dipole/Base/DipoleChainOrdering.h rename from DipoleShower/Base/DipoleChainOrdering.h rename to Shower/Dipole/Base/DipoleChainOrdering.h diff --git a/Shower/Dipole/Base/DipoleEventRecord.cc b/Shower/Dipole/Base/DipoleEventRecord.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Base/DipoleEventRecord.cc @@ -0,0 +1,814 @@ +// -*- C++ -*- +// +// DipoleEventRecord.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 DipoleEventRecord class. +// + +#include "DipoleEventRecord.h" +#include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" +#include "Herwig/Shower/ShowerHandler.h" + +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/PDF/PartonExtractor.h" + +#include + +#include + +using namespace Herwig; + +PList DipoleEventRecord::colourOrdered() { + + PList colour_ordered; + + size_t done_size = outgoing().size(); + if (incoming().first->coloured()) + ++done_size; + if (incoming().second->coloured()) + ++done_size; + + while (colour_ordered.size() != done_size) { + + PPtr current; + + // start with singlets, as long as we have some + + if (find(colour_ordered.begin(),colour_ordered.end(),incoming().first) == + colour_ordered.end() && incoming().first->coloured()) { + if (!incoming().first->hasColour() || !incoming().first->hasAntiColour()) + current = incoming().first; + } + + if (!current) { + for (PList::iterator p = outgoing().begin(); + p != outgoing().end(); ++p) { + if (find(colour_ordered.begin(),colour_ordered.end(),*p) == + colour_ordered.end() && (**p).coloured()) { + if (!(**p).hasColour() || !(**p).hasAntiColour()) { + current = *p; + break; + } + } + } + } + + if (!current) { + if (find(colour_ordered.begin(),colour_ordered.end(),incoming().second) == + colour_ordered.end() && incoming().second->coloured()) { + if (!incoming().second->hasColour() || !incoming().second->hasAntiColour()) + current = incoming().second; + } + } + + // then go on with anything else + + if (!current) { + if (find(colour_ordered.begin(),colour_ordered.end(),incoming().first) == + colour_ordered.end() && incoming().first->coloured()) { + current = incoming().first; + } + } + + if (!current) { + for (PList::iterator p = outgoing().begin(); + p != outgoing().end(); ++p) { + if (find(colour_ordered.begin(),colour_ordered.end(),*p) == + colour_ordered.end() && (**p).coloured()) { + current = *p; + break; + } + } + } + + if (!current) { + if (find(colour_ordered.begin(),colour_ordered.end(),incoming().second) == + colour_ordered.end() && incoming().second->coloured()) { + current = incoming().second; + } + } + + assert(current); + + PPtr next; + Ptr::ptr walk_the_line; + + while (true) { + + if (!walk_the_line) { + if (current->hasColour()) { + walk_the_line = current->colourLine(); + } + else if (current->hasAntiColour()) { + walk_the_line = current->antiColourLine(); + } + } + + if (!next) + for (tPVector::const_iterator p = walk_the_line->coloured().begin(); + p != walk_the_line->coloured().end(); ++p) { + if (*p == current) + continue; + if (find(outgoing().begin(),outgoing().end(),*p) != outgoing().end() || + *p == incoming().first || + *p == incoming().second) { + next = *p; + if (next->hasColour() && next->hasAntiColour()) { + walk_the_line = walk_the_line == next->colourLine() ? next->antiColourLine() : next->colourLine(); + } + break; + } + } + + if (!next) + for (tPVector::const_iterator p = walk_the_line->antiColoured().begin(); + p != walk_the_line->antiColoured().end(); ++p) { + if (*p == current) + continue; + if (find(outgoing().begin(),outgoing().end(),*p) != outgoing().end() || + *p == incoming().first || + *p == incoming().second) { + next = *p; + if (next->hasColour() && next->hasAntiColour()) { + walk_the_line = walk_the_line == next->colourLine() ? next->antiColourLine() : next->colourLine(); + } + break; + } + } + + assert(next); + + colour_ordered.push_back(current); + current = next; + + // done if next is not a gluon or next is already in colour_ordered + + if ((current->hasColour() && !current->hasAntiColour()) || + (!current->hasColour() && current->hasAntiColour())) { + colour_ordered.push_back(current); + break; + } + + if (next->hasColour() && next->hasAntiColour()) { + if (find(colour_ordered.begin(),colour_ordered.end(),next) != colour_ordered.end()) + break; + } + + next = PPtr(); + + } + + } + + return colour_ordered; + +} + +void DipoleEventRecord::popChain() { + assert(!theChains.empty()); + theDoneChains.push_back(DipoleChain()); + theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),theChains.front().dipoles()); + theChains.pop_front(); +} + +void DipoleEventRecord::popChain(list::iterator ch) { + assert(!theChains.empty()); + theDoneChains.push_back(DipoleChain()); + theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),ch->dipoles()); + theChains.erase(ch); +} + +void DipoleEventRecord::popChains(const list::iterator>& chs) { + + assert(!theChains.empty()); + + for ( list::iterator>::const_iterator ch = + chs.begin(); ch != chs.end(); ++ch ) { + theDoneChains.push_back(DipoleChain()); + theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),(*ch)->dipoles()); + } + + for ( list::iterator>::const_iterator ch = + chs.begin(); ch != chs.end(); ++ch ) + theChains.erase(*ch); + +} + +DipoleIndex +DipoleEventRecord::mergeIndex(list::iterator firstDipole, const pair& whichFirst, + list::iterator secondDipole, const pair& whichSecond) const { + tcPDPtr emitterData = + whichFirst.first ? firstDipole->leftParticle()->dataPtr() : firstDipole->rightParticle()->dataPtr(); + tcPDPtr spectatorData = + whichSecond.first ? secondDipole->leftParticle()->dataPtr() : secondDipole->rightParticle()->dataPtr(); + const PDF& emitterPDF = + whichFirst.first ? firstDipole->leftPDF() : firstDipole->rightPDF(); + const PDF& spectatorPDF = + whichSecond.first ? secondDipole->leftPDF() : secondDipole->rightPDF(); + return DipoleIndex(emitterData,spectatorData,emitterPDF,spectatorPDF); +} + + +SubleadingSplittingInfo +DipoleEventRecord::mergeSplittingInfo(list::iterator firstChain, list::iterator firstDipole, + const pair& whichFirst, + list::iterator secondChain, list::iterator secondDipole, + const pair& whichSecond) const { + SubleadingSplittingInfo res; + res.index(mergeIndex(firstDipole,whichFirst,secondDipole,whichSecond)); + res.emitter(whichFirst.first ? firstDipole->leftParticle() : firstDipole->rightParticle()); + res.spectator(whichSecond.first ? secondDipole->leftParticle() : secondDipole->rightParticle()); + res.emitterX(whichFirst.first ? firstDipole->leftFraction() : firstDipole->rightFraction()); + res.spectatorX(whichSecond.first ? secondDipole->leftFraction() : secondDipole->rightFraction()); + res.configuration(whichFirst); + res.spectatorConfiguration(whichSecond); + res.emitterChain(firstChain); + res.emitterDipole(firstDipole); + res.spectatorChain(secondChain); + res.spectatorDipole(secondDipole); + return res; +} + +void DipoleEventRecord::getSubleadingSplittings(list& res) { + static pair left(true,false); + static pair right(false,true); + res.clear(); + for ( list::iterator cit = theChains.begin(); + cit != theChains.end(); ++cit ) { + for ( list::iterator dit = cit->dipoles().begin(); + dit != cit->dipoles().end(); ++dit ) { + for ( list::iterator djt = dit; + djt != cit->dipoles().end(); ++djt ) { + res.push_back(mergeSplittingInfo(cit,dit,left,cit,djt,left)); + res.push_back(mergeSplittingInfo(cit,dit,right,cit,djt,right)); + if ( dit != djt ) { + res.push_back(mergeSplittingInfo(cit,dit,left,cit,djt,right)); + res.push_back(mergeSplittingInfo(cit,dit,right,cit,djt,left)); + } + } + } + list::iterator cjt = cit; ++cjt; + for ( ; cjt != theChains.end(); ++cjt ) { + for ( list::iterator dit = cit->dipoles().begin(); + dit != cit->dipoles().end(); ++dit ) { + for ( list::iterator djt = cjt->dipoles().begin(); + djt != cjt->dipoles().end(); ++djt ) { + res.push_back(mergeSplittingInfo(cit,dit,left,cjt,djt,left)); + res.push_back(mergeSplittingInfo(cit,dit,right,cjt,djt,right)); + res.push_back(mergeSplittingInfo(cit,dit,left,cjt,djt,right)); + res.push_back(mergeSplittingInfo(cit,dit,right,cjt,djt,left)); + } + } + } + } +} + +void DipoleEventRecord::splitSubleading(SubleadingSplittingInfo& dsplit, + pair::iterator,list::iterator>& childIterators, + DipoleChain*& firstChain, DipoleChain*& secondChain) { + if ( dsplit.emitterDipole() == dsplit.spectatorDipole() ) { + assert(dsplit.emitterChain() == dsplit.spectatorChain()); + split(dsplit.emitterDipole(),dsplit.emitterChain(),dsplit, + childIterators,firstChain,secondChain,false); + } else { + // first need to recoil, then split + recoil(dsplit.spectatorDipole(),dsplit.spectatorChain(),dsplit); + split(dsplit.emitterDipole(),dsplit.emitterChain(),dsplit, + childIterators,firstChain,secondChain,true); + } +} + +void DipoleEventRecord::findChains(const PList& ordered) { + + theChains.clear(); + theDoneChains.clear(); + + DipoleChain current_chain; + + // this whole thing needs to have a more elegant implementation at some point + + bool startIsTriplet = + (ordered.front()->hasColour() && !ordered.front()->hasAntiColour()) || + (!ordered.front()->hasColour() && ordered.front()->hasAntiColour()); + bool endIsTriplet = + (ordered.back()->hasColour() && !ordered.back()->hasAntiColour()) || + (!ordered.back()->hasColour() && ordered.back()->hasAntiColour()); + + bool is33bar = + ordered.size() == 2 && startIsTriplet && endIsTriplet; + + if (!is33bar) { + + PList::const_iterator theStart = ordered.begin(); + bool onceMore = false; + + for (PList::const_iterator p = ordered.begin(); + p != ordered.end(); ++p) { + + PList::const_iterator next_it = + p != --ordered.end() ? boost::next(p) : ordered.begin(); + + if (!DipolePartonSplitter::colourConnected(*p,*next_it)) { + // it may have happened that we need to close the chain due to another + // chain starting right now; see the above global comment for this fix + bool startIsOctet = + (**theStart).hasColour() && (**theStart).hasAntiColour(); + bool endIsOctet = + (**p).hasColour() && (**p).hasAntiColour(); + if ( DipolePartonSplitter::colourConnected(*p,*theStart) && + startIsOctet && endIsOctet ) { + swap(next_it,theStart); + onceMore = true; + } else { + theStart = next_it; + current_chain.check(); + theChains.push_back(current_chain); + current_chain.dipoles().clear(); + continue; + } + } + + pair initial_state (false,false); + initial_state.first = (*p == incoming().first || *p == incoming().second); + initial_state.second = (*next_it == incoming().first || *next_it == incoming().second); + + pair which_in (-1,-1); + if (initial_state.first) + which_in.first = *p == incoming().first ? 0 : 1; + if (initial_state.second) + which_in.second = *next_it == incoming().first ? 0 : 1; + + pair xs (1.,1.); + if (initial_state.first) + xs.first = *p == incoming().first ? fractions().first : fractions().second; + if (initial_state.second) + xs.second = *next_it == incoming().first ? fractions().first : fractions().second; + + pair pdf; + + if ( which_in.first == 0 ) + pdf.first = pdfs().first; + else if ( which_in.first == 1 ) + pdf.first = pdfs().second; + + if ( which_in.second == 0 ) + pdf.second = pdfs().first; + else if ( which_in.second == 1 ) + pdf.second = pdfs().second; + + current_chain.dipoles().push_back(Dipole(make_pair(*p,*next_it),pdf,xs)); + + if ( onceMore ) { + next_it = theStart; + current_chain.check(); + theChains.push_back(current_chain); + current_chain.dipoles().clear(); + onceMore = false; + } + + } + } else { + + // treat 2 -> singlet, singlet -> 2 and 1 + singlet -> 1 + singlet special + // to prevent duplicate dipole + + assert(DipolePartonSplitter::colourConnected(ordered.front(),ordered.back())); + + pair initial_state (false,false); + initial_state.first = (ordered.front() == incoming().first || ordered.front() == incoming().second); + initial_state.second = (ordered.back() == incoming().first || ordered.back() == incoming().second); + + pair which_in (-1,-1); + if (initial_state.first) + which_in.first = ordered.front() == incoming().first ? 0 : 1; + if (initial_state.second) + which_in.second = ordered.back() == incoming().first ? 0 : 1; + + pair xs (1.,1.); + if (initial_state.first) + xs.first = ordered.front() == incoming().first ? fractions().first : fractions().second; + if (initial_state.second) + xs.second = ordered.back() == incoming().first ? fractions().first : fractions().second; + + pair pdf; + + if ( which_in.first == 0 ) + pdf.first = pdfs().first; + else if ( which_in.first == 1 ) + pdf.first = pdfs().second; + + if ( which_in.second == 0 ) + pdf.second = pdfs().first; + else if ( which_in.second == 1 ) + pdf.second = pdfs().second; + + current_chain.dipoles().push_back(Dipole(make_pair(ordered.front(),ordered.back()),pdf,xs)); + + } + + if (!current_chain.dipoles().empty()) { + current_chain.check(); + theChains.push_back(current_chain); + } + +} + +void DipoleEventRecord::getAll(const ParticleVector& childs, + set& hardSet, + set& outgoingSet) { + + for ( ParticleVector::const_iterator p = childs.begin(); + p != childs.end(); ++p ) { + if ( ShowerHandler::currentHandler()->eventHandler()->currentCollision()->isRemnant(*p) ) + continue; + if ( (**p).children().empty() ) { + if ( (**p).coloured() && + outgoingSet.find(*p) == outgoingSet.end() ) + outgoingSet.insert(*p); + else if ( !(**p).coloured() && + hardSet.find(*p) == hardSet.end() ) + hardSet.insert(*p); + } else { + getAll((**p).children(),hardSet,outgoingSet); + } + } + +} + +const map& +DipoleEventRecord::prepare(tSubProPtr subpro, + tStdXCombPtr xc, + const pair& pdf, + bool dipoles) { + + subProcess(subpro); + + outgoing().clear(); + theHard.clear(); + theOriginals.clear(); + + PPair in = subpro->incoming(); + + assert(ShowerHandler::currentHandler()); + tPPair beam = ShowerHandler::currentHandler()->generator()->currentEvent()->incoming(); + + // don't take these from the XComb as it may be null + pair xs; + ThePEG::Direction<0> dir(true); + xs.first = in.first->momentum().dirPlus()/beam.first->momentum().dirPlus(); + dir.reverse(); + xs.second = in.second->momentum().dirPlus()/beam.second->momentum().dirPlus(); + + xcombPtr(xc); + pdfs() = pdf; + fractions() = xs; + + set allHard; + set allOutgoing; + + getAll(in.first->children(),allHard,allOutgoing); + getAll(in.second->children(),allHard,allOutgoing); + + vector original; + vector copies; + original.push_back(in.first); + original.push_back(in.second); + copy(allOutgoing.begin(),allOutgoing.end(),back_inserter(original)); + for ( vector::const_iterator p = original.begin(); + p != original.end(); ++p ) { + PPtr copy = new_ptr(Particle(**p)); + copies.push_back(copy); + theOriginals[*p] = copy; + } + + colourIsolate(original,copies); + + incoming().first = copies[0]; + ParticleVector children = incoming().first->children(); + for ( ParticleVector::const_iterator c = children.begin(); + c != children.end(); ++c ) + incoming().first->abandonChild(*c); + incoming().second = copies[1]; + children = incoming().second->children(); + for ( ParticleVector::const_iterator c = children.begin(); + c != children.end(); ++c ) + incoming().second->abandonChild(*c); + copy(copies.begin()+2,copies.end(),back_inserter(outgoing())); + + for ( set::const_iterator p = allHard.begin(); p != allHard.end(); ++p ) { + PPtr copy = new_ptr(Particle(**p)); + theHard.push_back(copy); + theOriginals[*p] = copy; + } + + if ( dipoles ) { + PList cordered = colourOrdered(); + findChains(cordered); + } + + PList::const_iterator XFirst, XLast; + + if ( !theHard.empty() ) { + XFirst = theHard.begin(); + XLast = theHard.end(); + } else { + XFirst = outgoing().begin(); + XLast = outgoing().end(); + } + + thePX = (**XFirst).momentum(); + ++XFirst; + for ( ; XFirst != XLast; ++XFirst ) + thePX += (**XFirst).momentum(); + identifyEventType(); + return theOriginals; + +} + +void DipoleEventRecord::clear() { + ShowerEventRecord::clear(); + theHard.clear(); + theChains.clear(); + theDoneChains.clear(); + theOriginals.clear(); +} + +void DipoleEventRecord::update(DipoleSplittingInfo& dsplit) { + + if ( incoming().first == dsplit.emitter() ) { + intermediates().push_back(dsplit.emitter()); + incoming().first = dsplit.splitEmitter(); + fractions().first /= dsplit.lastEmitterZ(); + } else if ( incoming().first == dsplit.spectator() ) { + intermediates().push_back(dsplit.spectator()); + incoming().first = dsplit.splitSpectator(); + fractions().first /= dsplit.lastSpectatorZ(); + } + + if ( incoming().second == dsplit.emitter() ) { + intermediates().push_back(dsplit.emitter()); + incoming().second = dsplit.splitEmitter(); + fractions().second /= dsplit.lastEmitterZ(); + } else if ( incoming().second == dsplit.spectator() ) { + intermediates().push_back(dsplit.spectator()); + incoming().second = dsplit.splitSpectator(); + fractions().second /= dsplit.lastSpectatorZ(); + } + + PList::iterator pos; + + pos = find(outgoing().begin(), outgoing().end(), dsplit.emitter()); + if (pos != outgoing().end()) { + intermediates().push_back(*pos); + *pos = dsplit.splitEmitter(); + } + + pos = find(outgoing().begin(), outgoing().end(), dsplit.spectator()); + if (pos != outgoing().end()) { + intermediates().push_back(*pos); + *pos = dsplit.splitSpectator(); + } + + outgoing().push_back(dsplit.emission()); + + if (dsplit.splittingKinematics()->doesTransform()) { + + for (PList::iterator p = intermediates().begin(); + p != intermediates().end(); ++p) { + (**p).set5Momentum(dsplit.splittingKinematics()->transform((**p).momentum())); + } + + for (PList::iterator h = theHard.begin(); + h != theHard.end(); ++h) { + (**h).set5Momentum(dsplit.splittingKinematics()->transform((**h).momentum())); + } + + for (PList::iterator p = outgoing().begin(); + p != outgoing().end(); ++p) + if ((*p) != dsplit.splitEmitter() && + (*p) != dsplit.splitSpectator() && + (*p) != dsplit.emission()) + (**p).set5Momentum(dsplit.splittingKinematics()->transform((**p).momentum())); + + } + +} + +void +DipoleEventRecord::split(list::iterator dip, + list::iterator ch, + DipoleSplittingInfo& dsplit, + pair::iterator,list::iterator>& childIterators, + DipoleChain*& firstChain, DipoleChain*& secondChain, + bool colourSpectator) { + + static DipoleChain empty; + + pair children = dip->split(dsplit,colourSpectator); + + list::iterator breakup = + ch->insertSplitting(dip,children,childIterators); + + if ( breakup == ch->dipoles().end() ) { + firstChain = &(*ch); + secondChain = ∅ + } else { + + DipoleChain other; + other.dipoles().splice(other.dipoles().end(),ch->dipoles(),breakup,ch->dipoles().end()); + + chains().push_back(other); + firstChain = &(*ch); + secondChain = &(chains().back()); + + // explicitly fix iterators in case the splice implementation + // at hand does invalidate iterators (the SGI docu says, it doesn't, + // but it seems that this behaviour is not part of the standard) + childIterators.first = --firstChain->dipoles().end(); + childIterators.second = secondChain->dipoles().begin(); + + } + + if ( !colourSpectator ) + update(dsplit); // otherwise done by recoil(...) + +} + +void DipoleEventRecord::recoil(list::iterator dip, + list::iterator ch, + DipoleSplittingInfo& dsplit) { + + dip->recoil(dsplit); + ch->updateDipole(dip); + + update(dsplit); + +} + +list::iterator,list::iterator> > +DipoleEventRecord::inDipoles() { + + list::iterator,list::iterator> > res; + + for ( list::iterator chit = theDoneChains.begin(); + chit != theDoneChains.end(); ++chit ) { + + bool haveOne = false; + + for ( list::iterator dit = chit->dipoles().begin(); + dit != chit->dipoles().end(); ++dit ) { + if ( dit->leftPDF().pdf() || dit->rightPDF().pdf() ) { + haveOne = true; + break; + } + } + + if ( haveOne ) { + theChains.splice(theChains.begin(),theDoneChains,chit); + for ( list::iterator dit = theChains.front().dipoles().begin(); + dit != theChains.front().dipoles().end(); ++dit ) { + if ( dit->leftPDF().pdf() || dit->rightPDF().pdf() ) { + res.push_back(make_pair(dit,theChains.begin())); + } + } + } + + } + + return res; + +} + +void DipoleEventRecord::transform(const SpinOneLorentzRotation& rot) { + + + Lorentz5Momentum tmp; + + for (PList::iterator p = intermediates().begin(); + p != intermediates().end(); ++p) { + tmp = (**p).momentum(); tmp = rot * tmp; + (**p).set5Momentum(tmp); + } + + for (PList::iterator h = theHard.begin(); + h != theHard.end(); ++h) { + tmp = (**h).momentum(); tmp = rot * tmp; + (**h).set5Momentum(tmp); + } + + for (PList::iterator p = outgoing().begin(); + p != outgoing().end(); ++p) { + tmp = (**p).momentum(); tmp = rot * tmp; + (**p).set5Momentum(tmp); + } + +} + +tPPair DipoleEventRecord::fillEventRecord(StepPtr step, bool firstInteraction, bool) { + + PPtr inSubPro = subProcess()->incoming().first; + PPtr inParticle; + if ( !(inSubPro->parents().empty()) ) + inParticle = inSubPro->parents()[0]; + else + inParticle = inSubPro; + PPtr inParton = theOriginals[inSubPro]; + theOriginals.erase(inSubPro); + updateColour(incoming().first,true); + if ( inParticle != inSubPro ) + inParticle->abandonChild(inSubPro); + inParton->addChild(inSubPro); + if ( inParticle != inSubPro ) + inParticle->addChild(incoming().first); + intermediates().push_back(inSubPro); + intermediates().push_back(inParton); + + inSubPro = subProcess()->incoming().second; + if ( !(inSubPro->parents().empty()) ) + inParticle = inSubPro->parents()[0]; + else + inParticle = inSubPro; + inParton = theOriginals[inSubPro]; + theOriginals.erase(inSubPro); + updateColour(incoming().second,true); + if ( inParticle != inSubPro ) + inParticle->abandonChild(inSubPro); + inParton->addChild(inSubPro); + if ( inParticle != inSubPro ) + inParticle->addChild(incoming().second); + intermediates().push_back(inSubPro); + intermediates().push_back(inParton); + + while ( !theOriginals.empty() ) { + PPtr outSubPro = theOriginals.begin()->first; + PPtr outParton = theOriginals.begin()->second; + // workaround for OS X Mavericks LLVM libc++ +#ifdef _LIBCPP_VERSION + map::const_iterator beg = theOriginals.begin(); +#else + map::iterator beg = theOriginals.begin(); +#endif + theOriginals.erase(beg); + updateColour(outParton,true); + outSubPro->addChild(outParton); + intermediates().push_back(outSubPro); + } + + step->addIntermediates(intermediates().begin(),intermediates().end()); + + for (PList::const_iterator p = outgoing().begin(); + p != outgoing().end(); ++p) + step->addDecayProduct(*p); + + for (PList::const_iterator p = theHard.begin(); + p != theHard.end(); ++p) + step->addDecayProduct(*p); + + if ( firstInteraction && + (incoming().first->coloured() || + incoming().second->coloured() ) ) { + ShowerHandler::currentHandler()->lastExtractor()->newRemnants(subProcess()->incoming(),incoming(),step); + } + + step->addIntermediate(incoming().first); + step->addIntermediate(incoming().second); + + return incoming(); + +} + +void DipoleEventRecord::debugLastEvent(ostream& os) const { + + bool first = ShowerHandler::currentHandler()->firstInteraction(); + + os << "--- DipoleEventRecord ----------------------------------------------------------\n"; + + os << " the " << (first ? "hard" : "secondary") << " subprocess is:\n" + << (*subProcess()); + + os << " using PDF's " << pdfs().first.pdf() << " and " + << pdfs().second.pdf() << "\n"; + + os << " chains showering currently:\n"; + + for ( list::const_iterator chit = theChains.begin(); + chit != theChains.end(); ++chit ) + os << (*chit); + + os << " chains which finished showering:\n"; + + for ( list::const_iterator chit = theDoneChains.begin(); + chit != theDoneChains.end(); ++chit ) + os << (*chit); + + os << "--------------------------------------------------------------------------------\n"; + + os << flush; + +} diff --git a/Shower/Dipole/Base/DipoleEventRecord.h b/Shower/Dipole/Base/DipoleEventRecord.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Base/DipoleEventRecord.h @@ -0,0 +1,387 @@ +// -*- C++ -*- +// +// DipoleEventRecord.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_DipoleEventRecord_H +#define HERWIG_DipoleEventRecord_H +// +// This is the declaration of the DipoleEventRecord class. +// + +#include "Herwig/Shower/ShowerEventRecord.h" +#include "ThePEG/PDF/PDF.h" +#include "ThePEG/Handlers/StandardXComb.h" +#include "Dipole.h" +#include "DipoleChain.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * \ingroup DipoleShower + * \author Simon Platzer + * + * \brief Generalized dipole splitting info to deal with subleading-N + * splittings. + */ +class SubleadingSplittingInfo + : public DipoleSplittingInfo { + +public: + + /** + * Default constructor + */ + SubleadingSplittingInfo() + : DipoleSplittingInfo() {} + + /** + * Get the iterator of the emitter dipole chain + */ + list::iterator emitterChain() const { return theEmitterChain; } + + /** + * Get the iterator of the emitter dipole + */ + list::iterator emitterDipole() const { return theEmitterDipole; } + + /** + * Get the iterator of the spectator dipole chain + */ + list::iterator spectatorChain() const { return theSpectatorChain; } + + /** + * Get the iterator of the spectator dipole + */ + list::iterator spectatorDipole() const { return theSpectatorDipole; } + + /** + * Get the starting scale + */ + Energy startScale() const { return theStartScale; } + + /** + * Set the iterator of the emitter dipole chain + */ + void emitterChain(list::iterator it) { theEmitterChain = it; } + + /** + * Set the iterator of the emitter dipole + */ + void emitterDipole(list::iterator it) { theEmitterDipole = it; } + + /** + * Set the iterator of the spectator dipole chain + */ + void spectatorChain(list::iterator it) { theSpectatorChain = it; } + + /** + * Set the iterator of the spectator dipole + */ + void spectatorDipole(list::iterator it) { theSpectatorDipole = it; } + + /** + * Set the starting scale + */ + void startScale(Energy s) { theStartScale = s; } + +private: + + /** + * Iterator of the emitter dipole chain + */ + list::iterator theEmitterChain; + + /** + * Iterator of the emitter dipole + */ + list::iterator theEmitterDipole; + + /** + * Iterator of the spectator dipole chain + */ + list::iterator theSpectatorChain; + + /** + * Iterator of the spectator dipole + */ + list::iterator theSpectatorDipole; + + /** + * The starting scale + */ + Energy theStartScale; + +}; + +/** + * \ingroup DipoleShower + * \author Simon Platzer + * + * \brief The DipoleEventRecord class is + * used internally by the dipole shower. + */ +class DipoleEventRecord : public ShowerEventRecord { + +public: + + /** + * The default constructor. + */ + DipoleEventRecord() {} + + /** + * The default destructor just cleans up. + */ + ~DipoleEventRecord() { clear(); } + +public: + + /** + * Return any non-coloured outgoing particles in the + * current subprocess. + */ + PList& hard() { return theHard; } + + /** + * Return any non-coloured outgoing particles in the + * current subprocess. + */ + const PList& hard() const { return theHard; } + + /** + * Return the momentum of the hard system + */ + const Lorentz5Momentum& pX() const { return thePX; } + + /** + * Transform all intermediate, hard and outgoing + * partciles using the given transformation. + */ + void transform(const SpinOneLorentzRotation& rot); + +public: + + /** + * Return the dipole chains to be showered. + */ + const list& chains() const { return theChains; } + + /** + * Access the dipole chains to be showered. + */ + list& chains() { return theChains; } + + /** + * Return the dipole chains which ceased evolving. + */ + const list& doneChains() const { return theDoneChains; } + + /** + * Access the dipole chains which ceased evolving. + */ + list& doneChains() { return theDoneChains; } + + /** + * Return true, if there are chains to be + * showered. + */ + bool haveChain() const { return !theChains.empty(); } + + /** + * Return the current dipole chain + */ + DipoleChain& currentChain() { assert(haveChain()); return theChains.front(); } + + /** + * Pop the current dipole chain + */ + void popChain(); + + /** + * Remove the given chain. + */ + void popChain(list::iterator); + + /** + * Remove the given chains. + */ + void popChains(const list::iterator>&); + + /** + * Create a merged dipole index given two independent dipoles; + * the first dipole is to provide the emitter. + */ + DipoleIndex + mergeIndex(list::iterator firstDipole, const pair& whichFirst, + list::iterator secondDipole, const pair& whichSecond) const; + + /** + * Create a SubleadingSplitingInfo given two independent dipoles; + * the first dipole is to provide the emitter. + */ + SubleadingSplittingInfo + mergeSplittingInfo(list::iterator firstChain, list::iterator firstDipole, + const pair& whichFirst, + list::iterator secondChain, list::iterator secondDipole, + const pair& whichSecond) const; + + /** + * Return a list of all possible subleading-N emitting pairs + */ + void getSubleadingSplittings(list&); + +public: + + /** + * Split the dipole pointed to by the given iterator. + * Return references to the affected chains, and update + * iterators pointing to the children in the returned + * chains. + */ + + void split(list::iterator dip, + DipoleSplittingInfo& dsplit, + pair::iterator,list::iterator>& childIterators, + DipoleChain*& firstChain, DipoleChain*& secondChain) { + split(dip,theChains.begin(),dsplit,childIterators,firstChain,secondChain,false); + } + + /** + * Split the dipole pointed to by the given iterator + * in the indicated chain, indicating a splitting with + * a colour spectator. + * Return references to the affected chains, and update + * iterators pointing to the children in the returned + * chains. + */ + void split(list::iterator dip, + list::iterator ch, + DipoleSplittingInfo& dsplit, + pair::iterator,list::iterator>& childIterators, + DipoleChain*& firstChain, DipoleChain*& secondChain, + bool colourSpectator = true); + + /** + * Let the given dipole take the recoil of + * the indicated splitting. + */ + void recoil(list::iterator dip, + list::iterator ch, + DipoleSplittingInfo& dsplit); + + /** + * Peform a subleading-N splitting + */ + void splitSubleading(SubleadingSplittingInfo& dsplit, + pair::iterator,list::iterator>& childIterators, + DipoleChain*& firstChain, DipoleChain*& secondChain); + + /** + * Update the particles upon insertion of the + * given splitting. + */ + void update(DipoleSplittingInfo& dsplit); + + /** + * Return the dipole(s) containing the incoming + * partons after the evolution has ended. Put back + * the chains containing these to the chains to be + * showered. + */ + list::iterator,list::iterator> > + inDipoles(); + + /** + * Fill the given step and return incoming partons. + */ + tPPair fillEventRecord(StepPtr step, bool firstInteraction, bool realigned); + +public: + + /** + * Prepare the event record for the given + * subprocess. + */ + const map& prepare(tSubProPtr subpro, + tStdXCombPtr xc, + const pair& pdf, + bool dipoles = true); + + /** + * Clear the event record: Give up ownership + * on any object involved in the evolution. + */ + virtual void clear(); + +public: + + /** + * Print event record at current state. + */ + void debugLastEvent(ostream&) const; + +protected: + + /** + * Sort the coloured partons into a colour ordered ensemble. + */ + PList colourOrdered(); + + /** + * Find the chains to be showered. + */ + void findChains(const PList& ordered); + + /** + * Add all particles to the relevant sets + */ + void getAll(const ParticleVector& childs, + set& hardSet, + set& outgoingSet); + +private: + + struct getMomentum { + const Lorentz5Momentum& operator() (PPtr particle) const { + return particle->momentum(); + } + }; + + /** + * The momentum of the hard system + */ + Lorentz5Momentum thePX; + + /** + * Any non-coloured outgoing particles in the + * current subprocess. + */ + PList theHard; + + /** + * Map originals to copies. + */ + map theOriginals; + + /** + * The dipole chains currently showered. + */ + list theChains; + + /** + * The dipole chains which ceased evolving. + */ + list theDoneChains; + +}; + + +} + +#endif /* HERWIG_DipoleEventRecord_H */ diff --git a/DipoleShower/Base/DipoleEventReweight.cc b/Shower/Dipole/Base/DipoleEventReweight.cc rename from DipoleShower/Base/DipoleEventReweight.cc rename to Shower/Dipole/Base/DipoleEventReweight.cc diff --git a/DipoleShower/Base/DipoleEventReweight.h b/Shower/Dipole/Base/DipoleEventReweight.h rename from DipoleShower/Base/DipoleEventReweight.h rename to Shower/Dipole/Base/DipoleEventReweight.h diff --git a/DipoleShower/Base/DipoleEvolutionOrdering.cc b/Shower/Dipole/Base/DipoleEvolutionOrdering.cc rename from DipoleShower/Base/DipoleEvolutionOrdering.cc rename to Shower/Dipole/Base/DipoleEvolutionOrdering.cc diff --git a/DipoleShower/Base/DipoleEvolutionOrdering.h b/Shower/Dipole/Base/DipoleEvolutionOrdering.h rename from DipoleShower/Base/DipoleEvolutionOrdering.h rename to Shower/Dipole/Base/DipoleEvolutionOrdering.h --- a/DipoleShower/Base/DipoleEvolutionOrdering.h +++ b/Shower/Dipole/Base/DipoleEvolutionOrdering.h @@ -1,184 +1,184 @@ // -*- C++ -*- // // DipoleEvolutionOrdering.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_DipoleEvolutionOrdering_H #define HERWIG_DipoleEvolutionOrdering_H // // This is the declaration of the DipoleEvolutionOrdering class. // #include "ThePEG/Handlers/HandlerBase.h" -#include "Herwig/DipoleShower/Base/Dipole.h" -#include "Herwig/DipoleShower/Base/DipoleChain.h" -#include "Herwig/DipoleShower/Kernels/DipoleSplittingKernel.h" +#include "Herwig/Shower/Dipole/Base/Dipole.h" +#include "Herwig/Shower/Dipole/Base/DipoleChain.h" +#include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleEvolutionOrdering defines a particular evolution * algortihm for the dipole shower. * */ class DipoleEvolutionOrdering: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DipoleEvolutionOrdering(); /** * The destructor. */ virtual ~DipoleEvolutionOrdering(); //@} public: /** * Return true, if this ordering requests * an independent dipole evolution. */ virtual bool independentDipoles() const { return false; } /** * For the given dipole and splitting kernel return * the hard scale. */ virtual Energy hardScale(tPPtr emitter, tPPtr spectator, double emitterX, double spectatorX, const DipoleSplittingKernel&, const DipoleIndex&) const = 0; /** * For the given performed splitting, dipole chain * and dipoles originating from the splitting, set the next * scale. */ virtual void setEvolutionScale(Energy scale, const DipoleSplittingInfo&, DipoleChain&, pair::iterator,list::iterator>) const = 0; /** * For the given performed splitting, dipole chain * and dipole taking a recoil, set the next * scale. */ virtual void setEvolutionScale(Energy scale, const DipoleSplittingInfo&, DipoleChain&, list::iterator) const = 0; /** * For the given selected splitting return the evolution scale. */ virtual Energy evolutionScale(const DipoleSplittingInfo&, const DipoleSplittingKernel&) const = 0; /** * Return the maximum pt corresponding to the given * evolution scale. */ virtual Energy maxPt(Energy scale, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const = 0; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initDipoleEvolutionOrdering; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleEvolutionOrdering & operator=(const DipoleEvolutionOrdering &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleEvolutionOrdering. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleEvolutionOrdering. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleEvolutionOrdering 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::DipoleEvolutionOrdering"; } /** * The name of a file containing the dynamic library where the class * DipoleEvolutionOrdering is implemented. It may also include several, space-separated, * libraries if the class DipoleEvolutionOrdering 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_DipoleEvolutionOrdering_H */ diff --git a/Shower/Dipole/Base/DipoleSplittingGenerator.cc b/Shower/Dipole/Base/DipoleSplittingGenerator.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Base/DipoleSplittingGenerator.cc @@ -0,0 +1,606 @@ +// -*- 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/Shower/Dipole/DipoleShowerHandler.h" + +using namespace Herwig; + +DipoleSplittingGenerator::DipoleSplittingGenerator() + : HandlerBase(), + theExponentialGenerator(0), prepared(false), presampling(false), + theDoCompensate(false), theSplittingWeight(1.) { + if ( ShowerHandler::currentHandler() ) + setGenerator(ShowerHandler::currentHandler()->generator()); +} + +DipoleSplittingGenerator::~DipoleSplittingGenerator() { + if ( theExponentialGenerator ) { + delete theExponentialGenerator; + theExponentialGenerator = 0; + } +} + +IBPtr DipoleSplittingGenerator::clone() const { + return new_ptr(*this); +} + +IBPtr DipoleSplittingGenerator::fullclone() const { + return new_ptr(*this); +} + +void DipoleSplittingGenerator::wrap(Ptr::ptr other) { + assert(!prepared); + theOtherGenerator = other; +} + +void DipoleSplittingGenerator::resetVariations() { + for ( map::iterator w = currentWeights.begin(); + w != currentWeights.end(); ++w ) + w->second = 1.; +} + +void DipoleSplittingGenerator::veto(const vector&, double p, double r) { + double factor = 1.; + if ( splittingReweight() ) { + if ( ( ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->firstInteraction() ) || + ( !ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->secondaryInteractions() ) ) { + factor = splittingReweight()->evaluate(generatedSplitting); + theSplittingWeight *= (r-factor*p)/(r-p); + } + } + splittingKernel()->veto(generatedSplitting, factor*p, r, currentWeights); +} + +void DipoleSplittingGenerator::accept(const vector&, double p, double r) { + double factor = 1.; + if ( splittingReweight() ) { + if ( ( ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->firstInteraction() ) || + ( !ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->secondaryInteractions() ) ) { + factor = splittingReweight()->evaluate(generatedSplitting); + theSplittingWeight *= factor; + } + } + splittingKernel()->accept(generatedSplitting, factor*p, r, currentWeights); +} + +void DipoleSplittingGenerator::prepare(const DipoleSplittingInfo& sp) { + + generatedSplitting = sp; + + generatedSplitting.splittingKinematics(splittingKernel()->splittingKinematics()); + generatedSplitting.splittingParameters().resize(splittingKernel()->nDimAdditional()); + + if ( wrapping() ) { + generatedSplitting.emitterData(theSplittingKernel->emitter(generatedSplitting.index())); + generatedSplitting.spectatorData(theSplittingKernel->spectator(generatedSplitting.index())); + generatedSplitting.emissionData(theSplittingKernel->emission(generatedSplitting.index())); + parameters.resize(theOtherGenerator->nDim()); + prepared = true; + return; + } + + generatedSplitting.emitterData(splittingKernel()->emitter(generatedSplitting.index())); + generatedSplitting.spectatorData(splittingKernel()->spectator(generatedSplitting.index())); + generatedSplitting.emissionData(splittingKernel()->emission(generatedSplitting.index())); + + presampledSplitting = generatedSplitting; + + prepared = true; + + parameters.resize(nDim()); + + theExponentialGenerator = + new exsample::exponential_generator(); + + 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 ( 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; + } + + 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; + + 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) ); + +} + +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 ( 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); + double jac = split.splittingKinematics()->jacobian(); + + // multiply in the profile scales when relevant + assert(ShowerHandler::currentHandler()); + if ( ShowerHandler::currentHandler()->firstInteraction() && + ShowerHandler::currentHandler()->profileScales() && + !presampling ) { + Energy hard = ShowerHandler::currentHandler()->hardScale(); + if ( hard > ZERO ) + kernel *= ShowerHandler::currentHandler()->profileScales()->hardScaleProfile(hard,split.lastPt()); + } + + split.lastValue( abs(jac) * kernel ); + + if ( isnan(split.lastValue()) || isinf(split.lastValue()) ) { + generator()->log() << "DipoleSplittingGenerator:evaluate(): problematic splitting kernel encountered for " + << splittingKernel()->name() << "\n" << flush; + split.lastValue(0.0); + } + + if ( kernel < 0. ) + return 0.; + + return split.lastValue(); + +} + +void DipoleSplittingGenerator::doGenerate(map& variations, + Energy optCutoff) { + + assert(!wrapping()); + + double res = 0.; + + Energy startPt = generatedSplitting.hardPt(); + double optKappaCutoff = 0.0; + if ( optCutoff > splittingKinematics()->IRCutoff() ) { + optKappaCutoff = splittingKinematics()->ptToRandom(optCutoff, + generatedSplitting.scale(), + generatedSplitting.emitterX(), + generatedSplitting.spectatorX(), + generatedSplitting.index(), + *splittingKernel()); + } + + resetVariations(); + theSplittingWeight = 1.; + + while (true) { + try { + if ( optKappaCutoff == 0.0 ) { + res = theExponentialGenerator->generate(); + } else { + res = theExponentialGenerator->generate(optKappaCutoff); + } + } catch (exsample::exponential_regenerate&) { + resetVariations(); + theSplittingWeight = 1.; + generatedSplitting.hardPt(startPt); + continue; + } catch (exsample::hit_and_miss_maxtry&) { + throw DipoleShowerHandler::RedoShower(); + } catch (exsample::selection_maxtry&) { + throw DipoleShowerHandler::RedoShower(); + } + break; + } + + for ( map::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,variations,optHardPt,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(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/Shower/Dipole/Base/DipoleSplittingGenerator.h b/Shower/Dipole/Base/DipoleSplittingGenerator.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Base/DipoleSplittingGenerator.h @@ -0,0 +1,491 @@ +// -*- C++ -*- +// +// DipoleSplittingGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator +// Copyright (C) 2002-2007 The Herwig Collaboration +// +// Herwig is licenced under version 2 of the GPL, see COPYING for details. +// Please respect the MCnet academic guidelines, see GUIDELINES for details. +// +#ifndef HERWIG_DipoleSplittingGenerator_H +#define HERWIG_DipoleSplittingGenerator_H +// +// This is the declaration of the DipoleSplittingGenerator class. +// + +#include "ThePEG/Handlers/HandlerBase.h" + +#include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" +#include "DipoleSplittingReweight.h" +#include "Herwig/Shower/Dipole/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(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); + + /** + * Indicate that an accept with the given kernel value and overestimate has occured. + */ + void accept(const vector&, double p, double r); + + /** + * Return the weight associated to the currently generated splitting + */ + double splittingWeight() const { + if ( wrapping() ) + return theOtherGenerator->splittingWeight(); + return theSplittingWeight; + } + + /** + * True, if sampler should apply compensation + */ + void doCompensate(bool yes = true) { theDoCompensate = yes; } + +public: + + /**@name Wrap to the exsample2 interface until this is finally cleaned up. */ + //@{ + + inline const vector& 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; + + /** + * The weight associated to the currently generated splitting + */ + double theSplittingWeight; + +private: + + /** + * The static object used to initialize the description of this class. + * Indicates that this is a concrete class with persistent data. + */ + static ClassDescription 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/Base/DipoleSplittingInfo.cc b/Shower/Dipole/Base/DipoleSplittingInfo.cc rename from DipoleShower/Base/DipoleSplittingInfo.cc rename to Shower/Dipole/Base/DipoleSplittingInfo.cc diff --git a/DipoleShower/Base/DipoleSplittingInfo.h b/Shower/Dipole/Base/DipoleSplittingInfo.h rename from DipoleShower/Base/DipoleSplittingInfo.h rename to Shower/Dipole/Base/DipoleSplittingInfo.h --- a/DipoleShower/Base/DipoleSplittingInfo.h +++ b/Shower/Dipole/Base/DipoleSplittingInfo.h @@ -1,616 +1,616 @@ // -*- C++ -*- // // DipoleSplittingInfo.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_DipoleSplittingInfo_H #define HERWIG_DipoleSplittingInfo_H // // This is the declaration of the DipoleIndex and DipoleSplittingInfo classes. // #include "ThePEG/PDF/PDF.h" #include "ThePEG/PDT/ParticleData.h" -#include "Herwig/DipoleShower/Kinematics/DipoleSplittingKinematics.h" +#include "Herwig/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; class DipoleSplittingKinematics; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleIndex is used to index splitting generators * for a particular dipole. * */ class DipoleIndex { public: /** * The default constructor. */ DipoleIndex(); /** * The standard constructor */ DipoleIndex(tcPDPtr newEmitter, tcPDPtr newSpectator, const PDF& newEmitterPDF = PDF(), const PDF& newSpectatorPDF = PDF()); public: /** * Compare for equality. */ bool operator ==(const DipoleIndex& x) const; /** * Compare for ordering. */ bool operator <(const DipoleIndex& x) const; /** * Swap emitter and spectator. */ void swap(); /** * Produce a pair of dipole indices given * a particle data object for the emission. * The ME correction is ignored in the children. * The emission is inserted between the emitter * and spectator, being a spectator in the first * dipole index containing the original emitter, * and an emitter in the second dipole, containing * the original spectator. */ pair split(tcPDPtr) const; public: /** * Return the emitter particle data object. */ tcPDPtr emitterData() const { return theEmitterData; } /** * Return true, if the emitter is an incoming parton */ bool initialStateEmitter() const { return theInitialStateEmitter; } /** * Return the PDF object associated with the emitter */ const PDF& emitterPDF() const { return theEmitterPDF; } /** * Return the spectator particle data object. */ tcPDPtr spectatorData() const { return theSpectatorData; } /** * Return true, if the spectator is an incoming parton */ bool initialStateSpectator() const { return theInitialStateSpectator; } /** * Return the PDF object associated with the spectator */ const PDF& spectatorPDF() const { return theSpectatorPDF; } public: /** * Put information to ostream */ void print(ostream&) const; private: /** * The particle data object of the emitter. */ tcPDPtr theEmitterData; /** * Wether or not the emitter is an incoming parton. */ bool theInitialStateEmitter; /** * The PDF object for the emitter. */ PDF theEmitterPDF; /** * The particle data object of the spectator. */ tcPDPtr theSpectatorData; /** * Wether or not the spectator is an incoming parton. */ bool theInitialStateSpectator; /** * The PDF object for the spectator. */ PDF theSpectatorPDF; }; inline ostream& operator << (ostream& os, const DipoleIndex& di) { di.print(os); return os; } /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleSplittingInfo contains all parameters to generate a full * dipole splitting. * */ class DipoleSplittingInfo { public: /** * The default constructor. */ DipoleSplittingInfo(); /** * Destructor */ virtual ~DipoleSplittingInfo() {} public: /** * Assign data from another splitting info */ void fill(const DipoleSplittingInfo&); public: /** * Return the dipole index */ const DipoleIndex& index() const { return theIndex; } /** * Return which of the particles * in the dipole should be considered emitter (true) * and spectator (false) */ const pair& configuration() const { return theConfiguration; } /** * Get the configuration marking the spectator */ const pair& spectatorConfiguration() const { return theSpectatorConfiguration; } /** * Return the particle data object of the emitter * after the splitting. */ tcPDPtr emitterData() const { return theEmitterData; } /** * Return the particle data object of the emission * after the splitting. */ tcPDPtr emissionData() const { return theEmissionData; } /** * Return the particle data object of the spectator * after the splitting. */ tcPDPtr spectatorData() const { return theSpectatorData; } /** * Return the momentum fraction of the emitter. */ double emitterX() const { return theEmitterX; } /** * Return the momentum fraction of the spectator. */ double spectatorX() const { return theSpectatorX; } public: /** * Return a pointer to the DipoleSplittingKinematics object * which is to be used to perform the splitting. */ Ptr::tptr splittingKinematics() const { return theSplittingKinematics; } /** * Return the dipole scale */ Energy scale() const { return theScale; } /** * Return the pt below which this * splitting has been generated. */ Energy hardPt() const { return theHardPt; } /** * Return the last generated pt */ Energy lastPt() const { return theLastPt; } /** * Return the last generated momentum fraction. */ double lastZ() const { return theLastZ; } /** * Return the last generated azimuthal angle. */ double lastPhi() const { return theLastPhi; } /** * Return the momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ double lastEmitterZ() const { return theLastEmitterZ; } /** * Return the momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ double lastSpectatorZ() const { return theLastSpectatorZ; } /** * Return any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ const vector& lastSplittingParameters() const { return theLastSplittingParameters; } /** * Return true, if this splitting will terminate * the evolution of the dipole considered. */ bool stoppedEvolving() const { return theStoppedEvolving; } public: /** * Set the index. */ void index(const DipoleIndex& ind) { theIndex = ind; } /** * Set the DipoleSplittingKinematics object */ void splittingKinematics(Ptr::tptr newSplittingKinematics) { theSplittingKinematics = newSplittingKinematics; } /** * Set the particle data object of the emitter * after the splitting. */ void emitterData(tcPDPtr p) { theEmitterData = p; } /** * Set the particle data object of the emission * after the splitting. */ void emissionData(tcPDPtr p) { theEmissionData = p; } /** * Set the particle data object of the spectator * after the splitting. */ void spectatorData(tcPDPtr p) { theSpectatorData = p; } /** * Set the dipole scale */ void scale(Energy s) { theScale = s; } /** * Set the emitter's momentum fraction */ void emitterX(double x) { theEmitterX = x; } /** * Set the spectator's momentum fraction */ void spectatorX(double x) { theSpectatorX = x; } /** * Set the pt below which this * splitting has been generated. */ void hardPt(Energy p) { theHardPt = p; } /** * Set the last generated pt */ void lastPt(Energy p) { theLastPt = p; } /** * Set the last generated momentum fraction. */ void lastZ(double z) { theLastZ = z; } /** * Set the last generated azimuthal angle. */ void lastPhi(double p) { theLastPhi = p; } /** * Set the momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ void lastEmitterZ(double z) { theLastEmitterZ = z; } /** * Set the momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ void lastSpectatorZ(double z) { theLastSpectatorZ = z; } /** * Return the last splitting kernel value encountered. */ double lastValue() const { return theLastValue; } /** * Set the last splitting kernel value encountered. */ void lastValue(double v) { theLastValue = v; } /** * Set the last splitting parameters. */ void lastSplittingParameters(const vector& p) { theLastSplittingParameters = p; } /** * Access the splitting parameters */ vector& splittingParameters() { return theLastSplittingParameters; } /** * Indicate that this splitting will terminate * the evolution of the dipole considered. */ void didStopEvolving() { theStoppedEvolving = true; } /** * Indicate that this splitting will not terminate * the evolution of the dipole considered. */ void continuesEvolving() { theStoppedEvolving = false; } /** * Reset the configuration. */ void configuration(const pair& newConfig) { theConfiguration = newConfig; } /** * Set the configuration marking the spectator */ void spectatorConfiguration(const pair& conf) { theSpectatorConfiguration = conf; } public: /** * Set a pointer to the emitter parton before emission. */ void emitter(tPPtr newEmitter) { theEmitter = newEmitter; } /** * Set a pointer to the spectator parton before emission. */ void spectator(tPPtr newSpectator) { theSpectator = newSpectator; } /** * Set a pointer to the emitter parton after emission. */ void splitEmitter(tPPtr newEmitter) { theSplitEmitter = newEmitter; } /** * Set a pointer to the spectator parton after emission. */ void splitSpectator(tPPtr newSpectator) { theSplitSpectator = newSpectator; } /** * Set a pointer to the emitted parton. */ void emission(tPPtr newEmission) { theEmission = newEmission; } /** * Return a pointer to the emitter parton before emission. */ tPPtr emitter() const { return theEmitter; } /** * Return a pointer to the spectator parton before emission. */ tPPtr spectator() const { return theSpectator; } /** * Return a pointer to the emitter parton after emission. */ tPPtr splitEmitter() const { return theSplitEmitter; } /** * Return a pointer to the spectator parton after emission. */ tPPtr splitSpectator() const { return theSplitSpectator; } /** * Return a pointer to the emitted parton. */ tPPtr emission() const { return theEmission; } public: /** * Put information to ostream */ void print(ostream&) const; private: /** * The DipoleIndex associated * with this splitting. */ DipoleIndex theIndex; /** * Flags indicateing which of the particles * in the dipole should be considered emitter (true) * and spectator (false) */ pair theConfiguration; /** * The configuration marking the spectator */ pair theSpectatorConfiguration; /** * The particle data object of the emitter * after the splitting. */ tcPDPtr theEmitterData; /** * The particle data object of the emission * after the splitting. */ tcPDPtr theEmissionData; /** * The particle data object of the spectator * after the splitting. */ tcPDPtr theSpectatorData; /** * A pointer to the DipoleSplittingKinematics object * which is to be used to perform the splitting. */ Ptr::tptr theSplittingKinematics; /** * The scale for this dipole. */ Energy theScale; /** * The momentum fraction of the emitter. */ double theEmitterX; /** * The momentum fraction of the spectator. */ double theSpectatorX; /** * The pt below which this splitting has * been generated. */ Energy theHardPt; /** * The last generated pt */ Energy theLastPt; /** * The last generated momentum fraction. */ double theLastZ; /** * The last generated azimuthal angle. */ double theLastPhi; /** * The momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ double theLastEmitterZ; /** * The momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ double theLastSpectatorZ; /** * The last splitting kernel value encountered. */ double theLastValue; /** * Any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ vector theLastSplittingParameters; /** * True, if this splitting will terminate * the evolution of the dipole considered. */ bool theStoppedEvolving; /** * A pointer to the emitter parton before emission. */ PPtr theEmitter; /** * A pointer to the spectator parton before emission. */ PPtr theSpectator; /** * A pointer to the emitter parton after emission. */ PPtr theSplitEmitter; /** * A pointer to the spectator parton after emission. */ PPtr theSplitSpectator; /** * A pointer to the emitted parton. */ PPtr theEmission; }; inline ostream& operator << (ostream& os, const DipoleSplittingInfo& di) { di.print(os); return os; } } #endif /* HERWIG_DipoleSplittingInfo_H */ diff --git a/Shower/Dipole/Base/DipoleSplittingReweight.cc b/Shower/Dipole/Base/DipoleSplittingReweight.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Base/DipoleSplittingReweight.cc @@ -0,0 +1,65 @@ +// -*- C++ -*- +// +// DipoleSplittingReweight.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 DipoleSplittingReweight class. +// + +#include +#include "DipoleSplittingReweight.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/Shower/Dipole/DipoleShowerHandler.h" + +using namespace Herwig; + +DipoleSplittingReweight::DipoleSplittingReweight() + : HandlerBase() {} + +DipoleSplittingReweight::~DipoleSplittingReweight() {} + +void DipoleSplittingReweight::updateCurrentHandler() { + if ( ShowerHandler::currentHandler() != theCurrentHandler ) { + Ptr::tptr sptr = ShowerHandler::currentHandler(); + theCurrentHandler = + dynamic_ptr_cast::tptr>(sptr); + } +} + +Ptr::tptr DipoleSplittingReweight::currentHandler() const { + return theCurrentHandler; +} + + +// If needed, insert default implementations of virtual function defined +// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). + + +void DipoleSplittingReweight::persistentOutput(PersistentOStream & ) const { +} + +void DipoleSplittingReweight::persistentInput(PersistentIStream &, int) { +} + +AbstractClassDescription DipoleSplittingReweight::initDipoleSplittingReweight; +// Definition of the static class description member. + +void DipoleSplittingReweight::Init() { + + static ClassDocumentation documentation + ("DipoleSplittingReweight is used by the dipole shower " + "to reweight splittings from a given dipole splitting kernel."); + +} + diff --git a/Shower/Dipole/Base/DipoleSplittingReweight.h b/Shower/Dipole/Base/DipoleSplittingReweight.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Base/DipoleSplittingReweight.h @@ -0,0 +1,167 @@ +// -*- C++ -*- +// +// DipoleSplittingReweight.h is a part of Herwig - A multi-purpose Monte Carlo event generator +// Copyright (C) 2002-2007 The Herwig Collaboration +// +// Herwig is licenced under version 2 of the GPL, see COPYING for details. +// Please respect the MCnet academic guidelines, see GUIDELINES for details. +// +#ifndef HERWIG_DipoleSplittingReweight_H +#define HERWIG_DipoleSplittingReweight_H +// +// This is the declaration of the DipoleSplittingReweight class. +// + +#include "ThePEG/Handlers/HandlerBase.h" +#include "DipoleSplittingInfo.h" + +#include "Herwig/Shower/Dipole/DipoleShowerHandler.fh" + +namespace Herwig { + +using namespace ThePEG; + +/** + * \ingroup DipoleShower + * \author Simon Platzer + * + * \brief DipoleSplittingReweight is used by the dipole shower + * to reweight splittings from a given dipole splitting kernel. + * + * @see \ref DipoleSplittingReweightInterfaces "The interfaces" + * defined for DipoleSplittingReweight. + */ +class DipoleSplittingReweight: public HandlerBase { + +public: + + /** @name Standard constructors and destructors. */ + //@{ + /** + * The default constructor. + */ + DipoleSplittingReweight(); + + /** + * The destructor. + */ + virtual ~DipoleSplittingReweight(); + //@} + +public: + + /** + * Return true, if the reweighting should be applied to the first + * interaction + */ + virtual bool firstInteraction() const { return true; } + + /** + * Return true, if the reweighting should be applied to the secondary + * interactions + */ + virtual bool secondaryInteractions() const { return false; } + + /** + * Update the pointer to the currently active dipole shower handler object. + */ + void updateCurrentHandler(); + + /** + * Return the pointer to the currently active dipole shower handler object. + */ + Ptr::tptr currentHandler() const; + + /** + * Return the reweighting factor for the given splitting type. + */ + virtual double evaluate(const DipoleSplittingInfo&) const = 0; + +public: + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +// If needed, insert declarations of virtual function defined in the +// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). + +private: + + /** + * The static object used to initialize the description of this class. + * Indicates that this is a concrete class with persistent data. + */ + static AbstractClassDescription initDipoleSplittingReweight; + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + DipoleSplittingReweight & operator=(const DipoleSplittingReweight &); + + /** + * A pointer to the currently active dipole shower handler object. + */ + Ptr::tptr theCurrentHandler; + +}; + +} + +#include "ThePEG/Utilities/ClassTraits.h" + +namespace ThePEG { + +/** @cond TRAITSPECIALIZATIONS */ + +/** This template specialization informs ThePEG about the + * base classes of DipoleSplittingReweight. */ +template <> +struct BaseClassTrait { + /** Typedef of the first base class of DipoleSplittingReweight. */ + typedef HandlerBase NthBase; +}; + +/** This template specialization informs ThePEG about the name of + * the DipoleSplittingReweight class and the shared object where it is defined. */ +template <> +struct ClassTraits + : public ClassTraitsBase { + /** Return a platform-independent class name */ + static string className() { return "Herwig::DipoleSplittingReweight"; } + /** + * The name of a file containing the dynamic library where the class + * DipoleSplittingReweight is implemented. It may also include several, space-separated, + * libraries if the class DipoleSplittingReweight depends on other classes (base classes + * excepted). In this case the listed libraries will be dynamically + * linked in the order they are specified. + */ + static string library() { return "HwDipoleShower.so"; } +}; + +/** @endcond */ + +} + +#endif /* HERWIG_DipoleSplittingReweight_H */ diff --git a/DipoleShower/Base/Makefile.am b/Shower/Dipole/Base/Makefile.am rename from DipoleShower/Base/Makefile.am rename to Shower/Dipole/Base/Makefile.am diff --git a/Shower/Dipole/DipoleShowerHandler.cc b/Shower/Dipole/DipoleShowerHandler.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/DipoleShowerHandler.cc @@ -0,0 +1,999 @@ +// -*- 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 "Herwig/PDF/MPIPDF.h" +#include "Herwig/PDF/MinBiasPDF.h" +#include "Herwig/PDF/HwRemDecayer.h" + +#include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" + +#include "Herwig/MatrixElement/Matchbox/Base/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), + realignmentScheme(0), + verbosity(0), printEvent(0), nTries(0), + didRadiate(false), didRealign(false), + theRenormalizationScaleFreeze(1.*GeV), + theFactorizationScaleFreeze(2.*GeV), theDoCompensate(false), + theFreezeGrid(500000), theDetuning(1.0), + maxPt(ZERO), muPt(ZERO) {} + +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; + + if ( eventRecord().truncatedShower() ) { + throw Exception() << "Inconsistent hard emission set-up in DipoleShowerHandler::cascade. " + << "No truncated shower needed with DipoleShowerHandler. Add " + << "'set MEMatching:TruncatedShower No' to input file." + << Exception::runerror; + } + + hardScales(lastXCombPtr()->lastShowerScale()); + + if ( verbosity > 1 ) { + generator()->log() << "DipoleShowerHandler starting off:\n"; + eventRecord().debugLastEvent(generator()->log()); + generator()->log() << flush; + } + + unsigned int nEmitted = 0; + + if ( firstMCatNLOEmission ) { + + if ( !eventRecord().isMCatNLOHEvent() ) + nEmissions = 1; + else + nEmissions = 0; + + } + + if ( !firstMCatNLOEmission ) { + + doCascade(nEmitted,optHardPt,optCutoff); + + if ( discardNoEmissions ) { + if ( !didRadiate ) + throw Veto(); + if ( nEmissions ) + if ( nEmissions < nEmitted ) + throw Veto(); + } + + } else { + + if ( nEmissions == 1 ) + doCascade(nEmitted,optHardPt,optCutoff); + + } + + if ( intrinsicPtGenerator ) { + if ( eventRecord().incoming().first->coloured() && + eventRecord().incoming().second->coloured() ) { + 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); + candidate.emitter(emitter); + candidate.spectator(spectator); + + if ( generators().find(candidate.index()) == generators().end() ) + getGenerators(candidate.index(),theSplittingReweight); + + // + // NOTE -- needs proper fixing at some point + // + // For some very strange reason, equal_range gives back + // key ranges it hasn't been asked for. This particularly + // happens e.g. for FI dipoles of the same kind, but different + // PDF (hard vs MPI PDF). I can't see a reason for this, + // as DipoleIndex properly implements comparison for equality + // and (lexicographic) ordering; for the time being, we + // use equal_range, extented by an explicit check for wether + // the key is indeed what we wanted. See line after (*) comment + // below. + // + + 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,currentWeights(),optHardPt,optCutoff); + Energy nextScale = evolutionOrdering()->evolutionScale(gen->second->lastSplitting(),*(gen->second->splittingKernel())); + + if ( nextScale > winnerScale ) { + winner.fill(candidate); + gen->second->completeSplitting(winner); + winnerGen = gen; + winnerScale = nextScale; + } + + reweight(reweight() * gen->second->splittingWeight()); + + } + + if ( winnerGen == generators().end() ) { + winner.didStopEvolving(); + return 0.0*GeV; + } + + if ( winner.stoppedEvolving() ) + return 0.0*GeV; + + return winnerScale; + +} + +void DipoleShowerHandler::doCascade(unsigned int& emDone, + Energy optHardPt, + Energy optCutoff) { + + if ( nEmissions ) + if ( emDone == nEmissions ) + return; + + DipoleSplittingInfo winner; + DipoleSplittingInfo dipoleWinner; + + while ( eventRecord().haveChain() ) { + + if ( verbosity > 2 ) { + generator()->log() << "DipoleShowerHandler selecting splittings for the chain:\n" + << eventRecord().currentChain() << flush; + } + + list::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() ) { + eventRecord().popChain(); + if ( theEventReweight && eventRecord().chains().empty() ) + if ( (theEventReweight->firstInteraction() && firstInteraction()) || + (theEventReweight->secondaryInteractions() && !firstInteraction()) ) { + double w = theEventReweight->weightCascade(eventRecord().incoming(), + eventRecord().outgoing(), + eventRecord().hard(),theGlobalAlphaS); + reweight(reweight()*w); + } + continue; + } + + // otherwise perform the splitting + + didRadiate = true; + + eventRecord().isMCatNLOSEvent(false); + eventRecord().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 ) + if ( (theEventReweight->firstInteraction() && firstInteraction()) || + (theEventReweight->secondaryInteractions() && !firstInteraction()) ) { + double w = theEventReweight->weight(eventRecord().incoming(), + eventRecord().outgoing(), + eventRecord().hard(),theGlobalAlphaS); + reweight(reweight()*w); + } + + if ( nEmissions ) + if ( ++emDone == nEmissions ) + return; + + } + +} + +bool DipoleShowerHandler::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 ) { + if ( !(**k).alphaS() ) + (**k).alphaS(as); + (**k).renormalizationScaleFreeze(theRenormalizationScaleFreeze); + (**k).factorizationScaleFreeze(theFactorizationScaleFreeze); + } + + // clear the generators to be rebuild + // actually, there shouldn't be any generators + // when this happens. + generators().clear(); + +} + +void DipoleShowerHandler::resetReweight(Ptr::tptr rw) { + for ( 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); + if ( renormalizationScaleFactor() != 1. ) + nGenerator->splittingKernel()->renormalizationScaleFactor(renormalizationScaleFactor()); + if ( factorizationScaleFactor() != 1. ) + nGenerator->splittingKernel()->factorizationScaleFactor(factorizationScaleFactor()); + if ( !nGenerator->splittingReweight() ) + nGenerator->splittingReweight(rw); + nGenerator->splittingKernel()->freezeGrid(theFreezeGrid); + nGenerator->splittingKernel()->detuning(theDetuning); + + GeneratorMap::const_iterator equivalent = generators().end(); + + for ( GeneratorMap::const_iterator eq = generators().begin(); + eq != generators().end(); ++eq ) { + if ( !eq->second->wrapping() ) + if ( (**k).canHandleEquivalent(ind,*(eq->second->splittingKernel()),eq->first) ) { + + equivalent = eq; + + if ( verbosity > 0 ) { + generator()->log() << "The dipole configuration " + << ind + << " can equivalently be handled by the existing\n" + << "generator for configuration " + << eq->first << " using the kernel '" + << eq->second->splittingKernel()->name() + << "'\n" << flush; + } + + break; + + } + } + + if ( equivalent != generators().end() ) { + nGenerator->wrap(equivalent->second); + } + + DipoleSplittingInfo dummy; + dummy.index(ind); + nGenerator->prepare(dummy); + + generators().insert(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 + << realignmentScheme << verbosity << printEvent + << ounit(theRenormalizationScaleFreeze,GeV) + << ounit(theFactorizationScaleFreeze,GeV) + << theShowerApproximation + << theDoCompensate << theFreezeGrid << theDetuning + << theEventReweight << theSplittingReweight << ounit(maxPt,GeV) + << ounit(muPt,GeV); +} + +void DipoleShowerHandler::persistentInput(PersistentIStream & is, int) { + is >> kernels >> theEvolutionOrdering + >> constituentReshuffler >> intrinsicPtGenerator + >> theGlobalAlphaS >> chainOrderVetoScales + >> nEmissions >> discardNoEmissions >> firstMCatNLOEmission + >> realignmentScheme >> verbosity >> printEvent + >> iunit(theRenormalizationScaleFreeze,GeV) + >> iunit(theFactorizationScaleFreeze,GeV) + >> theShowerApproximation + >> theDoCompensate >> theFreezeGrid >> theDetuning + >> theEventReweight >> theSplittingReweight >> 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 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 Parameter interfaceDetuning + ("Detuning", + "A value to detune the overestimate kernel.", + &DipoleShowerHandler::theDetuning, 1.0, 1.0, 0, + false, false, Interface::lowerlim); + + static Reference interfaceEventReweight + ("EventReweight", + "", + &DipoleShowerHandler::theEventReweight, false, false, true, true, false); + + static Reference interfaceSplittingReweight + ("SplittingReweight", + "Set the splitting reweight.", + &DipoleShowerHandler::theSplittingReweight, false, false, true, true, false); + +} + diff --git a/DipoleShower/DipoleShowerHandler.fh b/Shower/Dipole/DipoleShowerHandler.fh rename from DipoleShower/DipoleShowerHandler.fh rename to Shower/Dipole/DipoleShowerHandler.fh diff --git a/Shower/Dipole/DipoleShowerHandler.h b/Shower/Dipole/DipoleShowerHandler.h new file mode 100644 --- /dev/null +++ b/Shower/Dipole/DipoleShowerHandler.h @@ -0,0 +1,496 @@ +// -*- C++ -*- +// +// DipoleShowerHandler.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_DipoleShowerHandler_H +#define HERWIG_DipoleShowerHandler_H +// +// This is the declaration of the DipoleShowerHandler class. +// + +#include "Herwig/Shower/ShowerHandler.h" + +#include "Herwig/Shower/Dipole/DipoleShowerHandler.fh" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingReweight.h" + +#include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingGenerator.h" +#include "Herwig/Shower/Dipole/Base/DipoleEventRecord.h" +#include "Herwig/Shower/Dipole/Base/DipoleEvolutionOrdering.h" +#include "Herwig/Shower/Dipole/Base/DipoleEventReweight.h" +#include "Herwig/Shower/Dipole/Utility/ConstituentReshuffler.h" +#include "Herwig/Shower/Dipole/Utility/IntrinsicPtGenerator.h" +#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * \ingroup DipoleShower + * \author Simon Platzer + * + * \brief The DipoleShowerHandler class manages the showering using + * the dipole shower algorithm. + * + * @see \ref DipoleShowerHandlerInterfaces "The interfaces" + * defined for DipoleShowerHandler. + */ +class DipoleShowerHandler: public ShowerHandler { + +public: + + /** @name Standard constructors and destructors. */ + //@{ + /** + * The default constructor. + */ + DipoleShowerHandler(); + + /** + * The destructor. + */ + virtual ~DipoleShowerHandler(); + //@} + +public: + + /** + * Indicate a problem in the shower. + */ + struct RedoShower {}; + + /** + * Insert an additional splitting kernel. + */ + void addSplitting(Ptr::ptr sp) { + kernels.push_back(sp); + } + + /** + * Reset the alpha_s for all splitting kernels. + */ + void resetAlphaS(Ptr::tptr); + + /** + * Reset the splitting reweight for all splitting kernels. + */ + void resetReweight(Ptr::tptr); + + /** + * Return true, if the shower handler can generate a truncated + * shower for POWHEG style events generated using Matchbox + */ + virtual bool canHandleMatchboxTrunc() const { return false; } + + /** + * Return true, if this cascade handler will perform reshuffling from hard + * process masses. + */ + virtual bool isReshuffling() const { return false; } + + /** + * Return the relevant hard scale to be used in the profile scales + */ + virtual Energy hardScale() const { + return muPt; + } + +protected: + + typedef multimap::ptr> GeneratorMap; + + /** + * The main method which manages the showering of a subprocess. + */ + virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb) { + return cascade(sub,xcomb,ZERO,ZERO); + } + + /** + * The main method which manages the showering of a subprocess. + */ + tPPair cascade(tSubProPtr sub, XCPtr xcomb, + Energy optHardPt, Energy optCutoff); + + /** + * Build splitting generators for the given + * dipole index. + */ + void getGenerators(const DipoleIndex&, + Ptr::tptr rw = + Ptr::tptr()); + + /** + * Setup the hard scales. + */ + void hardScales(Energy2 scale); + + /** + * Return the evolution ordering + */ + Ptr::tptr evolutionOrdering() const { return theEvolutionOrdering; } + + /** + * Reshuffle to constituent mass shells + */ + void constituentReshuffle(); + + /** + * Access the generator map + */ + GeneratorMap& generators() { return theGenerators; } + + /** + * Access the event record + */ + DipoleEventRecord& eventRecord() { return theEventRecord; } + + /** + * Return the event record + */ + const DipoleEventRecord& eventRecord() const { return theEventRecord; } + + /** + * Return the splitting kernels. + */ + const vector::ptr>& splittingKernels() const { + return kernels; + } + + /** + * Realign the event such as to have the incoming partons along thre + * beam axes. + */ + bool realign(); + +private: + + /** + * Perform the cascade. + */ + void doCascade(unsigned int& emDone, + Energy optHardPt = ZERO, + Energy optCutoff = ZERO); + + /** + * Get the winning splitting for the + * given dipole and configuration. + */ + Energy getWinner(DipoleSplittingInfo& winner, + const Dipole& dip, + pair conf, + Energy optHardPt = ZERO, + Energy optCutoff = ZERO); + + /** + * Get the winning splitting for the + * given dipole and configuration. + */ + Energy getWinner(SubleadingSplittingInfo& winner, + Energy optHardPt = ZERO, + Energy optCutoff = ZERO); + + /** + * Get the winning splitting for the + * given dipole and configuration. + */ + Energy getWinner(DipoleSplittingInfo& winner, + const DipoleIndex& index, + double emitterX, double spectatorX, + pair conf, + tPPtr emitter, tPPtr spectator, + Energy startScale, + Energy optHardPt = ZERO, + Energy optCutoff = ZERO); + +public: + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +protected: + + /** @name Clone Methods. */ + //@{ + /** + * Make a simple clone of this object. + * @return a pointer to the new object. + */ + virtual IBPtr clone() const; + + /** Make a clone of this object, possibly modifying the cloned object + * to make it sane. + * @return a pointer to the new object. + */ + virtual IBPtr fullclone() const; + //@} + + +// If needed, insert declarations of virtual function defined in the +// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). + + +protected: + + /** @name Standard Interfaced functions. */ + //@{ + /** + * Initialize this object after the setup phase before saving an + * EventGenerator to disk. + * @throws InitException if object could not be initialized properly. + */ + virtual void doinit(); + + /** + * Initialize this object. Called in the run phase just before + * a run begins. + */ + virtual void doinitrun(); + + /** + * Finalize this object. Called in the run phase just after a + * run has ended. Used eg. to write out statistics. + */ + virtual void dofinish(); + //@} + + +private: + + /** + * The splitting kernels to be used. + */ + vector::ptr> kernels; + + /** + * The evolution ordering considered + */ + Ptr::ptr theEvolutionOrdering; + + /** + * The ConstituentReshuffler to be used + */ + Ptr::ptr constituentReshuffler; + + /** + * The intrinsic pt generator to be used. + */ + Ptr::ptr intrinsicPtGenerator; + + /** + * A global alpha_s to be used for all splitting kernels. + */ + Ptr::ptr theGlobalAlphaS; + + /** + * Apply chain ordering to events from matrix + * element corrections. + */ + bool chainOrderVetoScales; + + /** + * Limit the number of emissions. + * Limit applied if > 0. + */ + unsigned int nEmissions; + + /** + * Discard events which did not radiate. + */ + bool discardNoEmissions; + + /** + * Perform the first MC@NLO emission only. + */ + bool firstMCatNLOEmission; + + /** + * The realignment scheme + */ + int realignmentScheme; + +private: + + /** + * The verbosity level. + * 0 - print no info + * 1 - print diagnostic information on setting up + * splitting generators etc. + * 2 - print detailed event information for up to + * printEvent events. + * 3 - print dipole chains after each splitting. + */ + int verbosity; + + /** + * See verbosity. + */ + int printEvent; + +private: + + /** + * The splitting generators indexed by the dipole + * indices they can work on. + */ + GeneratorMap theGenerators; + + /** + * The evnt record used. + */ + DipoleEventRecord theEventRecord; + + /** + * The number of shoer tries so far. + */ + unsigned int nTries; + + /** + * Whether or not we did radiate anything + */ + bool didRadiate; + + /** + * Whether or not we did realign the event + */ + bool didRealign; + +private: + + /** + * A freezing value for the renormalization scale + */ + Energy theRenormalizationScaleFreeze; + + /** + * A freezing value for the factorization scale + */ + Energy theFactorizationScaleFreeze; + + /** + * The matching subtraction, if appropriate + */ + Ptr::tptr theShowerApproximation; + + /** + * True, if sampler should apply compensation + */ + bool theDoCompensate; + + /** + * Return the number of accepted points after which the grid should + * be frozen + */ + unsigned long theFreezeGrid; + + /** + * The detuning factor applied to the sampling overestimate kernel + */ + double theDetuning; + + /** + * A pointer to the dipole event reweight object + */ + Ptr::ptr theEventReweight; + + /** + * A pointer to a global dipole splitting reweight + */ + Ptr::ptr theSplittingReweight; + + /** + * True if no warnings have been issued yet + */ + static bool firstWarn; + + /** + * The shower starting scale for the last event encountered + */ + Energy maxPt; + + /** + * The shower hard scale for the last event encountered + */ + Energy muPt; + +private: + + /** + * The static object used to initialize the description of this class. + * Indicates that this is a concrete class with persistent data. + */ + static ClassDescription initDipoleShowerHandler; + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + DipoleShowerHandler & operator=(const DipoleShowerHandler &); + +}; + +} + +#include "ThePEG/Utilities/ClassTraits.h" + +namespace ThePEG { + +/** @cond TRAITSPECIALIZATIONS */ + +/** This template specialization informs ThePEG about the + * base classes of DipoleShowerHandler. */ +template <> +struct BaseClassTrait { + /** Typedef of the first base class of DipoleShowerHandler. */ + typedef Herwig::ShowerHandler NthBase; +}; + +/** This template specialization informs ThePEG about the name of + * the DipoleShowerHandler class and the shared object where it is defined. */ +template <> +struct ClassTraits + : public ClassTraitsBase { + /** Return a platform-independent class name */ + static string className() { return "Herwig::DipoleShowerHandler"; } + /** + * The name of a file containing the dynamic library where the class + * DipoleShowerHandler is implemented. It may also include several, space-separated, + * libraries if the class DipoleShowerHandler depends on other classes (base classes + * excepted). In this case the listed libraries will be dynamically + * linked in the order they are specified. + */ + static string library() { return "HwDipoleShower.so"; } +}; + +/** @endcond */ + +} + +#endif /* HERWIG_DipoleShowerHandler_H */ diff --git a/Shower/Dipole/Kernels/DipoleSplittingKernel.cc b/Shower/Dipole/Kernels/DipoleSplittingKernel.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Kernels/DipoleSplittingKernel.cc @@ -0,0 +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), + 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 << 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 >> theDetuning + >> theFlavour >> theMCCheck >> theStrictLargeN + >> theFactorizationScaleFactor + >> theRenormalizationScaleFactor + >> iunit(theRenormalizationScaleFreeze,GeV) + >> iunit(theFactorizationScaleFreeze,GeV) + >> theVirtualitySplittingScale; +} + +double DipoleSplittingKernel::alphaPDF(const DipoleSplittingInfo& split, + Energy optScale, + double rScaleFactor, + double fScaleFactor) const { + + Energy pt = optScale == ZERO ? split.lastPt() : optScale; + + Energy2 scale = ZERO; + if ( !virtualitySplittingScale() ) { + scale = sqr(pt) + sqr(theScreeningScale); + } else { + scale = sqr(splittingKinematics()->QFromPt(pt,split)) + sqr(theScreeningScale); + } + + Energy2 rScale = sqr(theRenormalizationScaleFactor*rScaleFactor)*scale; + rScale = rScale > sqr(renormalizationScaleFreeze()) ? rScale : sqr(renormalizationScaleFreeze()); + + Energy2 fScale = sqr(theFactorizationScaleFactor*fScaleFactor)*scale; + fScale = fScale > sqr(factorizationScaleFreeze()) ? fScale : sqr(factorizationScaleFreeze()); + + double alphas = 1.0; + double pdf = 1.0; + + // check if we are potentially reweighting and cache evaluations + bool evaluatePDF = true; + bool evaluateAlphaS = true; + bool variations = + !ShowerHandler::currentHandler()->showerVariations().empty() && + !presampling; + if ( variations ) { + /* + 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 ( 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/Shower/Dipole/Kernels/DipoleSplittingKernel.h rename from DipoleShower/Kernels/DipoleSplittingKernel.h rename to Shower/Dipole/Kernels/DipoleSplittingKernel.h --- a/DipoleShower/Kernels/DipoleSplittingKernel.h +++ b/Shower/Dipole/Kernels/DipoleSplittingKernel.h @@ -1,495 +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" +#include "Herwig/Shower/Dipole/Utility/PDFRatio.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" +#include "Herwig/Shower/Dipole/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&) { presampling = true; } /** * Inform this splitting kernel, that it is not being * presampled until a call to startPresampling */ virtual void stopPresampling(const DipoleIndex&) { presampling = false; } /** * Return the number of points to presample this * splitting generator. */ unsigned long presamplingPoints() const { return thePresamplingPoints; } /** * Return the maximum number of trials * to generate a splitting. */ unsigned long maxtry() const { return theMaxtry; } /** * Return the number of accepted points after which the grid should * be frozen */ unsigned long freezeGrid() const { return theFreezeGrid; } /** * Set the number of accepted points after which the grid should * be frozen */ void freezeGrid(unsigned long n) { theFreezeGrid = n; } /** * Set a detuning factor to be applied to the sampling overestimate kernel */ void detuning(double d) { theDetuning = d; } /** * Return the detuning factor applied to the sampling overestimate kernel */ double detuning() const { return theDetuning; } /** * Evaluate this splitting kernel for the given * dipole splitting. */ virtual double evaluate(const DipoleSplittingInfo&) const = 0; /** * 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, 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/Kernels/FFMgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc rename from DipoleShower/Kernels/FFMgx2ggxDipoleKernel.cc rename to Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FFMgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h rename from DipoleShower/Kernels/FFMgx2ggxDipoleKernel.h rename to Shower/Dipole/Kernels/FFMgx2ggxDipoleKernel.h diff --git a/DipoleShower/Kernels/FFMgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.cc rename from DipoleShower/Kernels/FFMgx2qqxDipoleKernel.cc rename to Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FFMgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.h rename from DipoleShower/Kernels/FFMgx2qqxDipoleKernel.h rename to Shower/Dipole/Kernels/FFMgx2qqxDipoleKernel.h diff --git a/DipoleShower/Kernels/FFMqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.cc rename from DipoleShower/Kernels/FFMqx2qgxDipoleKernel.cc rename to Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FFMqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.h rename from DipoleShower/Kernels/FFMqx2qgxDipoleKernel.h rename to Shower/Dipole/Kernels/FFMqx2qgxDipoleKernel.h diff --git a/DipoleShower/Kernels/FFgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc rename from DipoleShower/Kernels/FFgx2ggxDipoleKernel.cc rename to Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FFgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h rename from DipoleShower/Kernels/FFgx2ggxDipoleKernel.h rename to Shower/Dipole/Kernels/FFgx2ggxDipoleKernel.h diff --git a/DipoleShower/Kernels/FFgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.cc rename from DipoleShower/Kernels/FFgx2qqxDipoleKernel.cc rename to Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FFgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.h rename from DipoleShower/Kernels/FFgx2qqxDipoleKernel.h rename to Shower/Dipole/Kernels/FFgx2qqxDipoleKernel.h diff --git a/DipoleShower/Kernels/FFqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.cc rename from DipoleShower/Kernels/FFqx2qgxDipoleKernel.cc rename to Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FFqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.h rename from DipoleShower/Kernels/FFqx2qgxDipoleKernel.h rename to Shower/Dipole/Kernels/FFqx2qgxDipoleKernel.h diff --git a/DipoleShower/Kernels/FIMgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.cc rename from DipoleShower/Kernels/FIMgx2qqxDipoleKernel.cc rename to Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FIMgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.h rename from DipoleShower/Kernels/FIMgx2qqxDipoleKernel.h rename to Shower/Dipole/Kernels/FIMgx2qqxDipoleKernel.h diff --git a/DipoleShower/Kernels/FIMqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.cc rename from DipoleShower/Kernels/FIMqx2qgxDipoleKernel.cc rename to Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FIMqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.h rename from DipoleShower/Kernels/FIMqx2qgxDipoleKernel.h rename to Shower/Dipole/Kernels/FIMqx2qgxDipoleKernel.h diff --git a/DipoleShower/Kernels/FIgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc rename from DipoleShower/Kernels/FIgx2ggxDipoleKernel.cc rename to Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FIgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h rename from DipoleShower/Kernels/FIgx2ggxDipoleKernel.h rename to Shower/Dipole/Kernels/FIgx2ggxDipoleKernel.h diff --git a/DipoleShower/Kernels/FIgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.cc rename from DipoleShower/Kernels/FIgx2qqxDipoleKernel.cc rename to Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FIgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.h rename from DipoleShower/Kernels/FIgx2qqxDipoleKernel.h rename to Shower/Dipole/Kernels/FIgx2qqxDipoleKernel.h diff --git a/DipoleShower/Kernels/FIqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.cc rename from DipoleShower/Kernels/FIqx2qgxDipoleKernel.cc rename to Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.cc diff --git a/DipoleShower/Kernels/FIqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.h rename from DipoleShower/Kernels/FIqx2qgxDipoleKernel.h rename to Shower/Dipole/Kernels/FIqx2qgxDipoleKernel.h diff --git a/DipoleShower/Kernels/IFMgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.cc rename from DipoleShower/Kernels/IFMgx2ggxDipoleKernel.cc rename to Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IFMgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.h rename from DipoleShower/Kernels/IFMgx2ggxDipoleKernel.h rename to Shower/Dipole/Kernels/IFMgx2ggxDipoleKernel.h diff --git a/DipoleShower/Kernels/IFMgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.cc rename from DipoleShower/Kernels/IFMgx2qqxDipoleKernel.cc rename to Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IFMgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h rename from DipoleShower/Kernels/IFMgx2qqxDipoleKernel.h rename to Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h diff --git a/DipoleShower/Kernels/IFMqx2gqxDipoleKernel.cc b/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.cc rename from DipoleShower/Kernels/IFMqx2gqxDipoleKernel.cc rename to Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IFMqx2gqxDipoleKernel.h b/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h rename from DipoleShower/Kernels/IFMqx2gqxDipoleKernel.h rename to Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h diff --git a/DipoleShower/Kernels/IFMqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.cc rename from DipoleShower/Kernels/IFMqx2qgxDipoleKernel.cc rename to Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IFMqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h rename from DipoleShower/Kernels/IFMqx2qgxDipoleKernel.h rename to Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h diff --git a/DipoleShower/Kernels/IFgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.cc rename from DipoleShower/Kernels/IFgx2ggxDipoleKernel.cc rename to Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IFgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.h rename from DipoleShower/Kernels/IFgx2ggxDipoleKernel.h rename to Shower/Dipole/Kernels/IFgx2ggxDipoleKernel.h diff --git a/DipoleShower/Kernels/IFgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.cc rename from DipoleShower/Kernels/IFgx2qqxDipoleKernel.cc rename to Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IFgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.h rename from DipoleShower/Kernels/IFgx2qqxDipoleKernel.h rename to Shower/Dipole/Kernels/IFgx2qqxDipoleKernel.h diff --git a/DipoleShower/Kernels/IFqx2gqxDipoleKernel.cc b/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.cc rename from DipoleShower/Kernels/IFqx2gqxDipoleKernel.cc rename to Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IFqx2gqxDipoleKernel.h b/Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.h rename from DipoleShower/Kernels/IFqx2gqxDipoleKernel.h rename to Shower/Dipole/Kernels/IFqx2gqxDipoleKernel.h diff --git a/DipoleShower/Kernels/IFqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.cc rename from DipoleShower/Kernels/IFqx2qgxDipoleKernel.cc rename to Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IFqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.h rename from DipoleShower/Kernels/IFqx2qgxDipoleKernel.h rename to Shower/Dipole/Kernels/IFqx2qgxDipoleKernel.h diff --git a/DipoleShower/Kernels/IIgx2ggxDipoleKernel.cc b/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.cc rename from DipoleShower/Kernels/IIgx2ggxDipoleKernel.cc rename to Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IIgx2ggxDipoleKernel.h b/Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.h rename from DipoleShower/Kernels/IIgx2ggxDipoleKernel.h rename to Shower/Dipole/Kernels/IIgx2ggxDipoleKernel.h diff --git a/DipoleShower/Kernels/IIgx2qqxDipoleKernel.cc b/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.cc rename from DipoleShower/Kernels/IIgx2qqxDipoleKernel.cc rename to Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IIgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.h rename from DipoleShower/Kernels/IIgx2qqxDipoleKernel.h rename to Shower/Dipole/Kernels/IIgx2qqxDipoleKernel.h diff --git a/DipoleShower/Kernels/IIqx2gqxDipoleKernel.cc b/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.cc rename from DipoleShower/Kernels/IIqx2gqxDipoleKernel.cc rename to Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IIqx2gqxDipoleKernel.h b/Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.h rename from DipoleShower/Kernels/IIqx2gqxDipoleKernel.h rename to Shower/Dipole/Kernels/IIqx2gqxDipoleKernel.h diff --git a/DipoleShower/Kernels/IIqx2qgxDipoleKernel.cc b/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.cc rename from DipoleShower/Kernels/IIqx2qgxDipoleKernel.cc rename to Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.cc diff --git a/DipoleShower/Kernels/IIqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.h rename from DipoleShower/Kernels/IIqx2qgxDipoleKernel.h rename to Shower/Dipole/Kernels/IIqx2qgxDipoleKernel.h diff --git a/DipoleShower/Kernels/Makefile.am b/Shower/Dipole/Kernels/Makefile.am rename from DipoleShower/Kernels/Makefile.am rename to Shower/Dipole/Kernels/Makefile.am diff --git a/DipoleShower/Kinematics/DipoleSplittingKinematics.cc b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc rename from DipoleShower/Kinematics/DipoleSplittingKinematics.cc rename to Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc --- a/DipoleShower/Kinematics/DipoleSplittingKinematics.cc +++ b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.cc @@ -1,274 +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 "Herwig/Shower/Dipole/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); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverZ ) { pair kw = generate(inverse(0.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverOneMinusZ ) { pair kw = generate(inverse(1.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } if ( sampling == OneOverZOneMinusZ ) { pair kw = generate(inverse(0.0,zLims.first,zLims.second) + inverse(1.0,zLims.first,zLims.second),r); if ( kw.second != 0. ) { weight *= kw.second; return kw.first; } else { assert( kw.first < zLims.first || kw.first > zLims.second ); weight *= kw.second; return -1.; } } weight = 0.0; return 0.0; } Lorentz5Momentum DipoleSplittingKinematics::getKt(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2, Energy pt, double phi, bool spacelike) const { Lorentz5Momentum P; 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/DipoleSplittingKinematics.h b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h rename from DipoleShower/Kinematics/DipoleSplittingKinematics.h rename to Shower/Dipole/Kinematics/DipoleSplittingKinematics.h --- a/DipoleShower/Kinematics/DipoleSplittingKinematics.h +++ b/Shower/Dipole/Kinematics/DipoleSplittingKinematics.h @@ -1,507 +1,507 @@ // -*- 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. // #ifndef HERWIG_DipoleSplittingKinematics_H #define HERWIG_DipoleSplittingKinematics_H // // This is the declaration of the DipoleSplittingKinematics class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Vectors/Lorentz5Vector.h" -#include "Herwig/DipoleShower/Utility/DipoleMCCheck.h" +#include "Herwig/Shower/Dipole/Utility/DipoleMCCheck.h" namespace Herwig { using namespace ThePEG; class DipoleIndex; class DipoleSplittingInfo; class DipoleSplittingKernel; /** * \ingroup DipoleShower * \author Simon Platzer * * \brief DipoleSplittingKinematics is the base class for dipole splittings * as performed in the dipole shower. * * @see \ref DipoleSplittingKinematicsInterfaces "The interfaces" * defined for DipoleSplittingKinematics. */ class DipoleSplittingKinematics: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DipoleSplittingKinematics(); /** * The destructor. */ virtual ~DipoleSplittingKinematics(); //@} public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo&) const { return make_pair(0.0,1.0); } /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo&) const { return make_pair(0.0,1.0); } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { return sqrt(2.*pEmitter*pSpectator); } /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const = 0; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const = 0; /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const = 0; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const = 0; /** * Return the infrared cutoff. */ virtual Energy IRCutoff() const { return theIRCutoff; } /** * Return the minimum momentum fraction for * incoming partons */ double xMin() const { return theXMin; } /** * Generate a pt */ Energy generatePt(double r, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, double& weight) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const = 0; /** * Enumerate the variants of sampling z */ enum ZSamplingOptions { FlatZ = 0, OneOverZ, OneOverOneMinusZ, OneOverZOneMinusZ }; /** * Generate a z value flat */ double generateZ(double r, Energy pt, int sampling, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split, double& weight) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel&) = 0; /** * Get the splitting phasespace weight associated to * the last call to generateSplitting. This is taken to * be the single particle phasespace times 16 \pi^2 divided * by the relevant propagator invariant. */ double jacobian() const { return theJacobian; } /** * Return true, if this splitting kinematics * class is capable of delivering an overestimate * to the jacobian. */ virtual bool haveOverestimate() const { return false; } /** * Return the overestimated jacobian for the * last generated parameters. */ virtual double jacobianOverestimate() const { return -1.; } /** * Return the last generated pt */ Energy lastPt() const { return theLastPt; } /** * Return the last generated momentum fraction. */ double lastZ() const { return theLastZ; } /** * Return the last generated azimuthal angle. */ double lastPhi() const { return theLastPhi; } /** * Return the momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ double lastEmitterZ() const { return theLastEmitterZ; } /** * Return the momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ double lastSpectatorZ() const { return theLastSpectatorZ; } /** * Return any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ const vector& lastSplittingParameters() const { return theLastSplittingParameters; } /** * Complete a DipoleSplittingInfo object with * the parameters generated by the last call to * generateSplitting() */ void prepareSplitting(DipoleSplittingInfo& dInfo); public: /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) = 0; /** * Return the emitter's momentum after the splitting. */ const Lorentz5Momentum& lastEmitterMomentum() const { return theEmitterMomentum; } /** * Return the spectator's momentum after the splitting. */ const Lorentz5Momentum& lastSpectatorMomentum() const { return theSpectatorMomentum; } /** * Return the emission's momentum. */ const Lorentz5Momentum& lastEmissionMomentum() const { return theEmissionMomentum; } /* * Return true, if there is a transformation which should * be applied to all other final state particles except the ones * involved in the splitting after having performed the splitting */ virtual bool doesTransform () const { return false; } /* * perform the transformation, if existing */ virtual Lorentz5Momentum transform (const Lorentz5Momentum& p) const { return p; } protected: /** * Calculate a transverse momentum for the given momenta, * invariant pt and azimuth. */ Lorentz5Momentum getKt(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2, Energy pt, double phi, bool spacelike = false) const; /** * Set the splitting phasespace weight associated to * the last call to generateSplitting. This is taken to * be the single particle phasespace times 16 \pi^2 divided * by the relevant propagator invariant. */ void jacobian(double w) { theJacobian = w; } /** * Set the last generated pt */ void lastPt(Energy p) { theLastPt = p; } /** * Set the last generated momentum fraction. */ void lastZ(double z) { theLastZ = z; } /** * Set the last generated azimuthal angle. */ void lastPhi(double p) { theLastPhi = p; } /** * Set the momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ void lastEmitterZ(double z) { theLastEmitterZ = z; } /** * Set the momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ void lastSpectatorZ(double z) { theLastSpectatorZ = z; } /** * Access any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ vector& splittingParameters() { return theLastSplittingParameters; } /** * Set the emitter's momentum after the splitting. */ void emitterMomentum(const Lorentz5Momentum& p) { theEmitterMomentum = p; } /** * Set the spectator's momentum after the splitting. */ void spectatorMomentum(const Lorentz5Momentum& p) { theSpectatorMomentum = p; } /** * Set the emission's momentum. */ void emissionMomentum(const Lorentz5Momentum& p) { theEmissionMomentum = p; } public: /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The infrared cutoff associated to this * splitting kinematics. */ Energy theIRCutoff; /** * The minimum momentum fraction for * incoming partons */ double theXMin; /** * The last calculated splitting phase space weight. */ double theJacobian; /** * The last generated pt */ Energy theLastPt; /** * The last generated momentum fraction. */ double theLastZ; /** * The last generated azimuthal angle. */ double theLastPhi; /** * The momentum fraction, by which the emitter's * momentum fraction should be divided after the splitting. */ double theLastEmitterZ; /** * The momentum fraction, by which the spectator's * momentum fraction should be divided after the splitting. */ double theLastSpectatorZ; /** * Any additional parameters needed to * evaluate the splitting kernel or to generate the * full splitting. */ vector theLastSplittingParameters; /** * The emitter's momentum after the splitting. */ Lorentz5Momentum theEmitterMomentum; /** * The emission's momentum after the splitting. */ Lorentz5Momentum theEmissionMomentum; /** * The spectator's momentum after the splitting. */ Lorentz5Momentum theSpectatorMomentum; protected: /** * Pointer to a check histogram object */ Ptr::ptr theMCCheck; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class. */ static AbstractClassDescription initDipoleSplittingKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DipoleSplittingKinematics & operator=(const DipoleSplittingKinematics &); }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DipoleSplittingKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DipoleSplittingKinematics. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DipoleSplittingKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::DipoleSplittingKinematics"; } /** * The name of a file containing the dynamic library where the class * DipoleSplittingKinematics is implemented. It may also include several, space-separated, * libraries if the class DipoleSplittingKinematics depends on other classes (base classes * excepted). In this case the listed libraries will be dynamically * linked in the order they are specified. */ static string library() { return "HwDipoleShower.so"; } }; /** @endcond */ } #endif /* HERWIG_DipoleSplittingKinematics_H */ diff --git a/DipoleShower/Kinematics/FFLightKinematics.cc b/Shower/Dipole/Kinematics/FFLightKinematics.cc rename from DipoleShower/Kinematics/FFLightKinematics.cc rename to Shower/Dipole/Kinematics/FFLightKinematics.cc --- a/DipoleShower/Kinematics/FFLightKinematics.cc +++ b/Shower/Dipole/Kinematics/FFLightKinematics.cc @@ -1,173 +1,173 @@ // -*- C++ -*- // // FFLightKinematics.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 FFLightKinematics class. // #include "FFLightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" -#include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" using namespace Herwig; FFLightKinematics::FFLightKinematics() : DipoleSplittingKinematics() {} FFLightKinematics::~FFLightKinematics() {} IBPtr FFLightKinematics::clone() const { return new_ptr(*this); } IBPtr FFLightKinematics::fullclone() const { return new_ptr(*this); } Energy FFLightKinematics::ptMax(Energy dScale, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale/2.; } Energy FFLightKinematics::QMax(Energy dScale, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale; } Energy FFLightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale*sqrt(z*(1.-z)); } Energy FFLightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale/sqrt(z*(1.-z)); } pair FFLightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { double s = sqrt(1.-sqr(pt/dInfo.hardPt())); return make_pair(0.5*(1.-s),0.5*(1.+s)); } bool FFLightKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split) { double weight = 1.0; Energy pt = generatePt(kappa,info.scale(), info.emitterX(),info.spectatorX(), info.index(),split, weight); if ( pt < IRCutoff() || pt > info.hardPt() ) { jacobian(0.0); return false; } double z = 0.0; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { z = generateZ(xi,pt,FlatZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } } else { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } double y = sqr(pt/info.scale())/(z*(1.-z)); if ( z < 0.0 || z > 1.0 || y < 0.0 || y > 1.0 ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian(weight*(1.-y)); lastPt(pt); lastZ(z); lastPhi(phi); if ( theMCCheck ) theMCCheck->book(1.,1.,info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void FFLightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); double y = sqr(pt / (pEmitter+pSpectator).m()) / (z*(1.-z)); Lorentz5Momentum kt = getKt(pEmitter, pSpectator, pt, dInfo.lastPhi()); Lorentz5Momentum em = z*pEmitter + y*(1.-z)*pSpectator + kt; em.setMass(0.*GeV); em.rescaleEnergy(); Lorentz5Momentum emm = (1.-z)*pEmitter + z*y*pSpectator - kt; emm.setMass(0.*GeV); emm.rescaleEnergy(); Lorentz5Momentum spe = (1.-y)*pSpectator; 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 FFLightKinematics::persistentOutput(PersistentOStream & ) const { } void FFLightKinematics::persistentInput(PersistentIStream & , int) { } ClassDescription FFLightKinematics::initFFLightKinematics; // Definition of the static class description member. void FFLightKinematics::Init() { static ClassDocumentation documentation ("FFLightKinematics implements massless splittings " "off a final-final dipole."); } diff --git a/DipoleShower/Kinematics/FFLightKinematics.h b/Shower/Dipole/Kinematics/FFLightKinematics.h rename from DipoleShower/Kinematics/FFLightKinematics.h rename to Shower/Dipole/Kinematics/FFLightKinematics.h diff --git a/DipoleShower/Kinematics/FFMassiveKinematics.cc b/Shower/Dipole/Kinematics/FFMassiveKinematics.cc rename from DipoleShower/Kinematics/FFMassiveKinematics.cc rename to Shower/Dipole/Kinematics/FFMassiveKinematics.cc --- a/DipoleShower/Kinematics/FFMassiveKinematics.cc +++ b/Shower/Dipole/Kinematics/FFMassiveKinematics.cc @@ -1,343 +1,343 @@ // -*- C++ -*- // // FFMassiveKinematics.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 FFMassiveKinematics class. // #include "FFMassiveKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" -#include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" -#include "Herwig/DipoleShower/Kernels/DipoleSplittingKernel.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" +#include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" // TODO: remove after verification // only for checking for NaN or inf #include using namespace Herwig; FFMassiveKinematics::FFMassiveKinematics() : DipoleSplittingKinematics() {} FFMassiveKinematics::~FFMassiveKinematics() {} IBPtr FFMassiveKinematics::clone() const { return new_ptr(*this); } IBPtr FFMassiveKinematics::fullclone() const { return new_ptr(*this); } pair FFMassiveKinematics::kappaSupport(const DipoleSplittingInfo&) const { return make_pair(0.0,1.0); } pair FFMassiveKinematics::xiSupport(const DipoleSplittingInfo& split) const { double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); if ( split.index().emitterData()->id() == ParticleID::g ) { if ( split.emissionData()->id() != ParticleID::g ) return make_pair(0.5*(1.-c),0.5*(1.+c)); double b = log((1.+c)/(1.-c)); return make_pair(-b,b); } return make_pair(-log(0.5*(1.+c)),-log(0.5*(1.-c))); } Energy FFMassiveKinematics::dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { return (pEmitter+pSpectator).m(); } Energy FFMassiveKinematics::ptMax(Energy dScale, double, double, const DipoleIndex& ind, const DipoleSplittingKernel& split) const { double mui = split.emitter(ind)->mass() / dScale; double mu = split.emission(ind)->mass() / dScale; double muj = split.spectator(ind)->mass() / dScale; double mui2 = sqr( mui ), mu2 = sqr( mu ), muj2 = sqr( muj ); return rootOfKallen( mui2, mu2, sqr(1.-muj) ) / ( 2.-2.*sqrt(muj2) ) * dScale; } Energy FFMassiveKinematics::QMax(Energy dScale, double, double, const DipoleIndex& ind, const DipoleSplittingKernel&) const { assert(false && "implementation missing"); double Muj = ind.spectatorData()->mass() / dScale; return dScale * ( 1.-2.*Muj+sqr(Muj) ); } Energy FFMassiveKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { // from Martin's thesis double z = split.lastZ(); Energy mi = split.emitterData()->mass(); Energy m = split.emissionData()->mass(); Energy2 pt2 = z*(1.-z)*sqr(scale) - (1-z)*sqr(mi) - z*sqr(m); assert(pt2 >= ZERO); return sqrt(pt2); } Energy FFMassiveKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { // from Martin's thesis double z = split.lastZ(); Energy mi = split.emitterData()->mass(); Energy m = split.emissionData()->mass(); Energy2 Q2 = (sqr(scale) + (1-z)*sqr(mi) + z*sqr(m))/(z*(1.-z)); return sqrt(Q2); } double FFMassiveKinematics::ptToRandom(Energy pt, Energy, double,double, const DipoleIndex&, const DipoleSplittingKernel&) const { return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); } // own kinematics close to Dinsdale,Ternick,Weinzierl bool FFMassiveKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) { Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); if ( pt > info.hardPt() || pt < IRCutoff() ) { jacobian(0.0); return false; } double z; double mapZJacobian; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { z = xi; mapZJacobian = 1.; } else { z = exp(xi)/(1.+exp(xi)); mapZJacobian = z*(1.-z); } } else { z = 1.-exp(-xi); mapZJacobian = 1.-z; } // masses double mui2 = sqr( info.emitterData()->mass() / info.scale() ); double mu2 = sqr( info.emissionData()->mass() / info.scale() ); double muj2 = sqr( info.spectatorData()->mass() / info.scale() ); double Mui2 = 0.; if ( info.emitterData()->id() + info.emissionData()->id() == 0 ) Mui2 = 0.; // gluon else Mui2 = mui2; // (anti)quark double Muj2 = muj2; // new: 2011-08-31 // 2011-11-08: this does happen if( sqrt(mui2)+sqrt(mu2)+sqrt(muj2) > 1. ){ jacobian(0.0); return false; } double bar = 1.-mui2-mu2-muj2; double y = ( sqr( pt / info.scale() ) + sqr(1.-z)*mui2 + z*z*mu2 ) / (z*(1.-z)*bar); // do this here for simplicity Energy ptmax1 = rootOfKallen( mui2, mu2, sqr(1.-sqrt(muj2)) ) / ( 2.-2.*sqrt(muj2) ) * info.scale(); Energy auxHardPt = ptmax1 > info.hardPt() ? info.hardPt() : ptmax1; // 2011-11-09 assert(ptmax1>=info.hardPt()); // phasespace constraint to incorporate ptMax double zp1 = ( 1.+mui2-mu2+muj2-2.*sqrt(muj2) + rootOfKallen(mui2,mu2,sqr(1-sqrt(muj2))) * sqrt( 1.-sqr(pt/auxHardPt) ) ) / ( 2.*sqr(1.-sqrt(muj2)) ); double zm1 = ( 1.+mui2-mu2+muj2-2.*sqrt(muj2) - rootOfKallen(mui2,mu2,sqr(1-sqrt(muj2))) * sqrt( 1.-sqr(pt/auxHardPt) ) ) / ( 2.*sqr(1.-sqrt(muj2)) ); if ( z > zp1 || z < zm1 || pt > auxHardPt) { jacobian(0.0); return false; } // kinematic phasespace boundaries for (y,z) // same as in Dittmaier hep-ph/9904440v2 (equivalent to CS) double ym = 2.*sqrt(mui2)*sqrt(mu2)/bar; double yp = 1. - 2.*sqrt(muj2)*(1.-sqrt(muj2))/bar; if ( y < ym || y > yp ) { jacobian(0.0); return false; } double zm = ( (2.*mui2+bar*y)*(1.-y) - sqrt(y*y-ym*ym)*sqrt(sqr(2.*muj2+bar-bar*y)-4.*muj2) ) / ( 2.*(1.-y)*(mui2+mu2+bar*y) ); double zp = ( (2.*mui2+bar*y)*(1.-y) + sqrt(y*y-ym*ym)*sqrt(sqr(2.*muj2+bar-bar*y)-4.*muj2) ) / ( 2.*(1.-y)*(mui2+mu2+bar*y) ); if ( z < zm || z > zp ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian( 2. * mapZJacobian * (1.-y) * log(0.5 * generator()->maximumCMEnergy()/IRCutoff()) * bar / rootOfKallen(1.,Mui2,Muj2) ); lastPt(pt); lastZ(z); lastPhi(phi); if ( theMCCheck ) theMCCheck->book(1.,1.,info.scale(),info.hardPt(),pt,z,jacobian()); return true; } // kinematics close to Dinsdale,Ternick,Weinzierl // revised 2011-08-22 // revised 2011-11-06 void FFMassiveKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { double z = dInfo.lastZ(); Energy pt = dInfo.lastPt(); // masses double mui2 = sqr( dInfo.emitterData()->mass() / dInfo.scale() ); double mu2 = sqr( dInfo.emissionData()->mass() / dInfo.scale() ); double muj2 = sqr( dInfo.spectatorData()->mass() / dInfo.scale() ); double y = ( sqr( pt / dInfo.scale() ) + sqr(1.-z)*mui2 + z*z*mu2 ) / (z*(1.-z)*(1.-mui2-mu2-muj2)); Energy2 sbar = sqr(dInfo.scale()) *(1.-mui2-mu2-muj2); // CMF: particle energies Energy Ei = ( sbar*(1.-(1.-z)*(1.-y)) + 2.*sqr(dInfo.scale())*mui2 ) / (2.*dInfo.scale()); Energy E = ( sbar*(1.- z *(1.-y)) + 2.*sqr(dInfo.scale())*mu2 ) / (2.*dInfo.scale()); Energy Ej = ( sbar*(1.- y ) + 2.*sqr(dInfo.scale())*muj2 ) / (2.*dInfo.scale()); // CMF: momenta in z-direction (axis of pEmitter & pSpectator) Energy qi3 = (2.*Ei*Ej-z*(1.-y)*sbar ) / 2./sqrt(Ej*Ej-sqr(dInfo.scale())*muj2); Energy q3 = (2.*E *Ej-(1.-z)*(1.-y)*sbar) / 2./sqrt(Ej*Ej-sqr(dInfo.scale())*muj2); Energy qj3 = sqrt( sqr(Ej) - sqr(dInfo.scale())*muj2 ); // get z axis in the dipole's CMF which is parallel to pSpectator Boost toCMF = (pEmitter+pSpectator).findBoostToCM(); Lorentz5Momentum pjAux = pSpectator; pjAux.boost(toCMF); ThreeVector pjAxis = pjAux.vect().unit(); // set the momenta in this special reference frame // note that pt might in some cases differ from the physical pt! // phi is defined exactly as in getKt Energy ptResc = sqrt( sqr(Ei)-sqr(dInfo.scale())*mui2-sqr(qi3) ); Lorentz5Momentum em ( ptResc*cos(dInfo.lastPhi()), -ptResc*sin(dInfo.lastPhi()), qi3, Ei ); Lorentz5Momentum emm ( -ptResc*cos(dInfo.lastPhi()), ptResc*sin(dInfo.lastPhi()), q3, E ); Lorentz5Momentum spe ( 0.*GeV, 0.*GeV, qj3, Ej ); // output the mismatch between pt and physical pt // ofstream output1("ptDiffOnPtAxis-uub-m.dat",ofstream::app); // ofstream output2("ptDiffOnCosAxis-uub-m.dat",ofstream::app); // if( abs(dInfo.spectatorData()->id())==5 && dInfo.emitterData()->id()+dInfo.emissionData()->id()==0 && // abs(dInfo.emitterData()->id())==1 ) { // output1 << pt/dInfo.scale() << " " << abs(ptResc-pt)/(ptResc+pt) << " " << endl; // output2 << em.vect().unit()*emm.vect().unit() << " " << abs(ptResc-pt)/(ptResc+pt) << " " << endl; // } // output1.close(); output2.close(); // rotate back em.rotateUz (pjAxis); emm.rotateUz(pjAxis); spe.rotateUz(pjAxis); // boost back em.boost (-toCMF); emm.boost(-toCMF); spe.boost(-toCMF); // mass shells, rescale energy em.setMass(dInfo.scale()*sqrt(mui2)); em.rescaleEnergy(); emm.setMass(dInfo.scale()*sqrt(mu2)); emm.rescaleEnergy(); spe.setMass(dInfo.scale()*sqrt(muj2)); spe.rescaleEnergy(); // book emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); // TODO: remove // 2011-11-09: never occurred if(em.t()/GeV>=0. && emm.t()/GeV>=0. && spe.t()/GeV>=0.); else cout << "FFMassiveKinematics::generateKinematics momenta corrupt" << endl; // 2011-11-03 LEP run with full masses: // x,y,t no problem // z order > 5.e-7 happend 41 times in 10000 runs // maximum was 2.5e-6 // double order=2.4e-6; // Lorentz5Momentum pDif=em+emm+spe-pEmitter-pSpectator, pSum=em+emm+spe+pEmitter+pSpectator; // if(abs(pDif.x()/(pSum.x()==ZERO ? 1.*GeV : pSum.x())) FFMassiveKinematics::initFFMassiveKinematics; // Definition of the static class description member. void FFMassiveKinematics::Init() { static ClassDocumentation documentation ("FFMassiveKinematics implements massive splittings " "off a final-final dipole."); } diff --git a/DipoleShower/Kinematics/FFMassiveKinematics.h b/Shower/Dipole/Kinematics/FFMassiveKinematics.h rename from DipoleShower/Kinematics/FFMassiveKinematics.h rename to Shower/Dipole/Kinematics/FFMassiveKinematics.h diff --git a/DipoleShower/Kinematics/FILightKinematics.cc b/Shower/Dipole/Kinematics/FILightKinematics.cc rename from DipoleShower/Kinematics/FILightKinematics.cc rename to Shower/Dipole/Kinematics/FILightKinematics.cc --- a/DipoleShower/Kinematics/FILightKinematics.cc +++ b/Shower/Dipole/Kinematics/FILightKinematics.cc @@ -1,180 +1,180 @@ // -*- C++ -*- // // FILightKinematics.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 FILightKinematics class. // #include "FILightKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" -#include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" using namespace Herwig; FILightKinematics::FILightKinematics() : DipoleSplittingKinematics() {} FILightKinematics::~FILightKinematics() {} IBPtr FILightKinematics::clone() const { return new_ptr(*this); } IBPtr FILightKinematics::fullclone() const { return new_ptr(*this); } Energy FILightKinematics::ptMax(Energy dScale, double, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale * sqrt((1.-specX)/specX) /2.; } Energy FILightKinematics::QMax(Energy dScale, double, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const { return dScale * sqrt((1.-specX)/specX); } Energy FILightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale*sqrt(z*(1.-z)); } Energy FILightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { double z = split.lastZ(); return scale/sqrt(z*(1.-z)); } pair FILightKinematics::zBoundaries(Energy pt, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel&) const { double s = sqrt(1.-sqr(pt/dInfo.hardPt())); return make_pair(0.5*(1.-s),0.5*(1.+s)); } bool FILightKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split) { if ( 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.emissionData()->id() != ParticleID::g ) { z = generateZ(xi,pt,FlatZ, info,split,weight); } else { z = generateZ(xi,pt,OneOverZOneMinusZ, info,split,weight); } } else { z = generateZ(xi,pt,OneOverOneMinusZ, info,split,weight); } double x = 1./(1.+sqr(pt/info.scale())/(z*(1.-z))); if ( z < 0.0 || z > 1.0 || x < info.spectatorX() || x > 1.0 ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian(weight); lastPt(pt); lastZ(z); lastPhi(phi); lastSpectatorZ(x); if ( theMCCheck ) theMCCheck->book(1.,info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void FILightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); double x = 1./(1.+sqr(pt/dInfo.scale())/(z*(1.-z))); Lorentz5Momentum kt = getKt (pSpectator, pEmitter, pt, dInfo.lastPhi(),true); Lorentz5Momentum em = z*pEmitter + (1.-z)*((1.-x)/x)*pSpectator + kt; em.setMass(0.*GeV); em.rescaleEnergy(); Lorentz5Momentum emm = (1.-z)*pEmitter + z*((1.-x)/x)*pSpectator - kt; emm.setMass(0.*GeV); emm.rescaleEnergy(); Lorentz5Momentum spe = (1./x)*pSpectator; 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 FILightKinematics::persistentOutput(PersistentOStream & ) const { } void FILightKinematics::persistentInput(PersistentIStream & , int) { } ClassDescription FILightKinematics::initFILightKinematics; // Definition of the static class description member. void FILightKinematics::Init() { static ClassDocumentation documentation ("FILightKinematics implements massless splittings " "off a final-initial dipole."); } diff --git a/DipoleShower/Kinematics/FILightKinematics.h b/Shower/Dipole/Kinematics/FILightKinematics.h rename from DipoleShower/Kinematics/FILightKinematics.h rename to Shower/Dipole/Kinematics/FILightKinematics.h diff --git a/DipoleShower/Kinematics/FIMassiveKinematics.cc b/Shower/Dipole/Kinematics/FIMassiveKinematics.cc rename from DipoleShower/Kinematics/FIMassiveKinematics.cc rename to Shower/Dipole/Kinematics/FIMassiveKinematics.cc --- a/DipoleShower/Kinematics/FIMassiveKinematics.cc +++ b/Shower/Dipole/Kinematics/FIMassiveKinematics.cc @@ -1,278 +1,278 @@ // -*- C++ -*- // // FIMassiveKinematics.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 FIMassiveKinematics class. // #include "FIMassiveKinematics.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" -#include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h" -#include "Herwig/DipoleShower/Kernels/DipoleSplittingKernel.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" +#include "Herwig/Shower/Dipole/Kernels/DipoleSplittingKernel.h" using namespace Herwig; FIMassiveKinematics::FIMassiveKinematics() : DipoleSplittingKinematics() {} FIMassiveKinematics::~FIMassiveKinematics() {} IBPtr FIMassiveKinematics::clone() const { return new_ptr(*this); } IBPtr FIMassiveKinematics::fullclone() const { return new_ptr(*this); } pair FIMassiveKinematics::kappaSupport(const DipoleSplittingInfo&) const { return make_pair(0.0,1.0); } pair FIMassiveKinematics::xiSupport(const DipoleSplittingInfo& split) const { double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); if ( split.index().emitterData()->id() == ParticleID::g ) { if ( split.emissionData()->id() != ParticleID::g ) return make_pair(0.5*(1.-c),0.5*(1.+c)); double b = log((1.+c)/(1.-c)); return make_pair(-b,b); } return make_pair(-log(0.5*(1.+c)),-log(0.5*(1.-c))); } // sbar Energy FIMassiveKinematics::dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const { return sqrt(2.*(pEmitter*pSpectator)); } Energy FIMassiveKinematics::ptMax(Energy dScale, double, double specX, const DipoleIndex& ind, const DipoleSplittingKernel& split) const { Energy mi = split.emitter(ind)->mass(), m = split.emission(ind)->mass(); Energy2 mi2 = sqr(mi), m2 = sqr(m); // Energy2 Mi2 = split.emitter(int)->id() + split.emission(int)->id() == 0 ? // 0.*GeV2 : mi2; Energy2 Mi2 = mi2 == m2 ? 0.*GeV2 : mi2; // s^star/x Energy2 s = sqr(dScale) * (1.-specX)/specX + Mi2; return .5 * sqrt(s) * rootOfKallen( s/s, mi2/s, m2/s ); } // what is this? in FF it is given by y+*dScale = sqrt( 2qi*q / bar )->max Energy FIMassiveKinematics::QMax(Energy dScale, double, double specX, const DipoleIndex&, const DipoleSplittingKernel&) const { assert(false && "implementation missing"); cout << "FIMassiveKinematics::QMax called.\n" << flush; // this is sqrt( 2qi*q ) -> max; return dScale * sqrt((1.-specX)/specX); } Energy FIMassiveKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { // from Martin's thesis double z = split.lastZ(); Energy mi = split.emitterData()->mass(); Energy m = split.emissionData()->mass(); Energy2 pt2 = z*(1.-z)*sqr(scale) - (1-z)*sqr(mi) - z*sqr(m); assert(pt2 >= ZERO); return sqrt(pt2); } Energy FIMassiveKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { // from Martin's thesis double z = split.lastZ(); Energy mi = split.emitterData()->mass(); Energy m = split.emissionData()->mass(); Energy2 Q2 = (sqr(scale) + (1-z)*sqr(mi) + z*sqr(m))/(z*(1.-z)); return sqrt(Q2); } double FIMassiveKinematics::ptToRandom(Energy pt, Energy, double,double, const DipoleIndex&, const DipoleSplittingKernel&) const { return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); } bool FIMassiveKinematics::generateSplitting(double kappa, double xi, double rphi, DipoleSplittingInfo& info, const DipoleSplittingKernel&) { if ( info.spectatorX() < xMin() ) { jacobian(0.0); return false; } Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); if ( pt > info.hardPt() || pt < IRCutoff() ) { jacobian(0.0); return false; } double z; double mapZJacobian; if ( info.index().emitterData()->id() == ParticleID::g ) { if ( info.emissionData()->id() != ParticleID::g ) { z = xi; mapZJacobian = 1.; } else { z = exp(xi)/(1.+exp(xi)); mapZJacobian = z*(1.-z); } } else { z = 1.-exp(-xi); mapZJacobian = 1.-z; } // double s = z*(1.-z); // double xs = info.spectatorX(); // double x = 1. / ( 1. + sqr(pt/info.scale()) / s ); // double zp = 0.5*(1.+sqrt(1.-sqr(pt/info.hardPt()))); // double zm = 0.5*(1.-sqrt(1.-sqr(pt/info.hardPt()))); Energy2 mi2 = sqr(info.emitterData()->mass()); Energy2 m2 = sqr(info.emissionData()->mass()); Energy2 Mi2 = info.emitterData()->id()+info.emissionData()->id() == 0 ? 0.*GeV2 : mi2; // s^star/x Energy2 s = sqr(info.scale()) * (1.-info.spectatorX())/info.spectatorX() + Mi2; double xs = info.spectatorX(); double x = 1. / ( 1. + ( sqr(pt) + (1.-z)*mi2 + z*m2 - z*(1.-z)*Mi2 ) / ( z*(1.-z)*s ) ); double zm1 = .5*( 1.+(mi2-m2)/s - rootOfKallen(s/s,mi2/s,m2/s) * sqrt( 1.-sqr(pt/info.hardPt()) ) ); double zp1 = .5*( 1.+(mi2-m2)/s + rootOfKallen(s/s,mi2/s,m2/s) * sqrt( 1.-sqr(pt/info.hardPt()) ) ); if ( // pt < IRCutoff() || // pt > info.hardPt() || z > zp1 || z < zm1 || x < xs ) { jacobian(0.0); return false; } // additional purely kinematic constraints double mui2 = x*mi2/sqr(info.scale()); double mu2 = x*m2/sqr(info.scale()); double Mui2 = x*Mi2/sqr(info.scale()); double xp = 1. + Mui2 - sqr(sqrt(mui2)+sqrt(mu2)); double root = sqr(1.-x+Mui2-mui2-mu2)-4.*mui2*mu2; if( root < 0. && root>-1e-10 ) root = 0.; else if (root <0. ) { jacobian(0.0); return false; } root = sqrt(root); double zm = .5*( 1.-x+Mui2+mui2-mui2 - root ) / (1.-x+Mui2); double zp = .5*( 1.-x+Mui2+mui2-mui2 + root ) / (1.-x+Mui2); if (x > xp || z > zp || z < zm ) { jacobian(0.0); return false; } double phi = 2.*Constants::pi*rphi; jacobian( 2. * mapZJacobian * log(0.5 * generator()->maximumCMEnergy()/IRCutoff())); lastPt(pt); lastZ(z); lastPhi(phi); lastSpectatorZ(x); if ( theMCCheck ) theMCCheck->book(1.,info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); return true; } void FIMassiveKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) { Energy pt = dInfo.lastPt(); double z = dInfo.lastZ(); Lorentz5Momentum kt = getKt (pSpectator, pEmitter, pt, dInfo.lastPhi(),true); Energy2 mi2 = sqr(dInfo.emitterData()->mass()); Energy2 m2 = sqr(dInfo.emissionData()->mass()); Energy2 Mi2 = dInfo.emitterData()->id() + dInfo.emissionData()->id() == 0 ? 0.*GeV2 : mi2; double xInv = ( 1. + (pt*pt+(1.-z)*mi2+z*m2-z*(1.-z)*Mi2) / (z*(1.-z)*sqr(dInfo.scale())) ); Lorentz5Momentum em = z*pEmitter + (sqr(pt)+mi2-z*z*Mi2)/(z*sqr(dInfo.scale()))*pSpectator + kt; em.setMass(sqrt(mi2)); em.rescaleEnergy(); Lorentz5Momentum emm = (1.-z)*pEmitter + (pt*pt+m2-sqr(1.-z)*Mi2)/((1.-z)*sqr(dInfo.scale()))*pSpectator - kt; emm.setMass(sqrt(m2)); emm.rescaleEnergy(); Lorentz5Momentum spe = xInv*pSpectator; spe.setMass(ZERO); spe.rescaleEnergy(); emitterMomentum(em); emissionMomentum(emm); spectatorMomentum(spe); } // If needed, insert default implementations of function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FIMassiveKinematics::persistentOutput(PersistentOStream & ) const { } void FIMassiveKinematics::persistentInput(PersistentIStream & , int) { } ClassDescription FIMassiveKinematics::initFIMassiveKinematics; // Definition of the static class description member. void FIMassiveKinematics::Init() { static ClassDocumentation documentation ("FIMassiveKinematics implements massless splittings " "off a final-initial dipole."); } diff --git a/DipoleShower/Kinematics/FIMassiveKinematics.h b/Shower/Dipole/Kinematics/FIMassiveKinematics.h rename from DipoleShower/Kinematics/FIMassiveKinematics.h rename to Shower/Dipole/Kinematics/FIMassiveKinematics.h diff --git a/Shower/Dipole/Kinematics/IFLightKinematics.cc b/Shower/Dipole/Kinematics/IFLightKinematics.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Kinematics/IFLightKinematics.cc @@ -0,0 +1,256 @@ +// -*- C++ -*- +// +// IFLightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator +// Copyright (C) 2002-2007 The Herwig Collaboration +// +// Herwig is licenced under version 2 of the GPL, see COPYING for details. +// Please respect the MCnet academic guidelines, see GUIDELINES for details. +// +// +// This is the implementation of the non-inlined, non-templated member +// functions of the IFLightKinematics class. +// + +#include "IFLightKinematics.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Interface/Switch.h" + +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" + +using namespace Herwig; + +IFLightKinematics::IFLightKinematics() + : DipoleSplittingKinematics(), theCollinearScheme(true) {} + +IFLightKinematics::~IFLightKinematics() {} + +IBPtr IFLightKinematics::clone() const { + return new_ptr(*this); +} + +IBPtr IFLightKinematics::fullclone() const { + return new_ptr(*this); +} + +Energy IFLightKinematics::ptMax(Energy dScale, + double emX, double, + const DipoleIndex&, + const DipoleSplittingKernel&) const { + return dScale * sqrt((1.-emX)/emX) /2.; +} + +Energy IFLightKinematics::QMax(Energy, + double, double, + const DipoleIndex&, + const DipoleSplittingKernel&) const { + assert(false && "add this"); + return 0.0*GeV; +} + +Energy IFLightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { + double z = split.lastZ(); + return scale*sqrt(1.-z); +} + +Energy IFLightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { + double z = split.lastZ(); + return scale/sqrt(1.-z); +} + +pair IFLightKinematics::zBoundaries(Energy pt, + const DipoleSplittingInfo& dInfo, + const DipoleSplittingKernel&) const { + double x = dInfo.emitterX(); + double s = sqrt(1.-sqr(pt/dInfo.hardPt())); + return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); +} + + +bool IFLightKinematics::generateSplitting(double kappa, double xi, double rphi, + DipoleSplittingInfo& info, + const DipoleSplittingKernel& split) { + + if ( info.emitterX() < xMin() ) { + jacobian(0.0); + return false; + } + + double weight = 1.0; + + Energy pt = generatePt(kappa,info.scale(), + info.emitterX(),info.spectatorX(), + info.index(),split, + weight); + + if ( pt < IRCutoff() || pt > info.hardPt() ) { + jacobian(0.0); + return false; + } + + double z = 0.0; + + if ( info.index().emitterData()->id() == ParticleID::g ) { + if ( info.emitterData()->id() == ParticleID::g ) { + z = generateZ(xi,pt,OneOverZOneMinusZ, + info,split,weight); + } else { + z = generateZ(xi,pt,OneOverZ, + info,split,weight); + } + } + + if ( info.index().emitterData()->id() != ParticleID::g ) { + if ( info.emitterData()->id() != ParticleID::g ) { + z = generateZ(xi,pt,OneOverOneMinusZ, + info,split,weight); + } else { + z = generateZ(xi,pt,FlatZ, + info,split,weight); + } + } + + if ( weight == 0. && z == -1. ) { + jacobian(0.0); + return false; + } + + double ratio = sqr(pt/info.scale()); + + double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); + if ( rho < 0.0 ) { + jacobian(0.0); + return false; + } + + double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); + double u = 0.5*((1.-z+ratio)/(1.-z))*(1.-sqrt(rho)); + + if ( x < info.emitterX() || x > 1. || + u < 0. || u > 1. ) { + jacobian(0.0); + return false; + } + + double phi = 2.*Constants::pi*rphi; + + jacobian(weight*(1./z)); + + lastPt(pt); + lastZ(z); + lastPhi(phi); + lastEmitterZ(x); + + if ( theMCCheck ) + theMCCheck->book(info.emitterX(),1.,info.scale(),info.hardPt(),pt,z,jacobian()); + + return true; + +} + +void IFLightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, + const Lorentz5Momentum& pSpectator, + const DipoleSplittingInfo& dInfo) { + + Energy pt = dInfo.lastPt(); + double z = dInfo.lastZ(); + + double ratio = sqr(pt)/(2.*pEmitter*pSpectator); + double rho = 1. - 4.*ratio*z*(1.-z)/sqr(1.-z+ratio); + + double x = 0.5*((1.-z+ratio)/ratio)*(1.-sqrt(rho)); + double u = 0.5*((1.-z+ratio)/(1.-z))*(1.-sqrt(rho)); + + Lorentz5Momentum kt = + getKt (pEmitter, pSpectator, pt, dInfo.lastPhi(),true); + + Lorentz5Momentum em; + Lorentz5Momentum emm; + Lorentz5Momentum spe; + + if ( !theCollinearScheme && + x > u && (1.-x)/(x-u) < 1. ) { + + assert(false); + + em = + ((1.-u)/(x-u))*pEmitter + ((u/x)*(1.-x)/(x-u))*pSpectator - kt/(x-u); + em.setMass(0.*GeV); + em.rescaleEnergy(); + + emm = + ((1.-x)/(x-u))*pEmitter + ((u/x)*(1.-u)/(x-u))*pSpectator - kt/(x-u); + emm.setMass(0.*GeV); + emm.rescaleEnergy(); + + spe = + (1.-u/x)*pSpectator; + spe.setMass(0.*GeV); + spe.rescaleEnergy(); + + } else { + + em = (1./x)*pEmitter; + + emm = ((1.-x)*(1.-u)/x)*pEmitter + u*pSpectator + kt; + emm.setMass(0.*GeV); + emm.rescaleEnergy(); + + spe = ((1.-x)*u/x)*pEmitter + (1.-u)*pSpectator - kt; + spe.setMass(0.*GeV); + spe.rescaleEnergy(); + + } + + emitterMomentum(em); + emissionMomentum(emm); + spectatorMomentum(spe); + +} + +// If needed, insert default implementations of function defined +// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). + + +void IFLightKinematics::persistentOutput(PersistentOStream &) const { + //os << theCollinearScheme; +} + +void IFLightKinematics::persistentInput(PersistentIStream &, int) { + //is >> theCollinearScheme; +} + +ClassDescription IFLightKinematics::initIFLightKinematics; +// Definition of the static class description member. + +void IFLightKinematics::Init() { + + static ClassDocumentation documentation + ("IFLightKinematics implements massless splittings " + "off a initial-final dipole."); + + /* + static Switch interfaceCollinearScheme + ("CollinearScheme", + "[experimental] Switch on or off the collinear scheme", + &IFLightKinematics::theCollinearScheme, false, false, false); + static SwitchOption 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/IFLightKinematics.h b/Shower/Dipole/Kinematics/IFLightKinematics.h rename from DipoleShower/Kinematics/IFLightKinematics.h rename to Shower/Dipole/Kinematics/IFLightKinematics.h diff --git a/Shower/Dipole/Kinematics/IFMassiveKinematics.cc b/Shower/Dipole/Kinematics/IFMassiveKinematics.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Kinematics/IFMassiveKinematics.cc @@ -0,0 +1,315 @@ +// -*- C++ -*- +// +// IFMassiveKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator +// Copyright (C) 2002-2007 The Herwig Collaboration +// +// Herwig is licenced under version 2 of the GPL, see COPYING for details. +// Please respect the MCnet academic guidelines, see GUIDELINES for details. +// +// +// This is the implementation of the non-inlined, non-templated member +// functions of the IFMassiveKinematics class. +// + +#include "IFMassiveKinematics.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Interface/Switch.h" + +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" + +using namespace Herwig; + +IFMassiveKinematics::IFMassiveKinematics() + : DipoleSplittingKinematics(), theCollinearScheme(true) {} + +IFMassiveKinematics::~IFMassiveKinematics() {} + +IBPtr IFMassiveKinematics::clone() const { + return new_ptr(*this); +} + +IBPtr IFMassiveKinematics::fullclone() const { + return new_ptr(*this); +} + +pair IFMassiveKinematics::kappaSupport(const DipoleSplittingInfo&) const { + return make_pair(0.0,1.0); +} + +pair IFMassiveKinematics::xiSupport(const DipoleSplittingInfo& split) const { + + double c = sqrt(1.-4.*sqr(IRCutoff()/generator()->maximumCMEnergy())); + + if ( split.index().emitterData()->id() == ParticleID::g ) { + if ( split.emitterData()->id() == ParticleID::g ) { + double b = log((1.+c)/(1.-c)); + return make_pair(-b,b); + } else { + return make_pair(log(0.5*(1.-c)),log(0.5*(1.+c))); + } + } + + if ( split.index().emitterData()->id() != ParticleID::g && + split.emitterData()->id() != ParticleID::g ) { + return make_pair(-log(0.5*(1.+c)),-log(0.5*(1.-c))); + } + + return make_pair(0.5*(1.-c),0.5*(1.+c)); + +} + +// sbar +Energy IFMassiveKinematics::dipoleScale(const Lorentz5Momentum& pEmitter, + const Lorentz5Momentum& pSpectator) const { + return sqrt(2.*(pEmitter*pSpectator)); +} + +Energy IFMassiveKinematics::ptMax(Energy dScale, + double emX, double, + const DipoleIndex&, + const DipoleSplittingKernel&) const { + return dScale * sqrt(1.-emX) /2.; +} + +Energy IFMassiveKinematics::QMax(Energy, + double, double, + const DipoleIndex&, + const DipoleSplittingKernel&) const { + assert(false && "add this"); + return 0.0*GeV; +} + +Energy IFMassiveKinematics::PtFromQ(Energy, const DipoleSplittingInfo&) const { + assert(false && "add this"); + return 0.0*GeV; +} + +Energy IFMassiveKinematics::QFromPt(Energy, const DipoleSplittingInfo&) const { + assert(false && "add this"); + return 0.0*GeV; +} + + +double IFMassiveKinematics::ptToRandom(Energy pt, Energy, + double,double, + const DipoleIndex&, + const DipoleSplittingKernel&) const { + return log(pt/IRCutoff()) / log(0.5 * generator()->maximumCMEnergy()/IRCutoff()); +} + +bool IFMassiveKinematics::generateSplitting(double kappa, double xi, double rphi, + DipoleSplittingInfo& info, + const DipoleSplittingKernel&) { + + if ( info.emitterX() < xMin() ) { + jacobian(0.0); + return false; + } + + Energy pt = IRCutoff() * pow(0.5 * generator()->maximumCMEnergy()/IRCutoff(),kappa); + + if ( sqr(pt) > sqr(info.hardPt())/(1.+4.*sqr(info.hardPt()/info.scale())) ) { + jacobian(0.0); + return false; + } + + double z = 0.; + double mapZJacobian = 0.; + + if ( info.index().emitterData()->id() == ParticleID::g ) { + if ( info.emitterData()->id() == ParticleID::g ) { + z = exp(xi)/(1.+exp(xi)); + mapZJacobian = z*(1.-z); + } else { + z = exp(xi); + mapZJacobian = z; + } + } + + if ( info.index().emitterData()->id() != ParticleID::g ) { + if ( info.emitterData()->id() != ParticleID::g ) { + z = 1.-exp(-xi); + mapZJacobian = 1.-z; + } else { + z = xi; + mapZJacobian = 1.; + } + } + + double ratio = sqr(pt/info.scale()); + + double x = ( z*(1.-z) - ratio ) / ( 1. - z - ratio ); + double u = ratio/(1.-z); + + double up = (1.-x) / + ( 1.-x + x*sqr(info.spectatorData()->mass()/info.scale()) ); + + if ( x < 0. || x > 1. || u > up ) { + jacobian(0.0); + return false; + } + + double xe = info.emitterX(); + double zmx = 0.5*(1.+xe-(1.-xe)*sqrt(1.-sqr(pt/info.hardPt())) ); + double zpx = 0.5*(1.+xe+(1.-xe)*sqrt(1.-sqr(pt/info.hardPt())) ); + + double xq = sqr(pt/info.hardPt()); + double zpq = 0.5*( 1.+ xq + (1.-xq)*sqrt(1.-sqr(2.*pt/info.scale())/(1.-xq) ) ); + double zmq = 0.5*( 1.+ xq - (1.-xq)*sqrt(1.-sqr(2.*pt/info.scale())/(1.-xq) ) ); + + double zp = min(zpx,zpq); + double zm = max(zmx,zmq); + + if ( pt < IRCutoff() || + pt > info.hardPt() || + z > zp || z < zm || + x < xe ) { + jacobian(0.0); + return false; + } + + double phi = 2.*Constants::pi*rphi; + + jacobian(2. * mapZJacobian * log(0.5 * generator()->maximumCMEnergy()/IRCutoff()) * (1.-z-ratio)/sqr(z*(1.-z)-ratio) ); + + lastPt(pt); + lastZ(z); + lastPhi(phi); + lastEmitterZ(x); + + if ( theMCCheck ) + theMCCheck->book(info.emitterX(),1.,info.scale(),info.hardPt(),pt,z,jacobian()); + + return true; + +} + +void IFMassiveKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, + const Lorentz5Momentum& pSpectator, + const DipoleSplittingInfo& dInfo) { + Energy2 sbar = 2.*pEmitter*pSpectator; + Energy pt = dInfo.lastPt(); + double ratio = pt*pt/sbar; + double z = dInfo.lastZ(); + double x = (z*(1.-z)-ratio)/(1.-z-ratio); + double u = ratio / (1.-z); + + pt = sqrt(sbar*u*(1.-u)*(1.-x)); + Energy magKt = + sqrt(sbar*u*(1.-u)*(1.-x)/x - sqr(u*dInfo.spectatorData()->mass())); + Lorentz5Momentum kt = + getKt (pEmitter, pSpectator, magKt, dInfo.lastPhi(),true); + + Lorentz5Momentum em; + Lorentz5Momentum emm; + Lorentz5Momentum spe; + + Energy2 mj2 = dInfo.spectatorData()->mass()*dInfo.spectatorData()->mass(); + double alpha = 1. - 2.*mj2/sbar; + + // TODO: adjust phasespace boundary condition + if (!theCollinearScheme) + assert(false); + if ( !theCollinearScheme && + x > u && (1.-x)/(x-u) < 1. ) { + + double fkt = sqrt(sqr(x-u)+4.*x*u*mj2/sbar); + + // em = + // ((1.-u)/(x-u))*pEmitter + ((u/x)*(1.-x)/(x-u))*pSpectator - kt/(x-u); + Energy2 fa = (sbar*(x+u-2.*x*z)+2.*mj2*x*u) / sqrt(sqr(x-u)+4.*x*u*mj2/sbar); + double a = (-sbar+fa) / (2.*x*(sbar-mj2)); + double ap = (sbar+alpha*fa) / (2.*x*(sbar-mj2)); + em = ap*pEmitter + a*pSpectator - fkt*kt; + em.setMass(ZERO); + em.rescaleEnergy(); + + // emm = + // ((1.-x)/(x-u))*pEmitter + ((u/x)*(1.-u)/(x-u))*pSpectator - kt/(x-u); + Energy2 fb = abs(sbar*(u*(1.-u)-x*(1.-x))+2.*mj2*x*u) / sqrt(sqr(x-u)+4.*x*u*mj2/sbar); + double b = (-sbar*(1.-x-u)+fb) / (2.*x*(sbar-mj2)); + double bp = (sbar*(1.-x-u)+alpha*fb) / (2.*x*(sbar-mj2)); + emm = bp*pEmitter + b*pSpectator + fkt*kt; + emm.setMass(ZERO); + emm.rescaleEnergy(); + + // spe = + // (1.-u/x)*pSpectator; + Energy2 fc = sqrt(sqr(sbar*(x-u))+4.*sbar*mj2*x*u); + double c = (sbar*(x-u)-2.*x*mj2+fc) / (2.*x*(sbar-mj2)); + double cp = (-sbar*(x-u)+2.*x*mj2+alpha*fc) / (2.*x*(sbar-mj2)); + spe = cp*pEmitter + c*pSpectator; + spe.setMass(dInfo.spectatorData()->mass()); + spe.rescaleEnergy(); + + } else { + + em = (1./x)*pEmitter; + em.setMass(ZERO); + em.rescaleEnergy(); + + emm = (-kt*kt-u*u*mj2)/(u*sbar)*pEmitter + + u*pSpectator - kt; + emm.setMass(ZERO); + emm.rescaleEnergy(); + + spe = (-kt*kt + mj2*u*(2.-u))/((1.-u)*sbar)*pEmitter + + (1.-u)*pSpectator + kt; + spe.setMass(dInfo.spectatorData()->mass()); + spe.rescaleEnergy(); + + } + + emitterMomentum(em); + emissionMomentum(emm); + spectatorMomentum(spe); + +} + +// If needed, insert default implementations of function defined +// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). + + +void IFMassiveKinematics::persistentOutput(PersistentOStream &) const { + //os << theCollinearScheme; +} + +void IFMassiveKinematics::persistentInput(PersistentIStream &, int) { + //is >> theCollinearScheme; +} + +ClassDescription IFMassiveKinematics::initIFMassiveKinematics; +// Definition of the static class description member. + +void IFMassiveKinematics::Init() { + + static ClassDocumentation documentation + ("IFMassiveKinematics implements massless splittings " + "off a initial-final dipole."); + + /* + static Switch interfaceCollinearScheme + ("CollinearScheme", + "[experimental] Switch on or off the collinear scheme", + &IFMassiveKinematics::theCollinearScheme, false, false, false); + static SwitchOption interfaceCollinearSchemeOn + (interfaceCollinearScheme, + "On", + "Switch on the collinear scheme.", + true); + static SwitchOption interfaceCollinearSchemeOff + (interfaceCollinearScheme, + "Off", + "Switch off the collinear scheme", + false); + + interfaceCollinearScheme.rank(-1); + */ + +} + diff --git a/DipoleShower/Kinematics/IFMassiveKinematics.h b/Shower/Dipole/Kinematics/IFMassiveKinematics.h rename from DipoleShower/Kinematics/IFMassiveKinematics.h rename to Shower/Dipole/Kinematics/IFMassiveKinematics.h diff --git a/Shower/Dipole/Kinematics/IILightKinematics.cc b/Shower/Dipole/Kinematics/IILightKinematics.cc new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Kinematics/IILightKinematics.cc @@ -0,0 +1,290 @@ +// -*- C++ -*- +// +// IILightKinematics.cc is a part of Herwig - A multi-purpose Monte Carlo event generator +// Copyright (C) 2002-2007 The Herwig Collaboration +// +// Herwig is licenced under version 2 of the GPL, see COPYING for details. +// Please respect the MCnet academic guidelines, see GUIDELINES for details. +// +// +// This is the implementation of the non-inlined, non-templated member +// functions of the IILightKinematics class. +// + +#include "IILightKinematics.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Interface/Switch.h" + +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h" + +using namespace Herwig; + +IILightKinematics::IILightKinematics() + : DipoleSplittingKinematics(), theCollinearScheme(true), didCollinear(false) {} + +IILightKinematics::~IILightKinematics() {} + +IBPtr IILightKinematics::clone() const { + return new_ptr(*this); +} + +IBPtr IILightKinematics::fullclone() const { + return new_ptr(*this); +} + +Energy IILightKinematics::ptMax(Energy dScale, + double emX, double specX, + const DipoleIndex&, + const DipoleSplittingKernel&) const { + double tau = + !theCollinearScheme ? emX*specX : emX; + return (1.-tau) * dScale / (2.*sqrt(tau)); +} + +Energy IILightKinematics::QMax(Energy, + double, double, + const DipoleIndex&, + const DipoleSplittingKernel&) const { + assert(false && "add this"); + return 0.0*GeV; +} + +Energy IILightKinematics::PtFromQ(Energy scale, const DipoleSplittingInfo& split) const { + double z = split.lastZ(); + return scale*sqrt(1.-z); +} + +Energy IILightKinematics::QFromPt(Energy scale, const DipoleSplittingInfo& split) const { + double z = split.lastZ(); + return scale/sqrt(1.-z); +} + +pair IILightKinematics::zBoundaries(Energy pt, + const DipoleSplittingInfo& dInfo, + const DipoleSplittingKernel&) const { + double x = + !theCollinearScheme ? + dInfo.emitterX()*dInfo.spectatorX() : + dInfo.emitterX(); + double s = sqrt(1.-sqr(pt/dInfo.hardPt())); + return make_pair(0.5*(1.+x-(1.-x)*s),0.5*(1.+x+(1.-x)*s)); +} + +bool IILightKinematics::generateSplitting(double kappa, double xi, double rphi, + DipoleSplittingInfo& info, + const DipoleSplittingKernel& split) { + + if ( info.emitterX() < xMin() || + info.spectatorX() < xMin() ) { + jacobian(0.0); + return false; + } + + double weight = 1.0; + + Energy pt = generatePt(kappa,info.scale(), + info.emitterX(),info.spectatorX(), + info.index(),split, + weight); + + if ( pt < IRCutoff() || pt > info.hardPt() ) { + jacobian(0.0); + return false; + } + + double z = 0.0; + + if ( info.index().emitterData()->id() == ParticleID::g ) { + if ( info.emitterData()->id() == ParticleID::g ) { + z = generateZ(xi,pt,OneOverZOneMinusZ, + info,split,weight); + } else { + z = generateZ(xi,pt,OneOverZ, + info,split,weight); + } + } + + if ( info.index().emitterData()->id() != ParticleID::g ) { + if ( info.emitterData()->id() != ParticleID::g ) { + z = generateZ(xi,pt,OneOverOneMinusZ, + info,split,weight); + } else { + z = generateZ(xi,pt,FlatZ, + info,split,weight); + } + } + + if ( weight == 0. && z == -1. ) { + jacobian(0.0); + return false; + } + + double ratio = sqr(pt/info.scale()); + + double x = z*(1.-z)/(1.-z+ratio); + double v = ratio*z /(1.-z+ratio); + + if ( x < 0. || x > 1. || v < 0. || v > 1.-x ) { + jacobian(0.0); + return false; + } + + if ( !theCollinearScheme && + (1.-v-x)/(v+x) < 1. ) { + if ( (x+v) < info.emitterX() || + x/(x+v) < info.spectatorX() ) { + jacobian(0.0); + return false; + } + } else { + if ( x < info.emitterX() ) { + jacobian(0.0); + return false; + } + } + + double phi = 2.*Constants::pi*rphi; + + jacobian(weight*(1./z)); + + lastPt(pt); + lastZ(z); + lastPhi(phi); + + if ( !theCollinearScheme && + (1.-v-x)/(v+x) < 1. ) { + lastEmitterZ(x+v); + lastSpectatorZ(x/(x+v)); + } else { + lastEmitterZ(x); + lastSpectatorZ(1.); + } + + if ( theMCCheck ) + theMCCheck->book(info.emitterX(),info.spectatorX(),info.scale(),info.hardPt(),pt,z,jacobian()); + + return true; + +} + +void IILightKinematics::generateKinematics(const Lorentz5Momentum& pEmitter, + const Lorentz5Momentum& pSpectator, + const DipoleSplittingInfo& dInfo) { + + Energy pt = dInfo.lastPt(); + double z = dInfo.lastZ(); + + double ratio = sqr(pt)/(2.*pEmitter*pSpectator); + + double x = z*(1.-z)/(1.-z+ratio); + double v = ratio*z /(1.-z+ratio); + + Lorentz5Momentum kt = + getKt (pEmitter, pSpectator, pt, dInfo.lastPhi()); + + if ( !theCollinearScheme && + (1.-v-x)/(v+x) < 1. ) { + + assert(false); + + Lorentz5Momentum em = + (1./(v+x))*pEmitter+(v*(1.-v-x)/(x*(x+v)))*pSpectator+kt/(x+v); + em.setMass(0.*GeV); + em.rescaleEnergy(); + + Lorentz5Momentum emm = + ((1.-v-x)/(v+x))*pEmitter+(v/(x*(x+v)))*pSpectator+kt/(x+v); + emm.setMass(0.*GeV); + emm.rescaleEnergy(); + + Lorentz5Momentum spe = + (1.+v/x)*pSpectator; + spe.setMass(0.*GeV); + spe.rescaleEnergy(); + + emitterMomentum(em); + emissionMomentum(emm); + spectatorMomentum(spe); + + didCollinear = false; + + } else { + + Lorentz5Momentum em = + (1./x)*pEmitter; + em.setMass(0.*GeV); + em.rescaleEnergy(); + + Lorentz5Momentum emm = + ((1.-x-v)/x)*pEmitter+v*pSpectator+kt; + emm.setMass(0.*GeV); + emm.rescaleEnergy(); + + Lorentz5Momentum spe = + pSpectator; + + emitterMomentum(em); + emissionMomentum(emm); + spectatorMomentum(spe); + + K = em + spe - emm; + K2 = K.m2(); + + Ktilde = pEmitter + pSpectator; + KplusKtilde = K + Ktilde; + + KplusKtilde2 = KplusKtilde.m2(); + + didCollinear = true; + + } + +} + +// If needed, insert default implementations of function defined +// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). + + +void IILightKinematics::persistentOutput(PersistentOStream &) const { + //os << theCollinearScheme; +} + +void IILightKinematics::persistentInput(PersistentIStream &, 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/Kinematics/IILightKinematics.h b/Shower/Dipole/Kinematics/IILightKinematics.h rename from DipoleShower/Kinematics/IILightKinematics.h rename to Shower/Dipole/Kinematics/IILightKinematics.h diff --git a/DipoleShower/Kinematics/Makefile.am b/Shower/Dipole/Kinematics/Makefile.am rename from DipoleShower/Kinematics/Makefile.am rename to Shower/Dipole/Kinematics/Makefile.am diff --git a/Shower/Dipole/Makefile.am b/Shower/Dipole/Makefile.am new file mode 100644 --- /dev/null +++ b/Shower/Dipole/Makefile.am @@ -0,0 +1,14 @@ +SUBDIRS = Base Kernels Kinematics Utility AlphaS + +pkglib_LTLIBRARIES = HwDipoleShower.la + +HwDipoleShower_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 7:0:0 + +HwDipoleShower_la_LIBADD = \ + Base/libHwDipoleShowerBase.la \ + Kernels/libHwDipoleShowerKernels.la \ + Kinematics/libHwDipoleShowerKinematics.la \ + Utility/libHwDipoleShowerUtility.la + +HwDipoleShower_la_SOURCES = \ + DipoleShowerHandler.h DipoleShowerHandler.fh DipoleShowerHandler.cc diff --git a/DipoleShower/Utility/ConstituentReshuffler.cc b/Shower/Dipole/Utility/ConstituentReshuffler.cc rename from DipoleShower/Utility/ConstituentReshuffler.cc rename to Shower/Dipole/Utility/ConstituentReshuffler.cc --- a/DipoleShower/Utility/ConstituentReshuffler.cc +++ b/Shower/Dipole/Utility/ConstituentReshuffler.cc @@ -1,250 +1,250 @@ // -*- C++ -*- // // ConstituentReshuffler.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 ConstituentReshuffler class. // #include #include "ConstituentReshuffler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "DipolePartonSplitter.h" #include "Herwig/Utilities/GSLBisection.h" -#include "Herwig/DipoleShower/DipoleShowerHandler.h" +#include "Herwig/Shower/Dipole/DipoleShowerHandler.h" using namespace Herwig; ConstituentReshuffler::ConstituentReshuffler() : HandlerBase() {} ConstituentReshuffler::~ConstituentReshuffler() {} IBPtr ConstituentReshuffler::clone() const { return new_ptr(*this); } IBPtr ConstituentReshuffler::fullclone() const { return new_ptr(*this); } double ConstituentReshuffler::ReshuffleEquation::aUnit() { return 1.; } double ConstituentReshuffler::ReshuffleEquation::vUnit() { return 1.; } double ConstituentReshuffler::ReshuffleEquation::operator() (double xi) const { double r = - w/GeV; for (PList::iterator p = p_begin; p != p_end; ++p) { r += sqrt(sqr((**p).dataPtr()->constituentMass()) + xi*xi*(sqr((**p).momentum().t())-sqr((**p).dataPtr()->mass()))) / GeV; } return r; } void ConstituentReshuffler::reshuffle(PList& out, PPair& in, PList& intermediates) { if (out.size() == 0) return; if (out.size() == 1) { PPtr recoiler; PPtr parton = out.front(); if (DipolePartonSplitter::colourConnected(parton,in.first) && DipolePartonSplitter::colourConnected(parton,in.second)) { if (UseRandom::rnd() < .5) recoiler = in.first; else recoiler = in.second; } else if (DipolePartonSplitter::colourConnected(parton,in.first)) { recoiler = in.first; } else if (DipolePartonSplitter::colourConnected(parton,in.second)) { recoiler = in.second; } else assert(false); assert(abs(recoiler->momentum().vect().perp2()/GeV2) < 1e-6); double sign = recoiler->momentum().z() < 0.*GeV ? -1. : 1.; Energy2 qperp2 = parton->momentum().perp2(); if (qperp2/GeV2 < Constants::epsilon) { // no emission off a 2 -> singlet process which // needed a single forced splitting: should never happen (?) assert(false); throw Veto(); } Energy2 m2 = sqr(parton->dataPtr()->constituentMass()); Energy abs_q = parton->momentum().vect().mag(); Energy qz = parton->momentum().z(); Energy abs_pz = recoiler->momentum().t(); assert(abs_pz > 0.*GeV); Energy xi_pz = sign*(2.*qperp2*abs_pz + m2*(abs_q + sign*qz))/(2.*qperp2); Energy x_qz = (2.*qperp2*qz + m2*(qz+sign*abs_q))/(2.*qperp2); Lorentz5Momentum recoiler_momentum (0.*GeV,0.*GeV,xi_pz,xi_pz < 0.*GeV ? - xi_pz : xi_pz); recoiler_momentum.rescaleMass(); Lorentz5Momentum parton_momentum (parton->momentum().x(),parton->momentum().y(),x_qz,sqrt(m2+qperp2+x_qz*x_qz)); parton_momentum.rescaleMass(); PPtr n_parton = new_ptr(Particle(parton->dataPtr())); n_parton->set5Momentum(parton_momentum); DipolePartonSplitter::change(parton,n_parton,false); out.pop_front(); intermediates.push_back(parton); out.push_back(n_parton); PPtr n_recoiler = new_ptr(Particle(recoiler->dataPtr())); n_recoiler->set5Momentum(recoiler_momentum); DipolePartonSplitter::change(recoiler,n_recoiler,true); intermediates.push_back(recoiler); if (recoiler == in.first) { in.first = n_recoiler; } if (recoiler == in.second) { in.second = n_recoiler; } return; } Energy zero (0.*GeV); Lorentz5Momentum Q (zero,zero,zero,zero); for (PList::iterator p = out.begin(); p != out.end(); ++p) { Q += (**p).momentum(); } Boost beta = Q.findBoostToCM(); list mbackup; bool need_boost = (beta.mag2() > Constants::epsilon); if (need_boost) { for (PList::iterator p = out.begin(); p != out.end(); ++p) { Lorentz5Momentum mom = (**p).momentum(); mbackup.push_back(mom); (**p).set5Momentum(mom.boost(beta)); } } double xi; ReshuffleEquation solve (Q.m(),out.begin(),out.end()); GSLBisection solver(1e-10,1e-8,10000); try { xi = solver.value(solve,0.0,1.1); } catch (GSLBisection::GSLerror) { throw DipoleShowerHandler::RedoShower(); } catch (GSLBisection::IntervalError) { throw DipoleShowerHandler::RedoShower(); } PList reshuffled; list::const_iterator backup_it; if (need_boost) backup_it = mbackup.begin(); for (PList::iterator p = out.begin(); p != out.end(); ++p) { PPtr rp = new_ptr(Particle((**p).dataPtr())); DipolePartonSplitter::change(*p,rp,false); Lorentz5Momentum rm (xi*(**p).momentum().x(), xi*(**p).momentum().y(), xi*(**p).momentum().z(), sqrt(sqr((**p).dataPtr()->constituentMass()) + xi*xi*(sqr((**p).momentum().t())-sqr((**p).dataPtr()->mass())))); rm.rescaleMass(); if (need_boost) { (**p).set5Momentum(*backup_it); ++backup_it; rm.boost(-beta); } rp->set5Momentum(rm); intermediates.push_back(*p); reshuffled.push_back(rp); } out.clear(); out.splice(out.end(),reshuffled); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void ConstituentReshuffler::persistentOutput(PersistentOStream &) const { } void ConstituentReshuffler::persistentInput(PersistentIStream &, int) { } ClassDescription ConstituentReshuffler::initConstituentReshuffler; // Definition of the static class description member. void ConstituentReshuffler::Init() { static ClassDocumentation documentation ("The ConstituentReshuffler class implements reshuffling " "of partons on their nominal mass shell to their constituent " "mass shells."); } diff --git a/DipoleShower/Utility/ConstituentReshuffler.h b/Shower/Dipole/Utility/ConstituentReshuffler.h rename from DipoleShower/Utility/ConstituentReshuffler.h rename to Shower/Dipole/Utility/ConstituentReshuffler.h diff --git a/DipoleShower/Utility/DipoleMCCheck.cc b/Shower/Dipole/Utility/DipoleMCCheck.cc rename from DipoleShower/Utility/DipoleMCCheck.cc rename to Shower/Dipole/Utility/DipoleMCCheck.cc diff --git a/DipoleShower/Utility/DipoleMCCheck.h b/Shower/Dipole/Utility/DipoleMCCheck.h rename from DipoleShower/Utility/DipoleMCCheck.h rename to Shower/Dipole/Utility/DipoleMCCheck.h diff --git a/DipoleShower/Utility/DipolePartonSplitter.cc b/Shower/Dipole/Utility/DipolePartonSplitter.cc rename from DipoleShower/Utility/DipolePartonSplitter.cc rename to Shower/Dipole/Utility/DipolePartonSplitter.cc diff --git a/DipoleShower/Utility/DipolePartonSplitter.h b/Shower/Dipole/Utility/DipolePartonSplitter.h rename from DipoleShower/Utility/DipolePartonSplitter.h rename to Shower/Dipole/Utility/DipolePartonSplitter.h diff --git a/DipoleShower/Utility/IntrinsicPtGenerator.cc b/Shower/Dipole/Utility/IntrinsicPtGenerator.cc rename from DipoleShower/Utility/IntrinsicPtGenerator.cc rename to Shower/Dipole/Utility/IntrinsicPtGenerator.cc diff --git a/DipoleShower/Utility/IntrinsicPtGenerator.h b/Shower/Dipole/Utility/IntrinsicPtGenerator.h rename from DipoleShower/Utility/IntrinsicPtGenerator.h rename to Shower/Dipole/Utility/IntrinsicPtGenerator.h diff --git a/DipoleShower/Utility/Makefile.am b/Shower/Dipole/Utility/Makefile.am rename from DipoleShower/Utility/Makefile.am rename to Shower/Dipole/Utility/Makefile.am diff --git a/DipoleShower/Utility/PDFRatio.cc b/Shower/Dipole/Utility/PDFRatio.cc rename from DipoleShower/Utility/PDFRatio.cc rename to Shower/Dipole/Utility/PDFRatio.cc diff --git a/DipoleShower/Utility/PDFRatio.h b/Shower/Dipole/Utility/PDFRatio.h rename from DipoleShower/Utility/PDFRatio.h rename to Shower/Dipole/Utility/PDFRatio.h diff --git a/Shower/Makefile.am b/Shower/Makefile.am --- a/Shower/Makefile.am +++ b/Shower/Makefile.am @@ -1,50 +1,30 @@ -SUBDIRS = Matching . -pkglib_LTLIBRARIES = HwShower.la -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 +SUBDIRS = Dipole QTilde . 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 +libHwShower_la_LIBADD = \ +$(top_builddir)/PDF/libHwMPIPDF.la\ +$(top_builddir)/PDF/libHwRemDecayer.la + +libHwShower_la_SOURCES = \ +ShowerHandler.h ShowerHandler.fh ShowerHandler.cc \ +ShowerVariation.h ShowerVariation.cc \ +ShowerEventRecord.h ShowerEventRecord.cc \ +PerturbativeProcess.h PerturbativeProcess.fh \ +RealEmissionProcess.h RealEmissionProcess.fh \ +UEBase.h UEBase.cc UEBase.fh \ +QTilde/ShowerInteraction.h QTilde/ShowerConfig.h QTilde/ShowerConfig.cc \ +QTilde/Base/Branching.h \ +QTilde/Base/ShowerParticle.cc QTilde/Base/ShowerParticle.fh QTilde/Base/ShowerParticle.h \ +QTilde/Base/ShowerKinematics.fh QTilde/Base/ShowerKinematics.h QTilde/Base/ShowerKinematics.cc \ +QTilde/Base/ShowerBasis.fh QTilde/Base/ShowerBasis.h QTilde/Base/ShowerBasis.cc \ +QTilde/Base/ShowerTree.h QTilde/Base/ShowerTree.fh QTilde/Base/ShowerTree.cc \ +QTilde/Base/ShowerProgenitor.fh QTilde/Base/ShowerProgenitor.h \ +QTilde/Base/HardTree.h QTilde/Base/HardTree.fh QTilde/Base/HardTree.cc\ +QTilde/Base/SudakovFormFactor.cc QTilde/Base/SudakovFormFactor.h QTilde/Base/SudakovFormFactor.fh \ +QTilde/Base/HardBranching.h QTilde/Base/HardBranching.fh QTilde/Base/HardBranching.cc\ +QTilde/Couplings/ShowerAlpha.h QTilde/Couplings/ShowerAlpha.cc QTilde/Couplings/ShowerAlpha.fh\ +QTilde/SplittingFunctions/SplittingGenerator.cc QTilde/SplittingFunctions/SplittingGenerator.h\ +QTilde/SplittingFunctions/SplittingGenerator.fh \ +QTilde/SplittingFunctions/SplittingFunction.h QTilde/SplittingFunctions/SplittingFunction.fh \ +QTilde/SplittingFunctions/SplittingFunction.cc \ +QTilde/Base/ShowerVertex.cc QTilde/Base/ShowerVertex.fh QTilde/Base/ShowerVertex.h diff --git a/Shower/Matching/MatchingHandler.cc b/Shower/Matching/MatchingHandler.cc deleted file mode 100644 --- a/Shower/Matching/MatchingHandler.cc +++ /dev/null @@ -1,1089 +0,0 @@ -// -*- C++ -*- -// -// This is the implementation of the non-inlined, non-templated member -// functions of the MatchingHandler class. -// - -#include "MatchingHandler.h" -#include "ThePEG/Interface/ClassDocumentation.h" -#include "ThePEG/Interface/Reference.h" -#include "ThePEG/Interface/Switch.h" -#include "ThePEG/EventRecord/Particle.h" -#include "ThePEG/Repository/UseRandom.h" -#include "ThePEG/Repository/EventGenerator.h" -#include "ThePEG/Utilities/DescribeClass.h" -#include "ThePEG/Persistency/PersistentOStream.h" -#include "ThePEG/Persistency/PersistentIStream.h" -#include "ThePEG/PDF/PartonExtractor.h" -#include "ThePEG/PDF/BeamParticleData.h" -#include "ThePEG/PDF/PDF.h" -#include "ThePEG/Cuts/Cuts.h" -#include "Herwig/PDF/HwRemDecayer.h" -#include "Herwig/Shower/Base/Evolver.h" -#include "Herwig/Shower/Base/PartnerFinder.h" -#include "Herwig/Shower/Base/KinematicsReconstructor.h" -#include "ThePEG/MatrixElement/Tree2toNDiagram.h" -#include "ThePEG/Utilities/Throw.h" - -using namespace Herwig; - -namespace { -struct ParticleOrdering { - bool operator()(tcPDPtr p1, tcPDPtr p2) { - return abs(p1->id()) > abs(p2->id()) || - ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || - ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); - } -}; -} - -MatchingHandler::MatchingHandler(bool reWeight) - : reWeight_(reWeight), rejectNonAO_( true ), rejectNOHistories_( true ), - includeDecays_(false) -{} - -void MatchingHandler::persistentOutput(PersistentOStream & os) const { - os << alphaS_ << matrixElement_ << HWmatrixElement_ << includeDecays_ - << partonExtractor_ << cuts_ << rejectNonAO_ << rejectNOHistories_ - << allowedInitial_ << allowedFinal_; -} - -void MatchingHandler::persistentInput(PersistentIStream & is, int) { - is >> alphaS_ >> matrixElement_ >> HWmatrixElement_ >> includeDecays_ - >> partonExtractor_ >> cuts_ >> rejectNonAO_ >> rejectNOHistories_ - >> allowedInitial_ >> allowedFinal_; -} - -// *** Attention *** The following static variable is needed for the type -// description system in ThePEG. Please check that the template arguments -// are correct (the class and its base class), and that the constructor -// arguments are correct (the class name and the name of the dynamically -// loadable library where the class implementation can be found). -DescribeAbstractClass -describeHerwigMatchingHandler("Herwig::MatchingHandler", "HwMatching.so"); - -void MatchingHandler::Init() { - - static ClassDocumentation documentation - ("The MatchingHandler class is the base class implementating" - " many of the features needed for matching."); - - static Reference interfaceMatrixElement - ("MatrixElement", - "The matrix element class for the core 2->2 process", - &MatchingHandler::matrixElement_, false, false, true, true, false); - - static Reference interfacePartonExtractor - ("PartonExtractor", - "The PartonExtractor object used to construct remnants. If no object is " - "provided the LesHouchesEventHandler object must provide one instead.", - &MatchingHandler::partonExtractor_, true, false, true, false, false); - - static Reference interfaceCuts - ("Cuts", - "The Cuts object to be used for this reader. Note that these " - "must not be looser cuts than those used in the actual generation. " - "If no object is provided the LesHouchesEventHandler object must " - "provide one instead.", - &MatchingHandler::cuts_, true, false, true, false, false); - - static Reference interfaceShowerAlpha - ("ShowerAlpha", - "The object calculating the strong coupling constant", - &MatchingHandler::alphaS_, false, false, true, true, false); - - static Switch interfaceReject - ("RejectNonOrdered", - "Whether to reject non angular ordered cluster histories", - &MatchingHandler::rejectNonAO_, true, false, false); - static SwitchOption interfaceRejectYes - (interfaceReject, - "Reject", - "Reject all non angular ordered events", - true); - static SwitchOption interfaceRejectNo - (interfaceReject, - "Select", - "Select a history for non angular ordered events", - false); - - static Switch interfaceRejectNoHist - ("RejectNoHistories", - "Whether to reject events with no shower interpretation", - &MatchingHandler::rejectNOHistories_, true, false, false); - static SwitchOption interfaceRejectNoHistYes - (interfaceRejectNoHist, - "Reject", - "Reject all events with no shower interpretation", - true); - static SwitchOption interfaceRejectNoHistNo - (interfaceRejectNoHist, - "Shower", - "Shower events with no shower interpretation directly", - false); - - static Switch interfaceDecayingParticles - ("IncludeDecayingParticles", - "Separate production of decay of unstable particles", - &MatchingHandler::includeDecays_, false, false, false); - static SwitchOption interfaceDecayingParticlesYes - (interfaceDecayingParticles, - "Yes", - "Separate them", - true); - static SwitchOption interfaceDecayingParticlesNo - (interfaceDecayingParticles, - "No", - "Don't separate them", - false); - -} - -void MatchingHandler::doinit() { - ShowerHandler::doinit(); - HWmatrixElement_ = dynamic_ptr_cast(matrixElement_); - - - // check - if(reWeight_ && !alphaS_) { - throw Exception() << "ShowerAlpha must be set in MatchingHandler if " - << "reweighting events" - << Exception::runerror; - } - // extract the allowed branchings - // final-state - for(BranchingList::const_iterator - it = evolver()->splittingGenerator()->finalStateBranchings().begin(); - it != evolver()->splittingGenerator()->finalStateBranchings().end(); ++it) { - pair prod(make_pair(it->second.second[1],it->second.second[2])); - allowedFinal_.insert(make_pair(prod,it->second)); - swap(prod.first,prod.second); - allowedFinal_.insert(make_pair(prod,it->second)); - } - // initial-state - for(BranchingList::const_iterator - it = evolver()->splittingGenerator()->initialStateBranchings().begin(); - it != evolver()->splittingGenerator()->initialStateBranchings().end(); ++it) { - allowedInitial_.insert(make_pair(it->second.second[0],it->second)); - } -} - -void MatchingHandler::fillProtoTrees( ProtoTreePtr currentProtoTree ) { - if(currentProtoTree->branchings().size()==4) return; - for( set::const_iterator - ita = currentProtoTree->branchings().begin(); - ita!=currentProtoTree->branchings().end();++ita) { - for( set::const_iterator - itb = currentProtoTree->branchings().begin(); - itb!=ita;++itb) { - // can't merge two incoming branchings - if( (**ita).status() == HardBranching::Incoming && - (**itb).status() == HardBranching::Incoming ) continue; - // get a new branching for this pair - ProtoBranchingPtr currentBranching = getCluster(*ita,*itb); - if( ! currentBranching ) continue; - // branching allowed so make a new Tree out of these branchings - set< tProtoBranchingPtr > newTreeBranchings = currentProtoTree->branchings(); - newTreeBranchings.erase(*ita); - newTreeBranchings.erase(*itb); - newTreeBranchings.insert(currentBranching); - ProtoTreePtr newProtoTree = new_ptr( ProtoTree( newTreeBranchings ) ); - // remove duplicate trees - if( ! repeatProtoTree( newProtoTree ) ) protoTrees().insert( newProtoTree ); - // remove the current tree if it hasn't already been removed - if( protoTrees().find( currentProtoTree ) != protoTrees().end() ) - protoTrees().erase( currentProtoTree ); - // do recursion - fillProtoTrees( newProtoTree ); - } - } -} - -tProtoBranchingPtr MatchingHandler::getCluster( tProtoBranchingPtr b1, - tProtoBranchingPtr b2 ) { - //look for the clustered pair in protoBranchings_ - for(set::const_iterator cit = protoBranchings().begin(); - cit != protoBranchings().end(); ++cit) { - // both outgoing - if(b1->status()==HardBranching::Outgoing && - b2->status()==HardBranching::Outgoing) { - if((**cit).status()!=HardBranching::Outgoing|| - (**cit).children().empty()) continue; - if( ( b1 == (**cit).children()[0] && b2 == (**cit).children()[1] ) || - ( b1 == (**cit).children()[1] && b2 == (**cit).children()[0] ) ) - return *cit; - } - // first incoming - else if(b1->status()==HardBranching::Incoming) { - if((**cit).backChildren().empty() ) continue; - if(b1!=(**cit).backChildren()[0]) continue; - if(b2==(**cit).backChildren()[1]) return *cit; - } - // second incoming - else if(b2->status()==HardBranching::Incoming) { - if((**cit).backChildren().empty() ) continue; - if(b2!=(**cit).backChildren()[0]) continue; - if(b1==(**cit).backChildren()[1]) return *cit; - } - } - // is branching incoming or outgoing - bool incoming = b1->status()==HardBranching::Incoming || - b2->status()==HardBranching::Incoming; - // get the branching - BranchingElement theBranching; - if( !incoming ) theBranching = allowedFinalStateBranching( b1, b2 ); - else theBranching = allowedInitialStateBranching( b1, b2 ); - - //if branching is not allowed return null ProtoBrancing - if( !theBranching.first ) return ProtoBranchingPtr(); - - // get the PArticleData object for the new branching - tcPDPtr particle_data = incoming ? - getParticleData( theBranching.second[1] ) : getParticleData( theBranching.second[0] ); - - // create clustered ProtoBranching - ProtoBranchingPtr clusteredBranch; - // outgoing - if( !incoming ){ - Lorentz5Momentum pairMomentum = b1->momentum() + b2->momentum(); - pairMomentum.setMass(ZERO); - clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Outgoing, - pairMomentum, theBranching.first)); - } - // incoming - else { - Lorentz5Momentum pairMomentum = b1->momentum() - b2->momentum(); - pairMomentum.setMass( ZERO ); - // check for CC - if( particle_data->CC() && - ( b1->id() != theBranching.second[0] || - b2->id() != theBranching.second[2] ) ) { - particle_data = particle_data->CC(); - } - clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Incoming, - pairMomentum,theBranching.first)); - } - protoBranchings().insert(clusteredBranch); - //set children relations - // outgoing - if( !incoming ){ - clusteredBranch->addChild( b1 ); - clusteredBranch->addChild( b2 ); - } - else { - clusteredBranch->addBackChild( b1 ); - clusteredBranch->addBackChild( b2 ); - } - return clusteredBranch; -} - -BranchingElement MatchingHandler:: -allowedFinalStateBranching( tProtoBranchingPtr & b1, tProtoBranchingPtr & b2) { - // check with normal ID's - pair< long, long > ptest = make_pair( b1->id(), b2->id() ); - map< pair< long, long >, pair< SudakovPtr, IdList > >::const_iterator - split = allowedFinal_.find(ptest); - if( split != allowedFinal_.end() ) { - if( split->second.second[1] != ptest.first ) swap( b1, b2 ); - return split->second; - } - // check with CC - if( b1->particle()->CC() ) ptest.first *= -1; - if( b2->particle()->CC() ) ptest.second *= -1; - split = allowedFinal_.find( ptest ); - if( split != allowedFinal_.end() ) { - // cc the idlist only be for qbar g clusterings - BranchingElement ccBranch = split->second; - if( getParticleData( ccBranch.second[0] )->CC() ) ccBranch.second[0] *= -1; - if( getParticleData( ccBranch.second[1] )->CC() ) ccBranch.second[1] *= -1; - if( getParticleData( ccBranch.second[2] )->CC() ) ccBranch.second[2] *= -1; - if( split->second.second[1] != ptest.first ) swap( b1, b2); - return ccBranch; - } - // not found found null pointer - return make_pair( SudakovPtr(), IdList() ); -} - -BranchingElement MatchingHandler:: -allowedInitialStateBranching( tProtoBranchingPtr & b1, - tProtoBranchingPtr & b2) { - if(b2->status()==HardBranching::Incoming) swap(b1,b2); - // is initial parton an antiparticle - bool cc = b1->id() < 0; - //gives range of allowedInitial_ with matching first abs( id ) - pair< multimap< long, pair< SudakovPtr, IdList > >::const_iterator, - multimap< long, pair< SudakovPtr, IdList > >::const_iterator > - location = allowedInitial_.equal_range( abs( b1->id() ) ); - //iterates over this range - for( multimap< long, pair< SudakovPtr, IdList> >::const_iterator it = location.first; - it != location.second; ++it ) { - //test id for second particle in pair - long idtest = it->second.second[2]; - //if it is antiparticle *= -1 - if( cc && getParticleData( idtest )->CC() ) idtest *= -1; - // does second id match the test - if( idtest == b2->id() ) return it->second; - //if the the IS parton is a gluon and charge conjugate of second parton mathes accept - if( idtest == -b2->id() && - ! b1->particle()->CC() ) return it->second; - } - // not found found null pointer - return make_pair(SudakovPtr(),IdList()); -} - - -bool MatchingHandler::repeatProtoTree( ProtoTreePtr currentProtoTree ) { - // loop over all prototrees and see - // how many ProtoBranchings of current ProtoTree are found in each - for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); - cit != protoTrees().end(); ++cit ) { - unsigned int no_matches = 0; - for( set< tProtoBranchingPtr >::const_iterator ckt - = currentProtoTree->branchings().begin(); - ckt != currentProtoTree->branchings().end(); ckt++ ) { - if( (*cit)->branchings().find( *ckt ) != (*cit)->branchings().end() ) - ++no_matches; - } - // return true if all match - if( no_matches == currentProtoTree->branchings().size() ) - return true; - } - return false; -} - -double MatchingHandler::getDiagram(PotentialTree & tree) { - if(tree.diagrams().empty()) { - set::const_iterator cit; - tcPDPair incoming; - multiset outgoing; - //get the incoming and outgoing partons involved in hard process - for( cit = tree.tree()->branchings().begin(); - cit != tree.tree()->branchings().end(); ++cit ){ - if( (*cit)->status() ==HardBranching::Incoming) { - HardBranchingPtr parent = *cit; - while(parent->parent()) parent = parent->parent(); - if( parent->branchingParticle()->momentum().z()>ZERO ) - incoming.first = (*cit)->branchingParticle()->dataPtr(); - else - incoming.second = (*cit)->branchingParticle()->dataPtr(); - } - else { - outgoing.insert( (*cit)->branchingParticle()->dataPtr() ); - } - } - if(!incoming.first || !incoming.second) return 0.; - pair tag; - tag.first = incoming.first ->PDGName() + "," + incoming.second->PDGName() + "->"; - tag.second = incoming.second ->PDGName() + "," + incoming.first ->PDGName() + "->"; - - string tag_out; - for ( multiset::iterator i = outgoing.begin(); - i != outgoing.end(); ++i ) { - if ( i != outgoing.begin() ) tag_out += ","; - tag_out += (**i).PDGName(); - } - tag.first += tag_out; - tag.second += tag_out; - // find the diagrams - for ( int i = 0, N = matrixElement()->diagrams().size(); i < N; ++i ) { - string temp = matrixElement()->diagrams()[i]->getTag(); - if ( temp == tag.first || temp == tag.second ) - tree.diagrams().push_back(matrixElement()->diagrams()[i]); - } - } - if(tree.diagrams().empty()) return 0.; - // construct a set of on-shell momenta for the hard collison - vector meMomenta; - vector mePartonData; - PVector particles; - set::const_iterator it; - // incoming particles - for( it = tree.tree()->branchings().begin();it != tree.tree()->branchings().end(); ++it ) { - if( (**it).status() == HardBranching::Incoming ) { - meMomenta.push_back( (**it).branchingParticle()->momentum() ); - mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); - particles.push_back( (**it).branchingParticle() ); - } - } - assert(particles.size()==2); - for( it = tree.tree()->branchings().begin(); it != tree.tree()->branchings().end(); ++it ) { - if( (**it).status() == HardBranching::Outgoing ) { - meMomenta.push_back( (**it).branchingParticle()->momentum() ); - mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); - particles.push_back( (**it).branchingParticle() ); - } - } - const cPDVector partons = tree.diagrams()[0]->partons(); - // order of the incoming partons - if(mePartonData[0] != partons[0]) { - swap( mePartonData[0], mePartonData[1] ); - swap( meMomenta[0], meMomenta[1] ); - swap( particles[0], particles[1] ); - } - // order of the outgoing partons - for(unsigned int ix=2;ix0.) { - R.rotateZ(-axis.phi()); - R.rotateY(-acos(axis.z())); - } - for( unsigned int ix = 0; ix < meMomenta.size(); ++ix ) - meMomenta[ix].transform(R); - // now rescale to put on shell - Energy Ebeam = 0.5 * ( max(meMomenta[0].e(),abs(meMomenta[0].z())) + - max(meMomenta[1].e(),abs(meMomenta[1].z())) ); - for( unsigned int i = 0; i < 2; ++i ) { - meMomenta[i].setZ( meMomenta[i].z() / abs(meMomenta[i].z()) * Ebeam ); - meMomenta[i].setT( Ebeam ); - } - Energy2 s = 4.0 * sqr(Ebeam); - Energy m1 = mePartonData[2]->mass(); - Energy m2 = mePartonData[3]->mass(); - // \todo need to improve this - if(m1+m2>sqrt(s)) return 0.; - double lambda = 0.25/Ebeam/meMomenta[2].rho() * - sqrt( ( s - sqr(m1+m2) ) * ( s - sqr(m1-m2) ) ); - for( unsigned int i = 2; i < meMomenta.size(); ++i ) { - meMomenta[i] *= lambda; - meMomenta[i].setMass(mePartonData[i]->mass()); - meMomenta[i].rescaleEnergy(); - } - // incoming pair - PPair in( mePartonData[0]->produceParticle( meMomenta[0] ), - mePartonData[1]->produceParticle( meMomenta[1] ) ); - // outgoing - PVector out; - for(unsigned int ix=2;ixproduceParticle(meMomenta[ix])); - } - // call the matrix element to initialize - - matrixElement()->setKinematics(in,out); - if(HWMatrixElement()) { - vector momenta; - cPDVector data; - data.push_back(in. first->dataPtr()); - momenta.push_back(in. first->momentum()); - data.push_back(in.second->dataPtr()); - momenta.push_back(in.second->momentum()); - for(unsigned int ix=0;ixdataPtr()); - momenta.push_back(out[ix]->momentum()); - } - HWMatrixElement()->rescaleMomenta(momenta,data); - } - if(!cuts()->scale(matrixElement()->scale())) { - return 0.; - } - matrixElement()->dSigHatDR(); - - // select the diagram - if(!tree.diagram()) - tree.diagram(tree.diagrams()[matrixElement()->diagram(tree.diagrams())]); - // get the colour structure - if(!tree.colourLines()) { - Selector sel = matrixElement()->colourGeometries(tree.diagram()); - tree.colourLines(sel.select(rnd())); - } - PVector slike; - tPVector ret; - slike.push_back(particles[0]); - Ptr::const_pointer diagram2 = - dynamic_ptr_cast::const_pointer>(tree.diagram()); - for ( int i = 1; i < diagram2->nSpace() - 1; ++i ) - slike.push_back(diagram2->allPartons()[i]->produceParticle()); - slike.push_back(particles[1]); - ret = tPVector(slike.begin(), slike.end()); - int io = particles.size(); - PVector tlike(diagram2->allPartons().size() - diagram2->nSpace()); - for ( int i = diagram2->allPartons().size() - 1; i >= diagram2->nSpace(); --i ) { - int it = i - diagram2->nSpace(); - pair ch = diagram2->children(i); - bool iso = ch.first < 0; - if ( iso ) { - tlike[it] = particles[--io]; - } - else { - Lorentz5Momentum p = tlike[ch.first - diagram2->nSpace()]->momentum() + - tlike[ch.second - diagram2->nSpace()]->momentum(); - tlike[it] = diagram2->allPartons()[i]->produceParticle(p); - } - } - ret.insert( ret.end(), tlike.begin(), tlike.end() ); - tree.colourLines()->connect(ret); - for( unsigned int ix = 0; ix < ret.size(); ++ix ) { - PVector::iterator it = find( particles.begin(), particles.end(),ret[ix] ); - if( it == particles.end() ) { - ColinePtr line = ret[ix]->colourLine(); - if(line) line->removeColoured(ret[ix]); - line = ret[ix]->antiColourLine(); - if(line) line->removeAntiColoured(ret[ix]); - } - } - // now the colours of the rest of the particles - // for( set::const_iterator it = tree.tree()->branchings().begin(); - // it!=tree.tree()->branchings().end(); ++it ) (**it).fixColours(); - // now make the colour connections in the tree - ShowerParticleVector branchingParticles; - map branchingMap; - for( set< HardBranchingPtr >::iterator it = tree.tree()->branchings().begin(); - it != tree.tree()->branchings().end(); ++it ) { - branchingParticles.push_back((**it).branchingParticle()); - branchingMap.insert(make_pair((**it).branchingParticle(),*it)); - } - // find the colour partners - evolver()->showerModel()->partnerFinder() - ->setInitialEvolutionScales(branchingParticles,false, - ShowerInteraction::QCD,true); - for(unsigned int ix=0;ixpartner()) { - HardBranchingPtr partner = branchingMap[branchingParticles[ix]->partner()]; - branchingMap[branchingParticles[ix]]->colourPartner(partner); - } - } - double weight = 1.; - // calculate the weight if needed - if(reWeight_) { - if(matrixElement()->orderInAlphaS()>0) { - weight = pow(alphaS_->value( max(matrixElement()->scale(),sqr(pdfScale_)) ) - / alphaSMG_, int(matrixElement()->orderInAlphaS())); - } - } - // return the weight - return weight; -} - -bool MatchingHandler::updateSubProcess() { - assert( hardTree().diagram() && hardTree().tree() ); - PPair beams = lastXCombPtr()->lastParticles(); - - // PPair remnants; - // // remove children of beams - // PVector beam_children = beams.first->children(); - // for( unsigned int ix = 0; ix != beam_children.size(); ix++ ){ - // if (abs(beam_children[ix]->id())==82) - // remnants.first=beam_children[ix]; - // beams.first->abandonChild( beam_children[ix] ); - // } - // beam_children = beams.second->children(); - // for( unsigned int ix = 0; ix != beam_children.size(); ix++ ){ - // if (abs(beam_children[ix]->id())==82) - // remnants.second=beam_children[ix]; - // beams.second->abandonChild( beam_children[ix] ); - // } - - // remove children of beams - PVector beam_children = beams.first->children(); - for( unsigned int ix = 0; ix != beam_children.size(); ix++ ) - beams.first->abandonChild( beam_children[ix] ); - beam_children = beams.second->children(); - for( unsigned int ix = 0; ix != beam_children.size(); ix++ ) - beams.second->abandonChild( beam_children[ix] ); - - if( (**hardTree().tree()->incoming().begin()).branchingParticle()->momentum().z() / - beams.first->momentum().z() < 0.) - swap( beams.first, beams.second ); - Ptr::const_pointer diagram = - dynamic_ptr_cast::const_pointer>(hardTree().diagram()); - assert(diagram); - set::const_iterator it; - map< ColinePtr, ColinePtr> colourMap; - PPair incoming; - // loop over the branchings and sort out incoming particles - for( it = hardTree().tree()->branchings().begin(); - it != hardTree().tree()->branchings().end(); ++it) { - if( (*it)->status() == HardBranching::Outgoing ) continue; - PPtr newParticle = new_ptr( Particle( (**it).branchingParticle()->dataPtr() ) ); - newParticle->set5Momentum( (**it).showerMomentum() ); - if( (**it).branchingParticle()->colourLine() ) { - map< ColinePtr, ColinePtr>::iterator loc - = colourMap.find( (**it).branchingParticle()->colourLine() ); - if( loc != colourMap.end() ) { - loc->second->addColoured( newParticle ); - } - else { - ColinePtr newLine = new_ptr( ColourLine() ); - colourMap[ (**it).branchingParticle()->colourLine() ] = newLine; - newLine->addColoured( newParticle ); - } - } - if( (**it).branchingParticle()->antiColourLine() ) { - map< ColinePtr, ColinePtr> ::iterator loc - = colourMap.find( (**it).branchingParticle()->antiColourLine() ); - if( loc != colourMap.end() ) { - loc->second->addAntiColoured( newParticle ); - } - else { - ColinePtr newLine = new_ptr( ColourLine() ); - colourMap[ (**it).branchingParticle()->antiColourLine() ] = newLine; - newLine->addAntiColoured( newParticle ); - } - } - if( lastXCombPtr()->subProcess()->incoming().first->momentum().z() / - newParticle->momentum().z() > 0. ) - incoming.first = newParticle; - else - incoming.second = newParticle; - } - bool mirror = - incoming.first ->dataPtr() != diagram->partons()[0] && - incoming.second->dataPtr() != diagram->partons()[1]; - // create the new subprocess - SubProPtr newSubProcess = - new_ptr( SubProcess( incoming, lastXCombPtr()->subProcess()->collision(), - lastXCombPtr()->subProcess()->handler() ) ); - // add the spacelike intermediates - PVector slike; - slike.push_back( !mirror ? incoming.first : incoming.second); - for ( int i = 1; i < diagram->nSpace() - 1; ++i ) - slike.push_back(diagram->allPartons()[i]->produceParticle()); - slike.push_back( !mirror ? incoming.second : incoming.first); - tPVector ret = tPVector(slike.begin(), slike.end()); - for ( size_t i = 1; i < slike.size() - 1; ++i ) { - slike[i-1]->addChild(slike[i]); - newSubProcess->addIntermediate(slike[ mirror ? i: slike.size() - 1 - i], false); - } - // get the parton bins from the parton extractor if first time - static bool first = true; - if(first) { - first = false; - Energy e1 = lastXCombPtr()->lastParticles().first ->momentum().e(); - Energy e2 = lastXCombPtr()->lastParticles().second->momentum().e(); - Energy emax = 2.0*sqrt(e1*e2); - cPDPair inData = make_pair(lastXCombPtr()->lastParticles().first ->dataPtr(), - lastXCombPtr()->lastParticles().second->dataPtr()); - cuts()->initialize(sqr(emax),0.5*log(e1/e2)); - partonBins(partonExtractor()->getPartons(emax, inData, *cuts())); - } - // get the parton bins for this event - tcPBPair sel; - for ( int i = 0, N = partonBins().size(); i < N; ++i ) { - tcPBPtr bin = partonBins()[i].first; - tPPtr p = incoming.first; - while ( bin && p ) { - if ( p->dataPtr() != bin->parton() ) break; - bin = bin->incoming(); - p = p != lastXCombPtr()->lastParticles().first ? - lastXCombPtr()->lastParticles().first : PPtr(); - } - if ( bin || p ) continue; - bin = partonBins()[i].second; - p = incoming.second; - while ( bin && p ) { - if ( p->dataPtr() != bin->parton() ) break; - bin = bin->incoming(); - p = p != lastXCombPtr()->lastParticles().second ? - lastXCombPtr()->lastParticles().second : PPtr(); - } - if ( bin || p ) continue; - sel = partonBins()[i]; - break; - } - if ( !sel.first || !sel.second ) Throw() - << "Could not find appropriate " - << "PartonBin objects for event in " - << "MatchingHandler " << Exception::runerror; - // create the new parton bin instances - Direction<0> dir(true); - PBIPair partonBinInstances; - // temporary mother/daugther settings - // to get parton bin instances correct - lastXCombPtr()->lastParticles().first ->addChild(incoming.first ); - lastXCombPtr()->lastParticles().second->addChild(incoming.second); - // make the parton bin instances - partonBinInstances.first = - new_ptr(PartonBinInstance(incoming.first, sel.first, - lastXCombPtr()->partonBinInstances().first->scale())); - dir.reverse(); - partonBinInstances.second = - new_ptr(PartonBinInstance(incoming.second, sel.second, - lastXCombPtr()->partonBinInstances().second->scale())); - // remove temporary mother/daugther settings - lastXCombPtr()->lastParticles().first ->abandonChild(incoming.first ); - lastXCombPtr()->lastParticles().second->abandonChild(incoming.second); - // set the parton bin instances - lastXCombPtr()->setPartonBinInstances(partonBinInstances, - lastXCombPtr()->lastScale()); - // momenta of the time like partons - vector meMomenta; - vector mePartonData; - vector branchings; - for( it = hardTree().tree()->branchings().begin(); - it != hardTree().tree()->branchings().end(); ++it ) { - if( (**it).status() == HardBranching::Outgoing ) { - meMomenta.push_back( (**it).showerMomentum() ); - mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); - branchings.push_back(*it); - } - } - // order of the outgoing partons - for(int ix=2;ixpartons().size());++ix) { - for(int iy=ix-2;iypartons()[ix]==mePartonData[iy]) { - if(ix!=iy) { - swap(mePartonData[ix-2],mePartonData[iy]); - swap(meMomenta [ix-2],meMomenta [iy]); - swap(branchings [ix-2],branchings [iy]); - } - break; - } - } - } - // time like particles - int io = meMomenta.size(); - PVector tlike(diagram->allPartons().size() - diagram->nSpace()); - vector tBranchings; - tPVector out; - for ( int i = diagram->allPartons().size() - 1; i >= diagram->nSpace(); --i ) { - int it = i - diagram->nSpace(); - pair ch = diagram->children(i); - bool iso = ch.first < 0; - if ( iso ) { - tlike[it] = diagram->allPartons()[i]->produceParticle(meMomenta[--io]); - } - else { - Lorentz5Momentum p = tlike[ch.first - diagram->nSpace()]->momentum() + - tlike[ch.second - diagram->nSpace()]->momentum(); - tlike[it] = diagram->allPartons()[i]->produceParticle(p); - } - if ( diagram->parent(i) < diagram->nSpace() ) { - slike[diagram->parent(i)]->addChild(tlike[it]); - if ( diagram->parent(i) == diagram->nSpace() - 2 ) - slike[diagram->parent(i) + 1]->addChild(tlike[it]); - } - if ( !iso ) { - tlike[it]->addChild(tlike[ch.first - diagram->nSpace()]); - tlike[it]->addChild(tlike[ch.second - diagram->nSpace()]); - } - if ( iso ) { - out.push_back(tlike[it]); - tBranchings.push_back(branchings[io]); - } - else - newSubProcess->addIntermediate(tlike[it], false); - } - ret.insert(ret.end(), tlike.begin(), tlike.end()); - // select the colour structure now - const ColourLines & cl = matrixElement()->selectColourGeometry(hardTree().diagram()); - cl.connect(ret); - // add the particles - for ( int i = 0, N = out.size(); i < N; ++i ) { - tPPtr particle = out[mirror ? i: out.size() - i - 1]; - // if not including decays add as outgoing - if(!includeDecays_) { - newSubProcess->addOutgoing(particle, false); - continue; - } - HardBranchingPtr branching = tBranchings[mirror ? i: out.size() - i - 1]; - // move to end of chain for time-like branchings - while(!branching->children().empty()) { - bool found=false; - for(unsigned int ix=0;ixchildren().size();++ix) { - if(branching->children()[ix]->branchingParticle()->id()== - branching->branchingParticle()->id()) { - found = true; - branching = branching->children()[ix]; - break; - } - } - if(!found) break; - } - // check if from decay - map::const_iterator pit = parent(branching->branchingParticle()); - // if not add as outgoing - if(pit==decayingParticles_.end()) { - newSubProcess->addOutgoing(particle, false); - continue; - } - LorentzRotation decayBoost = branching->showerBoost(); - // final boost if FSR - Lorentz5Momentum pShower = decayBoost*(pit->first->momentum()); - decayBoost = LorentzRotation(-pShower.boostVector())*decayBoost; - decayBoost = LorentzRotation(particle->momentum().boostVector())*decayBoost; - // add decayed particle as intermediate - newSubProcess->addIntermediate(particle,false); - // add decay products - addDecayProducts(newSubProcess,particle,pit,decayBoost); - } - for ( PVector::size_type i = 0; i < slike.size() - 2; ++i ) { - pair ch = diagram->children(i); - slike[ch.first]->set5Momentum(slike[i]->momentum() - - tlike[ch.second - diagram->nSpace()]->momentum()); - } - - - - // // set parents of incoming particles?? - // PPair inParents = lastXCombPtr()->lastParticles(); - // if( incoming.first->momentum().z() / inParents.first->momentum().z() < 0.) - // swap( inParents.first, inParents.second ); - // if( remnants.first->momentum().z() / inParents.first->momentum().z() < 0.) - // swap( remnants.first, remnants.second ); - // if (incoming.first ->parents().empty()) { - // inParents.first ->addChild(incoming.first ); - // inParents.first ->addChild(remnants.first ); - // } - // if (incoming.second->parents().empty()){ - // inParents.second->addChild(incoming.second); - // inParents.second->addChild(remnants.second); - // } - - // set the subprocess - lastXCombPtr()->subProcess( newSubProcess ); - decayingParticles_.clear(); - return true; -} - -void MatchingHandler::findDecayingParticles(PPtr parent) { - ParticleVector decayProducts; - for(unsigned int ix=0;ixchildren().size();++ix) { - decayProducts.push_back(parent->children()[ix]); - if(!parent->children()[ix]->children().empty()) - findDecayingParticles(parent->children()[ix]); - } - if(decayingParticles_.find(parent)==decayingParticles_.end()) - decayingParticles_[parent] = decayProducts; -} - -PotentialTree MatchingHandler::doClustering() { - noShowerHists_ = false; - // clear storage of the protoTrees - protoBranchings().clear(); - protoTrees().clear(); - nonOrderedTrees_.clear(); - hardTrees_.clear(); - assert( matrixElement() ); - // get particles from the XComb object - ParticleVector outgoing = lastXCombPtr()->subProcess()->outgoing(); - PPair incoming = lastXCombPtr()->subProcess()->incoming(); - // storage of decayed particles - decayingParticles_.clear(); - // all outgoing particles as a set for checking - set outgoingset(outgoing.begin(),outgoing.end()); - // loop through the FS particles and create ProtoBranchings - for( unsigned int i = 0; i < outgoing.size(); ++i) { - tPPtr parent = outgoing[i]->parents()[0]; - bool decayProd = decayProduct(parent,lastXCombPtr()->subProcess()); - if(!decayProd||!includeDecays_) { - ProtoBranchingPtr currentBranching = - new_ptr(ProtoBranching(outgoing[i]->dataPtr(),HardBranching::Outgoing, - outgoing[i]->momentum(),tSudakovPtr())); - protoBranchings().insert(currentBranching); - } - else { - bool isHard = true; - PPtr newParent = findParent(parent,isHard,outgoingset,false, - lastXCombPtr()->subProcess()); - assert(newParent); - if(decayingParticles_.find(newParent)==decayingParticles_.end()) { - ProtoBranchingPtr currentBranching = - new_ptr(ProtoBranching(newParent->dataPtr(),HardBranching::Outgoing, - newParent->momentum(),tSudakovPtr())); - protoBranchings().insert(currentBranching); - findDecayingParticles(newParent); - } - } - } - // add IS hardBranchings - ProtoBranchingPtr currentBranching = - new_ptr(ProtoBranching(incoming.first ->dataPtr(),HardBranching::Incoming, - incoming.first ->momentum(),tSudakovPtr())); - protoBranchings().insert(currentBranching); - currentBranching = - new_ptr(ProtoBranching(incoming.second->dataPtr(),HardBranching::Incoming, - incoming.second->momentum(),tSudakovPtr())); - protoBranchings().insert(currentBranching); - //create and initialise the first tree - ProtoTreePtr initialProtoTree = new_ptr( ProtoTree() ); - for(set::const_iterator it=protoBranchings().begin(); - it!=protoBranchings().end();++it) { - initialProtoTree->addBranching(*it); - } - //fill _proto_trees with all possible trees - protoTrees().insert(initialProtoTree ); - fillProtoTrees( initialProtoTree ); - double totalWeight = 0., nonOrderedWeight = 0.; - // create a HardTree from each ProtoTree and fill hardTrees() - for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); - cit != protoTrees().end(); ++cit ) { - PotentialTree newTree; - newTree.tree((**cit).createHardTree()); - // check the created CKKWTree corresponds to an allowed LO configuration - // (does matrix element have a corresponding diagram) - double meWgt = getDiagram( newTree ); - if( !newTree.diagram() ) continue; - // set the beam particles - PPair beams = lastXCombPtr()->lastParticles(); - // remove children of beams - PVector beam_children = beams.first->children(); - if( (**newTree.tree()->incoming().begin()).branchingParticle()->momentum().z() / - beams.first->momentum().z() < 0.) - swap( beams.first, beams.second ); - set::iterator it = newTree.tree()->incoming().begin(); - HardBranchingPtr br = *it; - br->beam( beams.first ); - while ( !br->children().empty() ) { - for(unsigned int ix = 0; ix < br->children().size(); ++ix ) { - if( br->children()[ix]->status() == HardBranching::Incoming ) { - br = br->children()[ix]; - break; - } - } - br->beam( beams.first ); - } - ++it; - br = *it; - br->beam( beams.second ); - while ( !br->children().empty() ) { - for( unsigned int ix = 0; ix < br->children().size(); ++ix ) { - if( br->children()[ix]->status() == HardBranching::Incoming ) { - br = br->children()[ix]; - break; - } - } - br->beam( beams.second ); - } - // do inverse momentum reconstruction - if( !evolver()->showerModel()->kinematicsReconstructor() - ->deconstructHardJets( newTree.tree(), evolver(), ShowerInteraction::QCD ) ) - continue; - newTree.tree()->findNodes(); - if( newTree.tree()->ordered() ) { - // find the wgt and fill hardTrees() map - double treeWeight = 1.; - if(reWeight_) treeWeight = meWgt*sudakovWeight( newTree.tree() ); - newTree.weight(treeWeight); - hardTrees_.push_back( make_pair( newTree, treeWeight ) ); - totalWeight += treeWeight; - } - else { - nonOrderedTrees_.push_back( make_pair( newTree, 1. ) ); - nonOrderedWeight += 1.; - } - } - // if rejecting non-ordered trees return - if( hardTrees_.empty() && rejectNonAO_ ) return PotentialTree(); - - // select the tree - PotentialTree chosen_hardTree=chooseHardTree(totalWeight, - nonOrderedWeight); - protoBranchings().clear(); - protoTrees().clear(); - nonOrderedTrees_.clear(); - hardTrees_.clear(); - if(! chosen_hardTree.tree() ) { - noShowerHists_ = true; - return PotentialTree(); - } - else - return chosen_hardTree; -} - -void MatchingHandler::initialiseMatching(int minMult, int maxMult) { - if (!matrixElement_){ - tStdXCombPtr lastXC = dynamic_ptr_cast(lastXCombPtr()); - tStdXCombPtr headXC = lastXC->head(); - if (headXC) - matrixElement_ = dynamic_ptr_cast(headXC->matrixElement()); - else if (lastXC) - matrixElement_ = dynamic_ptr_cast(lastXC->matrixElement()); - } - - HWmatrixElement_ = dynamic_ptr_cast(matrixElement_); - - assert(matrixElement_); - - // check multiplicity of FS partons - int nOut = lastXCombPtr()->subProcess()->outgoing().size(); - // is it the lowest multiplicity - lowestMult_ = nOut == minMult; - // or the highest - highestMult_ = nOut == maxMult; - // centre-of-mass energy - sHat(lastXCombPtr()->lastSHat()); - // scale for the PDFs - pdfScale(sqrt(lastXCombPtr()->lastScale())); - // alphaS value used by the ME generate - alphaSMG(lastXCombPtr()->lastAlphaS()); - // create a hard tree by clustering the event - hardTree(doClustering()); -} - -map::const_iterator MatchingHandler::parent(PPtr parent) { - long id = parent->id(); - for(map::const_iterator it = decayingParticles_.begin(); - it!=decayingParticles_.end();++it) { - if(id!=it->first->id()) continue; - Energy2 diff = - sqr(it->first->momentum().x()-parent->momentum().x()) + - sqr(it->first->momentum().y()-parent->momentum().y()) + - sqr(it->first->momentum().z()-parent->momentum().z()) + - sqr(it->first->momentum().t()-parent->momentum().t()); - Energy2 sum = - sqr(it->first->momentum().x()+parent->momentum().x()) + - sqr(it->first->momentum().y()+parent->momentum().y()) + - sqr(it->first->momentum().z()+parent->momentum().z()) + - sqr(it->first->momentum().t()+parent->momentum().t()); - double ratio = diff/sum; - if(ratio<1e-10) return it; - } - return decayingParticles_.end(); -} - -void MatchingHandler::addDecayProducts(SubProPtr subProcess, PPtr parent, - map::const_iterator decay, - const LorentzRotation & boost) const { - // map colours of the parent - map cmap; - if(parent->colourLine()) - cmap.insert(make_pair(decay->first-> colourLine(), - parent-> colourLine())); - if(parent->antiColourLine()) - cmap.insert(make_pair(decay->first->antiColourLine(), - parent->antiColourLine())); - // add the decay products - for(unsigned int ix=0;ixsecond.size();++ix) { - Lorentz5Momentum pnew = boost*decay->second[ix]->momentum(); - PPtr newParticle = decay->second[ix]->dataPtr()->produceParticle(pnew); - parent->addChild(newParticle); - if(decay->second[ix]->colourLine()) { - if(cmap.find(decay->second[ix]->colourLine())==cmap.end()) { - ColinePtr newLine(new_ptr(ColourLine())); - cmap.insert(make_pair(decay->second[ix]->colourLine(),newLine)); - } - cmap[decay->second[ix]->colourLine()]->addColoured(newParticle); - } - if(decay->second[ix]->antiColourLine()) { - if(cmap.find(decay->second[ix]->antiColourLine())==cmap.end()) { - ColinePtr newLine(new_ptr(ColourLine())); - cmap.insert(make_pair(decay->second[ix]->antiColourLine(),newLine)); - } - cmap[decay->second[ix]->antiColourLine()]->addAntiColoured(newParticle); - } - map::const_iterator pit = - decayingParticles_.find(decay->second[ix]); - if(pit!=decayingParticles_.end()) { - subProcess->addIntermediate(newParticle, false); - addDecayProducts(subProcess,newParticle,pit,boost); - } - else { - subProcess->addOutgoing(newParticle, false); - } - } -} diff --git a/Shower/Matching/PowhegHandler.cc b/Shower/Matching/PowhegHandler.cc deleted file mode 100644 --- a/Shower/Matching/PowhegHandler.cc +++ /dev/null @@ -1,168 +0,0 @@ -// -*- C++ -*- -// -// This is the implementation of the non-inlined, non-templated member -// functions of the PowhegHandler class. -// - -#include "PowhegHandler.h" -#include "ThePEG/Interface/ClassDocumentation.h" -#include "ThePEG/Interface/Switch.h" -#include "ThePEG/Interface/Parameter.h" -#include "ThePEG/EventRecord/Particle.h" -#include "ThePEG/Repository/UseRandom.h" -#include "ThePEG/Repository/EventGenerator.h" -#include "ThePEG/Utilities/DescribeClass.h" -#include "ThePEG/Persistency/PersistentOStream.h" -#include "ThePEG/Persistency/PersistentIStream.h" -#include "ThePEG/PDF/PartonExtractor.h" -#include "ThePEG/PDF/BeamParticleData.h" -#include "ThePEG/PDF/PDF.h" -#include "ThePEG/Cuts/Cuts.h" -#include "Herwig/PDF/HwRemDecayer.h" -#include "Herwig/Shower/Base/Evolver.h" -#include "Herwig/Shower/Base/PartnerFinder.h" -#include "Herwig/Shower/Base/KinematicsReconstructor.h" -#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.h" - -using namespace Herwig; - -IBPtr PowhegHandler::clone() const { - return new_ptr(*this); -} - -IBPtr PowhegHandler::fullclone() const { - return new_ptr(*this); -} - -void PowhegHandler::persistentOutput(PersistentOStream & os) const { - os << pTDefinition_ << ounit(maxpT_,GeV); -} - -void PowhegHandler::persistentInput(PersistentIStream & is, int) { - is >> pTDefinition_ >> iunit(maxpT_,GeV); -} - - -// *** Attention *** The following static variable is needed for the type -// description system in ThePEG. Please check that the template arguments -// are correct (the class and its base class), and that the constructor -// arguments are correct (the class name and the name of the dynamically -// loadable library where the class implementation can be found). -DescribeClass -describeHerwigPowhegHandler("Herwig::PowhegHandler", "HwMatching.so"); - -void PowhegHandler::Init() { - - static ClassDocumentation documentation - ("The PowhegHandler class handles the generation of the shower, including truncated" - "showers for external processes using the POWHEG scheme."); - - static Switch interfacepTDefinition - ("pTDefinition", - "The choice of the definition of the pT for the maximum emission in the shower", - &PowhegHandler::pTDefinition_, 0, false, false); - static SwitchOption interfacepTDefinitionScale - (interfacepTDefinition, - "Scale", - "Use the value of the lastScale(), which if reading Les Houches events is SCALUP", - 0); - static SwitchOption interfacepTDefinitionScaleAndpT - (interfacepTDefinition, - "ScaleAndpT", - "Use the same choice as scale for non-emission events but the pT of the" - " emitted particle for emission events", - 1); - static SwitchOption interfacepTDefinitionmaxpTAndpT - (interfacepTDefinition, - "maxpTAndpT", - "Use the maxPt value fo non-emission events and the pT of the" - " emitted particle for emission events", - 2); - - static Parameter interfacemaxpT - ("maxpT", - "Maximum pT for emission from non-emission events.", - &PowhegHandler::maxpT_, GeV, 1.0*GeV, 0.0*GeV, 10.0*GeV, - false, false, Interface::limited); - -} - -double PowhegHandler::reweightCKKW(int minMult, int maxMult) { - // as not reweighting skip if in initialisation - if(generator()->state()==InterfacedBase::initializing) - return 1.; - initialiseMatching(minMult,maxMult); - if( ! hardTree().tree() ) return 1.; - // update sub process based on hardTree() - updateSubProcess(); - return 1.; -} - -HardTreePtr PowhegHandler::generateCKKW(ShowerTreePtr tree) const { - - //get com energy from the progenitors - Energy2 s = - (tree->incomingLines(). begin()->first->progenitor()->momentum() + - tree->incomingLines().rbegin()->first->progenitor()->momentum()).m2(); - // Get the HardTree from the CKKW handler. - CKKWTreePtr hardtree = getCKKWTree(); - - // if no hard tree return - if( ! hardtree ) return HardTreePtr(); - // check the trees match - if( ! hardtree->connect(tree) ) return HardTreePtr(); - // choice of the veto pT - Energy veto_pt = sqrt( s ); - // use the scale - if(pTDefinition_==0) { - veto_pt = sqrt(lastXCombPtr()->lastScale()); - } - // otherwise pT of emission if emitted - else if(!lowestMult()) { - veto_pt = hardtree->lowestPt( 1, s ); - for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it - = tree->outgoingLines().begin(); - it != tree->outgoingLines().end(); ++it ) { - if( ! it->second->coloured() ) continue; - it->first->maximumpT( veto_pt, ShowerInteraction::QCD ); - } - for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it - = tree->incomingLines().begin(); - it != tree->incomingLines().end(); ++it ) { - if( ! it->second->coloured() ) continue; - it->first->maximumpT( veto_pt, ShowerInteraction::QCD ); - } - } - else if(pTDefinition_==1) { - veto_pt = sqrt(lastXCombPtr()->lastScale()); - } - else if(pTDefinition_==2) { - veto_pt = maxpT_; - } - else - assert(false); - // that's it - return hardtree; -} - -PotentialTree PowhegHandler::chooseHardTree(double,double) { - PotentialTree chosen_hardTree; - Energy min_pt = Constants::MaxEnergy; - if( !hardTrees().empty() ){ - for(unsigned int ix = 0; ix < hardTrees().size(); ix++ ){ - if( hardTrees()[ix].first.tree()->totalPt() < min_pt ) { - min_pt = hardTrees()[ix].first.tree()->totalPt(); - chosen_hardTree = hardTrees()[ix].first; - } - } - } - else { - for(unsigned int ix = 0; ix < nonOrderedTrees().size(); ix++ ){ - if( nonOrderedTrees()[ix].first.tree()->totalPt() < min_pt ){ - min_pt = nonOrderedTrees()[ix].first.tree()->totalPt(); - chosen_hardTree=nonOrderedTrees()[ix].first; - } - } - } - return chosen_hardTree; -} diff --git a/Shower/PerturbativeProcess.fh b/Shower/PerturbativeProcess.fh new file mode 100644 --- /dev/null +++ b/Shower/PerturbativeProcess.fh @@ -0,0 +1,22 @@ +// -*- C++ -*- +// +// This is the forward declaration of the PerturbativeProcess class. +// +#ifndef HERWIG_PerturbativeProcess_FH +#define HERWIG_PerturbativeProcess_FH + +#include "ThePEG/Config/Pointers.h" + +namespace Herwig { + +class PerturbativeProcess; + +} + +namespace ThePEG { + +ThePEG_DECLARE_POINTERS(Herwig::PerturbativeProcess,PerturbativeProcessPtr); + +} + +#endif diff --git a/Shower/PerturbativeProcess.h b/Shower/PerturbativeProcess.h new file mode 100644 --- /dev/null +++ b/Shower/PerturbativeProcess.h @@ -0,0 +1,73 @@ +// -*- C++ -*- +// +// PerturbativeProcess.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_PerturbativeProcess_H +#define HERWIG_PerturbativeProcess_H + +#include "ThePEG/Config/ThePEG.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/EventRecord/SubProcess.h" +#include "ThePEG/Handlers/XComb.h" +#include "ThePEG/Config/Pointers.h" +#include "PerturbativeProcess.fh" + +namespace Herwig { +using namespace ThePEG; + +/** + * Simple struct for hard processes and decays + */ +class PerturbativeProcess : public Base { + +public: + + /** + * The incoming particles + */ + vector > & incoming() { + return incoming_; + } + + /** + * The outgoing particles + */ + vector > & outgoing() { + return outgoing_; + } + +protected: + + /** + * The incoming particles + */ + vector > incoming_; + + /* + * The outgoing particles + */ + vector > outgoing_; + + /** + * The subprocess + */ + tSubProPtr subprocess_; + + /** + * The XComb + */ + XCombPtr xcomb_; +}; + +/** + * Typedef for map of PerturbativeProcess for decays + */ +typedef multimap > DecayProcessMap; + +} + +#endif diff --git a/Shower/QTilde/Base/Branching.h b/Shower/QTilde/Base/Branching.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/Branching.h @@ -0,0 +1,69 @@ +// -*- C++ -*- +#ifndef HERWIG_Branching_H +#define HERWIG_Branching_H +// +// This is the declaration of the Branching struct. +// +#include "Herwig/Shower/QTilde/ShowerConfig.h" +#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" + +namespace Herwig { + +using namespace ThePEG; + + /** \ingroup Shower + * The branching struct is used to store information on the branching. + * The kinematics variable is a pointer to the ShowerKinematics for the branching + * The sudakov variable is a pointer to the SudakovFormFactor for the branching + * The ids variable is the list of particles in the branching + */ + struct Branching { + + /** + * Pointer to the ShowerKinematics object for the branching + */ + ShoKinPtr kinematics; + + /** + * PDG codes of the particles in the branching + */ + IdList ids; + + /** + * The SudakovFormFactor for the branching + */ + tSudakovPtr sudakov; + + /** + * The type of radiation line + */ + ShowerPartnerType::Type type; + + /** + * Whether or not it keep from forced hard emisson + */ + bool hard; + + /** + * Which of the children is same as incoming + */ + unsigned int iout; + + /** + * Constructor for the struct + * @param a pointer to the ShowerKinematics object for the branching + * @param c PDG codes of the particles in the branching + * @param d The SudakovFormFactor for the branching + */ + Branching(ShoKinPtr a, IdList c,tSudakovPtr d,ShowerPartnerType::Type t) + : kinematics(a), ids(c), sudakov(d), type(t), hard(false), iout(0) {} + + /** + * Default constructor + */ + Branching() : hard(false), iout(0) {} + }; + +} + +#endif /* HERWIG_Branching_H */ diff --git a/Shower/Base/Evolver.fh b/Shower/QTilde/Base/Evolver.fh rename from Shower/Base/Evolver.fh rename to Shower/QTilde/Base/Evolver.fh diff --git a/Shower/QTilde/Base/FullShowerVeto.cc b/Shower/QTilde/Base/FullShowerVeto.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/FullShowerVeto.cc @@ -0,0 +1,158 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the FullShowerVeto class. +// + +#include "FullShowerVeto.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Interface/Switch.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "Herwig/Shower/ShowerHandler.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +using namespace Herwig; + +void FullShowerVeto::persistentOutput(PersistentOStream & os) const { + os << type_ << behaviour_; +} + +void FullShowerVeto::persistentInput(PersistentIStream & is, int) { + is >> type_ >> behaviour_; +} + +void FullShowerVeto::doinit() { + Interfaced::doinit(); + // check reweighting + if(behaviour_==1&&type_!=2) + throw Exception() << "Reweighting in the FullShowerVeto is only" + << " supported for the primary hard process\n" + << Exception::runerror; +} + +DescribeAbstractClass +describeHerwigFullShowerVeto("Herwig::FullShowerVeto", "HwShower.so"); + +void FullShowerVeto::Init() { + + static ClassDocumentation documentation + ("The FullShowerVeto class allows the parton shower generated from a configuration to be vetoed."); + + static Switch interfaceType + ("Type", + "Which type of processes to consider", + &FullShowerVeto::type_, 1, false, false); + static SwitchOption interfaceTypeAll + (interfaceType, + "All", + "All Processes", + 0); + static SwitchOption interfaceTypeScattering + (interfaceType, + "Scattering", + "Only apply to scattering processes and not decays", + 1); + static SwitchOption interfaceTypePrimary + (interfaceType, + "Primary", + "Only apply to the primary scattering process", + 2); + static SwitchOption interfaceTypeDecay + (interfaceType, + "Decay", + "Only apply to decays", + 3); + + static Switch interfaceBehaviour + ("Behaviour", + "What to do if the shower if vetoed", + &FullShowerVeto::behaviour_, 0, false, false); + static SwitchOption interfaceBehaviourShower + (interfaceBehaviour, + "Shower", + "Veto the shower and try showering the process again", + 0); + static SwitchOption interfaceBehaviourShowerReweight + (interfaceBehaviour, + "ShowerReweight", + "Veto the shower and reweight the event to take this into account, only supported for the primary process", + 1); + static SwitchOption interfaceBehaviourEvent + (interfaceBehaviour, + "Event", + "Veto the event, cross section automatically reweigted", + 2); + +} + +int FullShowerVeto::applyVeto(ShowerTreePtr tree) { + // return if veto should not be calculated + // decay process and only doing hard processes + // or vice versa + if(((type_ == 1 || type_ ==2 ) && tree->isDecay() ) || + ( type_ == 3 && tree->isHard())) + return -1; + // not primary process and only doing those + if( type_ == 2 && !ShowerHandler::currentHandler()->firstInteraction() ) + return -1; + // extract the incoming and outgoing particles from the ShowerTree + finalState_.clear(); + incoming_.clear(); + outgoing_.clear(); + // incoming + for(map::const_iterator it=tree->incomingLines().begin(); + it!=tree->incomingLines().end();++it) { + incoming_.push_back(it->first->progenitor()); + } + // outgoing + for(map::const_iterator it=tree->outgoingLines().begin(); + it!=tree->outgoingLines().end();++it) { + outgoing_.push_back(it->first->progenitor()); + } + // call function in inheriting class to decide what to do + bool vetoed = vetoShower(); + // clear storage + finalState_.clear(); + incoming_.clear(); + outgoing_.clear(); + // return the answer + return vetoed ? behaviour_ : -1; +} + +namespace { + +void addFinal(vector & finalState, tPPtr particle) { + if(particle->children().empty()) { + finalState.push_back(particle); + return; + } + for(unsigned int ix=0;ixchildren().size();++ix) { + addFinal(finalState,particle->children()[ix]); + } +} +} + + +// extract the incoming and outgoing particles +const vector & FullShowerVeto::finalState() { + if(!finalState_.empty()) return finalState_; + // incoming + for(unsigned int ix=0;ixparents().empty()) continue; + tPPtr parent = incoming_[ix]->parents()[0]; + while (parent) { + addFinal(finalState_,parent->children()[1]); + if(parent->parents().empty()) break; + parent = parent->parents()[0]; + } + } + // outgoing + for(unsigned int ix=0;ix & incoming() {return incoming_;} + + /** + * Outgoing particles from the hard process + */ + const vector & outgoing() {return outgoing_;} + + /** + * The final-state particles at the end of the shower + */ + const vector & finalState(); + + +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(); + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + FullShowerVeto & operator=(const FullShowerVeto &); + +private: + + /** + * Switches + */ + //@{ + /** + * Which type of processes to consider + */ + unsigned int type_; + + /** + * What to do if the event is vetoed + */ + unsigned int behaviour_; + //} + + /** + * Temporary storage + */ + //@{ + /** + * Incoming to hard process + */ + vector incoming_; + + /** + * Outgoing from the hard process + */ + vector outgoing_; + + /** + * Final State particles + */ + vector finalState_; + //@} +}; + +} + +#endif /* Herwig_FullShowerVeto_H */ diff --git a/Shower/Base/HardBranching.cc b/Shower/QTilde/Base/HardBranching.cc rename from Shower/Base/HardBranching.cc rename to Shower/QTilde/Base/HardBranching.cc diff --git a/Shower/Base/HardBranching.fh b/Shower/QTilde/Base/HardBranching.fh rename from Shower/Base/HardBranching.fh rename to Shower/QTilde/Base/HardBranching.fh diff --git a/Shower/Base/HardBranching.h b/Shower/QTilde/Base/HardBranching.h rename from Shower/Base/HardBranching.h rename to Shower/QTilde/Base/HardBranching.h --- a/Shower/Base/HardBranching.h +++ b/Shower/QTilde/Base/HardBranching.h @@ -1,363 +1,363 @@ // -*- C++ -*- #ifndef HERWIG_HardBranching_H #define HERWIG_HardBranching_H // // This is the declaration of the HardBranching class. // #include "ThePEG/Config/ThePEG.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/ShowerTree.h" -#include "Herwig/Shower/Base/SudakovFormFactor.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/ShowerTree.h" +#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" #include "HardBranching.fh" #include "HardTree.fh" namespace Herwig { using namespace ThePEG; /** * The HardBranching class is designed to contain the information needed for * an individual branching in the POWHEG approach */ class HardBranching : public Base { /** * The HardTree is friend */ friend class HardTree; public: /** * Enum for the status */ enum Status {Outgoing=0,Incoming,Decay}; public: /** * The default constructor * @param particle The particle which is branching * @param sudakov The Sudakov form factor for the branching * @param parent The parent for the branching * @param status Whether the particle is incoming or outgoing */ HardBranching(ShowerParticlePtr particle, SudakovPtr sudakov, tHardBranchingPtr parent,Status status); /** * Add a child of the branching * @param child The child of the branching */ void addChild(HardBranchingPtr child) {_children.push_back(child);} /** * Clear the children */ void clearChildren() { _children.clear(); } /** * Set the momenta of the particles */ void setMomenta(LorentzRotation R, double alpha, Lorentz5Momentum pt, bool setMomentum=true); /** * Set and get members for the private member variables */ //@{ /** * Return the branching particle. */ tShowerParticlePtr branchingParticle() const {return _particle;} /** * Set the branching particle */ void branchingParticle(ShowerParticlePtr in) {_particle=in;} /** * Get the original momentum */ const Lorentz5Momentum & original() const {return _original;} /** * Set the original momentum */ void original(const Lorentz5Momentum & in) {_original=in;} /** * Get the p reference vector */ const Lorentz5Momentum & pVector() const {return _p;} /** * Set the p reference vector */ void pVector(const Lorentz5Momentum & in) {_p=in;} /** * Get the n reference vector */ const Lorentz5Momentum & nVector() const {return _n;} /** * Set the n reference vector */ void nVector(const Lorentz5Momentum & in) {_n=in;} /** * Get the transverse momentum vector */ const Lorentz5Momentum & qPerp() const {return _qt;} /** * Set the transverse momentum vector */ void qPerp(const Lorentz5Momentum & in) {_qt=in;} /** * Get the momentum the particle should have as the start of a shower */ const Lorentz5Momentum & showerMomentum() const {return _shower;} /** * Set the momentum the particle should have as the start of a shower */ void showerMomentum(const Lorentz5Momentum & in ) {_shower=in;} /** * Get the transverse momentum */ Energy pT() const {return _pt;} /** * Set the transverse momentum */ void pT(Energy in) { _pt=in;} /** * Get the fraction of beam momentum x */ double x_frac() const {return _x_frac;} /** * Set the fraction of beam momentum x */ void x_frac( double x ) { _x_frac = x; } /** * Get whether the branching is incoming, outgoing or decay */ Status status() const {return _status;} /** * Set whether the branching is incoming, outgoing or decay */ void status(Status in) {_status=in;} /** * The parent of the branching */ tHardBranchingPtr parent() const {return _parent;} /** * Set the parent of the branching */ void parent(tHardBranchingPtr in) {_parent=in;} /** * The Sudakov form-factor */ SudakovPtr sudakov() const {return _sudakov;} /** * The Sudakov form-factor */ void sudakov(SudakovPtr in) {_sudakov=in;} /** * Get the beam particle */ PPtr beam() const {return _beam;} /** * Set the beam particle */ void beam(PPtr in) {_beam=in;} /** * The children */ vector & children() {return _children;} //@} /** * Information on the Shower variables for the branching */ //@{ /** * Get the evolution scale */ Energy scale() const {return _scale;} /** * The evolution scale */ void scale(Energy in) {_scale=in;} /** * The energy fraction */ double z() const {return _z;} /** * The energy fraction */ void z(double in) {_z=in;} /** * The azimthual angle */ double phi() const {return _phi;} /** * The azimthual angle */ void phi(double in) {_phi=in;} //@} /** * Colour partners */ //@{ /** * Get the colour partner */ tHardBranchingPtr colourPartner() const {return _partner;} /** * The colour partner of the branching */ void colourPartner(tHardBranchingPtr in) {_partner=in;} //@} /** * Type of branching */ ShowerPartnerType::Type type() const { assert(type_!=ShowerPartnerType::Undefined); return type_; } /** * Type of branching */ void type(ShowerPartnerType::Type in) { type_ = in; assert(type_!=ShowerPartnerType::Undefined); } private: /** * The branching particle */ ShowerParticlePtr _particle; /** * The rescaled momentum */ Lorentz5Momentum _original; /** * The \f$p\f$ reference vector */ Lorentz5Momentum _p; /** * The \f$n\f$ reference vector */ Lorentz5Momentum _n; /** * The transverse momentum vector */ Lorentz5Momentum _qt; /** * The momentum the particle should have as the start of a shower */ Lorentz5Momentum _shower; /** * The transverse momentum */ Energy _pt; /** * The beam momentum fraction carried by an incoming parton x */ double _x_frac; /** * Whether the branching is incoming, outgoing or a decay */ Status _status; /** * Information on the Shower variables for the branching */ //@{ /** * The evolution scale */ Energy _scale; /** * The energy fraction */ double _z; /** * The azimthual angle */ double _phi; //@} /** * The parent of the branching */ tHardBranchingPtr _parent; /** * The Sudakov form-factor */ SudakovPtr _sudakov; /** * The children */ vector _children; /** * The beam particle */ PPtr _beam; /** * The colour partner */ tHardBranchingPtr _partner; /** * The type of branching */ ShowerPartnerType::Type type_; }; } #endif /* HERWIG_HardBranching_H */ diff --git a/Shower/QTilde/Base/HardTree.cc b/Shower/QTilde/Base/HardTree.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/HardTree.cc @@ -0,0 +1,347 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the HardTree class. +// + +#include "HardTree.h" +#include "ThePEG/PDT/EnumParticles.h" +#include "ThePEG/Repository/CurrentGenerator.h" +#include "Herwig/Shower/RealEmissionProcess.h" + +using namespace Herwig; + +HardTree::HardTree(vector branchings, + vector spacelike, + ShowerInteraction::Type type) + : interaction_(type), + branchings_(branchings.begin(),branchings.end()), + spacelike_ (spacelike .begin(),spacelike .end()), + partnersSet_(false) +{} + +bool HardTree::connect(ShowerTreePtr shower) { + particles_.clear(); + // extract the progenitors from the ShowerTree + vector progenitors = shower->extractProgenitors(); + vector connectedProgenitors(progenitors.size(),false); + // connect the trees up + for( set::iterator it = branchings().begin(); + it != branchings().end(); ++it) { + Energy2 dmin( 1e30*GeV2 ); + tShowerParticlePtr partner; + unsigned int progenitorsIndex(999); + for( unsigned int ix = 0; ix < progenitors.size(); ++ix ) { + if( connectedProgenitors[ix] ) continue; + if( (**it).branchingParticle()->id() != progenitors[ix]->progenitor()->id() ) continue; + if( (**it).branchingParticle()->isFinalState() != + progenitors[ix]->progenitor()->isFinalState() ) continue; + Energy2 dtest = + sqr( progenitors[ix]->progenitor()->momentum().x() - (**it).showerMomentum().x() ) + + sqr( progenitors[ix]->progenitor()->momentum().y() - (**it).showerMomentum().y() ) + + sqr( progenitors[ix]->progenitor()->momentum().z() - (**it).showerMomentum().z() ) + + sqr( progenitors[ix]->progenitor()->momentum().t() - (**it).showerMomentum().t() ); + if( dtest < dmin ) { + partner = progenitors[ix]->progenitor(); + progenitorsIndex = ix; + dmin = dtest; + } + } + if( !partner ) return false; + connectedProgenitors[progenitorsIndex] = true; + connect( partner, *it ); + if( (**it).status() == HardBranching::Incoming ) { + double z( (**it).z() ); + tHardBranchingPtr parent = (**it).parent(); + while (parent) { + z *= parent->z(); + parent = parent->parent(); + } + partner->x(z); + } + } + if( particles().size() == progenitors.size() ) return true; + else return false; +} + +ostream & Herwig::operator<<(ostream & os, const HardTree & x) { + os << "Output of HardTree " << &x << "\n"; + for(set::const_iterator it=x.branchings_.begin(); + it!=x.branchings_.end();++it) { + os << "Hard Particle: " << *(**it).branchingParticle() << " has Sudakov " + << (**it).sudakov() << " pT = " << (**it).pT()/GeV + << " scale = " << (**it).scale()/GeV << "\n"; + os << "Its colour lines are " << (**it).branchingParticle()->colourLine() << "\t" + << (**it).branchingParticle()->antiColourLine() << "\n"; + os << "Its basis vectors are " << (**it).pVector()/GeV + << " " << (**it).nVector()/GeV << "\n"; + os << "Its shower momentum is " << (**it).showerMomentum()/GeV << "\n"; + for(unsigned int iy=0;iy<(**it).children().size();++iy) { + os << "\t Children : " << *(**it).children()[iy]->branchingParticle() + << "\n"; + os << "It's colour lines are " + << (**it).children()[iy]->branchingParticle()->colourLine() << "\t" + << (**it).children()[iy]->branchingParticle()->antiColourLine() << "\n"; + } + } + for(set::const_iterator it=x.spacelike_.begin(); + it!=x.spacelike_.end();++it) { + os << "SpaceLike: " << *(**it).branchingParticle() << " has Sudakov" + << (**it).sudakov() << " pT = " << (**it).pT()/GeV + << " scale = " << (**it).scale()/GeV << "\n"; + os << "It's colour lines are " + << (**it).branchingParticle()->colourLine() << "\t" + << (**it).branchingParticle()->antiColourLine() << "\n"; + + for(unsigned int iy=0;iy<(**it).children().size();++iy) { + os << "\t Children: " << *(**it).children()[iy]->branchingParticle() + << "\n"; + os << "It's colour lines are " + << (**it).children()[iy]->branchingParticle()->colourLine() << "\t" + << (**it).children()[iy]->branchingParticle()->antiColourLine() << "\n"; + } + } + return os; +} + +HardTree::HardTree(RealEmissionProcessPtr real) + : interaction_(real->interaction()), + partnersSet_(false) { + // check the type + unsigned int pType = real->incoming().size() == 2 ? 1 : 2; + // create the Branchings for the incoming particles + vector spaceBranchings; + ShowerParticleVector incoming; + for(unsigned int ix=0;ixincoming().size();++ix) { + unsigned int type = ix!=real->emitter() ? pType : 0; + ShowerParticlePtr part(new_ptr(ShowerParticle(*real->incoming()[ix],type,false))); + incoming.push_back(part); + spaceBranchings.push_back(new_ptr(HardBranching(part,SudakovPtr(),HardBranchingPtr(), + HardBranching::Incoming))); + if(real->incoming().size()==2) { + assert(real->hadrons()[ix]); + spaceBranchings.back()->beam(real->hadrons()[ix]); + } + } + // create the outgoing particles + ShowerParticleVector outgoing; + vector timeBranchings; + for(unsigned int ix=0;ixoutgoing().size();++ix) { + unsigned int type = + int(ix)!=int(real->emitted()-real->incoming().size()) && + int(ix)!=int(real->emitter()-real->incoming().size()) ? pType : 0; + ShowerParticlePtr part(new_ptr(ShowerParticle(*real->outgoing()[ix],type,true))); + outgoing.push_back(part); + timeBranchings.push_back(new_ptr(HardBranching(part,SudakovPtr(),HardBranchingPtr(), + HardBranching::Outgoing))); + } + // create the branching for the radiating particle + HardBranchingPtr emitterBranch; + // inital-state emitter + if(real->emitter() < real->incoming().size()) { + unsigned int iemitter = real->emitter(); + unsigned int iemitted = real->emitted() -real->incoming().size(); + ShowerParticlePtr parent(new_ptr(ShowerParticle(real->bornIncoming()[iemitter]->dataPtr(),false))); + Lorentz5Momentum parentMomentum = + real->incoming()[iemitter]->momentum() - + real->outgoing()[iemitted]->momentum(); + parentMomentum.setMass(real->bornIncoming()[iemitter]->dataPtr()->mass()); + parent->set5Momentum(parentMomentum); + emitterBranch = new_ptr(HardBranching(parent,SudakovPtr(),HardBranchingPtr(), + HardBranching::Incoming)); + // QED radiation + if(real->interaction()==ShowerInteraction::QED) { + spaceBranchings[iemitter]->type(ShowerPartnerType::QED); + if(parent->id()!=ParticleID::gamma) { + if(spaceBranchings[iemitter]->branchingParticle()-> colourLine()) + spaceBranchings[iemitter]->branchingParticle()-> colourLine()->addColoured(parent); + if(spaceBranchings[iemitter]->branchingParticle()->antiColourLine()) + spaceBranchings[iemitter]->branchingParticle()->antiColourLine()->addAntiColoured(parent); + } + } + else { + if(real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour8) { + // g -> g g + if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour8) { + if(real->incoming()[iemitter]->colourLine()==real->outgoing()[iemitted]->colourLine()) { + real->incoming()[iemitter]->antiColourLine()->addAntiColoured(parent); + real->outgoing()[iemitted]->antiColourLine()-> addColoured(parent); + spaceBranchings[iemitter]->type(ShowerPartnerType::QCDColourLine); + } + else if(real->incoming()[iemitter]->antiColourLine()==real->outgoing()[iemitted]->antiColourLine()) { + real->incoming()[iemitter]->colourLine()-> addColoured(parent); + real->outgoing()[iemitted]->colourLine()->addAntiColoured(parent); + spaceBranchings[iemitter]->type(ShowerPartnerType::QCDAntiColourLine); + } + else + assert(false); + } + // q -> q g + else if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour3) { + timeBranchings[iemitted]->branchingParticle()->antiColourLine()->addColoured(parent); + spaceBranchings[iemitter]->type(ShowerPartnerType::QCDColourLine); + } + // qbar -> qbar g + else if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour3bar) { + timeBranchings[iemitted]->branchingParticle()->colourLine()->addAntiColoured(parent); + spaceBranchings[iemitter]->type(ShowerPartnerType::QCDAntiColourLine); + } + } + else if(real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour3) { + if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour8) { + real->incoming()[iemitter]->antiColourLine()->addAntiColoured(parent); + spaceBranchings[iemitter]->type(ShowerPartnerType::QCDAntiColourLine); + } + else if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour3) { + timeBranchings [iemitted]->branchingParticle()->colourLine()->addAntiColoured(parent); + spaceBranchings[iemitter]->branchingParticle()->colourLine()-> addColoured(parent); + spaceBranchings[iemitter]->type(ShowerPartnerType::QCDColourLine); + } + else + assert(false); + } + else if(real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour3bar) { + if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour8) { + real->incoming()[iemitter]->colourLine()->addColoured(parent); + spaceBranchings[iemitter]->type(ShowerPartnerType::QCDColourLine); + } + else if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour3bar) { + timeBranchings[iemitted ]->branchingParticle()->antiColourLine()-> addColoured(parent); + spaceBranchings[iemitter]->branchingParticle()->antiColourLine()->addAntiColoured(parent); + spaceBranchings[iemitter]->type(ShowerPartnerType::QCDAntiColourLine); + } + else + assert(false); + } + else + assert(false); + } + emitterBranch ->parent(spaceBranchings[iemitter]); + timeBranchings[iemitted]->parent(spaceBranchings[iemitter]); + spaceBranchings[iemitter]->addChild(emitterBranch); + spaceBranchings[iemitter]->addChild(timeBranchings[iemitted]); + if(real->spectator()< real->incoming().size()) { + unsigned int ispect = real->spectator(); + // set partners + emitterBranch ->colourPartner(spaceBranchings[ispect]); + spaceBranchings[ispect]->colourPartner(emitterBranch); + emitterBranch ->branchingParticle()->partner(spaceBranchings[ispect]->branchingParticle()); + spaceBranchings[ispect]->branchingParticle()->partner(emitterBranch ->branchingParticle()); + } + else { + unsigned int ispect = real->spectator()-real->incoming().size(); + // set partners + emitterBranch ->colourPartner(timeBranchings[ispect]); + timeBranchings[ispect]->colourPartner(emitterBranch); + emitterBranch ->branchingParticle()->partner(timeBranchings[ispect]->branchingParticle()); + timeBranchings[ispect]->branchingParticle()->partner(emitterBranch ->branchingParticle()); + } + } + // final-state emitter + else { + unsigned int iemitter = real->emitter() -real->incoming().size(); + unsigned int iemitted = real->emitted() -real->incoming().size(); + ShowerParticlePtr parent(new_ptr(ShowerParticle(real->bornOutgoing()[iemitter]->dataPtr(),true))); + Lorentz5Momentum parentMomentum = + real->outgoing()[iemitter]->momentum() + + real->outgoing()[iemitted]->momentum(); + parentMomentum.setMass(real->bornOutgoing()[iemitter]->dataPtr()->mass()); + parent->set5Momentum(parentMomentum); + emitterBranch = new_ptr(HardBranching(parent,SudakovPtr(),HardBranchingPtr(), + HardBranching::Outgoing)); + // QED radiation + if(real->interaction()==ShowerInteraction::QED) { + emitterBranch->type(ShowerPartnerType::QED); + if(parent->id()!=ParticleID::gamma) { + if(timeBranchings[iemitter]->branchingParticle()-> colourLine()) + timeBranchings[iemitter]->branchingParticle()-> colourLine()->addColoured(parent); + if(timeBranchings[iemitter]->branchingParticle()->antiColourLine()) + timeBranchings[iemitter]->branchingParticle()->antiColourLine()->addAntiColoured(parent); + } + } + else { + if(real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour8) { + // g -> g g + if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour8) { + if(real->outgoing()[iemitter]->colourLine()==real->outgoing()[iemitted]->antiColourLine()) { + real->outgoing()[iemitter]->antiColourLine()->addAntiColoured(parent); + real->outgoing()[iemitted]-> colourLine()-> addColoured(parent); + emitterBranch->type(ShowerPartnerType::QCDColourLine); + } + else if(real->outgoing()[iemitter]->antiColourLine()==real->outgoing()[iemitted]->colourLine()) { + real->outgoing()[iemitter]-> colourLine()-> addColoured(parent); + real->outgoing()[iemitted]->antiColourLine()->addAntiColoured(parent); + emitterBranch->type(ShowerPartnerType::QCDAntiColourLine); + } + else + assert(false); + } + // q -> q g + else if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour3) { + timeBranchings[iemitted]->branchingParticle()->colourLine()->addColoured(parent); + emitterBranch->type(ShowerPartnerType::QCDColourLine); + } + // qbar -> qbar g + else if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour3bar) { + timeBranchings[iemitted]->branchingParticle()->antiColourLine()->addAntiColoured(parent); + emitterBranch->type(ShowerPartnerType::QCDAntiColourLine); + } + } + else if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour3 && + real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour3bar) { + timeBranchings[iemitter]->branchingParticle()-> colourLine()-> addColoured(parent); + timeBranchings[iemitted]->branchingParticle()->antiColourLine()->addAntiColoured(parent); + emitterBranch->type(ShowerPartnerType::QCDColourLine); + } + else if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour3bar && + real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour3) { + timeBranchings[iemitter]->branchingParticle()->antiColourLine()->addAntiColoured(parent); + timeBranchings[iemitted]->branchingParticle()-> colourLine()-> addColoured(parent); + emitterBranch->type(ShowerPartnerType::QCDAntiColourLine); + } + else + assert(false); + } + emitterBranch->addChild(timeBranchings[iemitter]); + emitterBranch->addChild(timeBranchings[iemitted]); + if(real->spectator()< real->incoming().size()) { + unsigned int ispect = real->spectator(); + // set partners + emitterBranch ->colourPartner(spaceBranchings[ispect]); + spaceBranchings[ispect]->colourPartner(emitterBranch); + emitterBranch ->branchingParticle()->partner(spaceBranchings[ispect]->branchingParticle()); + spaceBranchings[ispect]->branchingParticle()->partner(emitterBranch ->branchingParticle()); + } + else { + unsigned int ispect = real->spectator()-real->incoming().size(); + // set partners + emitterBranch ->colourPartner(timeBranchings[ispect]); + timeBranchings[ispect]->colourPartner(emitterBranch); + emitterBranch ->branchingParticle()->partner(timeBranchings[ispect]->branchingParticle()); + timeBranchings[ispect]->branchingParticle()->partner(emitterBranch ->branchingParticle()); + } + } + assert(emitterBranch); + spacelike_=set(spaceBranchings.begin(),spaceBranchings.end()); + // insert the incoming branchings + for(unsigned int ix=0;ixemitter()incoming().size() && real->emitter()==ix) + inBranch = emitterBranch; + else + inBranch = spaceBranchings[ix]; + if(real->incoming().size()==2) + inBranch->beam(real->hadrons()[ix]); + branchings_.insert(inBranch); + } + // and the outgoing ones + for(unsigned int ix=0;ixemitter()>=real->incoming().size() && + real->emitter()==ix+real->incoming().size()) + branchings_.insert(emitterBranch); + else if(real->emitted()==ix+real->incoming().size()) + continue; + else + branchings_.insert(timeBranchings[ix]); + } +} diff --git a/Shower/Base/HardTree.fh b/Shower/QTilde/Base/HardTree.fh rename from Shower/Base/HardTree.fh rename to Shower/QTilde/Base/HardTree.fh diff --git a/Shower/QTilde/Base/HardTree.h b/Shower/QTilde/Base/HardTree.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/HardTree.h @@ -0,0 +1,143 @@ +// -*- C++ -*- +#ifndef HERWIG_HardTree_H +#define HERWIG_HardTree_H +// +// This is the declaration of the HardTree class. +// + +#include "ThePEG/Config/ThePEG.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/ShowerTree.h" +#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" +#include "Herwig/Shower/RealEmissionProcess.fh" +#include "HardBranching.h" +#include "HardTree.fh" + +namespace Herwig { + +using namespace ThePEG; +/** + * The HardTree class is designed to contain the information required + * to implement the POWHEG approach for Monte Carlo at next-to-leading order. + */ +class HardTree : public Base { + + /** + * Output operator for testing + */ + friend ostream & operator << (ostream &, const HardTree & ); + +public: + + /** + * The default constructor. + */ + HardTree(vector, vector, ShowerInteraction::Type); + + /** + * Contructor from Real emission process + */ + HardTree(RealEmissionProcessPtr real); + + /** + * Match particles in the ShowerTree to branchings in the HardTree + */ + bool connect(ShowerParticlePtr particle, HardBranchingPtr branching) { + if(branchings_.find(branching)==branchings_.end()) return false; + particles_[particle]=branching; + return true; + } + + /** + * Match the prticles in the ShowerTree to the branchings in the HardTree + */ + bool connect(ShowerTreePtr); + + /** + * Access the map between the ShowerParticle and the HardBranching + */ + map & particles() + {return particles_;} + + /** + * Access the set of branchings + */ + set & branchings() {return branchings_;} + + /** + * Access the incoming branchings + */ + set & incoming() {return spacelike_;} + + /** + * Type of interaction + */ + ShowerInteraction::Type interaction() {return interaction_;} + + /** + * Get the Rotation to be applied to the tree + */ + LorentzRotation showerRot() { return showerRot_; } + + /** + * Set the Rotation to be applied to the tree + */ + void showerRot( LorentzRotation r ) { showerRot_ = r; } + + /** + * Whether or not the evolution partners are set + */ + bool partnersSet() const {return partnersSet_;} + + /** + * Whether or not the evolution partners are set + */ + void partnersSet(bool in) {partnersSet_=in;} + +private: + + /** + * Type of interaction + */ + ShowerInteraction::Type interaction_; + + /** + * The ShowerTree + */ + ShowerTreePtr _tree; + + /** + * Map from the particles in the ShowerTree to the HardBranchings + */ + map particles_; + + /** + * The HardBranchings in the hard process + */ + set branchings_; + + /** + * The HardBranchings which initiate the space-like showers + */ + set spacelike_; + + /** + * Rotation to shower frame + */ + LorentzRotation showerRot_; + + /** + * Whether or not partners are set + */ + bool partnersSet_; + +}; + + /** + * Output operator for testing + */ + ostream & operator << (ostream &, const HardTree & ); + +} + +#endif /* HERWIG_HardTree_H */ diff --git a/Shower/Base/KinematicsReconstructor.cc b/Shower/QTilde/Base/KinematicsReconstructor.cc rename from Shower/Base/KinematicsReconstructor.cc rename to Shower/QTilde/Base/KinematicsReconstructor.cc diff --git a/Shower/Base/KinematicsReconstructor.fh b/Shower/QTilde/Base/KinematicsReconstructor.fh rename from Shower/Base/KinematicsReconstructor.fh rename to Shower/QTilde/Base/KinematicsReconstructor.fh diff --git a/Shower/QTilde/Base/KinematicsReconstructor.h b/Shower/QTilde/Base/KinematicsReconstructor.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/KinematicsReconstructor.h @@ -0,0 +1,132 @@ +// -*- C++ -*- +// +// KinematicsReconstructor.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_KinematicsReconstructor_H +#define HERWIG_KinematicsReconstructor_H +// +// This is the declaration of the KinematicsReconstructor class. +// + +#include "ThePEG/Interface/Interfaced.h" +#include "ShowerParticle.h" +#include "ShowerProgenitor.h" +#include "ShowerTree.h" +#include "HardTree.h" +#include "KinematicsReconstructor.fh" +#include + +namespace Herwig { + +using namespace ThePEG; + + /**\ingroup Shower + * Exception class + * used to communicate failure of kinematics + * reconstruction. + */ + struct KinematicsReconstructionVeto {}; + + +/** \ingroup Shower + * + * This class is responsible for the kinematical reconstruction + * after each showering step, and also for the necessary Lorentz boosts + * in order to preserve energy-momentum conservation in the overall collision, + * and also the invariant mass and the rapidity of the hard subprocess system. + * In the case of multi-step showering, there will be not unnecessary + * kinematical reconstructions. + * + * Notice: + * - although we often use the term "jet" in either methods or variables names, + * or in comments, which could appear applicable only for QCD showering, + * there is indeed no "dynamics" represented in this class: only kinematics + * is involved, as the name of this class remainds. Therefore it can be used + * for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung). + * + * @see \ref KinematicsReconstructorInterfaces "The interfaces" + * defined for KinematicsReconstructor. + */ +class KinematicsReconstructor: public Interfaced { + +public: + + /** + * Methods to reconstruct the kinematics of a scattering or decay process + */ + //@{ + /** + * Given the ShowerTree for the shower from a hard process + * the method does the reconstruction of the jets, + * including the appropriate boosts (kinematics reshufflings) + * needed to conserve the total energy-momentum of the collision + * and preserving the invariant mass and the rapidity of the + * hard subprocess system. + */ + virtual bool reconstructHardJets(ShowerTreePtr hard, + const map > & pt, + ShowerInteraction::Type type, + bool switchRecon) const=0; + + /** + * Given the ShowerTree for a decay shower + * the method does the reconstruction of the jets, + * including the appropriate boosts (kinematics reshufflings) + * needed to conserve the total energy-momentum of the collision + * and preserving the invariant mass and the rapidity of the + * hard subprocess system. + */ + virtual bool reconstructDecayJets(ShowerTreePtr decay, + ShowerInteraction::Type type) const=0; + //@} + + /** + * Methods to invert the reconstruction of the shower for + * a scattering or decay process and calculate + * the variables used to generate the + * shower given the particles produced. + * This is needed for the CKKW and POWHEG approaches + */ + //@{ + /** + * Given the particles, with a history which we wish to interpret + * as a shower reconstruct the variables used to generate the + * shower for a decay process + */ + virtual bool deconstructDecayJets(HardTreePtr decay,ShowerInteraction::Type) const=0; + + /** + * Given the particles, with a history which we wish to interpret + * as a shower reconstruct the variables used to generate the shower + * for a hard process + */ + virtual bool deconstructHardJets(HardTreePtr hard,ShowerInteraction::Type) const=0; + //@} + +public: + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + KinematicsReconstructor & operator=(const KinematicsReconstructor &); +}; + +} + +#endif /* HERWIG_KinematicsReconstructor_H */ diff --git a/Shower/Base/PartnerFinder.cc b/Shower/QTilde/Base/PartnerFinder.cc rename from Shower/Base/PartnerFinder.cc rename to Shower/QTilde/Base/PartnerFinder.cc --- a/Shower/Base/PartnerFinder.cc +++ b/Shower/QTilde/Base/PartnerFinder.cc @@ -1,634 +1,641 @@ // -*- C++ -*- // // PartnerFinder.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 PartnerFinder class. // #include "PartnerFinder.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ShowerParticle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; DescribeAbstractClass describePartnerFinder ("Herwig::PartnerFinder","HwShower.so"); // some useful functions to avoid using #define namespace { // return bool if final-state particle inline bool FS(const tShowerParticlePtr a) { return a->isFinalState(); } // return colour line pointer inline Ptr::transient_pointer CL(const tShowerParticlePtr a, unsigned int index=0) { return a->colourInfo()->colourLines().empty() ? ThePEG::tColinePtr() : const_ptr_cast(a->colourInfo()->colourLines()[index]); } // return colour line size inline unsigned int CLSIZE(const tShowerParticlePtr a) { return a->colourInfo()->colourLines().size(); } inline Ptr::transient_pointer ACL(const tShowerParticlePtr a, unsigned int index=0) { return a->colourInfo()->antiColourLines().empty() ? ThePEG::tColinePtr() : const_ptr_cast(a->colourInfo()->antiColourLines()[index]); } inline unsigned int ACLSIZE(const tShowerParticlePtr a) { return a->colourInfo()->antiColourLines().size(); } } void PartnerFinder::persistentOutput(PersistentOStream & os) const { os << partnerMethod_ << QEDPartner_ << scaleChoice_; } void PartnerFinder::persistentInput(PersistentIStream & is, int) { is >> partnerMethod_ >> QEDPartner_ >> scaleChoice_; } void PartnerFinder::Init() { static ClassDocumentation documentation ("This class is responsible for finding the partners for each interaction types ", "and within the evolution scale range specified by the ShowerVariables ", "then to determine the initial evolution scales for each pair of partners."); static Switch interfacePartnerMethod ("PartnerMethod", "Choice of partner finding method for gluon evolution.", &PartnerFinder::partnerMethod_, 0, false, false); static SwitchOption interfacePartnerMethodRandom (interfacePartnerMethod, "Random", "Choose partners of a gluon randomly.", 0); static SwitchOption interfacePartnerMethodMaximum (interfacePartnerMethod, "Maximum", "Choose partner of gluon with largest angle.", 1); static Switch interfaceQEDPartner ("QEDPartner", "Control of which particles to use as the partner for QED radiation", &PartnerFinder::QEDPartner_, 0, false, false); static SwitchOption interfaceQEDPartnerAll (interfaceQEDPartner, "All", "Consider all possible choices which give a positive contribution" " in the soft limit.", 0); static SwitchOption interfaceQEDPartnerIIandFF (interfaceQEDPartner, "IIandFF", "Only allow initial-initial or final-final combinations", 1); static SwitchOption interfaceQEDPartnerIF (interfaceQEDPartner, "IF", "Only allow initial-final combinations", 2); static Switch interfaceScaleChoice ("ScaleChoice", "The choice of the evolution scales", &PartnerFinder::scaleChoice_, 0, false, false); static SwitchOption interfaceScaleChoicePartner (interfaceScaleChoice, "Partner", "Scale of all interactions is that of the evolution partner", 0); static SwitchOption interfaceScaleChoiceDifferent (interfaceScaleChoice, "Different", "Allow each interaction to have different scales", 1); } void PartnerFinder::setInitialEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, ShowerInteraction::Type type, const bool setPartners) { // clear the existing partners for(ShowerParticleVector::const_iterator cit = particles.begin(); cit != particles.end(); ++cit) (*cit)->clearPartners(); // set them if(type==ShowerInteraction::QCD) { setInitialQCDEvolutionScales(particles,isDecayCase,setPartners); } else if(type==ShowerInteraction::QED) { setInitialQEDEvolutionScales(particles,isDecayCase,setPartners); } else if(type==ShowerInteraction::EW) { setInitialEWEvolutionScales(particles,isDecayCase,false); } else if(type==ShowerInteraction::QEDQCD) { setInitialQCDEvolutionScales(particles,isDecayCase,setPartners); setInitialQEDEvolutionScales(particles,isDecayCase,false); } else if(type==ShowerInteraction::ALL) { setInitialQCDEvolutionScales(particles,isDecayCase,setPartners); setInitialQEDEvolutionScales(particles,isDecayCase,false); setInitialEWEvolutionScales(particles,isDecayCase,false); } else assert(false); // \todo EW scales here // print out for debugging if(Debug::level>=10) { for(ShowerParticleVector::const_iterator cit = particles.begin(); cit != particles.end(); ++cit) { generator()->log() << "Particle: " << **cit << "\n"; if(!(**cit).partner()) continue; generator()->log() << "Primary partner: " << *(**cit).partner() << "\n"; for(vector::const_iterator it= (**cit).partners().begin(); it!=(**cit).partners().end();++it) { generator()->log() << it->type << " " << it->weight << " " << it->scale/GeV << " " << *(it->partner) << "\n"; } } generator()->log() << flush; } } void PartnerFinder::setInitialQCDEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, const bool setPartners) { // set the partners and the scales if(setPartners) { // Loop over particles and consider only coloured particles which don't // have already their colour partner fixed and that don't have children // (the latter requirement is relaxed in the case isDecayCase is true). // Build a map which has as key one of these particles (i.e. a pointer // to a ShowerParticle object) and as a corresponding value the vector // of all its possible *normal* candidate colour partners, defined as follows: // --- have colour, and no children (this is not required in the case // isDecayCase is true); // --- if both are initial (incoming) state particles, then the (non-null) colourLine() // of one of them must match the (non-null) antiColourLine() of the other. // --- if one is an initial (incoming) state particle and the other is // a final (outgoing) state particle, then both must have the // same (non-null) colourLine() or the same (non-null) antiColourLine(); // Notice that this definition exclude the special case of baryon-violating // processes (as in R-parity Susy), which will show up as particles // without candidate colour partners, and that we will be treated a part later // (this means that no modifications of the following loop is needed!) ShowerParticleVector::const_iterator cit, cjt; for(cit = particles.begin(); cit != particles.end(); ++cit) { // Skip colourless particles if(!(*cit)->data().coloured()) continue; // find the partners vector< pair > partners = findQCDPartners(*cit,particles); // must have a partner if(partners.empty()) { throw Exception() << "`Failed to make colour connections in " << "PartnerFinder::setQCDInitialEvolutionScales" << (**cit) << Exception::eventerror; } // Calculate the evolution scales for all possible pairs of of particles vector > scales; for(unsigned int ix=0;ix< partners.size();++ix) { scales.push_back(calculateInitialEvolutionScales(ShowerPPair(*cit,partners[ix].second), isDecayCase)); } // In the case of more than one candidate colour partners, // there are now two approaches to choosing the partner. The // first method is based on two assumptions: // 1) the choice of which is the colour partner is done // *randomly* between the available candidates. // 2) the choice of which is the colour partner is done // *independently* from each particle: in other words, // if for a particle "i" its selected colour partner is // the particle "j", then the colour partner of "j" // does not have to be necessarily "i". // The second method always chooses the furthest partner // for hard gluons and gluinos. // store the choice int position(-1); // random choice if( partnerMethod_ == 0 ) { // random choice of partner position = UseRandom::irnd(partners.size()); } // take the one with largest angle else if (partnerMethod_ == 1 ) { if ((*cit)->perturbative() == 1 && (*cit)->dataPtr()->iColour()==PDT::Colour8 ) { assert(partners.size()==2); // Determine largest angle double maxAngle(0.); for(unsigned int ix=0;ixmomentum().vect(). angle(partners[ix].second->momentum().vect()); if(angle>maxAngle) { maxAngle = angle; position = ix; } } } else position = UseRandom::irnd(partners.size()); } else assert(false); // set the evolution partner (*cit)->partner(partners[position].second); for(unsigned int ix=0;ixdata().coloured()) continue; // find the partners vector< pair > partners = findQCDPartners(*cit,particles); // must have a partner if(partners.empty()) { throw Exception() << "`Failed to make colour connections in " << "PartnerFinder::setQCDInitialEvolutionScales" << (**cit) << Exception::eventerror; } // Calculate the evolution scales for all possible pairs of of particles vector > scales; int position(-1); for(unsigned int ix=0;ix< partners.size();++ix) { if(partners[ix].second) position = ix; scales.push_back(calculateInitialEvolutionScales(ShowerPPair(*cit,partners[ix].second), isDecayCase)); } assert(position>=0); for(unsigned int ix=0;ixcharged() && - (**cit).id()!=ParticleID::gamma) continue; + if(!(**cit).dataPtr()->charged()) continue; + // if(!(**cit).dataPtr()->charged() && + // (**cit).id()!=ParticleID::gamma) continue; // find the potential partners vector > partners = findQEDPartners(*cit,particles,isDecayCase); if(partners.empty()) { throw Exception() << "Failed to find partner in " << "PartnerFinder::setQEDInitialEvolutionScales" << (**cit) << Exception::eventerror; } // calculate the probabilities double prob(0.); for(unsigned int ix=0;ixpartner()) { for(unsigned int ix=0;ixpartner()==partners[ix].second) { position = ix; break; } } } // set the partner if(setPartners||!(*cit)->partner()||position<0) { prob = UseRandom::rnd(); for(unsigned int ix=0;ixprob) { position = ix; break; } prob -= partners[ix].first; } if(position>=0&&(setPartners||!(*cit)->partner())) { (*cit)->partner(partners[position].second); } } // must have a partner if(position<0) throw Exception() << "Failed to find partner in " << "PartnerFinder::setQEDInitialEvolutionScales" << (**cit) << Exception::eventerror; // Calculate the evolution scales for all possible pairs of of particles vector > scales; for(unsigned int ix=0;ix< partners.size();++ix) { scales.push_back(calculateInitialEvolutionScales(ShowerPPair(*cit,partners[ix].second), isDecayCase)); } // store all the possible partners for(unsigned int ix=0;ix PartnerFinder:: calculateInitialEvolutionScales(const ShowerPPair &particlePair, const bool isDecayCase) { bool FS1=FS(particlePair.first),FS2= FS(particlePair.second); if(FS1 && FS2) return calculateFinalFinalScales(particlePair); else if(FS1 && !FS2) { ShowerPPair a(particlePair.second, particlePair.first); pair rval = calculateInitialFinalScales(a,isDecayCase); return pair(rval.second,rval.first); } else if(!FS1 &&FS2) return calculateInitialFinalScales(particlePair,isDecayCase); else return calculateInitialInitialScales(particlePair); } vector< pair > PartnerFinder::findQCDPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles) { vector< pair > partners; ShowerParticleVector::const_iterator cjt; for(cjt = particles.begin(); cjt != particles.end(); ++cjt) { if(!(*cjt)->data().coloured() || particle==*cjt) continue; // one initial-state and one final-state particle if(FS(particle) != FS(*cjt)) { // loop over all the colours of both particles for(unsigned int ix=0; ixsourceNeighbours().first) { tColinePair cpair = col->sourceNeighbours(); for(cjt=particles.begin();cjt!=particles.end();++cjt) { if(( FS(*cjt) && ( CL(*cjt) == cpair.first || CL(*cjt) == cpair.second))|| (!FS(*cjt) && (ACL(*cjt) == cpair.first || ACL(*cjt) == cpair.second ))) { partners.push_back(make_pair(ShowerPartnerType:: QCDColourLine,*cjt)); } } } else if(col&&col->sinkNeighbours().first) { tColinePair cpair = col->sinkNeighbours(); for(cjt=particles.begin();cjt!=particles.end();++cjt) { if(( FS(*cjt) && (ACL(*cjt) == cpair.first || ACL(*cjt) == cpair.second))|| (!FS(*cjt) && ( CL(*cjt) == cpair.first || CL(*cjt) == cpair.second))) { partners.push_back(make_pair(ShowerPartnerType:: QCDColourLine,*cjt)); } } } col = ACL(particle); if(FS(particle)&&col&&col->sinkNeighbours().first) { tColinePair cpair = col->sinkNeighbours(); for(cjt=particles.begin();cjt!=particles.end();++cjt) { if(( FS(*cjt) && (ACL(*cjt) == cpair.first || ACL(*cjt) == cpair.second))|| (!FS(*cjt) && ( CL(*cjt) == cpair.first || CL(*cjt) == cpair.second ))) { partners.push_back(make_pair(ShowerPartnerType::QCDAntiColourLine,*cjt)); } } } else if(col&&col->sourceNeighbours().first) { tColinePair cpair = col->sourceNeighbours(); for(cjt=particles.begin();cjt!=particles.end();++cjt) { if(( FS(*cjt) && ( CL(*cjt) == cpair.first || CL(*cjt) == cpair.second))|| (!FS(*cjt) && (ACL(*cjt) == cpair.first ||ACL(*cjt) == cpair.second))) { partners.push_back(make_pair(ShowerPartnerType::QCDAntiColourLine,*cjt)); } } } } // return the partners return partners; } vector< pair > PartnerFinder::findQEDPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles, const bool isDecayCase) { vector< pair > partners; ShowerParticleVector::const_iterator cjt; double pcharge = particle->id()==ParticleID::gamma ? 1 : double(particle->data().iCharge()); + // vector< pair > photons; for(cjt = particles.begin(); cjt != particles.end(); ++cjt) { - if(!(*cjt)->data().charged() || particle == *cjt) continue; + if(particle == *cjt) continue; + // if((**cjt).id()==ParticleID::gamma) photons.push_back(make_pair(1.,*cjt)); + if(!(*cjt)->data().charged() ) continue; double charge = pcharge*double((*cjt)->data().iCharge()); if( FS(particle) != FS(*cjt) ) charge *=-1.; if( QEDPartner_ != 0 && !isDecayCase ) { // only include II and FF as requested if( QEDPartner_ == 1 && FS(particle) != FS(*cjt) ) continue; // only include IF is requested else if(QEDPartner_ == 2 && FS(particle) == FS(*cjt) ) continue; } if(particle->id()==ParticleID::gamma) charge = -abs(charge); // only keep positive dipoles if(charge<0.) partners.push_back(make_pair(-charge,*cjt)); } + // if(particle->id()==ParticleID::gamma&& partners.empty()) { + // return photons; + // } return partners; } void PartnerFinder::setInitialEWEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, const bool setPartners) { // loop over all the particles for(ShowerParticleVector::const_iterator cit = particles.begin(); cit != particles.end(); ++cit) { // if not weakly interacting continue if( !weaklyInteracting( (**cit).dataPtr())) continue; // find the potential partners vector > partners = findEWPartners(*cit,particles,isDecayCase); if(partners.empty()) { throw Exception() << "Failed to find partner in " << "PartnerFinder::setEWInitialEvolutionScales" << (**cit) << Exception::eventerror; } // calculate the probabilities double prob(0.); for(unsigned int ix=0;ixpartner()) { for(unsigned int ix=0;ixpartner()==partners[ix].second) { position = ix; break; } } } // set the partner if(setPartners||!(*cit)->partner()||position<0) { prob = UseRandom::rnd(); for(unsigned int ix=0;ixprob) { position = ix; break; } prob -= partners[ix].first; } if(position>=0&&(setPartners||!(*cit)->partner())) { (*cit)->partner(partners[position].second); } } // must have a partner if(position<0) throw Exception() << "Failed to find partner in " << "PartnerFinder::setEWInitialEvolutionScales" << (**cit) << Exception::eventerror; // Calculate the evolution scales for all possible pairs of of particles vector > scales; for(unsigned int ix=0;ix< partners.size();++ix) { scales.push_back(calculateInitialEvolutionScales(ShowerPPair(*cit,partners[ix].second), isDecayCase)); } // store all the possible partners for(unsigned int ix=0;ix > PartnerFinder::findEWPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles, const bool isDecayCase ) { vector< pair > partners; ShowerParticleVector::const_iterator cjt; for(cjt = particles.begin(); cjt != particles.end(); ++cjt) { if(!weaklyInteracting((*cjt)->dataPtr()) || particle == *cjt) continue; if( QEDPartner_ != 0 && !isDecayCase ) { // only include II and FF as requested if( QEDPartner_ == 1 && FS(particle) != FS(*cjt) ) continue; // only include IF is requested else if(QEDPartner_ == 2 && FS(particle) == FS(*cjt) ) continue; } double charge = 1.; // only keep positive dipoles if(charge>0.) partners.push_back(make_pair(charge,*cjt)); } return partners; } diff --git a/Shower/Base/PartnerFinder.fh b/Shower/QTilde/Base/PartnerFinder.fh rename from Shower/Base/PartnerFinder.fh rename to Shower/QTilde/Base/PartnerFinder.fh diff --git a/Shower/Base/PartnerFinder.h b/Shower/QTilde/Base/PartnerFinder.h rename from Shower/Base/PartnerFinder.h rename to Shower/QTilde/Base/PartnerFinder.h --- a/Shower/Base/PartnerFinder.h +++ b/Shower/QTilde/Base/PartnerFinder.h @@ -1,236 +1,235 @@ // -*- C++ -*- // // PartnerFinder.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_PartnerFinder_H #define HERWIG_PartnerFinder_H // // This is the declaration of the PartnerFinder class. // -#include "Herwig/Shower/ShowerConfig.h" -#include "ThePEG/PDT/ParticleData.h" +#include "Herwig/Shower/QTilde/ShowerConfig.h" #include "ThePEG/Interface/Interfaced.h" #include "Evolver.fh" #include "PartnerFinder.fh" namespace Herwig { using namespace ThePEG; /** * typedef of a pair of particle for calculating the evolution scales */ typedef pair ShowerPPair; /** \ingroup Shower * * This class is responsible of two related tasks: * - it finds the partners * - for each pair of partners (and interaction therefore) * it sets the initial evolution scales of both of them. * * In general the finding of the partners is performed by this class but * the calculation of the initial evolution scales should be implemented * for different shower evolution models in classes inheriting from this one. * Notice that a given particle has, in general, a different partner * for each different interaction; however, given a partner, its * initial evolution scale, Q, is purely a kinematical relationship * between the pair, without dependence on the dynamics (i.e. type of interaction). * * @see \ref PartnerFinderInterfaces "The interfaces" * defined for PartnerFinder. */ class PartnerFinder: public Interfaced { public: /** * The default constructor. */ PartnerFinder() : partnerMethod_(0), QEDPartner_(0), scaleChoice_(0) {} /** * Given in input a collection of particles (ShowerParticle objects), * each of these methods set the initial evolution scales of those particles, * between the ones given in input, that do not have yet their * evolution scale set. * The input collection of particles can be either the full collection of * showering particles (kept in the main class ShowerHandler, * in the case isDecayCase is false, or simply, in the case isDecayCase * is true, the decaying particle and its decay products. * The methods returns true, unless something wrong (inconsistencies, * or undefined values) happens. * * These methods are virtual but in most cases inheriting classes should not * need to overide them as they simply find the relevant partner and call * one of the calculateScale members to calculate the scale. */ //@{ /** * Set the initial scales * @param particles The particles to be considered * @param isDecayCase Whether or not this is a decay * @param setPartners Whether to set the colour partners or just the scales */ virtual void setInitialEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, ShowerInteraction::Type, const bool setPartners=true); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly 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: /** * Members to set the scales for different interactions */ //@{ /** * Set initial scales for a QCD interaction */ virtual void setInitialQCDEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, const bool setPartners=true); /** * Set initial scales for a QED interaction */ virtual void setInitialQEDEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, const bool setPartners=true); /** * Set initial scales for a EW interaction */ virtual void setInitialEWEvolutionScales(const ShowerParticleVector &particles, const bool isDecayCase, const bool setPartners=true); //@} /** * Find the QCD partners * @param particle The particle to find the partners for * @param particles The full set of particles to search */ vector< pair > findQCDPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles); /** * Find the QED partners * @param particle The particle to find the partners for * @param particles The full set of particles to search */ vector< pair > findQEDPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles, const bool isDecayCase); /** * Find the EW partners * @param particle The particle to find the partners for * @param particles The full set of particles to search */ vector< pair > findEWPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles, const bool isDecayCase); /** * Given a pair of particles, supposedly partners w.r.t. an interaction, * this method returns their initial evolution scales as a pair. * If something wrong happens, it returns the null (ZERO,ZERO) pair. * This method is used by the above setXXXInitialEvolutionScales * methods. * These methods must be overiden in inheriting classes */ //@{ /** * General method to calculate the initial evolution scales */ virtual pair calculateInitialEvolutionScales(const ShowerPPair &, const bool isDecayCase); /** * Calculate the initial evolution scales for two final-state particles */ virtual pair calculateFinalFinalScales(const ShowerPPair &)=0; /** * Calculate the initial evolution scales for two initial-state particles */ virtual pair calculateInitialInitialScales(const ShowerPPair &)=0; /** * Calculate the initial evolution scales for one initial * and one final-state particles */ virtual pair calculateInitialFinalScales(const ShowerPPair &, const bool isDecayCase)=0; //@} protected: /** * Find weakling interacting particles */ bool weaklyInteracting(tcPDPtr pd) { long id = abs(pd->id()); return ( id==ParticleID::Wplus || id ==ParticleID::Z0 || (id>=1 && id<=6 ) || (id>=11 && id<=16)); } private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ PartnerFinder & operator=(const PartnerFinder &); private: /** * Method for choosing colour partner */ int partnerMethod_; /** * Choice for the QED radiation partner */ int QEDPartner_; /** * Choice of the scale */ int scaleChoice_; }; } #endif /* HERWIG_PartnerFinder_H */ diff --git a/Shower/QTilde/Base/ShowerBasis.cc b/Shower/QTilde/Base/ShowerBasis.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/ShowerBasis.cc @@ -0,0 +1,81 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the ShowerBasis class. +// + +#include "ShowerBasis.h" +#include "ShowerParticle.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/Utilities/DescribeClass.h" + +using namespace Herwig; + + +// The following static variable is needed for the type +// description system in ThePEG. +DescribeNoPIOClass +describeHerwigShowerBasis("Herwig::ShowerBasis", "libHerwig.so"); + +void ShowerBasis::setBasis(const Lorentz5Momentum & p, + const Lorentz5Momentum & n, + Frame inframe) { + pVector_ = p; + nVector_ = n; + frame_ = inframe; + Boost beta_bb; + if(frame()==BackToBack) { + beta_bb = -(pVector_ + nVector_).boostVector(); + } + else if(frame()==Rest) { + beta_bb = -pVector().boostVector(); + } + else + assert(false); + Lorentz5Momentum p_bb = pVector(); + Lorentz5Momentum n_bb = nVector(); + p_bb.boost( beta_bb ); + n_bb.boost( beta_bb ); + // rotate to have z-axis parallel to p/n + Axis axis; + if(frame()==BackToBack) { + axis = p_bb.vect().unit(); + } + else if(frame()==Rest) { + axis = n_bb.vect().unit(); + } + else + assert(false); + LorentzRotation rot; + if(axis.perp2()>1e-10) { + double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); + rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); + } + else if(axis.z()<0.) { + rot.rotate(Constants::pi,Axis(1.,0.,0.)); + } + xPerp_=LorentzVector(1.,0.,0.,0.); + yPerp_=LorentzVector(0.,1.,0.,0.); + xPerp_.transform(rot); + yPerp_.transform(rot); + // boost back + xPerp_.boost( -beta_bb ); + yPerp_.boost( -beta_bb ); +} + +void ShowerBasis::transform(const LorentzRotation & r) { + pVector_ *= r; + nVector_ *= r; + xPerp_ *= r; + yPerp_ *= r; +} + +vector ShowerBasis::getBasis() const { + vector dum; + dum.push_back( pVector_ ); + dum.push_back( nVector_ ); + return dum; +} diff --git a/Shower/QTilde/Base/ShowerBasis.fh b/Shower/QTilde/Base/ShowerBasis.fh new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/ShowerBasis.fh @@ -0,0 +1,21 @@ +// -*- C++ -*- +// +// This is the forward declaration of the ShowerBasis class. +// +#ifndef Herwig_ShowerBasis_FH +#define Herwig_ShowerBasis_FH + +#include "ThePEG/Config/ThePEG.h" + +namespace Herwig { + +class ShowerBasis; +} + +namespace ThePEG { + +ThePEG_DECLARE_POINTERS(Herwig::ShowerBasis,ShowerBasisPtr); + +} + +#endif \ No newline at end of file diff --git a/Shower/QTilde/Base/ShowerBasis.h b/Shower/QTilde/Base/ShowerBasis.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/ShowerBasis.h @@ -0,0 +1,130 @@ +// -*- C++ -*- +#ifndef Herwig_ShowerBasis_H +#define Herwig_ShowerBasis_H +// +// This is the declaration of the ShowerBasis class. +// + +#include "ShowerBasis.fh" +#include "ShowerParticle.fh" +#include "Herwig/Shower/QTilde/ShowerConfig.h" +#include "ThePEG/Config/ThePEG.h" +#include "ThePEG/Vectors/Lorentz5Vector.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * The ShowerBasis class stores the basis vectors used by the shower + */ +class ShowerBasis: public Base { + +public: + + /** + * enum for the frame definition + */ + enum Frame {BackToBack,Rest}; + +public: + + /** + * The default constructor. + */ + ShowerBasis() {} + + /** + * Access to the frame definition + */ + Frame frame() const {return frame_;} + + /** + * Implementation of the virtual function returning a set of basis vectors, specific to + * the type of evolution. This function will be used by the + * ForwardShowerEvolver in order to access \f$p\f$ + * and \f$n\f$. + */ + virtual vector getBasis() const; + + /** + * Set the basis vectors + */ + void setBasis(const Lorentz5Momentum &p, const Lorentz5Momentum & n, + Frame frame); + + /** + * Access to the \f$p\f$ vector used to describe the kinematics. + */ + const Lorentz5Momentum & pVector() const {return pVector_;} + + /** + * Access to the \f$n\f$ vector used to describe the kinematics. + */ + const Lorentz5Momentum & nVector() const {return nVector_;} + + /** + * Dot product of thew basis vectors + */ + Energy2 p_dot_n() const {return pVector_*nVector_;} + + /** + * Transform the shower kinematics (usually the reference vectors) + */ + virtual void transform(const LorentzRotation & r); + + /** + * Converts a Sudakov parametrization of a momentum w.r.t. the given + * basis \f$p\f$ and \f$n\f$ into a 5 momentum. + * @param alpha The \f$\alpha\f$ parameter of the Sudakov parameterisation + * @param beta The \f$\beta\f$ parameter of the Sudakov parameterisation + * @param px The \f$x\f$-component of the transverse momentum in the Sudakov + * parameterisation + * @param py The \f$x\f$-component of the transverse momentum in the Sudakov + * parameterisation + */ + Lorentz5Momentum sudakov2Momentum(double alpha, double beta, + Energy px, Energy py) const { + return alpha*pVector_ + beta*nVector_ + px*xPerp_ + py*yPerp_; + } + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + ShowerBasis & operator=(const ShowerBasis &); + +private: + + /** + * The frame in which the basis vectors are defined + */ + Frame frame_; + + /** + * The \f$p\f$ reference vector + */ + Lorentz5Momentum pVector_; + + /** + * The \f$n\f$ reference vector + */ + Lorentz5Momentum nVector_; + + /** + * x \f$q_\perp\f$ reference vector + */ + LorentzVector xPerp_; + + /** + * y \f$q_\perp\f$reference vector + */ + LorentzVector yPerp_; + +}; + +} + +#endif /* Herwig_ShowerBasis_H */ diff --git a/Shower/Base/ShowerKinematics.cc b/Shower/QTilde/Base/ShowerKinematics.cc rename from Shower/Base/ShowerKinematics.cc rename to Shower/QTilde/Base/ShowerKinematics.cc diff --git a/Shower/Base/ShowerKinematics.fh b/Shower/QTilde/Base/ShowerKinematics.fh rename from Shower/Base/ShowerKinematics.fh rename to Shower/QTilde/Base/ShowerKinematics.fh diff --git a/Shower/Base/ShowerKinematics.h b/Shower/QTilde/Base/ShowerKinematics.h rename from Shower/Base/ShowerKinematics.h rename to Shower/QTilde/Base/ShowerKinematics.h --- a/Shower/Base/ShowerKinematics.h +++ b/Shower/QTilde/Base/ShowerKinematics.h @@ -1,303 +1,303 @@ // -*- C++ -*- // // ShowerKinematics.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_ShowerKinematics_H #define HERWIG_ShowerKinematics_H // // This is the declaration of the ShowerKinematics class. // -#include "Herwig/Shower/ShowerConfig.h" +#include "Herwig/Shower/QTilde/ShowerConfig.h" #include "ThePEG/Config/ThePEG.h" -#include "Herwig/Shower/Base/SudakovFormFactor.h" +#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" #include "ShowerKinematics.fh" namespace Herwig { using namespace ThePEG; /**\ingroup Shower * * This is the abstract base class from which all other shower * kinematics classes derive. The main purpose of the * shower kinematics classes is to allow the reconstruction * of jet masses, at the end of the showering (indeed, for * multi-scale showering, at the end of each scale-range evolution). * This is necessary for the kinematics reshuffling * in order to compensate the recoil of the emissions. * The KinematicsReconstructor class is in * charge of this job, and which is the main "user" of * ShowerKinematics and its derived classes. * How this is done depends on the choice of kinematics variables * and whether the jet is time-like (forward evolved) or * space-like (backward evolved), whereas the class ShowerKinematics * describes only the common features which are independent by them. * * In general there are a number of methods specific to a shower approach * * @see KinematicsReconstructor */ class ShowerKinematics: public Base { public: /** * The default constructor. */ ShowerKinematics() : Base(), _isTheJetStartingPoint( false ), _scale(), _z( 0.0 ), _phi( 0.0 ), _pt(), _sudakov() {} /** * The updateChildren and updateParent * members to update the values of the \f$\alpha\f$ and * \f$p_\perp\f$ variables during the shower evolution. */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. * @param parent The parent * @param children The children * @param partnerType The type of evolution partner */ virtual void updateChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType, bool massVeto ) const; virtual void resetChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the KinematicsReconstructor. * @param parent The parent * @param children The children * @param partnerType The type of evolution partner */ virtual void updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param last The particle. * @param px The \f$x\f$ component of the \f$p_T\f$. * @param py The \f$y\f$ component of the \f$p_T\f$. */ virtual void updateLast(const tShowerParticlePtr last, Energy px, Energy py) const; //@} /** * The reconstructLast, reconstructChildren and reconstructParent members * are used during the reconstruction */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. * @param parent The parent * @param children The children */ virtual void reconstructChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children) const; /** * Reconstruct the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the KinematicsReconstructor. * @param parent The parent * @param children The children */ virtual void reconstructParent(const tShowerParticlePtr parent, const ParticleVector & children) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param last The particle. * @param mass The mass to be used, if less than zero on-shell */ virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const; //@} public: /** * Set/access the flag that tells whether or not this ShowerKinematics * object is associated to the starting particle of the jet: only in this * case it is sensible to use the two main virtual methods below. */ //@{ /** * Set the starting point flag */ void isTheJetStartingPoint(const bool ); /** * Get the starting point flag */ bool isTheJetStartingPoint() const; //@} /** * Set/Get methods for the kinematic variables */ //@{ /** * Access the scale of the splitting. */ Energy scale() const { return _scale; } /** * Set the scale of the splitting. */ void scale(const Energy in) { _scale=in; } /** * Access the energy fraction, \f$z\f$. */ double z() const { return _z; } /** * Set the energy fraction, \f$z\f$. */ void z(const double in) { _z=in; } /** * Access the azimuthal angle, \f$\phi\f$. */ double phi() const { return _phi; } /** * Set the azimuthal angle, \f$\phi\f$. */ void phi(const double in) { _phi=in; } /** * Access the relative \f$p_T\f$ for the branching */ Energy pT() const { return _pt; } /** * Set the relative \f$p_T\f$ for the branching */ void pT(const Energy in) const { _pt=in; } //@} /** * Set and get methods for the SplittingFunction object */ //@{ /** * Access the SplittingFunction object responsible of the * eventual branching of this particle. */ tSplittingFnPtr splittingFn() const { return _sudakov-> splittingFn(); } //@} /** * Set and get methods for the SudakovFormFactor object */ /** * Access the SudakovFormFactor object responsible of the * eventual branching of this particle. */ tSudakovPtr SudakovFormFactor() const { return _sudakov; } /** * Set the SudakovFormFactor object responsible of the * eventual branching of this particle. */ void SudakovFormFactor(const tSudakovPtr sud) { _sudakov=sud; } //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerKinematics & operator=(const ShowerKinematics &); private: /** * Is this the starting point of the jet */ bool _isTheJetStartingPoint; /** * The \f$\tilde{q}\f$ evolution variable. */ Energy _scale; /** * The energy fraction, \f$z\f$ */ double _z; /** * The azimuthal angle, \f$\phi\f$. */ double _phi; /** * The relative \f$p_T\f$ */ mutable Energy _pt; /** * The splitting function for the branching of the particle */ tSudakovPtr _sudakov; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of ShowerKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of ShowerKinematics. */ typedef Base NthBase; }; /** This template specialization informs ThePEG about the name of * the ShowerKinematics 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::ShowerKinematics"; } }; /** @endcond */ } #endif /* HERWIG_ShowerKinematics_H */ diff --git a/Shower/QTilde/Base/ShowerModel.cc b/Shower/QTilde/Base/ShowerModel.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/ShowerModel.cc @@ -0,0 +1,65 @@ +// -*- C++ -*- +// +// ShowerModel.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 ShowerModel class. +// + +#include "ShowerModel.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Interface/Reference.h" +#include "ThePEG/Interface/RefVector.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" +#include "KinematicsReconstructor.h" +#include "PartnerFinder.h" +#include "SudakovFormFactor.h" +#include "ThePEG/Utilities/DescribeClass.h" + +using namespace Herwig; + +DescribeAbstractClass +describeShowerModel ("Herwig::ShowerModel","HwShower.so"); + +void ShowerModel::persistentOutput(PersistentOStream & os) const { + os << _reconstructor << _partnerfinder << _sudakovs; +} + +void ShowerModel::persistentInput(PersistentIStream & is, int) { + is >> _reconstructor >> _partnerfinder >> _sudakovs; +} + +void ShowerModel::doinit() { + Interfaced::doinit(); + checkConsistency(); +} + +void ShowerModel::Init() { + + static ClassDocumentation documentation + ("The ShowerModel class contains the references for the classes which" + " are specific to the shower evolution scheme."); + + static Reference interfaceKinematicsReconstructor + ("KinematicsReconstructor", + "Reference to the KinematicsReconstructor object", + &ShowerModel::_reconstructor, false, false, true, false, false); + + static Reference interfacePartnerFinder + ("PartnerFinder", + "Reference to the PartnerFinder object", + &ShowerModel::_partnerfinder, false, false, true, false, false); + + static RefVector interfaceSudakovFormFactors + ("SudakovFormFactors", + "Vector of references to the SudakovFormFactor objects", + &ShowerModel::_sudakovs, -1, false, false, true, false, false); + +} + diff --git a/Shower/Base/ShowerModel.fh b/Shower/QTilde/Base/ShowerModel.fh rename from Shower/Base/ShowerModel.fh rename to Shower/QTilde/Base/ShowerModel.fh diff --git a/Shower/Base/ShowerModel.h b/Shower/QTilde/Base/ShowerModel.h rename from Shower/Base/ShowerModel.h rename to Shower/QTilde/Base/ShowerModel.h diff --git a/Shower/Base/ShowerParticle.cc b/Shower/QTilde/Base/ShowerParticle.cc rename from Shower/Base/ShowerParticle.cc rename to Shower/QTilde/Base/ShowerParticle.cc --- a/Shower/Base/ShowerParticle.cc +++ b/Shower/QTilde/Base/ShowerParticle.cc @@ -1,594 +1,594 @@ // -*- C++ -*- // // ShowerParticle.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 ShowerParticle class. // #include "ShowerParticle.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" -#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include using namespace Herwig; PPtr ShowerParticle::clone() const { return new_ptr(*this); } PPtr ShowerParticle::fullclone() const { return new_ptr(*this); } ClassDescription ShowerParticle::initShowerParticle; // Definition of the static class description member. void ShowerParticle::vetoEmission(ShowerPartnerType::Type, Energy scale) { scales_.QED = min(scale,scales_.QED ); scales_.QED_noAO = min(scale,scales_.QED_noAO ); scales_.QCD_c = min(scale,scales_.QCD_c ); scales_.QCD_c_noAO = min(scale,scales_.QCD_c_noAO ); scales_.QCD_ac = min(scale,scales_.QCD_ac ); scales_.QCD_ac_noAO = min(scale,scales_.QCD_ac_noAO); scales_.EW = min(scale,scales_.EW ); } void ShowerParticle::addPartner(EvolutionPartner in ) { partners_.push_back(in); } namespace { LorentzRotation boostToShower(Lorentz5Momentum & porig, tShowerBasisPtr basis) { LorentzRotation output; assert(basis); if(basis->frame()==ShowerBasis::BackToBack) { // we are doing the evolution in the back-to-back frame // work out the boostvector Boost boostv(-(basis->pVector()+basis->nVector()).boostVector()); // momentum of the parton Lorentz5Momentum ptest(basis->pVector()); // construct the Lorentz boost output = LorentzRotation(boostv); ptest *= output; Axis axis(ptest.vect().unit()); // now rotate so along the z axis as needed for the splitting functions if(axis.perp2()>1e-10) { double sinth(sqrt(1.-sqr(axis.z()))); output.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { output.rotate(Constants::pi,Axis(1.,0.,0.)); } porig = output*basis->pVector(); porig.setX(ZERO); porig.setY(ZERO); } else { output = LorentzRotation(-basis->pVector().boostVector()); porig = output*basis->pVector(); porig.setX(ZERO); porig.setY(ZERO); porig.setZ(ZERO); } return output; } RhoDMatrix bosonMapping(ShowerParticle & particle, const Lorentz5Momentum & porig, VectorSpinPtr vspin, const LorentzRotation & rot) { // rotate the original basis vector sbasis; for(unsigned int ix=0;ix<3;++ix) { sbasis.push_back(vspin->getProductionBasisState(ix)); sbasis.back().transform(rot); } // splitting basis vector fbasis; bool massless(particle.id()==ParticleID::g||particle.id()==ParticleID::gamma); VectorWaveFunction wave(porig,particle.dataPtr(),outgoing); for(unsigned int ix=0;ix<3;++ix) { if(massless&&ix==1) { fbasis.push_back(LorentzPolarizationVector()); } else { wave.reset(ix); fbasis.push_back(wave.wave()); } } // work out the mapping RhoDMatrix mapping=RhoDMatrix(PDT::Spin1,false); for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy) { mapping(ix,iy)= sbasis[iy].dot(fbasis[ix].conjugate()); if(particle.id()<0) mapping(ix,iy)=conj(mapping(ix,iy)); } } // \todo need to fix this mapping = RhoDMatrix(PDT::Spin1,false); if(massless) { mapping(0,0) = 1.; mapping(2,2) = 1.; } else { mapping(0,0) = 1.; mapping(1,1) = 1.; mapping(2,2) = 1.; } return mapping; } RhoDMatrix fermionMapping(ShowerParticle & particle, const Lorentz5Momentum & porig, FermionSpinPtr fspin, const LorentzRotation & rot) { // extract the original basis states vector > sbasis; for(unsigned int ix=0;ix<2;++ix) { sbasis.push_back(fspin->getProductionBasisState(ix)); sbasis.back().transform(rot); } // calculate the states in the splitting basis vector > fbasis; SpinorWaveFunction wave(porig,particle.dataPtr(), particle.id()>0 ? incoming : outgoing); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); fbasis.push_back(wave.dimensionedWave()); } RhoDMatrix mapping=RhoDMatrix(PDT::Spin1Half,false); for(unsigned int ix=0;ix<2;++ix) { if(fbasis[0].s2()==complex()) { mapping(ix,0) = sbasis[ix].s3()/fbasis[0].s3(); mapping(ix,1) = sbasis[ix].s2()/fbasis[1].s2(); } else { mapping(ix,0) = sbasis[ix].s2()/fbasis[0].s2(); mapping(ix,1) = sbasis[ix].s3()/fbasis[1].s3(); } } return mapping; } FermionSpinPtr createFermionSpinInfo(ShowerParticle & particle, const Lorentz5Momentum & porig, const LorentzRotation & rot, Helicity::Direction dir) { // calculate the splitting basis for the branching // and rotate back to construct the basis states LorentzRotation rinv = rot.inverse(); SpinorWaveFunction wave; if(particle.id()>0) wave=SpinorWaveFunction(porig,particle.dataPtr(),incoming); else wave=SpinorWaveFunction(porig,particle.dataPtr(),outgoing); FermionSpinPtr fspin = new_ptr(FermionSpinInfo(particle.momentum(),dir==outgoing)); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); LorentzSpinor basis = wave.dimensionedWave(); basis.transform(rinv); fspin->setBasisState(ix,basis); fspin->setDecayState(ix,basis); } particle.spinInfo(fspin); return fspin; } VectorSpinPtr createVectorSpinInfo(ShowerParticle & particle, const Lorentz5Momentum & porig, const LorentzRotation & rot, Helicity::Direction dir) { // calculate the splitting basis for the branching // and rotate back to construct the basis states LorentzRotation rinv = rot.inverse(); bool massless(particle.id()==ParticleID::g||particle.id()==ParticleID::gamma); VectorWaveFunction wave(porig,particle.dataPtr(),dir); VectorSpinPtr vspin = new_ptr(VectorSpinInfo(particle.momentum(),dir==outgoing)); for(unsigned int ix=0;ix<3;++ix) { LorentzPolarizationVector basis; if(massless&&ix==1) { basis = LorentzPolarizationVector(); } else { wave.reset(ix); basis = wave.wave(); } basis *= rinv; vspin->setBasisState(ix,basis); vspin->setDecayState(ix,basis); } particle.spinInfo(vspin); vspin-> DMatrix() = RhoDMatrix(PDT::Spin1); vspin->rhoMatrix() = RhoDMatrix(PDT::Spin1); if(massless) { vspin-> DMatrix()(0,0) = 0.5; vspin->rhoMatrix()(0,0) = 0.5; vspin-> DMatrix()(2,2) = 0.5; vspin->rhoMatrix()(2,2) = 0.5; } return vspin; } + } RhoDMatrix ShowerParticle::extractRhoMatrix(bool forward) { // get the spin density matrix and the mapping RhoDMatrix mapping; SpinPtr inspin; bool needMapping = getMapping(inspin,mapping); // set the decayed flag inspin->decay(); // get the spin density matrix RhoDMatrix rho = forward ? inspin->rhoMatrix() : inspin->DMatrix(); // map to the shower basis if needed if(needMapping) { RhoDMatrix rhop(rho.iSpin(),false); for(int ixa=0;ixaperturbative()) { // mapping is the identity output=this->spinInfo(); mapping=RhoDMatrix(this->dataPtr()->iSpin()); if(output) { return false; } else { Lorentz5Momentum porig; LorentzRotation rot = boostToShower(porig,showerBasis()); Helicity::Direction dir = this->isFinalState() ? outgoing : incoming; if(this->dataPtr()->iSpin()==PDT::Spin0) { assert(false); } else if(this->dataPtr()->iSpin()==PDT::Spin1Half) { output = createFermionSpinInfo(*this,porig,rot,dir); } else if(this->dataPtr()->iSpin()==PDT::Spin1) { output = createVectorSpinInfo(*this,porig,rot,dir); } else { assert(false); } return false; } } // if particle is final-state and is from the hard process else if(this->isFinalState()) { assert(this->perturbative()==1 || this->perturbative()==2); // get transform to shower frame Lorentz5Momentum porig; LorentzRotation rot = boostToShower(porig,showerBasis()); // the rest depends on the spin of the particle PDT::Spin spin(this->dataPtr()->iSpin()); mapping=RhoDMatrix(spin,false); // do the spin dependent bit if(spin==PDT::Spin0) { ScalarSpinPtr sspin=dynamic_ptr_cast(this->spinInfo()); if(!sspin) { ScalarWaveFunction::constructSpinInfo(this,outgoing,true); } output=this->spinInfo(); return false; } else if(spin==PDT::Spin1Half) { FermionSpinPtr fspin=dynamic_ptr_cast(this->spinInfo()); // spin info exists get information from it if(fspin) { output=fspin; mapping = fermionMapping(*this,porig,fspin,rot); return true; } // spin info does not exist create it else { output = createFermionSpinInfo(*this,porig,rot,outgoing); return false; } } else if(spin==PDT::Spin1) { VectorSpinPtr vspin=dynamic_ptr_cast(this->spinInfo()); // spin info exists get information from it if(vspin) { output=vspin; mapping = bosonMapping(*this,porig,vspin,rot); return true; } else { output = createVectorSpinInfo(*this,porig,rot,outgoing); return false; } } // not scalar/fermion/vector else assert(false); } // incoming to hard process else if(this->perturbative()==1 && !this->isFinalState()) { // get the basis vectors // get transform to shower frame Lorentz5Momentum porig; LorentzRotation rot = boostToShower(porig,showerBasis()); porig *= this->x(); // the rest depends on the spin of the particle PDT::Spin spin(this->dataPtr()->iSpin()); mapping=RhoDMatrix(spin); // do the spin dependent bit if(spin==PDT::Spin0) { cerr << "testing spin 0 not yet implemented " << endl; assert(false); } // spin-1/2 else if(spin==PDT::Spin1Half) { FermionSpinPtr fspin=dynamic_ptr_cast(this->spinInfo()); // spin info exists get information from it if(fspin) { output=fspin; mapping = fermionMapping(*this,porig,fspin,rot); return true; } // spin info does not exist create it else { output = createFermionSpinInfo(*this,porig,rot,incoming); return false; } } // spin-1 else if(spin==PDT::Spin1) { VectorSpinPtr vspin=dynamic_ptr_cast(this->spinInfo()); // spinInfo exists map it if(vspin) { output=vspin; mapping = bosonMapping(*this,porig,vspin,rot); return true; } // create the spininfo else { output = createVectorSpinInfo(*this,porig,rot,incoming); return false; } } assert(false); } // incoming to decay else if(this->perturbative() == 2 && !this->isFinalState()) { // get the basis vectors Lorentz5Momentum porig; LorentzRotation rot=boostToShower(porig,showerBasis()); // the rest depends on the spin of the particle PDT::Spin spin(this->dataPtr()->iSpin()); mapping=RhoDMatrix(spin); // do the spin dependent bit if(spin==PDT::Spin0) { cerr << "testing spin 0 not yet implemented " << endl; assert(false); } // spin-1/2 else if(spin==PDT::Spin1Half) { // FermionSpinPtr fspin=dynamic_ptr_cast(this->spinInfo()); // // spin info exists get information from it // if(fspin) { // output=fspin; // mapping = fermionMapping(*this,porig,fspin,rot); // return true; // // spin info does not exist create it // else { // output = createFermionSpinInfo(*this,porig,rot,incoming); // return false; // } // } assert(false); } // // spin-1 // else if(spin==PDT::Spin1) { // VectorSpinPtr vspin=dynamic_ptr_cast(this->spinInfo()); // // spinInfo exists map it // if(vspin) { // output=vspin; // mapping = bosonMapping(*this,porig,vspin,rot); // return true; // } // // create the spininfo // else { // output = createVectorSpinInfo(*this,porig,rot,incoming); // return false; // } // } // assert(false); assert(false); } else assert(false); return true; } void ShowerParticle::constructSpinInfo(bool timeLike) { // now construct the required spininfo and calculate the basis states PDT::Spin spin(dataPtr()->iSpin()); if(spin==PDT::Spin0) { ScalarWaveFunction::constructSpinInfo(this,outgoing,timeLike); } // calculate the basis states and construct the SpinInfo for a spin-1/2 particle else if(spin==PDT::Spin1Half) { // outgoing particle if(id()>0) { vector > stemp; SpinorBarWaveFunction::calculateWaveFunctions(stemp,this,outgoing); SpinorBarWaveFunction::constructSpinInfo(stemp,this,outgoing,timeLike); } // outgoing antiparticle else { vector > stemp; SpinorWaveFunction::calculateWaveFunctions(stemp,this,outgoing); SpinorWaveFunction::constructSpinInfo(stemp,this,outgoing,timeLike); } } // calculate the basis states and construct the SpinInfo for a spin-1 particle else if(spin==PDT::Spin1) { bool massless(id()==ParticleID::g||id()==ParticleID::gamma); vector vtemp; VectorWaveFunction::calculateWaveFunctions(vtemp,this,outgoing,massless); VectorWaveFunction::constructSpinInfo(vtemp,this,outgoing,timeLike,massless); } else { throw Exception() << "Spins higher than 1 are not yet implemented in " << "FS_QtildaShowerKinematics1to2::constructVertex() " << Exception::runerror; } } void ShowerParticle::initializeDecay() { Lorentz5Momentum p, n, ppartner, pcm; assert(perturbative()!=1); // this is for the initial decaying particle if(perturbative()==2) { ShowerBasisPtr newBasis; p = momentum(); Lorentz5Momentum ppartner(partner()->momentum()); // removed to make inverse recon work properly //if(partner->thePEGBase()) ppartner=partner->thePEGBase()->momentum(); pcm=ppartner; Boost boost(p.findBoostToCM()); pcm.boost(boost); n = Lorentz5Momentum( ZERO,0.5*p.mass()*pcm.vect().unit()); n.boost( -boost); newBasis = new_ptr(ShowerBasis()); newBasis->setBasis(p,n,ShowerBasis::Rest); showerBasis(newBasis,false); } else { showerBasis(dynamic_ptr_cast(parents()[0])->showerBasis(),true); } } void ShowerParticle::initializeInitialState(PPtr parent) { // For the time being we are considering only 1->2 branching Lorentz5Momentum p, n, pthis, pcm; assert(perturbative()!=2); if(perturbative()==1) { ShowerBasisPtr newBasis; // find the partner and its momentum if(!partner()) return; if(partner()->isFinalState()) { Lorentz5Momentum pa = -momentum()+partner()->momentum(); Lorentz5Momentum pb = momentum(); Energy scale=parent->momentum().t(); Lorentz5Momentum pbasis(ZERO,parent->momentum().vect().unit()*scale); Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if(axis.perp2()>1e-20) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); } if(abs(1.-pa.e()/pa.vect().mag())>1e-6) rot.boostZ( pa.e()/pa.vect().mag()); pb *= rot; if(pb.perp2()/GeV2>1e-20) { Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot.boost(trans); } pbasis *=rot; rot.invert(); n = rot*Lorentz5Momentum(ZERO,-pbasis.vect()); p = rot*Lorentz5Momentum(ZERO, pbasis.vect()); } else { pcm = parent->momentum(); p = Lorentz5Momentum(ZERO, pcm.vect()); n = Lorentz5Momentum(ZERO, -pcm.vect()); } newBasis = new_ptr(ShowerBasis()); newBasis->setBasis(p,n,ShowerBasis::BackToBack); showerBasis(newBasis,false); } else { showerBasis(dynamic_ptr_cast(children()[0])->showerBasis(),true); } } void ShowerParticle::initializeFinalState() { // set the basis vectors Lorentz5Momentum p,n; if(perturbative()!=0) { ShowerBasisPtr newBasis; // find the partner() and its momentum if(!partner()) return; Lorentz5Momentum ppartner(partner()->momentum()); // momentum of the emitting particle p = momentum(); Lorentz5Momentum pcm; // if the partner is a final-state particle then the reference // vector is along the partner in the rest frame of the pair if(partner()->isFinalState()) { Boost boost=(p + ppartner).findBoostToCM(); pcm = ppartner; pcm.boost(boost); n = Lorentz5Momentum(ZERO,pcm.vect()); n.boost( -boost); } else if(!partner()->isFinalState()) { // if the partner is an initial-state particle then the reference // vector is along the partner which should be massless if(perturbative()==1) { n = Lorentz5Momentum(ZERO,ppartner.vect()); } // if the partner is an initial-state decaying particle then the reference // vector is along the backwards direction in rest frame of decaying particle else { Boost boost=ppartner.findBoostToCM(); pcm = p; pcm.boost(boost); n = Lorentz5Momentum( ZERO, -pcm.vect()); n.boost( -boost); } } newBasis = new_ptr(ShowerBasis()); newBasis->setBasis(p,n,ShowerBasis::BackToBack); showerBasis(newBasis,false); } else if(initiatesTLS()) { showerBasis(dynamic_ptr_cast(parents()[0]->children()[0])->showerBasis(),true); } else { showerBasis(dynamic_ptr_cast(parents()[0])->showerBasis(),true); } } void ShowerParticle::setShowerMomentum(bool timeLike) { Energy m = this->mass() > ZERO ? this->mass() : this->data().mass(); // calculate the momentum of the assuming on-shell Energy2 pt2 = sqr(this->showerParameters().pt); double alpha = timeLike ? this->showerParameters().alpha : this->x(); double beta = 0.5*(sqr(m) + pt2 - sqr(alpha)*showerBasis()->pVector().m2())/(alpha*showerBasis()->p_dot_n()); Lorentz5Momentum porig=showerBasis()->sudakov2Momentum(alpha,beta, this->showerParameters().ptx, this->showerParameters().pty); porig.setMass(m); this->set5Momentum(porig); } diff --git a/Shower/Base/ShowerParticle.fh b/Shower/QTilde/Base/ShowerParticle.fh rename from Shower/Base/ShowerParticle.fh rename to Shower/QTilde/Base/ShowerParticle.fh diff --git a/Shower/Base/ShowerParticle.h b/Shower/QTilde/Base/ShowerParticle.h rename from Shower/Base/ShowerParticle.h rename to Shower/QTilde/Base/ShowerParticle.h --- a/Shower/Base/ShowerParticle.h +++ b/Shower/QTilde/Base/ShowerParticle.h @@ -1,543 +1,542 @@ // -*- C++ -*- // // ShowerParticle.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_ShowerParticle_H #define HERWIG_ShowerParticle_H // // This is the declaration of the ShowerParticle class. // #include "ThePEG/EventRecord/Particle.h" -#include "Herwig/Shower/SplittingFunctions/SplittingFunction.fh" -#include "Herwig/Shower/ShowerConfig.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.fh" +#include "Herwig/Shower/QTilde/ShowerConfig.h" #include "ShowerBasis.h" #include "ShowerKinematics.h" #include "ShowerParticle.fh" #include namespace Herwig { using namespace ThePEG; /** \ingroup Shower * This class represents a particle in the showering process. * It inherits from the Particle class of ThePEG and has some * specifics information useful only during the showering process. * * Notice that: * - for forward evolution, it is clear what is meant by parent/child; * for backward evolution, however, it depends whether we want * to keep a physical picture or a Monte-Carlo effective one. * In the former case, an incoming particle (emitting particle) * splits into an emitted particle and the emitting particle after * the emission: the latter two are then children of the * emitting particle, the parent. In the Monte-Carlo effective * picture, we have that the particle close to the hard subprocess, * with higher (space-like) virtuality, splits into an emitted particle * and the emitting particle at lower virtuality: the latter two are, * in this case, the children of the first one, the parent. However we * choose a more physical picture where the new emitting particle is the * parented of the emitted final-state particle and the original emitting * particle. * - the pointer to a SplitFun object is set only in the case * that the particle has undergone a shower emission. This is similar to * the case of the decay of a normal Particle where * the pointer to a Decayer object is set only in the case * that the particle has undergone to a decay. * In the case of particle connected directly to the hard subprocess, * there is no pointer to the hard subprocess, but there is a method * isFromHardSubprocess() which returns true only in this case. * * @see Particle * @see ShowerConfig * @see ShowerKinematics */ class ShowerParticle: public Particle { public: /** * Struct for all the info on an evolution partner */ struct EvolutionPartner { /** * Constructor */ EvolutionPartner(tShowerParticlePtr p,double w, ShowerPartnerType::Type t, Energy s) : partner(p), weight(w), type(t), scale(s) {} /** * The partner */ tShowerParticlePtr partner; /** * Weight */ double weight; /** * Type */ ShowerPartnerType::Type type; /** * The assoicated evolution scale */ Energy scale; }; /** * Struct to store the evolution scales */ struct EvolutionScales { /** * Constructor */ EvolutionScales() : QED(),QCD_c(),QCD_ac(), QED_noAO(),QCD_c_noAO(),QCD_ac_noAO(),EW(), Max_Q2(Constants::MaxEnergy2) {} /** * QED scale */ Energy QED; /** * QCD colour scale */ Energy QCD_c; /** * QCD anticolour scale */ Energy QCD_ac; /** * QED scale */ Energy QED_noAO; /** * QCD colour scale */ Energy QCD_c_noAO; /** * QCD anticolour scale */ Energy QCD_ac_noAO; /** * EW scale */ Energy EW; /** * EW scale */ Energy EW_noAO; /** * Maximum allowed virtuality of the particle */ Energy2 Max_Q2; }; /** @name Construction and descruction functions. */ //@{ /** * Standard Constructor. Note that the default constructor is * private - there is no particle without a pointer to a * ParticleData object. * @param x the ParticleData object * @param fs Whether or not the particle is an inital or final-state particle * @param tls Whether or not the particle initiates a time-like shower */ ShowerParticle(tcEventPDPtr x, bool fs, bool tls=false) : Particle(x), _isFinalState(fs), _perturbative(0), _initiatesTLS(tls), _x(1.0), _showerKinematics(), _vMass(ZERO), _thePEGBase() {} /** * Copy constructor from a ThePEG Particle * @param x ThePEG particle * @param pert Where the particle came from * @param fs Whether or not the particle is an inital or final-state particle * @param tls Whether or not the particle initiates a time-like shower */ ShowerParticle(const Particle & x, unsigned int pert, bool fs, bool tls=false) : Particle(x), _isFinalState(fs), _perturbative(pert), _initiatesTLS(tls), _x(1.0), _showerKinematics(), _vMass(ZERO), _thePEGBase(&x) {} //@} public: /** * Set a preliminary momentum for the particle */ void setShowerMomentum(bool timelike); /** * Construct the spin info object for a shower particle */ void constructSpinInfo(bool timelike); /** * Perform any initial calculations needed after the branching has been selected */ void initializeDecay(); /** * Perform any initial calculations needed after the branching has been selected * @param parent The beam particle */ void initializeInitialState(PPtr parent); /** * Perform any initial calculations needed after the branching has been selected */ void initializeFinalState(); /** * Access/Set various flags about the state of the particle */ //@{ /** * Access the flag that tells if the particle is final state * or initial state. */ bool isFinalState() const { return _isFinalState; } /** * Access the flag that tells if the particle is initiating a * time like shower when it has been emitted in an initial state shower. */ bool initiatesTLS() const { return _initiatesTLS; } /** * Access the flag which tells us where the particle came from * This is 0 for a particle produced in the shower, 1 if the particle came * from the hard sub-process and 2 is it came from a decay. */ unsigned int perturbative() const { return _perturbative; } //@} /** * Set/Get the momentum fraction for initial-state particles */ //@{ /** * For an initial state particle get the fraction of the beam momentum */ void x(double x) { _x = x; } /** * For an initial state particle set the fraction of the beam momentum */ double x() const { return _x; } //@} /** * Set/Get methods for the ShowerKinematics objects */ //@{ /** * Access/ the ShowerKinematics object. */ const ShoKinPtr & showerKinematics() const { return _showerKinematics; } /** * Set the ShowerKinematics object. */ void showerKinematics(const ShoKinPtr in) { _showerKinematics = in; } //@} /** * Set/Get methods for the ShowerBasis objects */ //@{ /** * Access/ the ShowerBasis object. */ const ShowerBasisPtr & showerBasis() const { return _showerBasis; } /** * Set the ShowerBasis object. */ void showerBasis(const ShowerBasisPtr in, bool copy) { if(!copy) _showerBasis = in; else { _showerBasis = new_ptr(ShowerBasis()); _showerBasis->setBasis(in->pVector(),in->nVector(),in->frame()); } } //@} /** * Members relating to the initial evolution scale and partner for the particle */ //@{ /** * Veto emission at a given scale */ void vetoEmission(ShowerPartnerType::Type type, Energy scale); /** * Access to the evolution scales */ const EvolutionScales & scales() const {return scales_;} /** * Access to the evolution scales */ EvolutionScales & scales() {return scales_;} /** * Return the virtual mass\f$ */ Energy virtualMass() const { return _vMass; } /** * Set the virtual mass */ void virtualMass(Energy mass) { _vMass = mass; } /** * Return the partner */ tShowerParticlePtr partner() const { return _partner; } /** * Set the partner */ void partner(const tShowerParticlePtr partner) { _partner = partner; } /** * Get the possible partners */ vector & partners() { return partners_; } /** * Add a possible partners */ void addPartner(EvolutionPartner in ); /** * Clear the evolution partners */ void clearPartners() { partners_.clear(); } /** * Return the progenitor of the shower */ tShowerParticlePtr progenitor() const { return _progenitor; } /** * Set the progenitor of the shower */ void progenitor(const tShowerParticlePtr progenitor) { _progenitor = progenitor; } //@} /** * Members to store and provide access to variables for a specific * shower evolution scheme */ //@{ struct Parameters { Parameters() : alpha(1.), beta(), ptx(), pty(), pt() {} double alpha; double beta; Energy ptx; Energy pty; Energy pt; }; /** * Set the vector containing dimensionless variables */ Parameters & showerParameters() { return _parameters; } //@} /** * If this particle came from the hard process get a pointer to ThePEG particle * it came from */ const tcPPtr thePEGBase() const { return _thePEGBase; } - + public: /** * Extract the rho matrix including mapping needed in the shower */ RhoDMatrix extractRhoMatrix(bool forward); protected: /** * For a particle which came from the hard process get the spin density and * the mapping required to the basis used in the Shower * @param rho The \f$\rho\f$ matrix * @param mapping The mapping * @param showerkin The ShowerKinematics object */ bool getMapping(SpinPtr &, RhoDMatrix & map); - protected: /** * Standard clone function. */ virtual PPtr clone() const; /** * Standard clone function. */ virtual PPtr fullclone() const; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initShowerParticle; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ShowerParticle & operator=(const ShowerParticle &); private: /** * Whether the particle is in the final or initial state */ bool _isFinalState; /** * Whether the particle came from */ unsigned int _perturbative; /** * Does a particle produced in the backward shower initiate a time-like shower */ bool _initiatesTLS; /** * Dimensionless parameters */ Parameters _parameters; /** * The beam energy fraction for particle's in the initial state */ double _x; /** * The shower kinematics for the particle */ ShoKinPtr _showerKinematics; /** * The shower basis for the particle */ ShowerBasisPtr _showerBasis; /** * Storage of the evolution scales */ EvolutionScales scales_; /** * Virtual mass */ Energy _vMass; /** * Partners */ tShowerParticlePtr _partner; /** * Pointer to ThePEG Particle this ShowerParticle was created from */ const tcPPtr _thePEGBase; /** * Progenitor */ tShowerParticlePtr _progenitor; /** * Partners */ vector partners_; }; inline ostream & operator<<(ostream & os, const ShowerParticle::EvolutionScales & es) { os << "Scales: QED=" << es.QED / GeV << " QCD_c=" << es.QCD_c / GeV << " QCD_ac=" << es.QCD_ac / GeV << " EW=" << es.EW / GeV << " QED_noAO=" << es.QED_noAO / GeV << " QCD_c_noAO=" << es.QCD_c_noAO / GeV << " QCD_ac_noAO=" << es.QCD_ac_noAO / GeV << " EW_noAO=" << es.EW_noAO / GeV << '\n'; return os; } } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of ShowerParticle. */ template <> struct BaseClassTrait { /** Typedef of the first base class of ShowerParticle. */ typedef Particle NthBase; }; /** This template specialization informs ThePEG about the name of * the ShowerParticle class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::ShowerParticle"; } /** Create a Event object. */ static TPtr create() { return TPtr::Create(Herwig::ShowerParticle(tcEventPDPtr(),true)); } }; /** @endcond */ } #endif /* HERWIG_ShowerParticle_H */ diff --git a/Shower/Base/ShowerProgenitor.fh b/Shower/QTilde/Base/ShowerProgenitor.fh rename from Shower/Base/ShowerProgenitor.fh rename to Shower/QTilde/Base/ShowerProgenitor.fh diff --git a/Shower/Base/ShowerProgenitor.h b/Shower/QTilde/Base/ShowerProgenitor.h rename from Shower/Base/ShowerProgenitor.h rename to Shower/QTilde/Base/ShowerProgenitor.h --- a/Shower/Base/ShowerProgenitor.h +++ b/Shower/QTilde/Base/ShowerProgenitor.h @@ -1,263 +1,263 @@ // -*- C++ -*- // // ShowerProgenitor.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_ShowerProgenitor_H #define HERWIG_ShowerProgenitor_H // // This is the declaration of the ShowerProgenitor struct. // #include "ThePEG/Config/ThePEG.h" -#include "Herwig/Shower/ShowerConfig.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/ShowerConfig.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ShowerProgenitor.fh" #include "ThePEG/PDF/BeamParticleData.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * A struct to store information on the perturbative particle which * initiates a shower */ class ShowerProgenitor : public Base { public: /** * Enum for the reconstruction state of this progentitor */ enum Reconstructed { notReconstructed=0, done, dontReconstruct}; /** * Typedef for the BeamParticleData objects */ typedef Ptr::transient_const_pointer tcBeamPtr; public: /** * Constructor for the class * @param original The original particle * @param copy The colour isolated copy * @param particle The ShowerPArticle copy * @param pT The \f$p_t\f$ of the hardest emission * @param emitted Whether or not the particle has radiated */ ShowerProgenitor(PPtr original,PPtr copy, ShowerParticlePtr particle, Energy pT=ZERO,bool emitted=false) : _original(original), _copy(copy), _perturbative(true), _particle(particle), _highestpT(pT), _maxHardPt(ZERO), _hardScale(ZERO), _hasEmitted(emitted), _reconstructed(notReconstructed) { // get the BeamParticleData object if ( original->parents().empty() ) { _beam=dynamic_ptr_cast(original->dataPtr()); } else { _beam=dynamic_ptr_cast(original->parents()[0]->dataPtr()); } } /** * Access to the particle */ ShowerParticlePtr progenitor() const { return _particle; } /** * Set the particle */ void progenitor(ShowerParticlePtr in) { _particle=in; } /** * Access to the original particle */ PPtr original() const { return _original; } /** * Access to the colour isolated copy */ PPtr copy() const { return _copy; } /** * Set the copy */ void copy(PPtr in) { _copy=in; } /** * Whether the particle came from the hard process or was added by * the matrix element correction */ bool perturbative() const { return _perturbative; } /** * Whether the particle came from the hard process or was added by * the matrix element correction */ void perturbative(bool in) { _perturbative=in; } /** * Set/Get methods for the hardest \f$p_T\f$ so far */ //@{ /** * Access the \f$p_T\f$ of the hardest emission so far */ Energy highestpT() const { return _highestpT; } /** * Set the \f$p_T\f$ of the hardest emission so far */ void highestpT(Energy in) { _highestpT=in; } //@} /** * Set/Get methods for the maximum \f$p_T\f$ */ //@{ /** * Access the maximum \f$p_T\f$ for radiation */ Energy maximumpT(ShowerInteraction::Type type) const { assert(type!=ShowerInteraction::QEDQCD && type!=ShowerInteraction::ALL && type!=ShowerInteraction::UNDEFINED); map::const_iterator it = _maxpT.find(type); return it !=_maxpT.end() ? it->second : Constants::MaxEnergy; } /** * Set the maximum \f$p_T\f$ for radiation */ void maximumpT(Energy in,ShowerInteraction::Type type) { _maxpT[type]=in; } //@} /** * Set/Get methods for whether the particle has radiated */ //@{ /** * Access the maximum hard \f$p_T\f$, given by the hard process */ Energy maxHardPt() const { return _maxHardPt; } /** * Set the maximum hard \f$p_T\f$, given by the hard process */ void maxHardPt(Energy in) { _maxHardPt = in; } /** * Access the relevant hard scale to be used in profile scales; usually * this is taken to be the maximum pt, except for other choices such as * hfact. */ Energy hardScale() const { return _hardScale; } /** * Set the relevant hard scale to be used in profile scales; usually * this is taken to be the maximum pt, except for other choices such as * hfact. */ void hardScale(Energy in) { _hardScale = in; } /** * Has this particle radiated */ bool hasEmitted() const { return _hasEmitted; } /** * Set whether or not this particle has radiated */ void hasEmitted(bool in) { _hasEmitted=in; } //@} /** * The id of the particle */ long id() const { return _particle->id(); } /** * The BeamParticleData object */ tcBeamPtr beam() { return _beam; } /** * Whether or not the recon has been performed */ Reconstructed reconstructed() const {return _reconstructed;} /** * Whether or not the recon has been performed */ void reconstructed(Reconstructed recon) {_reconstructed = recon;} private: /** * Pointer to the original particle */ PPtr _original; /** * Pointer to the colour isolated copy of the original particle */ PPtr _copy; /** * Whether the particle came from the hard process or was added by * the matrix element correction */ bool _perturbative; /** * Pointer to the ShowerParticle */ ShowerParticlePtr _particle; /** * Highest \f$p_T\f$ emitted in the shower from this particle */ Energy _highestpT; /** * Maximum allowed \f$p_T\f$ for emission from this particle */ map _maxpT; /** * maximum hard \f$p_T\f$ from the hard process */ Energy _maxHardPt; /** * The relevant hard scale to be used in profile scales; usually * this is taken to be the maximum pt, except for other choices such as * hfact. */ Energy _hardScale; /** * Has there been radiation */ bool _hasEmitted; /** * The BeamParticleData object */ tcBeamPtr _beam; /** * Whether or not the reconstruction has been performed */ Reconstructed _reconstructed; }; } #endif /* HERWIG_ShowerProgenitor_H */ diff --git a/Shower/QTilde/Base/ShowerTree.cc b/Shower/QTilde/Base/ShowerTree.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/ShowerTree.cc @@ -0,0 +1,924 @@ +// -*- C++ -*- +// +// ShowerTree.cc is a part of Herwig - A multi-purpose Monte Carlo event generator +// Copyright (C) 2002-2011 The Herwig Collaboration +// +// Herwig is licenced under version 2 of the GPL, see COPYING for details. +// Please respect the MCnet academic guidelines, see GUIDELINES for details. +// +#include "ShowerProgenitor.h" +#include "ThePEG/EventRecord/MultiColour.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ShowerTree.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/ShowerHandler.h" +#include "ThePEG/PDT/DecayMode.h" +#include "ThePEG/Handlers/EventHandler.h" +#include "ThePEG/Handlers/XComb.h" +#include "KinematicsReconstructor.h" +#include +#include "ThePEG/Repository/CurrentGenerator.h" +#include "ThePEG/PDT/StandardMatchers.h" + +using namespace Herwig; +using namespace ThePEG; + +bool ShowerTree::_spaceTime = false; + +Energy2 ShowerTree::_vmin2 = 0.1*GeV2; + +namespace { + void findBeam(tPPtr & beam, PPtr incoming) { + while(!beam->children().empty()) { + bool found=false; + for(unsigned int ix=0;ixchildren().size();++ix) { + if(beam->children()[ix]==incoming) { + found = true; + break; + } + } + if(found) break; + beam = beam->children()[0]; + } + } +} + +ShowerTree::ShowerTree(PerturbativeProcessPtr process) + : _hardMECorrection(false), + _parent(), _hasShowered(false) { + // get the incoming and outgoing particles and make copies + vector original,copy; + for(unsigned int ix=0;ixincoming().size();++ix) { + original.push_back(process->incoming()[ix].first); + copy .push_back(new_ptr(Particle(*original.back()))); + } + for(unsigned int ix=0;ixoutgoing().size();++ix) { + original.push_back(process->outgoing()[ix].first); + copy .push_back(new_ptr(Particle(*original.back()))); + } + // isolate the colour + colourIsolate(original,copy); + // hard process + unsigned int itype(1); + if(process->incoming().size()==2) { + _wasHard = true; + // set the beams and incoming particles + tPPair beam = CurrentGenerator::current().currentEvent()->incoming(); + findBeam(beam.first ,process->incoming()[0].first); + findBeam(beam.second,process->incoming()[1].first); + _incoming = make_pair(process->incoming()[0].first, + process->incoming()[1].first); + double x1(_incoming.first ->momentum().rho()/beam.first ->momentum().rho()); + double x2(_incoming.second->momentum().rho()/beam.second->momentum().rho()); + // must have two incoming particles + assert(_incoming.first && _incoming.second); + // set the parent tree + _parent=ShowerTreePtr(); + for(unsigned int ix=0;ix<2;++ix) { + ShowerParticlePtr temp=new_ptr(ShowerParticle(*copy[ix],itype,false)); + fixColour(temp); + temp->x(ix==0 ? x1 : x2); + _incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix], + copy[ix],temp)),temp)); + _backward.insert(temp); + } + } + // decay process + else if(process->incoming().size()==1) { + _wasHard = false; + itype=2; + // create the parent shower particle + ShowerParticlePtr sparent(new_ptr(ShowerParticle(*copy[0],itype,false))); + fixColour(sparent); + _incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[0],copy[0],sparent)) + ,sparent)); + // return if not decayed + if(original.size()==1) return; + } + else + assert(false); + // create the children + assert(copy.size() == original.size()); + for (unsigned int ix=process->incoming().size();ixid()==progenitor->id(); + } + ShowerParticlePtr newpart; + if(matches[0]&&matches[1]) { + if(parent->showerKinematics()->z()>0.5) newpart=children[0]; + else newpart=children[1]; + } + else if(matches[0]) newpart=children[0]; + else if(matches[1]) newpart=children[1]; + _outgoingLines[progenitor]=newpart; +} + +void ShowerTree::updateInitialStateShowerProduct(ShowerProgenitorPtr progenitor, + ShowerParticlePtr newParent) { + _incomingLines[progenitor]=newParent; +} + +void ShowerTree::insertHard(StepPtr pstep, bool ISR, bool) { + assert(_incomingLines.size()==2); + colourLines().clear(); + map::const_iterator cit; + // construct the map of colour lines for hard process + for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { + if(!cit->first->perturbative()) continue; + mapColour(cit->first->original(),cit->first->copy()); + } + map::const_iterator cjt; + for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { + if(!cjt->first->perturbative()) continue; + mapColour(cjt->first->original(),cjt->first->copy()); + } + // initial-state radiation + if(ISR) { + for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) { + ShowerParticlePtr init=(*cit).first->progenitor(); + assert(init->thePEGBase()); + PPtr original = (*cit).first->original(); + if(original->parents().empty()) continue; + PPtr hadron= original->parents()[0]; + assert(!original->children().empty()); + PPtr copy=cit->first->copy(); + ParticleVector intermediates=original->children(); + for(unsigned int ix=0;ixabandonChild(intermediates[ix]); + copy->abandonChild(intermediates[ix]); + } + // if not from a matrix element correction + if(cit->first->perturbative()) { + // break mother/daugther relations + init->addChild(original); + hadron->abandonChild(original); + // if particle showers add shower + if(cit->first->hasEmitted()) { + addInitialStateShower(init,hadron,pstep,false); + } + // no showering for this particle + else { + updateColour(init,false); + hadron->addChild(init); + pstep->addIntermediate(init); + init->setLifeLength(Lorentz5Distance()); + init->setVertex(LorentzPoint()); + } + } + // from matrix element correction + else { + // break mother/daugther relations + hadron->abandonChild(original); + copy->addChild(original); + updateColour(copy,false); + init->addChild(copy); + pstep->addIntermediate(copy); + copy->setLifeLength(Lorentz5Distance()); + copy->setVertex(LorentzPoint()); + // if particle showers add shower + if(cit->first->hasEmitted()) { + addInitialStateShower(init,hadron,pstep,false); + } + // no showering for this particle + else { + updateColour(init,false); + hadron->addChild(init); + pstep->addIntermediate(init); + init->setLifeLength(Lorentz5Distance()); + init->setVertex(LorentzPoint()); + } + } + } + } + else { + for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) { + ShowerParticlePtr init=(*cit).first->progenitor(); + assert(init->thePEGBase()); + PPtr original = (*cit).first->original(); + if(original->parents().empty()) continue; + PPtr hadron= original->parents()[0]; + assert(!original->children().empty()); + PPtr copy=cit->first->copy(); + ParticleVector intermediates=original->children(); + for(unsigned int ix=0;ixabandonChild(intermediates[ix]); + copy->abandonChild(intermediates[ix]); + } + // break mother/daugther relations + init->addChild(original); + hadron->abandonChild(original); + // no showering for this particle + updateColour(init,false); + hadron->addChild(init); + pstep->addIntermediate(init); + init->setLifeLength(Lorentz5Distance()); + init->setVertex(LorentzPoint()); + original->setLifeLength(Lorentz5Distance()); + original->setVertex(LorentzPoint()); + } + } + // final-state radiation + for(cjt=outgoingLines().begin();cjt!=outgoingLines().end();++cjt) { + ShowerParticlePtr init=(*cjt).first->progenitor(); + assert(init->thePEGBase()); + // ZERO the distance of original + (*cjt).first->original()->setLifeLength(Lorentz5Distance()); + (*cjt).first->original()->setVertex(LorentzPoint()); + // if not from a matrix element correction + if(cjt->first->perturbative()) { + // register the shower particle as a + // copy of the one from the hard process + tParticleVector parents=init->parents(); + for(unsigned int ix=0;ixabandonChild(init); + (*cjt).first->original()->addChild(init); + pstep->addDecayProduct(init); + } + // from a matrix element correction + else { + if(cjt->first->original()==_incoming.first|| + cjt->first->original()==_incoming.second) { + updateColour((*cjt).first->copy(),false); + (*cjt).first->original()->parents()[0]-> + addChild((*cjt).first->copy()); + pstep->addDecayProduct((*cjt).first->copy()); + (*cjt).first->copy()->addChild(init); + pstep->addDecayProduct(init); + } + else { + updateColour((*cjt).first->copy(),false); + (*cjt).first->original()->addChild((*cjt).first->copy()); + pstep->addDecayProduct((*cjt).first->copy()); + (*cjt).first->copy()->addChild(init); + pstep->addDecayProduct(init); + } + // ZERO the distance of copy ??? \todo change if add space-time + (*cjt).first->copy()->setLifeLength(Lorentz5Distance()); + (*cjt).first->copy()->setVertex(LorentzPoint()); + } + // copy so travels no distance + init->setLifeLength(Lorentz5Distance()); + init->setVertex(init->parents()[0]->decayVertex()); + // sort out the colour + updateColour(init,false); + // insert shower products + addFinalStateShower(init,pstep); + } + colourLines().clear(); +} + +void ShowerTree::addFinalStateShower(PPtr p, StepPtr s) { + // if endpoint assume doesn't travel + if(p->children().empty()) { + if(p->dataPtr()->stable()||ShowerHandler::currentHandler()->decaysInShower(p->id())) + p->setLifeLength(Lorentz5Distance()); + else { + Length ctau = p->dataPtr()->generateLifeTime(p->mass(), p->dataPtr()->width()); + Lorentz5Distance lifeLength(ctau,p->momentum().vect()*(ctau/p->mass())); + p->setLifeLength(lifeLength); + } + return; + } + // set the space-time distance + else { + p->setLifeLength(spaceTimeDistance(p)); + } + ParticleVector::const_iterator child; + for(child=p->children().begin(); child != p->children().end(); ++child) { + updateColour(*child,false); + s->addDecayProduct(*child); + (**child).setVertex(p->decayVertex()); + addFinalStateShower(*child,s); + } +} + +void ShowerTree::addInitialStateShower(PPtr p, PPtr hadron, + StepPtr s, bool addchildren) { + // Each parton here should only have one parent + if(!p->parents().empty()) { + if(p->parents().size()!=1) + throw Exception() << "Particle must only have one parent in ShowerTree" + << "::addInitialStateShower" << Exception::runerror; + // set the space-time distances + if(addchildren) { + p->setLifeLength(spaceTimeDistance(p)); + p->setVertex(p->children()[0]->vertex()-p->lifeLength()); + } + else { + p->setLifeLength(spaceTimeDistance(p)); + p->setVertex(-p->lifeLength()); + } + // recurse + addInitialStateShower(p->parents()[0],hadron,s); + } + else { + hadron->addChild(p); + s->addIntermediate(p); + p->setVertex(p->children()[0]->vertex()); + p->setLifeLength(Lorentz5Distance()); + } + updateColour(p,false); + // if not adding children return + if(!addchildren) return; + // add children + ParticleVector::const_iterator child; + for(child = p->children().begin(); child != p->children().end(); ++child) { + // if a final-state particle update the colour + ShowerParticlePtr schild = + dynamic_ptr_cast(*child); + (**child).setVertex(p->decayVertex()); + if(schild && schild->isFinalState()) updateColour(*child,false); + // if there are grandchildren of p + if(!(*child)->children().empty()) { + // Add child as intermediate + s->addIntermediate(*child); + // If child is shower particle and final-state, add children + if(schild && schild->isFinalState()) addFinalStateShower(schild,s); + } + else + s->addDecayProduct(*child); + } +} + +void ShowerTree::update(PerturbativeProcessPtr newProcess) { + // must be one incoming particle + assert(_incomingLines.size()==1); + colourLines().clear(); + // copy the particles and isolate the colour + vector original,copy; + for(unsigned int ix=0;ixincoming().size();++ix) { + original.push_back(newProcess->incoming()[ix].first); + copy .push_back(new_ptr(Particle(*original.back()))); + } + for(unsigned int ix=0;ixoutgoing().size();++ix) { + original.push_back(newProcess->outgoing()[ix].first); + copy .push_back(new_ptr(Particle(*original.back()))); + } + // isolate the colour + colourIsolate(original,copy); + // make the new progenitor + ShowerParticlePtr stemp=new_ptr(ShowerParticle(*copy[0],2,false)); + fixColour(stemp); + ShowerProgenitorPtr newprog=new_ptr(ShowerProgenitor(original[0],copy[0],stemp)); + _incomingLines.clear(); + _incomingLines.insert(make_pair(newprog,stemp)); + // create the children + assert(copy.size() == original.size()); + for (unsigned int ix=newProcess->incoming().size();ix_treelinks.empty()) + final = _parent->_treelinks[this].second; + else + final=_incomingLines.begin()->first->original(); + // construct the map of colour lines + PPtr copy=_incomingLines.begin()->first->copy(); + mapColour(final,copy); + // now this is the ONE instance of the particle which should have a life length + // \todo change if space-time picture added + // set the lifelength, need this so that still in right direction after + // any ISR recoils + Length ctau = copy->lifeTime(); + Lorentz5Distance lifeLength(ctau,final->momentum().vect()*(ctau/final->mass())); + final->setLifeLength(lifeLength); + // initial-state radiation + if(ISR&&!_incomingLines.begin()->first->progenitor()->children().empty()) { + ShowerParticlePtr init=_incomingLines.begin()->first->progenitor(); + updateColour(init,false); + final->addChild(init); + pstep->addDecayProduct(init); + // just a copy doesn't travel + init->setLifeLength(Lorentz5Distance()); + init->setVertex(final->decayVertex()); + // insert shower products + addFinalStateShower(init,pstep); + // sort out colour + final=_incomingLines.begin()->second; + colourLines().clear(); + mapColour(final,copy); + } + // get the decaying particles + // make the copy + tColinePair cline=make_pair(copy->colourLine(),copy->antiColourLine()); + updateColour(copy,false); + // sort out sinks and sources if needed + if(cline.first) { + if(cline.first->sourceNeighbours().first) { + copy->colourLine()->setSourceNeighbours(cline.first->sourceNeighbours().first, + cline.first->sourceNeighbours().second); + } + else if (cline.first->sinkNeighbours().first) { + copy->colourLine()->setSinkNeighbours(cline.first->sinkNeighbours().first, + cline.first->sinkNeighbours().second); + } + } + if(cline.second) { + if(cline.second->sourceNeighbours().first) { + copy->antiColourLine()->setSourceNeighbours(cline.second->sourceNeighbours().first, + cline.second->sourceNeighbours().second); + } + else if (cline.second->sinkNeighbours().first) { + copy->antiColourLine()->setSinkNeighbours(cline.second->sinkNeighbours().first, + cline.second->sinkNeighbours().second); + } + } + // copy of the one from the hard process + tParticleVector dpar=copy->parents(); + for(unsigned int ix=0;ixabandonChild(copy); + final->addChild(copy); + pstep->addDecayProduct(copy); + // just a copy does not move + copy->setLifeLength(Lorentz5Distance()); + copy->setVertex(final->decayVertex()); + // final-state radiation + map::const_iterator cit; + for(cit=outgoingLines().begin();cit!=outgoingLines().end();++cit) { + ShowerParticlePtr init=cit->first->progenitor(); + // ZERO the distance + init->setLifeLength(Lorentz5Distance()); + if(!init->thePEGBase()) + throw Exception() << "Final-state particle must have a ThePEGBase" + << " in ShowerTree::insertDecay()" + << Exception::runerror; + // if not from matrix element correction + if(cit->first->perturbative()) { + // add the child + updateColour(cit->first->copy(),false); + PPtr orig=cit->first->original(); + orig->setLifeLength(Lorentz5Distance()); + orig->setVertex(copy->decayVertex()); + copy->addChild(orig); + pstep->addDecayProduct(orig); + orig->addChild(cit->first->copy()); + pstep->addDecayProduct(cit->first->copy()); + // register the shower particle as a + // copy of the one from the hard process + tParticleVector parents=init->parents(); + for(unsigned int ix=0;ixabandonChild(init);} + (*cit).first->copy()->addChild(init); + pstep->addDecayProduct(init); + updateColour(init,false); + } + // from a matrix element correction + else { + if(copy->children().end()== + find(copy->children().begin(),copy->children().end(), + cit->first->original())) { + updateColour(cit->first->original(),false); + copy->addChild(cit->first->original()); + pstep->addDecayProduct(cit->first->original()); + } + updateColour(cit->first->copy(),false); + cit->first->original()->addChild(cit->first->copy()); + pstep->addDecayProduct(cit->first->copy()); + // register the shower particle as a + // copy of the one from the hard process + tParticleVector parents=init->parents(); + for(unsigned int ix=0;ixabandonChild(init);} + (*cit).first->copy()->addChild(init); + pstep->addDecayProduct(init); + updateColour(init,false); + } + // ZERO the distances as just copies + cit->first->copy()->setLifeLength(Lorentz5Distance()); + init->setLifeLength(Lorentz5Distance()); + cit->first->copy()->setVertex(copy->decayVertex()); + init->setVertex(copy->decayVertex()); + // insert shower products + addFinalStateShower(init,pstep); + } + colourLines().clear(); +} + +void ShowerTree::clear() { + // reset the has showered flag + _hasShowered=false; + // clear the colour map + colourLines().clear(); + map::const_iterator cit; + map::const_iterator cjt; + // abandon the children of the outgoing particles + for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit) { + ShowerParticlePtr orig=cit->first->progenitor(); + orig->set5Momentum(cit->first->copy()->momentum()); + ParticleVector children=orig->children(); + for(unsigned int ix=0;ixabandonChild(children[ix]); + _outgoingLines[cit->first]=orig; + cit->first->hasEmitted(false); + cit->first->reconstructed(ShowerProgenitor::notReconstructed); + } + // forward products + _forward.clear(); + for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit) + _forward.insert(cit->first->progenitor()); + // if a decay + if(!_wasHard) { + ShowerParticlePtr orig=_incomingLines.begin()->first->progenitor(); + orig->set5Momentum(_incomingLines.begin()->first->copy()->momentum()); + ParticleVector children=orig->children(); + for(unsigned int ix=0;ixabandonChild(children[ix]); + _incomingLines.begin()->first->reconstructed(ShowerProgenitor::notReconstructed); + } + // if a hard process + else { + for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt) { + tPPtr parent = cjt->first->original()->parents().empty() ? + tPPtr() : cjt->first->original()->parents()[0]; + ShowerParticlePtr temp= + new_ptr(ShowerParticle(*cjt->first->copy(), + cjt->first->progenitor()->perturbative(), + cjt->first->progenitor()->isFinalState())); + fixColour(temp); + temp->x(cjt->first->progenitor()->x()); + cjt->first->hasEmitted(false); + if(!(cjt->first->progenitor()==cjt->second)&&cjt->second&&parent) + parent->abandonChild(cjt->second); + cjt->first->progenitor(temp); + _incomingLines[cjt->first]=temp; + cjt->first->reconstructed(ShowerProgenitor::notReconstructed); + } + } + // reset the particles at the end of the shower + _backward.clear(); + // if hard process backward products + if(_wasHard) + for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt) + _backward.insert(cjt->first->progenitor()); + clearTransforms(); +} + +void ShowerTree::resetShowerProducts() { + map::const_iterator cit; + map::const_iterator cjt; + _backward.clear(); + _forward.clear(); + for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) + _backward.insert(cit->second); + for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) + _forward.insert(cjt->second); +} + +void ShowerTree::updateAfterShower(ShowerDecayMap & decay) { + // update the links + map::const_iterator mit; + map >::iterator tit; + for(tit=_treelinks.begin();tit!=_treelinks.end();++tit) { + if(tit->second.first) { + mit=_outgoingLines.find(tit->second.first); + if(mit!=_outgoingLines.end()) tit->second.second=mit->second; + } + } + // get the particles coming from those in the hard process + set hard; + for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) + hard.insert(mit->second); + // find the shower particles which should be decayed in the + // shower but didn't come from the hard process + set::const_iterator cit; + for(cit=_forward.begin();cit!=_forward.end();++cit) { + if((ShowerHandler::currentHandler()->decaysInShower((**cit).id())&& + !(**cit).dataPtr()->stable()) && + hard.find(*cit)==hard.end()) { + PerturbativeProcessPtr newProcess(new_ptr(PerturbativeProcess())); + newProcess->incoming().push_back(make_pair(*cit,PerturbativeProcessPtr())); + ShowerTreePtr newtree=new_ptr(ShowerTree(newProcess)); + newtree->setParents(); + newtree->_parent=this; + Energy width=(**cit).dataPtr()->generateWidth((**cit).mass()); + decay.insert(make_pair(width,newtree)); + _treelinks.insert(make_pair(newtree, + make_pair(tShowerProgenitorPtr(),*cit))); + } + } +} + +void ShowerTree::addFinalStateBranching(ShowerParticlePtr parent, + const ShowerParticleVector & children) { + assert(children.size()==2); + _forward.erase(parent); + for(unsigned int ix=0; ix >::const_iterator tit; + for(tit=_treelinks.begin();tit!=_treelinks.end();++tit) + tit->first->_parent=this; +} + +vector ShowerTree::extractProgenitors() { + // extract the particles from the ShowerTree + map::const_iterator mit; + vector ShowerHardJets; + for(mit=incomingLines().begin();mit!=incomingLines().end();++mit) + ShowerHardJets.push_back((*mit).first); + map::const_iterator mjt; + for(mjt=outgoingLines().begin();mjt!=outgoingLines().end();++mjt) + ShowerHardJets.push_back((*mjt).first); + return ShowerHardJets; +} + +void ShowerTree::transform(const LorentzRotation & boost, bool applyNow) { + if(applyNow) { + // now boost all the particles + map::const_iterator cit; + // incoming + for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { + cit->first->progenitor()->deepTransform(boost); + cit->first->copy()->deepTransform(boost); + } + // outgoing + map::const_iterator cjt; + for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { + cjt->first->progenitor()->deepTransform(boost); + cjt->first->copy()->deepTransform(boost); + } + } + else { + _transforms.transform(boost); + } + // child trees + for(map >::const_iterator + tit=_treelinks.begin();tit!=_treelinks.end();++tit) + tit->first->transform(boost,applyNow); +} + +void ShowerTree::applyTransforms() { + // now boost all the particles + map::const_iterator cit; + // incoming + for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) { + cit->first->progenitor()->deepTransform(_transforms); + cit->first->copy()->deepTransform(_transforms); + } + // outgoing + map::const_iterator cjt; + for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) { + cjt->first->progenitor()->deepTransform(_transforms); + cjt->first->copy()->deepTransform(_transforms); + } + // child trees + for(map >::const_iterator + tit=_treelinks.begin();tit!=_treelinks.end();++tit) + tit->first->applyTransforms(); + _transforms = LorentzRotation(); +} + +void ShowerTree::clearTransforms() { + _transforms = LorentzRotation(); + // // child trees + // for(map >::const_iterator + // tit=_treelinks.begin();tit!=_treelinks.end();++tit) + // tit->first->clearTransforms(); +} + +void ShowerTree::fixColour(tShowerParticlePtr part) { + if(!part->colourInfo()->colourLines().empty()) { + if(part->colourInfo()->colourLines().size()==1) { + ColinePtr line=part->colourLine(); + if(line) { + line->removeColoured(part); + line->addColoured(part); + } + } + else { + Ptr::pointer colour = + dynamic_ptr_cast::pointer>(part->colourInfo()); + vector lines = colour->colourLines(); + for(unsigned int ix=0;ix(lines[ix]); + if(line) { + line->removeColoured(part); + line->addColoured(part); + } + } + } + } + if(!part->colourInfo()->antiColourLines().empty()) { + if(part->colourInfo()->antiColourLines().size()==1) { + ColinePtr line=part->antiColourLine(); + if(line) { + line->removeAntiColoured(part); + line->addAntiColoured(part); + } + } + else { + Ptr::pointer colour = + dynamic_ptr_cast::pointer>(part->colourInfo()); + vector lines = colour->antiColourLines(); + for(unsigned int ix=0;ix(lines[ix]); + if(line) { + line->removeAntiColoured(part); + line->addAntiColoured(part); + } + } + } + } +} + +vector ShowerTree::extractProgenitorParticles() { + vector particles; + // incoming particles + for(map::const_iterator + cit=incomingLines().begin(); cit!=incomingLines().end();++cit) + particles.push_back(cit->first->progenitor()); + // outgoing particles + for(map::const_iterator + cjt=outgoingLines().begin(); cjt!=outgoingLines().end();++cjt) + particles.push_back(cjt->first->progenitor()); + return particles; +} + +Lorentz5Distance ShowerTree::spaceTimeDistance(tPPtr particle) { + if(!_spaceTime) return Lorentz5Distance(); + Energy2 q2 = particle->mass() > ZERO ? sqr(particle->mass()) : -sqr(particle->mass()); + const tcPDPtr data = particle->dataPtr(); + // calculate width imposing min value + Energy conMass = max(data->constituentMass(),200*MeV); + Energy width = max(data->generateWidth(particle->mass()),_vmin2/conMass); + // offshellness + Energy2 offShell = q2-sqr(data->constituentMass()); + if(abs(offShell)<1e-10*GeV2) offShell = ZERO; + InvEnergy2 fact = UseRandom::rndExp(1./sqrt((sqr(offShell)+sqr(q2*width/conMass)))); + Lorentz5Distance output = (hbarc*fact)*particle->momentum(); + return output; +} + +void ShowerTree::constructTrees(ShowerTreePtr & hardTree, + ShowerDecayMap & decayTrees, + PerturbativeProcessPtr hard, + DecayProcessMap decay) { + map treeMap; + // convert the hard process + if(hardTree) { + hardTree->update(hard); + } + else { + hardTree = new_ptr(ShowerTree(hard)); + } + treeMap.insert(make_pair(hard,hardTree)); + for(DecayProcessMap::const_iterator it=decay.begin();it!=decay.end();++it) { + ShowerTreePtr newTree = new_ptr(ShowerTree(it->second)); + treeMap.insert(make_pair(it->second,newTree)); + decayTrees.insert(make_pair(it->first,newTree)); + } + // set up the links between the trees + for(map::const_iterator it=treeMap.begin(); + it!=treeMap.end();++it) { + // links to daughter trees + map::const_iterator mit; + for(mit=it->second->_outgoingLines.begin(); + mit!=it->second->_outgoingLines.end();++mit) { + unsigned int iloc=0; + for(;ilocfirst->outgoing().size();++iloc) { + if(it->first->outgoing()[iloc].first==mit->first->original()) + break; + } + if(it->first->outgoing()[iloc].second) + it->second->_treelinks.insert(make_pair(treeMap[it->first->outgoing()[iloc].second], + make_pair(mit->first,mit->first->progenitor()))); + } + // links to parent trees + if(it->first->incoming()[0].second) { + it->second->_parent = treeMap[it->first->incoming()[0].second]; + } + } +} + +namespace { + +Lorentz5Momentum sumMomenta(tPPtr particle) { + if(particle->children().empty()) + return particle->momentum(); + Lorentz5Momentum output; + for(unsigned int ix=0;ixchildren().size();++ix) { + output += sumMomenta(particle->children()[ix]); + } + return output; +} + +} + +void ShowerTree::checkMomenta() { + vector pin; + for(map::const_iterator it=_incomingLines.begin(); + it!=_incomingLines.end();++it) { + if(isDecay()) { + tPPtr parent = it->first->progenitor(); + pin.push_back(parent->momentum()); + while(!parent->children().empty()) { + pin.back() -= sumMomenta(parent->children()[1]); + parent = parent->children()[0]; + } + } + else { + tPPtr parent = it->second; + pin.push_back(parent->momentum()); + while(!parent->children().empty()&&parent->children().size()==2) { + pin.back() -= sumMomenta(parent->children()[1]); + parent = parent->children()[0]; + if(parent==it->first->progenitor()) break; + } + } + } + vector pout; + for(map::const_iterator it= _outgoingLines.begin(); + it!=_outgoingLines.end();++it) { + pout.push_back(sumMomenta(it->first->progenitor())); + } + Lorentz5Momentum psum; + for(unsigned int ix=0;ix< pin.size();++ix) { + CurrentGenerator::log() << "pin " << ix << pin[ix]/GeV << "\n"; + psum +=pin[ix]; + } + CurrentGenerator::log() << "In total " << psum/GeV << " " << psum.m()/GeV << "\n"; + Lorentz5Momentum psum2; + for(unsigned int ix=0;ix< pout.size();++ix) { + CurrentGenerator::log() << "pout " << ix << pout[ix]/GeV << "\n"; + psum2 +=pout[ix]; + } + CurrentGenerator::log() << "Out total " << psum2/GeV << " " << psum2.m()/GeV << "\n"; + CurrentGenerator::log() << "Total " << (psum-psum2)/GeV << "\n"; +} + +RealEmissionProcessPtr ShowerTree::perturbativeProcess() { + RealEmissionProcessPtr output(new_ptr(RealEmissionProcess())); + // add the incoming particles + unsigned int ix=0; + pair x; + for(map::const_iterator it=_incomingLines.begin(); + it!=_incomingLines.end();++it) { + output->bornIncoming().push_back(it->first->progenitor()); + if(!it->first->original()->parents().empty()) + output->hadrons().push_back(it->first->original()->parents()[0]); + else + output->hadrons().push_back(it->first->progenitor()); + if(ix==0) x.first = it->second->x(); + else x.second = it->second->x(); + ++ix; + } + output->x(x); + // add the outgoing particles + for(map::const_iterator it= _outgoingLines.begin(); + it!=_outgoingLines.end();++it) { + output->bornOutgoing().push_back(it->first->progenitor()); + } + return output; +} + +void ShowerTree::setVetoes(const map & pTs, + unsigned int type) { + if(type==1||type==3) { + for(map::const_iterator it=_incomingLines.begin(); + it!=_incomingLines.end();++it) { + for(map::const_iterator jt=pTs.begin();jt!=pTs.end();++jt) + it->first->maximumpT(jt->second,jt->first); + } + } + if(type==2||type==3) { + for(map::const_iterator it= _outgoingLines.begin(); + it!=_outgoingLines.end();++it) { + for(map::const_iterator jt=pTs.begin();jt!=pTs.end();++jt) + it->first->maximumpT(jt->second,jt->first); + } + } +} diff --git a/Shower/Base/ShowerTree.fh b/Shower/QTilde/Base/ShowerTree.fh rename from Shower/Base/ShowerTree.fh rename to Shower/QTilde/Base/ShowerTree.fh diff --git a/Shower/QTilde/Base/ShowerTree.h b/Shower/QTilde/Base/ShowerTree.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/ShowerTree.h @@ -0,0 +1,414 @@ +// -*- C++ -*- +// +// ShowerTree.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_ShowerTree_H +#define HERWIG_ShowerTree_H + +#include "ThePEG/Config/ThePEG.h" +#include "Herwig/Shower/ShowerHandler.fh" +#include "Herwig/Shower/PerturbativeProcess.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Shower/ShowerEventRecord.h" +#include "Herwig/Shower/QTilde/ShowerConfig.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "ShowerProgenitor.h" +#include "ThePEG/EventRecord/Step.h" +#include +#include "ShowerTree.fh" + +namespace Herwig { + +/** + * Typedef for map of ShowerTrees for decays + */ +typedef multimap > ShowerDecayMap; + +using namespace ThePEG; + +/** \ingroup Shower + * + * The ShowerTree class stores the basic information needed for + * each hard interaction, either a scattering process or decay, which + * needs to be showered. + * + */ +class ShowerTree : public ShowerEventRecord { + + friend class ShowerHandler; + +public: + + /** + * Constructor from a perturbative process + * @param process The perturbative process + */ + ShowerTree(PerturbativeProcessPtr process); + + /** + * Calculate the space-time displacement + * @param particle The particle for which to calculate the displacement + */ + static Lorentz5Distance spaceTimeDistance(tPPtr particle); + + /** + * Construct the trees from the hard process + * @param hardTree The output ShowerTree for the hard process + * @param decayTrees The output ShowerTrees for any decays. + * @param hard The output ShowerTree for the hard process + * @param decay The output ShowerTrees for any decays. + */ + static void constructTrees(ShowerTreePtr & hardTree, + ShowerDecayMap & decayTrees, + PerturbativeProcessPtr hard, + DecayProcessMap decay); + +public: + + /** + * Insert the tree into the event record + * @param pstep The step into which the particles should be inserted + * @param ISR Whether or not ISR is switched on + * @param FSR Whether or not FSR is switched on + */ + void fillEventRecord(StepPtr pstep,bool ISR,bool FSR) { + if(_wasHard) + insertHard (pstep,ISR,FSR); + else + insertDecay(pstep,ISR,FSR); + } + + + /** + * Set the parent tree to this tree for trees which come from this one. + * This needs to be run after the constructor. + */ + void setParents(); + + /** + * Access methods for the type of interaction + */ + //@{ + /** + * Whether or not this is a scattering process + */ + bool isHard() const { return _wasHard; } + + + /** + * Whether or not this is a decay. + */ + bool isDecay() const { return !_wasHard; } + //@} + + /** + * Flags relating to the application of the hard matrix element correction + */ + //@{ + /** + * Was the hard matrix element correction applied + */ + bool hardMatrixElementCorrection() const { return _hardMECorrection; } + + /** + * Set whether or not the hard matrix element correction was applied + */ + void hardMatrixElementCorrection(bool in) { _hardMECorrection=in; } + //@} + + /** + * Get the incoming shower particles + */ + map & incomingLines() { + return _incomingLines; + } + + /** + * Get the outgoing shower particles + */ + map & outgoingLines() { + return _outgoingLines; + } + + /** + * Update the shower product for a final-state particle + */ + void updateFinalStateShowerProduct(ShowerProgenitorPtr progenitor, + ShowerParticlePtr parent, + const ShowerParticleVector & children); + + /** + * Update the shower product for an initial-state particle + */ + void updateInitialStateShowerProduct(ShowerProgenitorPtr progenitor, + ShowerParticlePtr newParent); + + /** + * Get the current final shower product for a final-state particle + */ + tShowerParticlePtr getFinalStateShowerProduct(ShowerProgenitorPtr progenitor) { + return _outgoingLines.find(progenitor)==_outgoingLines.end() + ? tShowerParticlePtr() : _outgoingLines[progenitor]; + } + + /** + * Add a final-state branching. This method removes the parent of the branching + * from the list of particles at the end of the shower and inserts the children + * @param parent The parent for the branching + * @param children The outgoing particles in the branching + */ + void addFinalStateBranching(ShowerParticlePtr parent, + const ShowerParticleVector & children); + + /** + * Add an initial-state branching. This method removes the oldParent of the + * branching and inserts the result of the backward evolution and the + * outgoing particle into the relevant lists. + * @param oldParent The particle being backward evolved + * @param newParent The initial-state particle resulting from the backward evolution + * @param otherChild The final-state particle produced in the evolution. + */ + void addInitialStateBranching(ShowerParticlePtr oldParent, + ShowerParticlePtr newParent, + ShowerParticlePtr otherChild); + + // /** + // * Member called at the end of the shower of a tree to perform a number of + // * updates. + // * @param decay The map of widths and ShowerTrees for the decays so that + // * any unstable decay products can be added. + // */ + void updateAfterShower(ShowerDecayMap & decay); + + /** + * Access and set the flag for whether this tree has been showered + */ + //@{ + /** + * Access the flag + */ + bool hasShowered() const { return _hasShowered; } + + /** + * Set the flag + */ + void hasShowered(bool in) { _hasShowered=in; } + //@} + + /** + * Access the parent tree + */ + ShowerTreePtr parent() const { return _parent; } + + /** + * Clear all the shower products so that the event can be reshowered + * if the first attempt fail + */ + void clear(); + + /** + * Reset the particles resulting from the shower to those which started + * the shower + */ + void resetShowerProducts(); + + /** + * Set maximum Emission scales + */ + void setVetoes(const map & pTs, + unsigned int type); + + /** + * Extract the progenitors for the reconstruction + */ + vector extractProgenitors(); + + /** + * Access to the outgoing particles + */ + const set & forwardParticles() const { return _forward; } + + /** + * Map of particles in this Tree which are the initial particles in other + * trees + */ + const map > & + treelinks() const {return _treelinks;} + + /** + * Update the link between shower particle and tree + */ + void updateLink(tShowerTreePtr tree, + pair in) { + _treelinks[tree] = in; + } + + /** + * Transform the tree + */ + void transform(const LorentzRotation & rot, bool applyNow); + + /** + * Apply any postphoned transformations + */ + void applyTransforms(); + + /** + * Clear any postphoned transformations + */ + void clearTransforms(); + + /** + * Transform which needs to be applied + */ + const LorentzRotation & transform() {return _transforms;} + + /** + * Get all the progenitors + */ + vector extractProgenitorParticles(); + + /** + * Check the momentum conservation in the tree + */ + void checkMomenta(); + + /** + * Update tree after the parent has been decayed. + */ + void update(PerturbativeProcessPtr newProcess); + + /** + * The perturbative process + */ + RealEmissionProcessPtr perturbativeProcess(); + +protected: + + /** + * Functions to add the shower to the event record. + */ + //@{ + /** + * Insert a hard process + * @param pstep The step into which the particles should be inserted + * @param ISR Whether or not ISR is switched on + * @param FSR Whether or not FSR is switched on + */ + void insertHard(StepPtr pstep,bool ISR,bool FSR); + + /** + * Insert a decay process + * @param pstep The step into which the particles should be inserted + * @param ISR Whether or not ISR is switched on + * @param FSR Whether or not FSR is switched on + */ + void insertDecay(StepPtr pstep,bool ISR,bool FSR); + + /** + * Recursively add the final-state shower from the particle to the event record. + * @param particle The final-state particle + * @param step The step + */ + void addFinalStateShower(PPtr particle, StepPtr step); + + /** + * Add the initial-state shwoer from the particle to the step + * @param particle The final-state particle + * @param hadron The incoming hadron + * @param step The step + * @param addchildren Add the children of the particle + */ + void addInitialStateShower(PPtr particle, PPtr hadron, + StepPtr step, bool addchildren=true); + //@} + + /** + * After the creatation of a ShowerParticle make sure it is properly attached + * to its ColourLine + * @param part The particle + */ + void fixColour(tShowerParticlePtr part); + +private: + + /** + * Incoming partons for the hard process + */ + PPair _incoming; + + /** + * The incoming ShowerParticles connected to the interaction + * as the index of a map with the particle the shower backward evolves + * them to as the value + */ + map _incomingLines; + + /** + * The outgoing ShowerParticles connected to the interaction + * as the index of a map with the particle the shower + * evolves them to as the value + */ + map _outgoingLines; + + /** + * The outgoing ShowerParticles at the end of the final-state shower + */ + set _forward; + + /** + * The incoming ShowerParticles at the end of the initial-state shower + */ + set _backward; + + /** + * Was the hard matrix element correction applied + */ + bool _hardMECorrection; + + /** + * Was this a scattering process or a decay + */ + bool _wasHard; + + /** + * Map of particles in this Tree which are the initial particles in other + * trees + */ + map > _treelinks; + + /** + * The parent tree + */ + tShowerTreePtr _parent; + + /** + * Has this tree showered + */ + bool _hasShowered; + + /** + * The transforms which still need to be applied + */ + LorentzRotation _transforms; + +private: + + /** + * Whether or not to include space-time distances + */ + static bool _spaceTime; + + /** + * Minimum virtuality for the space-time model + */ + static Energy2 _vmin2; + +}; +} + +#endif diff --git a/Shower/Base/ShowerVertex.cc b/Shower/QTilde/Base/ShowerVertex.cc rename from Shower/Base/ShowerVertex.cc rename to Shower/QTilde/Base/ShowerVertex.cc diff --git a/Shower/Base/ShowerVertex.fh b/Shower/QTilde/Base/ShowerVertex.fh rename from Shower/Base/ShowerVertex.fh rename to Shower/QTilde/Base/ShowerVertex.fh diff --git a/Shower/Base/ShowerVertex.h b/Shower/QTilde/Base/ShowerVertex.h rename from Shower/Base/ShowerVertex.h rename to Shower/QTilde/Base/ShowerVertex.h diff --git a/Shower/Base/ShowerVeto.cc b/Shower/QTilde/Base/ShowerVeto.cc rename from Shower/Base/ShowerVeto.cc rename to Shower/QTilde/Base/ShowerVeto.cc diff --git a/Shower/Base/ShowerVeto.fh b/Shower/QTilde/Base/ShowerVeto.fh rename from Shower/Base/ShowerVeto.fh rename to Shower/QTilde/Base/ShowerVeto.fh diff --git a/Shower/QTilde/Base/ShowerVeto.h b/Shower/QTilde/Base/ShowerVeto.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Base/ShowerVeto.h @@ -0,0 +1,138 @@ +// -*- C++ -*- +// +// ShowerVeto.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_ShowerVeto_H +#define HERWIG_ShowerVeto_H +// +// This is the declaration of the ShowerVeto class. +// + +#include "ThePEG/Interface/Interfaced.h" +#include "ShowerVeto.fh" +#include "Herwig/Shower/QTilde/ShowerConfig.h" +#include "ShowerParticle.fh" +#include "ShowerProgenitor.fh" + +namespace Herwig { + +struct Branching; + +using namespace ThePEG; + +/**\ingroup Shower + * Exception class for vetoing a showering + */ +struct VetoShower { }; + +/**\ingroup Shower + * ShowerVeto is a general interface for performing + * vetoes during showering. + * + * @see \ref ShowerVetoInterfaces "The interfaces" + * defined for ShowerVeto. + */ +class ShowerVeto: public Interfaced { + +public: + + /** + * Define types of ShowerVetoes + */ + enum ShowerVetoType { + + /** + * Throw away emission, if veto encountered. Set the scale to + * the scale of vetoed emission. + */ + Emission = 1, + + /** + * Throw away showering + */ + Shower, + + /** + * Throw away event + */ + Event + }; + +public: + + /** + * Constructor giving the behaviour of this veto + */ + ShowerVeto (ShowerVetoType vetoType) : _vetoType(vetoType) {} + + /** + * Return the type of this veto + */ + ShowerVetoType vetoType () const {return _vetoType;} + +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: + + /** + * Return true, if the selected emission off the given + * particle and progenitor is vetoed. + */ + virtual bool vetoTimeLike (tcShowerProgenitorPtr, tcShowerParticlePtr, + const Branching&) = 0; + + /** + * Return true, if the selected emission off the given + * particle and progenitor is vetoed. + */ + virtual bool vetoSpaceLike (tcShowerProgenitorPtr, tcShowerParticlePtr, + const Branching&) = 0; + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + ShowerVeto & operator=(const ShowerVeto &); + +private: + + /** + * The type of this veto. + */ + ShowerVetoType _vetoType; + +}; + +} + +#endif /* HERWIG_ShowerVeto_H */ diff --git a/Shower/Base/SudakovFormFactor.cc b/Shower/QTilde/Base/SudakovFormFactor.cc rename from Shower/Base/SudakovFormFactor.cc rename to Shower/QTilde/Base/SudakovFormFactor.cc --- a/Shower/Base/SudakovFormFactor.cc +++ b/Shower/QTilde/Base/SudakovFormFactor.cc @@ -1,345 +1,345 @@ // -*- 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 { double ratio=alphaSVetoRatio(pt2,1.); return UseRandom::rnd() > ratio; } double SudakovFormFactor::alphaSVetoRatio(Energy2 pt2, double factor) const { factor *= renormalizationScaleFactor(); return ThePEG::Math::powi(alpha_->ratio(pt2, factor), splittingFn_->interactionOrder()); } bool SudakovFormFactor::PDFVeto(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, Ptr::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()*factor); if (theScale < sqr(freeze_)) theScale = sqr(freeze_); double newpdf(0.0), oldpdf(0.0); newpdf=pdf_->xfx(beam,parton0,theScale,x/z()); oldpdf=pdf_->xfx(beam,parton1,theScale,x); if(newpdf<=0.) return 0.; if(oldpdf<=0.) return 1.; double ratio = newpdf/oldpdf; double maxpdf = pdfmax_; switch (pdffactor_) { case 1: maxpdf /= z(); break; case 2: maxpdf /= 1.-z(); break; case 3: maxpdf /= (z()*(1.-z())); break; } if (ratio > maxpdf) { generator()->log() << "PDFVeto warning: Ratio > " << name() << ":PDFmax (by a factor of " << ratio/maxpdf <<") for " << parton0->PDGName() << " to " << parton1->PDGName() << "\n"; } return ratio/maxpdf ; } void SudakovFormFactor::addSplitting(const IdList & in) { bool add=true; for(unsigned int ix=0;ix::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 double & detune) const { + double detune) const { unsigned int pdfopt = iopt!=1 ? 0 : pdffactor_; double c = 1./((splittingFn_->integOverP(zlimits_.second,ids,pdfopt) - splittingFn_->integOverP(zlimits_.first ,ids,pdfopt))* alpha_->overestimateValue()/Constants::twopi*enhance*detune); assert(iopt<=2); if(iopt==1) { c/=pdfmax_; //symmetry of FS gluon splitting if(ident) c*=0.5; } else if(iopt==2) c*=-1.; if(splittingFn_->interactionOrder()==1) { double r = UseRandom::rnd(); if(iopt!=2 || c*log(r)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.fh b/Shower/QTilde/Base/SudakovFormFactor.fh rename from Shower/Base/SudakovFormFactor.fh rename to Shower/QTilde/Base/SudakovFormFactor.fh diff --git a/Shower/Base/SudakovFormFactor.h b/Shower/QTilde/Base/SudakovFormFactor.h rename from Shower/Base/SudakovFormFactor.h rename to Shower/QTilde/Base/SudakovFormFactor.h --- a/Shower/Base/SudakovFormFactor.h +++ b/Shower/QTilde/Base/SudakovFormFactor.h @@ -1,723 +1,723 @@ // -*- 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 "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h" +#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.fh" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ThePEG/EventRecord/RhoDMatrix.h" #include "ThePEG/EventRecord/SpinInfo.h" #include "ShowerKinematics.fh" #include "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 * defined. */ virtual ShoKinPtr generateNextTimeBranching(const Energy startingScale, const IdList &ids, const RhoDMatrix & rho, double enhance, double detuning, Energy2 maxQ2)=0; /** * Return the scale of the next space-like decay branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param stoppingScale stopping scale for the evolution * @param minmass The minimum mass allowed for the spake-like particle. * @param ids The PDG codes of the particles in the splitting * defined. * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale, const Energy stoppingScale, const Energy minmass, const IdList &ids, const RhoDMatrix & rho, double enhance, double detuning)=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, double detuning)=0; //@} /** * Generate the azimuthal angle of the branching for forward evolution * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiForward(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, 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 double & detune) const; + double enhance, bool identical, double detune) const; /** * Veto on the PDF for the initial-state shower * @param t The scale * @param x The fraction of the beam momentum * @param parton0 Pointer to the particleData for the * new parent (this is the particle we evolved back to) * @param parton1 Pointer to the particleData for the * original particle * @param beam The BeamParticleData object */ bool PDFVeto(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, tcBeamPtr beam) const; /** * The PDF veto ratio */ double PDFVetoRatio(const Energy2 t, const double x, const tcPDPtr parton0, const tcPDPtr parton1, tcBeamPtr beam,double factor) const; /** * The veto on the splitting function. * @param t The scale * @param ids The PDG codes of the particles in the splitting * @param mass Whether or not to use the massive splitting functions * @return true if vetoed */ bool SplittingFnVeto(const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix & rho, const double & detune) const { return UseRandom::rnd()>SplittingFnVetoRatio(t,ids,mass,rho,detune); } /** * The Splitting function veto ratio */ double SplittingFnVetoRatio(const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix & rho, const double & detune) const { return splittingFn_->ratioP(z_, t, ids,mass,rho)/detune; } /** * The veto on the coupling constant * @param pt2 The value of ther transverse momentum squared, \f$p_T^2\f$. * @return true if vetoed */ bool alphaSVeto(Energy2 pt2) const; /** * The alpha S veto ratio */ double alphaSVetoRatio(Energy2 pt2,double factor) const; //@} /** * 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.cc b/Shower/QTilde/Couplings/ShowerAlpha.cc rename from Shower/Couplings/ShowerAlpha.cc rename to Shower/QTilde/Couplings/ShowerAlpha.cc diff --git a/Shower/Couplings/ShowerAlpha.fh b/Shower/QTilde/Couplings/ShowerAlpha.fh rename from Shower/Couplings/ShowerAlpha.fh rename to Shower/QTilde/Couplings/ShowerAlpha.fh diff --git a/Shower/Couplings/ShowerAlpha.h b/Shower/QTilde/Couplings/ShowerAlpha.h rename from Shower/Couplings/ShowerAlpha.h rename to Shower/QTilde/Couplings/ShowerAlpha.h diff --git a/Shower/Couplings/ShowerAlphaQCD.cc b/Shower/QTilde/Couplings/ShowerAlphaQCD.cc rename from Shower/Couplings/ShowerAlphaQCD.cc rename to Shower/QTilde/Couplings/ShowerAlphaQCD.cc diff --git a/Shower/Couplings/ShowerAlphaQCD.h b/Shower/QTilde/Couplings/ShowerAlphaQCD.h rename from Shower/Couplings/ShowerAlphaQCD.h rename to Shower/QTilde/Couplings/ShowerAlphaQCD.h diff --git a/Shower/Couplings/ShowerAlphaQED.cc b/Shower/QTilde/Couplings/ShowerAlphaQED.cc rename from Shower/Couplings/ShowerAlphaQED.cc rename to Shower/QTilde/Couplings/ShowerAlphaQED.cc diff --git a/Shower/Couplings/ShowerAlphaQED.h b/Shower/QTilde/Couplings/ShowerAlphaQED.h rename from Shower/Couplings/ShowerAlphaQED.h rename to Shower/QTilde/Couplings/ShowerAlphaQED.h diff --git a/Shower/Default/Decay_QTildeShowerKinematics1to2.cc b/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.cc rename from Shower/Default/Decay_QTildeShowerKinematics1to2.cc rename to Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.cc --- a/Shower/Default/Decay_QTildeShowerKinematics1to2.cc +++ b/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.cc @@ -1,117 +1,113 @@ // -*- C++ -*- // // Decay_QTildeShowerKinematics1to2.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 Decay_QTildeShowerKinematics1to2 class. // #include "Decay_QTildeShowerKinematics1to2.h" #include "ThePEG/PDT/EnumParticles.h" -#include "Herwig/Shower/SplittingFunctions/SplittingFunction.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include #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" -#include "Herwig/Shower/Base/ShowerVertex.h" +#include "Herwig/Shower/QTilde/Base/ShowerVertex.h" using namespace Herwig; void Decay_QTildeShowerKinematics1to2:: updateChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType, bool massVeto) const { assert(children.size() == 2); // calculate the scales splittingFn()->evaluateDecayScales(partnerType,scale(),z(),parent, children[0],children[1]); // set the maximum virtual masses IdList ids(3); ids[0] = parent->dataPtr(); ids[1] = children[0]->dataPtr(); ids[2] = children[1]->dataPtr(); const vector & virtualMasses = SudakovFormFactor()->virtualMasses(ids); Energy2 q2 = sqr(virtualMasses[0])-(1.-z())*sqr(scale()); children[0]->virtualMass(sqrt(q2)); if(massVeto) { children[1]->scales().Max_Q2 = (1.-z())/z()*(z()*sqr(virtualMasses[0])-q2); } // determine alphas of children according to interpretation of z const ShowerParticle::Parameters & params = parent->showerParameters(); ShowerParticle::Parameters & child0 = children[0]->showerParameters(); ShowerParticle::Parameters & child1 = children[1]->showerParameters(); child0.alpha = z() * params.alpha; child1.alpha = (1.-z()) * params.alpha; child0.ptx = pT() * cos(phi()) + z()* params.ptx; child0.pty = pT() * sin(phi()) + z()* params.pty; child0.pt = sqrt( sqr(child0.ptx) + sqr(child0.pty) ); child1.ptx = -pT() * cos(phi()) + (1.-z()) * params.ptx; child1.pty = -pT() * sin(phi()) + (1.-z()) * params.pty; child1.pt = sqrt( sqr(child1.ptx) + sqr(child1.pty) ); // set up the colour connections splittingFn()->colourConnection(parent,children[0],children[1],partnerType,false); // make the products children of the parent parent->addChild(children[0]); parent->addChild(children[1]); // set the momenta of the children for(ShowerParticleVector::const_iterator pit=children.begin(); pit!=children.end();++pit) { (**pit).showerBasis(parent->showerBasis(),true); (**pit).setShowerMomentum(true); } } void Decay_QTildeShowerKinematics1to2:: reconstructParent( const tShowerParticlePtr, const ParticleVector &) const { throw Exception() << "Decay_QTildeShowerKinematics1to2::reconstructParent not implemented" << Exception::abortnow; } void Decay_QTildeShowerKinematics1to2:: reconstructLast(const tShowerParticlePtr last, Energy mass) const { // set beta component and consequently all missing data from that, // using the nominal (i.e. PDT) mass. Energy theMass = mass > ZERO ? mass : last->data().constituentMass(); last->showerParameters().beta= (sqr(theMass) + sqr(last->showerParameters().pt) - sqr( last->showerParameters().alpha )*last->showerBasis()->pVector().m2()) - / ( 2.*last->showerParameters().alpha*last->showerBasis()->p_dot_n() ); + / ( 2.*last->showerParameters().alpha*last->showerBasis()->p_dot_n() ); // set that new momentum last->set5Momentum( last->showerBasis()->sudakov2Momentum( last->showerParameters().alpha, last->showerParameters().beta, last->showerParameters().ptx, last->showerParameters().pty) ); } void Decay_QTildeShowerKinematics1to2::updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type) const { IdList ids(3); ids[0] = parent->dataPtr(); ids[1] = children[0]->dataPtr(); ids[2] = children[1]->dataPtr(); const vector & virtualMasses = SudakovFormFactor()->virtualMasses(ids); children[0]->virtualMass(sqrt(sqr(virtualMasses[0])-(1.-z())*sqr(scale()))); if(children[1]->children().empty()) children[1]->virtualMass(virtualMasses[2]); // compute the new pT of the branching Energy2 pt2=(1.-z())*(z()*sqr(virtualMasses[0])-sqr(children[0]->virtualMass())) -z()*sqr(children[1]->virtualMass()); if(pt2>ZERO) { pT(sqrt(pt2)); } else { parent->virtualMass(ZERO); } } diff --git a/Shower/Default/Decay_QTildeShowerKinematics1to2.h b/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.h rename from Shower/Default/Decay_QTildeShowerKinematics1to2.h rename to Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.h --- a/Shower/Default/Decay_QTildeShowerKinematics1to2.h +++ b/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.h @@ -1,101 +1,101 @@ // -*- C++ -*- // // Decay_QTildeShowerKinematics1to2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-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_Decay_QTildeShowerKinematics1to2_H #define HERWIG_Decay_QTildeShowerKinematics1to2_H // // This is the declaration of the Decay_QTildeShowerKinematics1to2 class. // -#include "Herwig/Shower/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This (concrete) class provides the specific decay shower * kinematics information. * * @see ShowerKinematics * @see IS_QTildeShowerKinematics1to2 * @see FS_QTildeShowerKinematics1to2 * @see KinematicsReconstructor * */ class Decay_QTildeShowerKinematics1to2: public ShowerKinematics { public: /** * The updateChildren, updateParent and updateLast * members to update the values of the \f$\alpha\f$ and * \f$p_\perp\f$ variables during the shower evolution. */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. This method is used by the * ForwardShowerEvolver. * @param parent The branching particle * @param children The particles produced in the branching * @param partnerType The type of evolution partner */ virtual void updateChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType, bool massVeto) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the * KinematicsReconstructor. */ virtual void reconstructParent( const tShowerParticlePtr parent, const ParticleVector & children ) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param last The particle to update * @param mass The mass to be used, if less than zero on-shell */ virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the KinematicsReconstructor. * @param parent The parent * @param children The children * @param partnerType The type of evolution partner */ virtual void updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType) const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Decay_QTildeShowerKinematics1to2 & operator=(const Decay_QTildeShowerKinematics1to2 &); }; } #endif /* HERWIG_Decay_QTildeShowerKinematics1to2_H */ diff --git a/Shower/Default/FS_QTildeShowerKinematics1to2.cc b/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.cc rename from Shower/Default/FS_QTildeShowerKinematics1to2.cc rename to Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.cc --- a/Shower/Default/FS_QTildeShowerKinematics1to2.cc +++ b/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.cc @@ -1,200 +1,199 @@ // -*- C++ -*- // // FS_QTildeShowerKinematics1to2.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 FS_QTildeShowerKinematics1to2 class. // #include "FS_QTildeShowerKinematics1to2.h" #include "ThePEG/PDT/EnumParticles.h" -#include "Herwig/Shower/SplittingFunctions/SplittingFunction.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Utilities/Debug.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" -#include "Herwig/Shower/Base/ShowerVertex.h" +#include "Herwig/Shower/QTilde/QTildeShowerHandler.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/ShowerModel.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Base/ShowerVertex.h" using namespace Herwig; void FS_QTildeShowerKinematics1to2:: updateParameters(tShowerParticlePtr theParent, tShowerParticlePtr theChild0, tShowerParticlePtr theChild1, bool setAlpha) const { const ShowerParticle::Parameters & parent = theParent->showerParameters(); ShowerParticle::Parameters & child0 = theChild0->showerParameters(); ShowerParticle::Parameters & child1 = theChild1->showerParameters(); // determine alphas of children according to interpretation of z if ( setAlpha ) { child0.alpha = z() * parent.alpha; child1.alpha = (1.-z()) * parent.alpha; } // set the values double cphi = cos(phi()); double sphi = sin(phi()); child0.ptx = pT() * cphi + z() * parent.ptx; child0.pty = pT() * sphi + z() * parent.pty; child0.pt = sqrt( sqr(child0.ptx) + sqr(child0.pty) ); child1.ptx = -pT() * cphi + (1.-z())* parent.ptx; child1.pty = -pT() * sphi + (1.-z())* parent.pty; child1.pt = sqrt( sqr(child1.ptx) + sqr(child1.pty) ); } void FS_QTildeShowerKinematics1to2:: updateChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType, bool massVeto) const { assert(children.size()==2); // calculate the scales splittingFn()->evaluateFinalStateScales(partnerType,scale(),z(),parent, children[0],children[1]); // set the maximum virtual masses if(massVeto) { Energy2 q2 = z()*(1.-z())*sqr(scale()); IdList ids(3); ids[0] = parent->dataPtr(); ids[1] = children[0]->dataPtr(); ids[2] = children[1]->dataPtr(); const vector & virtualMasses = SudakovFormFactor()->virtualMasses(ids); if(ids[0]->id()!=ParticleID::g && ids[0]->id()!=ParticleID::gamma ) { q2 += sqr(virtualMasses[0]); } // limits on further evolution children[0]->scales().Max_Q2 = z() *(q2-sqr(virtualMasses[2])/(1.-z())); children[1]->scales().Max_Q2 = (1.-z())*(q2-sqr(virtualMasses[1])/ z() ); } // update the parameters updateParameters(parent, children[0], children[1], true); // set up the colour connections splittingFn()->colourConnection(parent,children[0],children[1],partnerType,false); // make the products children of the parent parent->addChild(children[0]); parent->addChild(children[1]); // set the momenta of the children for(ShowerParticleVector::const_iterator pit=children.begin(); pit!=children.end();++pit) { (**pit).showerBasis(parent->showerBasis(),true); (**pit).setShowerMomentum(true); } // sort out the helicity stuff - if(! ShowerHandler::currentHandler()->evolver()->correlations()) return; + if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return; SpinPtr pspin(parent->spinInfo()); - if(!pspin || !ShowerHandler::currentHandler()->evolver()->spinCorrelations() ) return; + if(!pspin || !dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations() ) return; Energy2 t = sqr(scale())*z()*(1.-z()); IdList ids; ids.push_back(parent->dataPtr()); ids.push_back(children[0]->dataPtr()); ids.push_back(children[1]->dataPtr()); // create the vertex SVertexPtr vertex(new_ptr(ShowerVertex())); // set the matrix element vertex->ME(splittingFn()->matrixElement(z(),t,ids,phi(),true)); // set the incoming particle for the vertex parent->spinInfo()->decayVertex(vertex); for(ShowerParticleVector::const_iterator pit=children.begin(); pit!=children.end();++pit) { // construct the spin info for the children (**pit).constructSpinInfo(true); // connect the spinInfo object to the vertex (*pit)->spinInfo()->productionVertex(vertex); } } void FS_QTildeShowerKinematics1to2:: reconstructParent(const tShowerParticlePtr parent, const ParticleVector & children ) const { assert(children.size() == 2); ShowerParticlePtr c1 = dynamic_ptr_cast(children[0]); ShowerParticlePtr c2 = dynamic_ptr_cast(children[1]); parent->showerParameters().beta= c1->showerParameters().beta + c2->showerParameters().beta; Lorentz5Momentum pnew = c1->momentum() + c2->momentum(); Energy2 m2 = sqr(pT())/z()/(1.-z()) + sqr(c1->mass())/z() + sqr(c2->mass())/(1.-z()); pnew.setMass(sqrt(m2)); parent->set5Momentum( pnew ); } void FS_QTildeShowerKinematics1to2::reconstructLast(const tShowerParticlePtr last, Energy mass) const { // set beta component and consequently all missing data from that, // using the nominal (i.e. PDT) mass. Energy theMass = mass > ZERO ? mass : last->data().constituentMass(); Lorentz5Momentum pVector = last->showerBasis()->pVector(); ShowerParticle::Parameters & lastParam = last->showerParameters(); Energy2 denom = 2. * lastParam.alpha * last->showerBasis()->p_dot_n(); if(abs(denom)/(sqr(pVector.e())+pVector.rho2())<1e-10) { throw KinematicsReconstructionVeto(); } lastParam.beta = ( sqr(theMass) + sqr(lastParam.pt) - sqr(lastParam.alpha) * pVector.m2() ) / denom; // set that new momentum Lorentz5Momentum newMomentum = last->showerBasis()-> sudakov2Momentum( lastParam.alpha, lastParam.beta, lastParam.ptx , lastParam.pty); newMomentum.setMass(theMass); newMomentum.rescaleEnergy(); if(last->data().stable()) { last->set5Momentum( newMomentum ); } else { last->boost(last->momentum().findBoostToCM()); last->boost(newMomentum.boostVector()); } } void FS_QTildeShowerKinematics1to2::updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type) const { IdList ids(3); ids[0] = parent->dataPtr(); ids[1] = children[0]->dataPtr(); ids[2] = children[1]->dataPtr(); const vector & virtualMasses = SudakovFormFactor()->virtualMasses(ids); if(children[0]->children().empty()) children[0]->virtualMass(virtualMasses[1]); if(children[1]->children().empty()) children[1]->virtualMass(virtualMasses[2]); // compute the new pT of the branching Energy2 pt2=sqr(z()*(1.-z()))*sqr(scale()) - sqr(children[0]->virtualMass())*(1.-z()) - sqr(children[1]->virtualMass())* z() ; if(ids[0]->id()!=ParticleID::g) pt2 += z()*(1.-z())*sqr(virtualMasses[0]); if(pt2>ZERO) { Energy2 q2 = sqr(children[0]->virtualMass())/z() + sqr(children[1]->virtualMass())/(1.-z()) + pt2/z()/(1.-z()); parent->virtualMass(sqrt(q2)); pT(sqrt(pt2)); } else { parent->virtualMass(ZERO); } } void FS_QTildeShowerKinematics1to2:: resetChildren(const tShowerParticlePtr parent, const ShowerParticleVector & children) const { updateParameters(parent, children[0], children[1], false); for(unsigned int ix=0;ixchildren().empty()) continue; ShowerParticleVector newChildren; for(unsigned int iy=0;iychildren().size();++iy) newChildren.push_back(dynamic_ptr_cast (children[ix]->children()[iy])); children[ix]->showerKinematics()->resetChildren(children[ix],newChildren); } } diff --git a/Shower/Default/FS_QTildeShowerKinematics1to2.h b/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h rename from Shower/Default/FS_QTildeShowerKinematics1to2.h rename to Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h --- a/Shower/Default/FS_QTildeShowerKinematics1to2.h +++ b/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h @@ -1,117 +1,117 @@ // -*- C++ -*- // // FS_QTildeShowerKinematics1to2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-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_FS_QTildeShowerKinematics1to2_H #define HERWIG_FS_QTildeShowerKinematics1to2_H // // This is the declaration of the FS_QTildeShowerKinematics1to2 class. // -#include "Herwig/Shower/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This (concrete) class provides the specific Final State shower * kinematics information. * * @see ShowerKinematics * @see IS_QTildeShowerKinematics1to2 * @see Decay_QTildeShowerKinematics1to2 * @see KinematicsReconstructor */ class FS_QTildeShowerKinematics1to2: public ShowerKinematics { public: /** * Default constructor */ inline FS_QTildeShowerKinematics1to2() {} /** * The updateChildren, updateParent and updateLast * members to update the values of the \f$\alpha\f$ and * \f$p_\perp\f$ variables during the shower evolution. */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. This method is used by the * ForwardShowerEvolver. * @param parent The branching particle * @param children The particles produced in the branching * @param partnerType The type of evolution partner */ private: void updateParameters(tShowerParticlePtr theParent, tShowerParticlePtr theChild0, tShowerParticlePtr theChild1, bool setAlpha) const; public: virtual void updateChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType, bool massVeto ) const; virtual void resetChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the KinematicsReconstructor. * @param parent The parent * @param children The children * @param partnerType The type of evolution partner */ virtual void updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the * KinematicsReconstructor. */ virtual void reconstructParent( const tShowerParticlePtr parent, const ParticleVector & children ) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param last The particle to update * @param mass The mass to be used, if less than zero on-shell */ virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FS_QTildeShowerKinematics1to2 & operator=(const FS_QTildeShowerKinematics1to2 &); }; } #endif /* HERWIG_FS_QTildeShowerKinematics1to2_H */ diff --git a/Shower/Default/IS_QTildeShowerKinematics1to2.cc b/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.cc rename from Shower/Default/IS_QTildeShowerKinematics1to2.cc rename to Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.cc --- a/Shower/Default/IS_QTildeShowerKinematics1to2.cc +++ b/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.cc @@ -1,151 +1,150 @@ // -*- C++ -*- // // IS_QTildeShowerKinematics1to2.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 IS_QTildeShowerKinematics1to2 class. // #include "IS_QTildeShowerKinematics1to2.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Interface/ClassDocumentation.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Utilities/Debug.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" -#include "Herwig/Shower/Base/ShowerVertex.h" +#include "Herwig/Shower/QTilde/QTildeShowerHandler.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/ShowerModel.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Base/ShowerVertex.h" #include using namespace Herwig; void IS_QTildeShowerKinematics1to2:: updateChildren( const tShowerParticlePtr theParent, const ShowerParticleVector & children, ShowerPartnerType::Type, bool massVeto) const { const ShowerParticle::Parameters & parent = theParent->showerParameters(); ShowerParticle::Parameters & child0 = children[0]->showerParameters(); ShowerParticle::Parameters & child1 = children[1]->showerParameters(); double cphi = cos(phi()); double sphi = sin(phi()); child1.alpha = (1.-z()) * parent.alpha; child1.ptx = (1.-z()) * parent.ptx - cphi * pT(); child1.pty = (1.-z()) * parent.pty - sphi * pT(); child1.pt = sqrt( sqr(child1.ptx) + sqr(child1.pty) ); // space-like child child0.alpha = parent.alpha - child1.alpha; child0.beta = parent.beta - child1.beta; child0.ptx = parent.ptx - child1.ptx; child0.pty = parent.pty - child1.pty; if(massVeto) { Energy2 q2 = (1.-z())*sqr(scale()); children[1]->scales().Max_Q2 = (1.-z())*q2/z(); } } void IS_QTildeShowerKinematics1to2:: updateParent(const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType) const { // calculate the scales splittingFn()->evaluateInitialStateScales(partnerType,scale(),z(),parent, children[0],children[1]); // set proper colour connections splittingFn()->colourConnection(parent,children[0],children[1], partnerType,true); // set proper parent/child relationships parent->addChild(children[0]); parent->addChild(children[1]); parent->x(children[0]->x()/z()); // sort out the helicity stuff // construct the spin info for parent and timelike child // temporary assignment of shower parameters to calculate correlations parent->showerParameters().alpha = parent->x(); children[1]->showerParameters().alpha = (1.-z()) * parent->x(); children[1]->showerParameters().ptx = - cos(phi()) * pT(); children[1]->showerParameters().pty = - sin(phi()) * pT(); children[1]->showerParameters().pt = pT(); parent ->showerBasis(children[0]->showerBasis(),true); children[1]->showerBasis(children[0]->showerBasis(),true); parent ->setShowerMomentum(false); children[1]->setShowerMomentum(true); - if(! ShowerHandler::currentHandler()->evolver()->correlations()) return; + if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return; SpinPtr pspin(children[0]->spinInfo()); - if(!pspin || !ShowerHandler::currentHandler()->evolver()->spinCorrelations() ) return; + if(!pspin || !dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations() ) return; // compute the matrix element for spin correlations IdList ids; ids.push_back(parent->dataPtr()); ids.push_back(children[0]->dataPtr()); ids.push_back(children[1]->dataPtr()); Energy2 t = (1.-z())*sqr(scale())/z(); // create the vertex SVertexPtr vertex(new_ptr(ShowerVertex())); // set the matrix element vertex->ME(splittingFn()->matrixElement(z(),t,ids,phi(),false)); // set the incoming particle for the vertex // (in reality the first child as going backwards) pspin->decayVertex(vertex); // construct the spin infos parent ->constructSpinInfo(false); children[1]->constructSpinInfo(true); // connect the spinInfo objects to the vertex parent ->spinInfo()->productionVertex(vertex); children[1]->spinInfo()->productionVertex(vertex); } void IS_QTildeShowerKinematics1to2:: reconstructParent(const tShowerParticlePtr parent, const ParticleVector & children ) const { PPtr c1 = children[0]; ShowerParticlePtr c2 = dynamic_ptr_cast(children[1]); ShowerParticle::Parameters & c2param = c2->showerParameters(); // get shower variables from 1st child in order to keep notation // parent->(c1, c2) clean even though the splitting was initiated // from c1. The name updateParent is still referring to the // timelike branching though. // on-shell child c2param.beta = 0.5*( sqr(c2->data().constituentMass()) + sqr(c2param.pt) ) / ( c2param.alpha * parent->showerBasis()->p_dot_n() ); Lorentz5Momentum pnew = parent->showerBasis()-> sudakov2Momentum(c2param.alpha, c2param.beta, c2param.ptx , c2param.pty); pnew.setMass(c2->data().constituentMass()); pnew.rescaleEnergy(); c2->set5Momentum( pnew ); // spacelike child Lorentz5Momentum pc1(parent->momentum() - c2->momentum()); pc1.rescaleMass(); c1->set5Momentum(pc1); } void IS_QTildeShowerKinematics1to2:: updateLast( const tShowerParticlePtr theLast,Energy px,Energy py) const { if(theLast->isFinalState()) return; Lorentz5Momentum pVector = theLast->showerBasis()->pVector(); ShowerParticle::Parameters & last = theLast->showerParameters(); Energy2 pt2 = sqr(px) + sqr(py); last.alpha = theLast->x(); last.beta = 0.5 * pt2 / last.alpha / theLast->showerBasis()->p_dot_n(); last.ptx = ZERO; last.pty = ZERO; last.pt = ZERO; // momentum Lorentz5Momentum ntemp = Lorentz5Momentum(ZERO,-pVector.vect()); double beta = 0.5 * pt2 / last.alpha / ( pVector * ntemp); Lorentz5Momentum plast = Lorentz5Momentum( (pVector.z()>ZERO ? px : -px), py, ZERO, ZERO) + theLast->x() * pVector + beta * ntemp; plast.rescaleMass(); theLast->set5Momentum(plast); } diff --git a/Shower/Default/IS_QTildeShowerKinematics1to2.h b/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h rename from Shower/Default/IS_QTildeShowerKinematics1to2.h rename to Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h --- a/Shower/Default/IS_QTildeShowerKinematics1to2.h +++ b/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h @@ -1,112 +1,112 @@ // -*- C++ -*- // // IS_QTildeShowerKinematics1to2.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-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_IS_QTildeShowerKinematics1to2_H #define HERWIG_IS_QTildeShowerKinematics1to2_H // // This is the declaration of the IS_QTildeShowerKinematics1to2 class. // -#include "Herwig/Shower/Base/ShowerKinematics.h" +#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * This (concrete) class provides the specific Intial State shower * kinematics information. * * @see ShowerKinematics * @see FS_QTildeShowerKinematics1to2 * @see Decay_QTildeShowerKinematics1to2 * @see KinematicsReconstructor */ class IS_QTildeShowerKinematics1to2: public ShowerKinematics { public: /** @name Standard constructors and destructors. */ //@{ /** * Construct in terms of the basis states */ inline IS_QTildeShowerKinematics1to2() {} //@} public: /** * The updateChildren, updateParent and updateLast * members to update the values of the \f$\alpha\f$ and * \f$p_\perp\f$ variables during the shower evolution. */ //@{ /** * Along with the showering evolution --- going forward for * time-like (forward) evolution, and going backward for space-like * (backward) evolution --- the kinematical variables of the * branching products are calculated and updated from the knowledge * of the parent kinematics. This method is used by the * ForwardShowerEvolver. * @param parent The branching particle * @param children The particles produced in the branching * @param partnerType The type of evolution partner */ virtual void updateChildren( const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType, bool massVeto) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the * KinematicsReconstructor. * @param parent The branching particle * @param children The particles produced in the branching * @param partnerType The type of evolution partner */ virtual void updateParent( const tShowerParticlePtr parent, const ShowerParticleVector & children, ShowerPartnerType::Type partnerType) const; /** * Update the parent Kinematics from the knowledge of the kinematics * of the children. This method will be used by the * KinematicsReconstructor. */ virtual void reconstructParent( const tShowerParticlePtr parent, const ParticleVector & children ) const; /** * Update the kinematical data of a particle when a reconstruction * fixpoint was found. This will highly depend on the kind of * kinematics chosen and will be defined in the inherited concrete * classes. This method will be used by the KinematicsReconstructor. * @param theLast The particle. * @param px The \f$x\f$ component of the \f$p_T\f$. * @param py The \f$y\f$ component of the \f$p_T\f$. */ virtual void updateLast(const tShowerParticlePtr theLast, Energy px, Energy py) const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IS_QTildeShowerKinematics1to2 & operator=(const IS_QTildeShowerKinematics1to2 &); }; } #endif /* HERWIG_IS_QTildeShowerKinematics1to2_H */ diff --git a/Shower/Default/QTildeFinder.cc b/Shower/QTilde/Default/QTildeFinder.cc rename from Shower/Default/QTildeFinder.cc rename to Shower/QTilde/Default/QTildeFinder.cc --- a/Shower/Default/QTildeFinder.cc +++ b/Shower/QTilde/Default/QTildeFinder.cc @@ -1,273 +1,273 @@ // -*- C++ -*- // // QTildeFinder.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 QTildeFinder class. // #include "QTildeFinder.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/EventRecord/Event.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; DescribeClass describeQTildeFinder ("Herwig::QTildeFinder","HwShower.so"); void QTildeFinder::persistentOutput(PersistentOStream & os) const { os << _finalFinalConditions << _initialFinalDecayConditions << _initialInitialConditions; } void QTildeFinder::persistentInput(PersistentIStream & is, int) { is >> _finalFinalConditions >> _initialFinalDecayConditions >>_initialInitialConditions; } void QTildeFinder::Init() { static ClassDocumentation documentation ("This class is responsible for finding the partners for each interaction types ", "and within the evolution scale range specified by the ShowerVariables ", "then to determine the initial evolution scales for each pair of partners."); static Switch interfaceFinalFinalConditions ("FinalFinalConditions", "The initial conditions for the shower of a final-final colour connection", &QTildeFinder::_finalFinalConditions, 0, false, false); static SwitchOption interfaceFinalFinalConditionsSymmetric (interfaceFinalFinalConditions, "Symmetric", "The symmetric choice", 0); static SwitchOption interfaceFinalFinalConditionsColoured (interfaceFinalFinalConditions, "Coloured", "Maximal radiation from the coloured particle", 1); static SwitchOption interfaceFinalFinalConditionsAntiColoured (interfaceFinalFinalConditions, "AntiColoured", "Maximal emission from the anticoloured particle", 2); static SwitchOption interfaceFinalFinalConditionsRandom (interfaceFinalFinalConditions, "Random", "Randomly selected maximal emission from one of the particles", 3); static Switch interfaceInitialFinalDecayConditions ("InitialFinalDecayConditions", "The initial conditions for the shower of an initial-final" " decay colour connection.", &QTildeFinder::_initialFinalDecayConditions, 0, false, false); static SwitchOption interfaceInitialFinalDecayConditionsSymmetric (interfaceInitialFinalDecayConditions, "Symmetric", "The symmetric choice", 0); static SwitchOption interfaceInitialFinalDecayConditionsMaximal (interfaceInitialFinalDecayConditions, "Maximal", "Maximal radiation from the decay product", 1); static SwitchOption interfaceInitialFinalDecayConditionsSmooth (interfaceInitialFinalDecayConditions, "Smooth", "Smooth matching in the soft limit", 2); static Switch interfaceInitialInitialConditions ("InitialInitialConditions", "The initial conditions for the shower of an initial-initial" " colour connection.", &QTildeFinder::_initialInitialConditions, 0, false, false); static SwitchOption interfaceInitialInitialConditionsSymmetric (interfaceInitialInitialConditions, "Symmetric", "The symmetric choice", 0); static SwitchOption interfaceInitialInitialConditionsMaximiseB (interfaceInitialInitialConditions, "MaximiseB", "Maximal radiation from parton b", 1); static SwitchOption interfaceInitialInitialConditionsMaximiseC (interfaceInitialInitialConditions, "MaximiseC", "Maximal radiation from parton c", 2); } pair QTildeFinder:: calculateInitialFinalScales(const ShowerPPair &ppair, const bool isDecayCase) { return calculateInitialFinalScales(ppair.first->momentum(),ppair.second->momentum(),isDecayCase); } pair QTildeFinder:: calculateInitialFinalScales(const Lorentz5Momentum& pb, const Lorentz5Momentum& pc, const bool isDecayCase) { if(!isDecayCase) { // In this case from JHEP 12(2003)045 we find the conditions // ktilde_b = (1+c) and ktilde_c = (1+2c) // We also find that c = m_c^2/Q^2. The process is a+b->c where // particle a is not colour connected (considered as a colour singlet). // Therefore we simply find that q_b = sqrt(Q^2+m_c^2) and // q_c = sqrt(Q^2+2 m_c^2) // We also assume that the first particle in the pair is the initial // state particle and the second is the final state one c Energy2 mc2 = sqr(pc.mass()); Energy2 Q2 = -(pb-pc).m2(); return pair(sqrt(Q2+mc2), sqrt(Q2+2*mc2)); } else { // In this case from JHEP 12(2003)045 we find, for the decay // process b->c+a(neutral), the condition // (ktilde_b-1)*(ktilde_c-c)=(1/4)*sqr(1-a+c+lambda). // We also assume that the first particle in the pair is the initial // state particle (b) and the second is the final state one (c). // - We find maximal phase space coverage through emissions from // c if we set ktilde_c = 4.*(sqr(1.-sqrt(a))-c) // - We find the most 'symmetric' way to populate the phase space // occurs for (ktilde_b-1)=(ktilde_c-c)=(1/2)*(1-a+c+lambda) // - We find the most 'smooth' way to populate the phase space // occurs for... Energy2 mb2(sqr(pb.mass())); double a=(pb-pc).m2()/mb2; double c=sqr(pc.mass())/mb2; double lambda = 1. + a*a + c*c - 2.*a - 2.*c - 2.*a*c; lambda = sqrt(max(lambda,0.)); double PROD = 0.25*sqr(1. - a + c + lambda); double ktilde_b, ktilde_c,cosi(0.); switch(initialFinalDecayConditions()) { case 0: // the 'symmetric' choice ktilde_c = 0.5*(1-a+c+lambda) + c ; ktilde_b = 1.+PROD/(ktilde_c-c) ; break; case 1: // the 'maximal' choice ktilde_c = 4.0*(sqr(1.-sqrt(a))-c); ktilde_b = 1.+PROD/(ktilde_c-c) ; break; case 2: // the 'smooth' choice // c is a problem if very small here use 1GeV as minimum c = max(c,1.*GeV2/mb2); cosi = (sqr(1-sqrt(c))-a)/lambda; ktilde_b = 2.0/(1.0-cosi); ktilde_c = (1.0-a+c+lambda)*(1.0+c-a-lambda*cosi)/(2.0*(1.0+cosi)); break; default: throw Exception() << "Invalid option for decay shower's phase space" << " QTildeFinder::calculateInitialFinalScales" << Exception::abortnow; } return pair(sqrt(mb2*ktilde_b),sqrt(mb2*ktilde_c)); } } pair QTildeFinder:: calculateInitialInitialScales(const ShowerPPair &ppair) { return calculateInitialInitialScales(ppair.first->momentum(), ppair.second->momentum()); } pair QTildeFinder:: calculateInitialInitialScales(const Lorentz5Momentum& p1, const Lorentz5Momentum& p2) { // This case is quite simple. From JHEP 12(2003)045 we find the condition // that ktilde_b = ktilde_c = 1. In this case we have the process // b+c->a so we need merely boost to the CM frame of the two incoming // particles and then qtilde is equal to the energy in that frame Energy Q = sqrt((p1+p2).m2()); if(_initialInitialConditions==1) { return pair(sqrt(2.0)*Q,sqrt(0.5)*Q); } else if(_initialInitialConditions==2) { return pair(sqrt(0.5)*Q,sqrt(2.0)*Q); } else { return pair(Q,Q); } } pair QTildeFinder:: calculateFinalFinalScales(const ShowerPPair & pp) { bool colouredFirst = pp.first->colourLine()&& pp.first->colourLine()==pp.second->antiColourLine(); return calculateFinalFinalScales(pp.first->momentum(),pp.second->momentum(), colouredFirst); } pair QTildeFinder:: calculateFinalFinalScales(Lorentz5Momentum p1, Lorentz5Momentum p2, bool colouredFirst) { static const double eps=1e-7; // Using JHEP 12(2003)045 we find that we need ktilde = 1/2(1+b-c+lambda) // ktilde = qtilde^2/Q^2 therefore qtilde = sqrt(ktilde*Q^2) // find momenta in rest frame of system // calculate quantities for the scales Energy2 Q2 = (p1+p2).m2(); double b = p1.mass2()/Q2; double c = p2.mass2()/Q2; if(b<0.) { if(b<-eps) { throw Exception() << "Negative Mass squared b = " << b << "in QTildeFinder::calculateFinalFinalScales()" << Exception::eventerror; } b = 0.; } if(c<0.) { if(c<-eps) { throw Exception() << "Negative Mass squared c = " << c << "in QTildeFinder::calculateFinalFinalScales()" << Exception::eventerror; } c = 0.; } // KMH & PR - 16 May 2008 - swapped lambda calculation from // double lam=2.*p1.vect().mag()/Q; to sqrt(kallen(1,b,c)), // which should be identical for p1 & p2 onshell in their COM // but in the inverse construction for the Nason method, this // was not the case, leading to misuse. double lam=sqrt((1.+sqrt(b)+sqrt(c))*(1.-sqrt(b)-sqrt(c)) *(sqrt(b)-1.-sqrt(c))*(sqrt(c)-1.-sqrt(b))); // symmetric case unsigned int iopt=finalFinalConditions(); Energy firstQ,secondQ; if(iopt==0) { firstQ = sqrt(0.5*Q2*(1.+b-c+lam)); secondQ = sqrt(0.5*Q2*(1.-b+c+lam)); } // assymetric choice else { double kappab,kappac; // calculate kappa with coloured line getting maximum if((iopt==1&&colouredFirst)|| // first particle coloured+maximal for coloured (iopt==2&&!colouredFirst)|| // first particle anticoloured+maximal for acoloured (iopt==3&&UseRandom::rndbool(0.5))) { // random choice kappab=4.*(1.-2.*sqrt(c)-b+c); kappac=c+0.25*sqr(1.-b-c+lam)/(kappab-b); } else { kappac=4.*(1.-2.*sqrt(b)-c+b); kappab=b+0.25*sqr(1.-b-c+lam)/(kappac-c); } // calculate the scales firstQ = sqrt(Q2*kappab); secondQ = sqrt(Q2*kappac); } return pair(firstQ, secondQ); } diff --git a/Shower/QTilde/Default/QTildeFinder.h b/Shower/QTilde/Default/QTildeFinder.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Default/QTildeFinder.h @@ -0,0 +1,206 @@ +// -*- C++ -*- +// +// QTildeFinder.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_QTildeFinder_H +#define HERWIG_QTildeFinder_H +// +// This is the declaration of the QTildeFinder class. +// + +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/ShowerConfig.h" +#include "ThePEG/Interface/Interfaced.h" + +namespace Herwig { +using namespace ThePEG; + +/** \ingroup Shower + * + * The QTildeFinder class is responsible for finding the partners and + * setting the initial evolution scales for the shower evolution described + * in JHEP 0312:045,2003. + * + * @see \ref QTildeFinderInterfaces "The interfaces" + * defined for QTildeFinder. + */ +class QTildeFinder: public PartnerFinder { + +public: + + /** + * The default constructor. + */ + QTildeFinder() : _finalFinalConditions(0), + _initialFinalDecayConditions(0), + _initialInitialConditions(0) {} + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +public: + + /** + * Calculate the initial evolution scales given momenta + */ + pair calculateFinalFinalScales(Lorentz5Momentum p1, Lorentz5Momentum p2, + bool colouredfirst); + + /** + * Calculate the initial evolution scales given momenta + */ + pair calculateInitialInitialScales(const Lorentz5Momentum& p1, + const Lorentz5Momentum& p2); + + /** + * Calculate the initial evolution scales given momenta + */ + pair calculateInitialFinalScales(const Lorentz5Momentum& pb, const Lorentz5Momentum& pc, + const bool isDecayCase); + +protected: + + /** + * Given a pair of particles, supposedly partners w.r.t. an interaction, + * this method returns their initial evolution scales as a pair. + * If something wrong happens, it returns the null (ZERO,ZERO) pair. + * This method is used by the above setXXXInitialEvolutionScales + * methods. + */ + //@{ + /** + * Calculate the initial evolution scales for two final-state particles + */ + virtual pair calculateFinalFinalScales(const ShowerPPair &); + + /** + * Calculate the initial evolution scales for two initial-state particles + */ + virtual pair calculateInitialInitialScales(const ShowerPPair &); + + /** + * Calculate the initial evolution scales for one initial + * and one final-state particles + */ + virtual pair calculateInitialFinalScales(const ShowerPPair &, + const bool isDecayCase); + //@} + + /** + * Access function for the initial conditions for the shower + */ + //@{ + /** + * Initial conditions for the shower of a final-final colour connection + * - 0 is the symmetric choice + * - 1 is maximal emmision from the coloured particle + * - 2 is maximal emmision from the anticoloured particle + * - 3 is randomly selected maximal emmision + */ + unsigned int finalFinalConditions() const + {return _finalFinalConditions;} + + /** + * Initial conditions for the shower of an initial-final decay colour connection + * - 0 is the symmetric choice + * - 1 is maximal emission from the decay product + * - 2 is the smooth choice + */ + unsigned int initialFinalDecayConditions() const + {return _initialFinalDecayConditions;} + //@} + +protected: + + /** @name Clone Methods. */ + //@{ + /** + * Make a simple clone of this object. + * @return a pointer to the new object. + */ + virtual IBPtr clone() const {return new_ptr(*this);} + + /** Make a clone of this object, possibly modifying the cloned object + * to make it sane. + * @return a pointer to the new object. + */ + virtual IBPtr fullclone() const {return new_ptr(*this);} + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + QTildeFinder & operator=(const QTildeFinder &); + +private: + + /** + * Flags controlling the initial conditions for the shower + */ + //@{ + /** + * Initial conditions for the shower with a final-final colour + * connection + */ + unsigned int _finalFinalConditions; + + /** + * Initial conditions for the shower with an initial-final decay colour + * connection. This is done according to the top decay colour + * connection calculation in JHEP12(2003)_045. The options act as follows: + * 0: This is the default 'symmetric' choice which more or less divides + * the phase space evenly between the parent and its charged child. + * 1: This 'maximal' choice maximises the phase space available for + * gluons emitted from the charged child. + * 2: This (experimental) 'smooth' choice does not suffer from + * a discontinuity at the boundary between the region populated by + * emissions from the charged child and the region populated by emissions + * from the parent. This does, however, mean that the phase space + * available for emissions from the charged child is fairly minimal. + */ + unsigned int _initialFinalDecayConditions; + + /** + * Initial conditions for the shower with an initial-initial colour + * connection. This is done according to the colour connection + * calculation in JHEP12(2003)_045. The options act as follows: + * 0: This is the default 'symmetric' choice which more or less divides + * the phase space evenly between the two incoming partons. + * 1: This increases the phase space for emission from "parton b". + * 2: This increases the phase space for emission from "parton c". + */ + unsigned int _initialInitialConditions; + //@} +}; + +} + +#endif /* HERWIG_QTildeFinder_H */ diff --git a/Shower/QTilde/Default/QTildeModel.cc b/Shower/QTilde/Default/QTildeModel.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Default/QTildeModel.cc @@ -0,0 +1,61 @@ +// -*- C++ -*- +// +// QTildeModel.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 QTildeModel class. +// + +#include "QTildeModel.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "QTildeReconstructor.h" +#include "QTildeFinder.h" +#include "QTildeSudakov.h" +#include "ThePEG/Utilities/Throw.h" +#include "ThePEG/Utilities/DescribeClass.h" + +using namespace Herwig; + +DescribeNoPIOClass +describeQTildeModel ("Herwig::QTildeModel","HwShower.so"); + +IBPtr QTildeModel::clone() const { + return new_ptr(*this); +} + +IBPtr QTildeModel::fullclone() const { + return new_ptr(*this); +} + +void QTildeModel::Init() { + + static ClassDocumentation documentation + ("The QTildeModel class is the ShowerModel object for the Herwig shower."); + +} + +void QTildeModel::checkConsistency() { + // check KinematicsReconstructor + if(!dynamic_ptr_cast::pointer>(kinematicsReconstructor())) + Throw() << "KinematicsReconstructor must be either " + << "QTildeKinematicsReconstructor or a class inheriting from it" + << "in QTildeModel::checkConsistency()"; + // check PartnerFinder + if(!dynamic_ptr_cast::pointer>(partnerFinder())) + Throw() << "PartnerFinder must be either " + << "QTildeFinder or a class inheriting from it" + << "in QTildeModel::checkConsistency()"; + // Sudakov form factors + vector::const_iterator sit; + for(sit=sudakovFormFactors().begin();sit!=sudakovFormFactors().end();++sit) { + if(!dynamic_ptr_cast::pointer>(*sit)) + Throw() << "SudakovFormFactors must be either " + << "QTildeSudakov or a class inheriting from it" + << "in QTildeModel::checkConsistency()"; + } +} diff --git a/Shower/Default/QTildeModel.h b/Shower/QTilde/Default/QTildeModel.h rename from Shower/Default/QTildeModel.h rename to Shower/QTilde/Default/QTildeModel.h --- a/Shower/Default/QTildeModel.h +++ b/Shower/QTilde/Default/QTildeModel.h @@ -1,77 +1,77 @@ // -*- C++ -*- // // QTildeModel.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_QTildeModel_H #define HERWIG_QTildeModel_H // // This is the declaration of the QTildeModel class. // -#include "Herwig/Shower/Base/ShowerModel.h" +#include "Herwig/Shower/QTilde/Base/ShowerModel.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * The QTildeModel class inherits from the ShowerModel class and implements the * checkConsistency member for the default Herwig Shower. * * @see \ref QTildeModelInterfaces "The interfaces" * defined for QTildeModel. */ class QTildeModel: public ShowerModel { public: /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * The implementation of the virtual member from the base class to * check that the correct objects are loaded */ virtual void checkConsistency(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeModel & operator=(const QTildeModel &); }; } #endif /* HERWIG_QTildeModel_H */ diff --git a/Shower/Default/QTildeReconstructor.cc b/Shower/QTilde/Default/QTildeReconstructor.cc rename from Shower/Default/QTildeReconstructor.cc rename to Shower/QTilde/Default/QTildeReconstructor.cc --- a/Shower/Default/QTildeReconstructor.cc +++ b/Shower/QTilde/Default/QTildeReconstructor.cc @@ -1,2938 +1,2923 @@ // -*- C++ -*- // // QTildeReconstructor.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 QTildeReconstructor class. // #include "QTildeReconstructor.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" -#include "Herwig/Shower/Base/Evolver.h" -#include "Herwig/Shower/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "Herwig/Shower/SplittingFunctions/SplittingFunction.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/EventRecord/ColourLine.h" #include "ThePEG/Utilities/DescribeClass.h" +#include "Herwig/Shower/QTilde/QTildeShowerHandler.h" #include using namespace Herwig; DescribeClass describeQTildeReconstructor("Herwig::QTildeReconstructor", "HwShower.so"); namespace { /** * Struct to order the jets in off-shellness */ struct JetOrdering { bool operator() (const JetKinStruct & j1, const JetKinStruct & j2) { Energy diff1 = j1.q.m()-j1.p.m(); Energy diff2 = j2.q.m()-j2.p.m(); if(diff1!=diff2) { return diff1>diff2; } else if( j1.q.e() != j2.q.e() ) return j1.q.e()>j2.q.e(); else return j1.parent->uniqueId>j2.parent->uniqueId; } }; } void QTildeReconstructor::persistentOutput(PersistentOStream & os) const { os << _reconopt << _initialBoost << ounit(_minQ,GeV) << _noRescale << _noRescaleVector << _finalStateReconOption << _initialStateReconOption; } void QTildeReconstructor::persistentInput(PersistentIStream & is, int) { is >> _reconopt >> _initialBoost >> iunit(_minQ,GeV) >> _noRescale >> _noRescaleVector >> _finalStateReconOption >> _initialStateReconOption; } void QTildeReconstructor::Init() { static ClassDocumentation documentation ( "This class is responsible for the kinematics reconstruction of the showering,", " including the kinematics reshuffling necessary to compensate for the recoil" "of the emissions." ); static Switch interfaceReconstructionOption ("ReconstructionOption", "Option for the kinematics reconstruction", &QTildeReconstructor::_reconopt, 0, false, false); static SwitchOption interfaceReconstructionOptionGeneral (interfaceReconstructionOption, "General", "Use the general solution which ignores the colour structure for all processes", 0); static SwitchOption interfaceReconstructionOptionColour (interfaceReconstructionOption, "Colour", "Use the colour structure of the process to determine the reconstruction procedure.", 1); static SwitchOption interfaceReconstructionOptionColour2 (interfaceReconstructionOption, "Colour2", "Make the most use possible of the colour structure of the process to determine the reconstruction procedure. " "Start with FF, then IF then II colour connections", 2); static SwitchOption interfaceReconstructionOptionColour3 (interfaceReconstructionOption, "Colour3", "Make the most use possible of the colour structure of the process to determine the reconstruction procedure. " "Do the colour connections in order of the pT's emitted in the shower starting with the hardest." " The colour partner is fully reconstructed at the same time.", 3); static SwitchOption interfaceReconstructionOptionColour4 (interfaceReconstructionOption, "Colour4", "Make the most use possible of the colour structure of the process to determine the reconstruction procedure. " "Do the colour connections in order of the pT's emitted in the shower starting with the hardest, while leaving" " the colour partner on mass-shell", 4); static Parameter interfaceMinimumQ2 ("MinimumQ2", "The minimum Q2 for the reconstruction of initial-final systems", &QTildeReconstructor::_minQ, GeV, 0.001*GeV, 1e-6*GeV, 10.0*GeV, false, false, Interface::limited); static RefVector interfaceNoRescale ("NoRescale", "Particles which shouldn't be rescaled to be on shell by the shower", &QTildeReconstructor::_noRescaleVector, -1, false, false, true, false, false); static Switch interfaceInitialInitialBoostOption ("InitialInitialBoostOption", "Option for how the boost from the system before ISR to that after ISR is applied.", &QTildeReconstructor::_initialBoost, 0, false, false); static SwitchOption interfaceInitialInitialBoostOptionOneBoost (interfaceInitialInitialBoostOption, "OneBoost", "Apply one boost from old CMS to new CMS", 0); static SwitchOption interfaceInitialInitialBoostOptionLongTransBoost (interfaceInitialInitialBoostOption, "LongTransBoost", "First apply a longitudinal and then a transverse boost", 1); static Switch interfaceFinalStateReconOption ("FinalStateReconOption", "Option for how to reconstruct the momenta of the final-state system", &QTildeReconstructor::_finalStateReconOption, 0, false, false); static SwitchOption interfaceFinalStateReconOptionDefault (interfaceFinalStateReconOption, "Default", "All the momenta are rescaled in the rest frame", 0); static SwitchOption interfaceFinalStateReconOptionMostOffShell (interfaceFinalStateReconOption, "MostOffShell", "All particles put on the new-mass shell and then the most off-shell and" " recoiling system are rescaled to ensure 4-momentum is conserved.", 1); static SwitchOption interfaceFinalStateReconOptionRecursive (interfaceFinalStateReconOption, "Recursive", "Recursively put on shell by putting the most off-shell particle which" " hasn't been rescaled on-shell by rescaling the particles and the recoiling system. ", 2); static SwitchOption interfaceFinalStateReconOptionRestMostOffShell (interfaceFinalStateReconOption, "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.", 3); static SwitchOption interfaceFinalStateReconOptionRestRecursive (interfaceFinalStateReconOption, "RestRecursive", "As 3 but recursive treated the currently most-off shell," " only makes a difference if more than 3 partons.", 4); static Switch interfaceInitialStateReconOption ("InitialStateReconOption", "Option for the reconstruction of initial state radiation", &QTildeReconstructor::_initialStateReconOption, 0, false, false); static SwitchOption interfaceInitialStateReconOptionRapidity (interfaceInitialStateReconOption, "Rapidity", "Preserve shat and rapidity", 0); static SwitchOption interfaceInitialStateReconOptionLongitudinal (interfaceInitialStateReconOption, "Longitudinal", "Preserve longitudinal momentum", 1); static SwitchOption interfaceInitialStateReconOptionSofterFraction (interfaceInitialStateReconOption, "SofterFraction", "Preserve the momentum fraction of the parton which has emitted softer.", 2); } void QTildeReconstructor::doinit() { KinematicsReconstructor::doinit(); _noRescale = set(_noRescaleVector.begin(),_noRescaleVector.end()); } bool QTildeReconstructor:: reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent) const { assert(particleJetParent); bool emitted=true; // if this is not a fixed point in the reconstruction if( !particleJetParent->children().empty() ) { // if not a reconstruction fixpoint, dig deeper for all children: for ( ParticleVector::const_iterator cit = particleJetParent->children().begin(); cit != particleJetParent->children().end(); ++cit ) reconstructTimeLikeJet(dynamic_ptr_cast(*cit)); } // it is a reconstruction fixpoint, ie kinematical data has to be available else { // check if the parent was part of the shower ShowerParticlePtr jetGrandParent; if(!particleJetParent->parents().empty()) jetGrandParent= dynamic_ptr_cast (particleJetParent->parents()[0]); // update if so if (jetGrandParent) { if (jetGrandParent->showerKinematics()) { if(particleJetParent->id()==_progenitor->id()&& !_progenitor->data().stable()) { jetGrandParent->showerKinematics()->reconstructLast(particleJetParent, _progenitor->mass()); } else { jetGrandParent->showerKinematics()->reconstructLast(particleJetParent); } } } // otherwise else { Energy dm = particleJetParent->data().constituentMass(); if (abs(dm-particleJetParent->momentum().m())>0.001*MeV &&particleJetParent->dataPtr()->stable() &&particleJetParent->id()!=ParticleID::gamma &&_noRescale.find(particleJetParent->dataPtr())==_noRescale.end()) { Lorentz5Momentum dum = particleJetParent->momentum(); dum.setMass(dm); dum.rescaleEnergy(); particleJetParent->set5Momentum(dum); } else { emitted=false; } } } // recursion has reached an endpoint once, ie we can reconstruct the // kinematics from the children. if( !particleJetParent->children().empty() ) particleJetParent->showerKinematics() ->reconstructParent( particleJetParent, particleJetParent->children() ); return emitted; } bool QTildeReconstructor:: reconstructHardJets(ShowerTreePtr hard, const map > & intrinsic, ShowerInteraction::Type type, bool switchRecon) const { _currentTree = hard; _intrinsic=intrinsic; // extract the particles from the ShowerTree vector ShowerHardJets=hard->extractProgenitors(); for(unsigned int ix=0;ixprogenitor()] = vector(); } for(map >::const_iterator tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { _treeBoosts[tit->first] = vector(); } try { // old recon method, using new member functions if(_reconopt == 0 || switchRecon ) { reconstructGeneralSystem(ShowerHardJets); } // reconstruction based on coloured systems else if( _reconopt == 1) { reconstructColourSinglets(ShowerHardJets,type); } // reconstruction of FF, then IF, then II else if( _reconopt == 2) { reconstructFinalFirst(ShowerHardJets); } // reconstruction based on coloured systems else if( _reconopt == 3 || _reconopt == 4) { reconstructColourPartner(ShowerHardJets); } else assert(false); } catch(KinematicsReconstructionVeto) { _progenitor=tShowerParticlePtr(); _intrinsic.clear(); for(map >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot); } } _boosts.clear(); for(map >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot,false); } } _currentTree = tShowerTreePtr(); _treeBoosts.clear(); return false; } catch (Exception & ex) { _progenitor=tShowerParticlePtr(); _intrinsic.clear(); _currentTree = tShowerTreePtr(); _boosts.clear(); _treeBoosts.clear(); throw ex; } _progenitor=tShowerParticlePtr(); _intrinsic.clear(); // ensure x<1 for(map::const_iterator cit=hard->incomingLines().begin();cit!=hard->incomingLines().end();++cit) { tPPtr parent = cit->first->progenitor(); while (!parent->parents().empty()) { parent = parent->parents()[0]; } tPPtr hadron; if ( cit->first->original()->parents().empty() ) { hadron = cit->first->original(); } else { hadron = cit->first->original()->parents()[0]; } if( ! (hadron->id() == parent->id() && hadron->children().size() <= 1) && parent->momentum().rho() > hadron->momentum().rho()) { _progenitor=tShowerParticlePtr(); _intrinsic.clear(); for(map >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot); } } _boosts.clear(); for(map >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot,false); } } _currentTree = tShowerTreePtr(); _treeBoosts.clear(); return false; } } _boosts.clear(); _treeBoosts.clear(); _currentTree = tShowerTreePtr(); return true; } double QTildeReconstructor::solveKfactor(const Energy & root_s, const JetKinVect & jets) const { Energy2 s = sqr(root_s); // must be at least two jets if ( jets.size() < 2) throw KinematicsReconstructionVeto(); // sum of jet masses must be less than roots if(momConsEq( 0.0, root_s, jets )>ZERO) throw KinematicsReconstructionVeto(); // if two jets simple solution if ( jets.size() == 2 ) { static const Energy2 eps = 1.0e-4 * MeV2; if ( sqr(jets[0].p.x()+jets[1].p.x()) < eps && sqr(jets[0].p.y()+jets[1].p.y()) < eps && sqr(jets[0].p.z()+jets[1].p.z()) < eps ) { Energy test = (jets[0].p+jets[1].p).vect().mag(); if(test > 1.0e-4 * MeV) throw KinematicsReconstructionVeto(); if ( jets[0].p.vect().mag2() < eps ) throw KinematicsReconstructionVeto(); Energy2 m1sq(jets[0].q.m2()),m2sq(jets[1].q.m2()); return sqrt( ( sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq ) /(4.*s*jets[0].p.vect().mag2()) ); } else throw KinematicsReconstructionVeto(); } // i.e. jets.size() > 2, numerically // check convergence, if it's a problem maybe use Newton iteration? else { double k1 = 0.,k2 = 1.,k = 0.; if ( momConsEq( k1, root_s, jets ) < ZERO ) { while ( momConsEq( k2, root_s, jets ) < ZERO ) { k1 = k2; k2 *= 2; } while ( fabs( (k1 - k2)/(k1 + k2) ) > 1.e-10 ) { if( momConsEq( k2, root_s, jets ) == ZERO ) { return k2; } else { k = (k1+k2)/2.; if ( momConsEq( k, root_s, jets ) > ZERO ) { k2 = k; } else { k1 = k; } } } return k1; } else throw KinematicsReconstructionVeto(); } throw KinematicsReconstructionVeto(); } bool QTildeReconstructor:: reconstructSpaceLikeJet( const tShowerParticlePtr p) const { bool emitted = true; tShowerParticlePtr child; tShowerParticlePtr parent; if(!p->parents().empty()) parent = dynamic_ptr_cast(p->parents()[0]); if(parent) { emitted=true; reconstructSpaceLikeJet(parent); } // if branching reconstruct time-like child if(p->children().size()==2) child = dynamic_ptr_cast(p->children()[1]); if(p->perturbative()==0 && child) { dynamic_ptr_cast(p->children()[0])-> showerKinematics()->reconstructParent(p,p->children()); if(!child->children().empty()) { _progenitor=child; reconstructTimeLikeJet(child); // calculate the momentum of the particle Lorentz5Momentum pnew=p->momentum()-child->momentum(); pnew.rescaleMass(); p->children()[0]->set5Momentum(pnew); } } return emitted; } Boost QTildeReconstructor:: solveBoostBeta( const double k, const Lorentz5Momentum & newq, const Lorentz5Momentum & oldp ) { // try something different, purely numerical first: // a) boost to rest frame of newq, b) boost with kp/E Energy q = newq.vect().mag(); Energy2 qs = sqr(q); Energy2 Q2 = newq.m2(); Energy kp = k*(oldp.vect().mag()); Energy2 kps = sqr(kp); // usually we take the minus sign, since this boost will be smaller. // we only require |k \vec p| = |\vec q'| which leaves the sign of // the boost open but the 'minus' solution gives a smaller boost // parameter, i.e. the result should be closest to the previous // result. this is to be changed if we would get many momentum // conservation violations at the end of the shower from a hard // process. double betam = (q*sqrt(qs + Q2) - kp*sqrt(kps + Q2))/(kps + qs + Q2); // move directly to 'return' Boost beta = -betam*(k/kp)*oldp.vect(); // note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper. // leave this out if it's running properly! if ( betam >= 0 ) return beta; else return Boost(0., 0., 0.); } bool QTildeReconstructor:: reconstructDecayJets(ShowerTreePtr decay, ShowerInteraction::Type) const { _currentTree = decay; // extract the particles from the ShowerTree vector ShowerHardJets=decay->extractProgenitors(); for(unsigned int ix=0;ixprogenitor()] = vector(); } for(map >::const_iterator tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { _treeBoosts[tit->first] = vector(); } try { bool radiated[2]={false,false}; // find the decaying particle and check if particles radiated ShowerProgenitorPtr initial; for(unsigned int ix=0;ixprogenitor()->isFinalState()) { radiated[1] |=ShowerHardJets[ix]->hasEmitted(); } else { initial=ShowerHardJets[ix]; radiated[0]|=ShowerHardJets[ix]->hasEmitted(); } } // find boost to the rest frame if needed Boost boosttorest=-initial->progenitor()->momentum().boostVector(); double gammarest = initial->progenitor()->momentum().e()/ initial->progenitor()->momentum().mass(); // check if need to boost to rest frame bool gottaBoost = (boosttorest.mag() > 1e-12); // if initial state radiation reconstruct the jet and set up the basis vectors Lorentz5Momentum pjet; Lorentz5Momentum nvect; // find the partner ShowerParticlePtr partner = initial->progenitor()->partner(); Lorentz5Momentum ppartner[2]; if(partner) ppartner[0]=partner->momentum(); // get the n reference vector if(partner) { if(initial->progenitor()->showerKinematics()) { nvect = initial->progenitor()->showerBasis()->getBasis()[1]; } else { Lorentz5Momentum ppartner=initial->progenitor()->partner()->momentum(); if(gottaBoost) ppartner.boost(boosttorest,gammarest); nvect = Lorentz5Momentum( ZERO,0.5*initial->progenitor()->mass()* ppartner.vect().unit()); nvect.boost(-boosttorest,gammarest); } } // if ISR if(radiated[0]) { // reconstruct the decay jet reconstructDecayJet(initial->progenitor()); // momentum of decaying particle after ISR pjet=initial->progenitor()->momentum() -decay->incomingLines().begin()->second->momentum(); pjet.rescaleMass(); } // boost initial state jet and basis vector if needed if(gottaBoost) { pjet.boost(boosttorest,gammarest); nvect.boost(boosttorest,gammarest); ppartner[0].boost(boosttorest,gammarest); } // loop over the final-state particles and do the reconstruction JetKinVect possiblepartners; JetKinVect jetKinematics; bool atLeastOnce = radiated[0]; LorentzRotation restboost(boosttorest,gammarest); Energy inmass(ZERO); for(unsigned int ix=0;ixprogenitor()->isFinalState()) { inmass=ShowerHardJets[ix]->progenitor()->mass(); continue; } // do the reconstruction JetKinStruct tempJetKin; tempJetKin.parent = ShowerHardJets[ix]->progenitor(); if(ShowerHardJets.size()==2) { Lorentz5Momentum dum=ShowerHardJets[ix]->progenitor()->momentum(); dum.setMass(inmass); dum.rescaleRho(); tempJetKin.parent->set5Momentum(dum); } tempJetKin.p = ShowerHardJets[ix]->progenitor()->momentum(); if(gottaBoost) tempJetKin.p.boost(boosttorest,gammarest); _progenitor=tempJetKin.parent; if(ShowerHardJets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) { atLeastOnce |= reconstructTimeLikeJet(tempJetKin.parent); ShowerHardJets[ix]->reconstructed(ShowerProgenitor::done); } if(gottaBoost) deepTransform(tempJetKin.parent,restboost); tempJetKin.q = ShowerHardJets[ix]->progenitor()->momentum(); jetKinematics.push_back(tempJetKin); } if(partner) ppartner[1]=partner->momentum(); // calculate the rescaling parameters double k1,k2; Lorentz5Momentum qt; if(!solveDecayKFactor(initial->progenitor()->mass(),nvect,pjet, jetKinematics,partner,ppartner,k1,k2,qt)) { for(map >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot); } } _boosts.clear(); for(map >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot,false); } } _treeBoosts.clear(); _currentTree = tShowerTreePtr(); return false; } // apply boosts and rescalings to final-state jets for(JetKinVect::iterator it = jetKinematics.begin(); it != jetKinematics.end(); ++it) { LorentzRotation Trafo = LorentzRotation(); if(it->parent!=partner) { // boost for rescaling if(atLeastOnce) { map >::const_iterator tit; for(tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { if(tit->second.first && tit->second.second==it->parent) break; } if(it->parent->children().empty()&&!it->parent->spinInfo() && tit==_currentTree->treelinks().end()) { Lorentz5Momentum pnew(k2*it->p.vect(), sqrt(sqr(k2*it->p.vect().mag())+it->q.mass2()), it->q.mass()); it->parent->set5Momentum(pnew); } else { // rescaling boost can't ever work in this case if(k2<0. && it->q.mass()==ZERO) throw KinematicsReconstructionVeto(); Trafo = solveBoost(k2, it->q, it->p); } } if(gottaBoost) Trafo.boost(-boosttorest,gammarest); if(atLeastOnce || gottaBoost) deepTransform(it->parent,Trafo); } else { Lorentz5Momentum pnew=ppartner[0]; pnew *=k1; pnew-=qt; pnew.setMass(ppartner[1].mass()); pnew.rescaleEnergy(); LorentzRotation Trafo=solveBoost(1.,ppartner[1],pnew); if(gottaBoost) Trafo.boost(-boosttorest,gammarest); deepTransform(partner,Trafo); } } } catch(KinematicsReconstructionVeto) { for(map >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot); } } _boosts.clear(); for(map >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) { for(vector::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) { LorentzRotation rot = rit->inverse(); bit->first->transform(rot,false); } } _treeBoosts.clear(); _currentTree = tShowerTreePtr(); return false; } catch (Exception & ex) { _currentTree = tShowerTreePtr(); _boosts.clear(); _treeBoosts.clear(); throw ex; } _boosts.clear(); _treeBoosts.clear(); _currentTree = tShowerTreePtr(); return true; } bool QTildeReconstructor:: reconstructDecayJet( const tShowerParticlePtr p) const { if(p->children().empty()) return false; tShowerParticlePtr child; // if branching reconstruct time-like child child = dynamic_ptr_cast(p->children()[1]); if(child) { _progenitor=child; reconstructTimeLikeJet(child); // calculate the momentum of the particle Lorentz5Momentum pnew=p->momentum()-child->momentum(); pnew.rescaleMass(); p->children()[0]->set5Momentum(pnew); child=dynamic_ptr_cast(p->children()[0]); reconstructDecayJet(child); return true; } return false; } bool QTildeReconstructor:: solveDecayKFactor(Energy mb, const Lorentz5Momentum & n, const Lorentz5Momentum & pjet, const JetKinVect & jetKinematics, ShowerParticlePtr partner, Lorentz5Momentum ppartner[2], double & k1, double & k2, Lorentz5Momentum & qt) const { Energy2 pjn = partner ? pjet.vect()*n.vect() : ZERO; Energy2 pcn = partner ? ppartner[0].vect()*n.vect() : 1.*MeV2; Energy2 nmag = n.vect().mag2(); Lorentz5Momentum pn = partner ? (pjn/nmag)*n : Lorentz5Momentum(); qt=pjet-pn; qt.setE(ZERO); Energy2 pt2=qt.vect().mag2(); Energy Ejet = pjet.e(); // magnitudes of the momenta for fast access vector pmag; Energy total(Ejet); for(unsigned int ix=0;ixmb) return false; Energy2 pcmag=ppartner[0].vect().mag2(); // used newton-raphson to get the rescaling static const Energy eps=1e-8*GeV; long double d1(1.),d2(1.); Energy roots, ea, ec, ds; unsigned int ix=0; do { ++ix; d2 = d1 + pjn/pcn; roots = Ejet; ds = ZERO; for(unsigned int iy=0;iyeps && ix<100); k1=d1; k2=d2; // return true if N-R succeed, otherwise false return ix<100; } bool QTildeReconstructor:: -deconstructDecayJets(HardTreePtr decay, cEvolverPtr, - ShowerInteraction::Type) const { +deconstructDecayJets(HardTreePtr decay,ShowerInteraction::Type) const { // extract the momenta of the particles vector pin; vector pout; // on-shell masses of the decay products vector mon; Energy mbar(-GeV); // the hard branchings of the particles set::iterator cit; set branchings=decay->branchings(); // properties of the incoming particle bool ISR = false; HardBranchingPtr initial; Lorentz5Momentum qisr; // find the incoming particle, both before and after // any ISR for(cit=branchings.begin();cit!=branchings.end();++cit){ if((*cit)->status()==HardBranching::Incoming|| (*cit)->status()==HardBranching::Decay) { // search back up isr if needed HardBranchingPtr branch = *cit; while(branch->parent()) branch=branch->parent(); initial=branch; // momentum or original parent pin.push_back(branch->branchingParticle()->momentum()); // ISR? ISR = !branch->branchingParticle()->children().empty(); // ISR momentum qisr = pin.back()-(**cit).branchingParticle()->momentum(); qisr.rescaleMass(); } } assert(pin.size()==1); // compute boost to rest frame Boost boostv=-pin[0].boostVector(); // partner for ISR ShowerParticlePtr partner; Lorentz5Momentum ppartner; if(initial->branchingParticle()->partner()) { partner=initial->branchingParticle()->partner(); ppartner=partner->momentum(); } // momentum of the decay products for(cit=branchings.begin();cit!=branchings.end();++cit) { if((*cit)->status()!=HardBranching::Outgoing) continue; // find the mass of the particle // including special treatment for off-shell resonances // to preserve off-shell mass Energy mass; if(!(**cit).branchingParticle()->dataPtr()->stable()) { HardBranchingPtr branch=*cit; while(!branch->children().empty()) { for(unsigned int ix=0;ixchildren().size();++ix) { if(branch->children()[ix]->branchingParticle()->id()== (**cit).branchingParticle()->id()) { branch = branch->children()[ix]; continue; } } }; mass = branch->branchingParticle()->mass(); } else { mass = (**cit).branchingParticle()->dataPtr()->mass(); } // if not evolution partner of decaying particle if((*cit)->branchingParticle()!=partner) { pout.push_back((*cit)->branchingParticle()->momentum()); mon.push_back(mass); } // evolution partner of decaying particle else { mbar = mass; } } // boost all the momenta to the rest frame of the decaying particle for(unsigned int ix=0;ixbranchingParticle()->partner()) { ppartner.boost(boostv); qisr.boost(boostv); } // compute the rescaling factors double k1,k2; if(!ISR) { if(partner) { pout.push_back(ppartner); mon.push_back(mbar); } k1=k2=inverseRescalingFactor(pout,mon,pin[0].mass()); if(partner) { pout.pop_back(); mon.pop_back(); } } else { if(!inverseDecayRescalingFactor(pout,mon,pin[0].mass(), ppartner,mbar,k1,k2)) return false; } // now calculate the p reference vectors unsigned int ifinal=0; for(cit=branchings.begin();cit!=branchings.end();++cit) { if((**cit).status()!=HardBranching::Outgoing) continue; // for partners other than colour partner of decaying particle if((*cit)->branchingParticle()!=partner) { Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum(); pvect.boost(boostv); pvect /= k1; pvect.setMass(mon[ifinal]); ++ifinal; pvect.rescaleEnergy(); pvect.boost(-boostv); (*cit)->pVector(pvect); (*cit)->showerMomentum(pvect); } // for colour partner of decaying particle else { Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum(); pvect.boost(boostv); Lorentz5Momentum qtotal; for(unsigned int ix=0;ixpVector(pvect); (*cit)->showerMomentum(pvect); } } -// // find the evolution partners -// ShowerParticleVector particles; -// particles.push_back((**decay->incoming().begin()).branchingParticle()); -// for(cit=branchings.begin();cit!=branchings.end();++cit) { -// if((**cit).status()==HardBranching::Outgoing) -// particles.push_back((*cit)->branchingParticle()); -// } -// // partners should -// evolver->showerModel()->partnerFinder() -// ->setInitialEvolutionScales(particles,true,type,false); // For initial-state if needed if(initial) { tShowerParticlePtr newPartner=initial->branchingParticle()->partner(); if(newPartner) { tHardBranchingPtr branch; for( set::iterator clt = branchings.begin(); clt != branchings.end(); ++clt ) { if((**clt).branchingParticle()==newPartner) { initial->colourPartner(*clt); branch=*clt; break; } } Lorentz5Momentum pvect = initial->branchingParticle()->momentum(); initial->pVector(pvect); Lorentz5Momentum ptemp = branch->pVector(); ptemp.boost(boostv); Lorentz5Momentum nvect = Lorentz5Momentum( ZERO, 0.5*initial->branchingParticle()->mass()* ptemp.vect().unit()); nvect.boost(-boostv); initial->nVector(nvect); } } // calculate the reference vectors, then for outgoing particles for(cit=branchings.begin();cit!=branchings.end();++cit){ if((**cit).status()!=HardBranching::Outgoing) continue; // find the partner branchings tShowerParticlePtr newPartner=(*cit)->branchingParticle()->partner(); if(!newPartner) continue; tHardBranchingPtr branch; for( set::iterator clt = branchings.begin(); clt != branchings.end(); ++clt ) { if(cit==clt) continue; if((**clt).branchingParticle()==newPartner) { (**cit).colourPartner(*clt); branch=*clt; break; } } if((**decay->incoming().begin()).branchingParticle()==newPartner) { (**cit).colourPartner(*decay->incoming().begin()); branch = *decay->incoming().begin(); } // final-state colour partner if(branch->status()==HardBranching::Outgoing) { Boost boost=((*cit)->pVector()+branch->pVector()).findBoostToCM(); Lorentz5Momentum pcm = branch->pVector(); pcm.boost(boost); Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect()); nvect.boost( -boost); (*cit)->nVector(nvect); } // initial-state colour partner else { Boost boost=branch->pVector().findBoostToCM(); Lorentz5Momentum pcm = (*cit)->pVector(); pcm.boost(boost); Lorentz5Momentum nvect = Lorentz5Momentum( ZERO, -pcm.vect()); nvect.boost( -boost); (*cit)->nVector(nvect); } } // now compute the new momenta // and calculate the shower variables for(cit=branchings.begin();cit!=branchings.end();++cit) { if((**cit).status()!=HardBranching::Outgoing) continue; LorentzRotation B=LorentzRotation(-boostv); LorentzRotation A=LorentzRotation(boostv),R; if((*cit)->branchingParticle()==partner) { Lorentz5Momentum qnew; Energy2 dot=(*cit)->pVector()*(*cit)->nVector(); double beta = 0.5*((*cit)->branchingParticle()->momentum().m2() -sqr((*cit)->pVector().mass()))/dot; qnew=(*cit)->pVector()+beta*(*cit)->nVector(); qnew.rescaleMass(); // compute the boost R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A; } else { Lorentz5Momentum qnew; if((*cit)->branchingParticle()->partner()) { Energy2 dot=(*cit)->pVector()*(*cit)->nVector(); double beta = 0.5*((*cit)->branchingParticle()->momentum().m2() -sqr((*cit)->pVector().mass()))/dot; qnew=(*cit)->pVector()+beta*(*cit)->nVector(); qnew.rescaleMass(); } else { qnew = (*cit)->pVector(); } // compute the boost R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A; } // reconstruct the momenta (*cit)->setMomenta(R,1.0,Lorentz5Momentum()); } if(initial) { initial->setMomenta(LorentzRotation(),1.0,Lorentz5Momentum()); } return true; } double QTildeReconstructor:: inverseRescalingFactor(vector pout, vector mon, Energy roots) const { double lambda=1.; if(pout.size()==2) { double mu_q1(pout[0].m()/roots), mu_q2(pout[1].m()/roots); double mu_p1(mon[0]/roots) , mu_p2(mon[1]/roots); lambda = ((1.+mu_q1+mu_q2)*(1.-mu_q1-mu_q2)*(mu_q1-1.-mu_q2)*(mu_q2-1.-mu_q1))/ ((1.+mu_p1+mu_p2)*(1.-mu_p1-mu_p2)*(mu_p1-1.-mu_p2)*(mu_p2-1.-mu_p1)); if(lambda<0.) throw Exception() << "Rescaling factor is imaginary in QTildeReconstructor::" << "inverseRescalingFactor lambda^2= " << lambda << Exception::eventerror; lambda = sqrt(lambda); } else { unsigned int ntry=0; // compute magnitudes once for speed vector pmag; for(unsigned int ix=0;ix root(pout.size()); do { // compute new energies Energy sum(ZERO); for(unsigned int ix=0;ix::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) in .jets.push_back(*it); else out.jets.push_back(*it); } LorentzRotation toRest,fromRest; bool applyBoost(false); // do the initial-state reconstruction deconstructInitialInitialSystem(applyBoost,toRest,fromRest, tree,in.jets,type); // do the final-state reconstruction deconstructFinalStateSystem(toRest,fromRest,tree, - out.jets,evolver,type); + out.jets,type); // only at this point that we can be sure all the reference vectors // are correct for(set::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) continue; if((**it).branchingParticle()->coloured()) (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } for(set::const_iterator it=tree->incoming().begin(); it!=tree->incoming().end();++it) { (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } return true; } bool QTildeReconstructor::deconstructHardJets(HardTreePtr tree, - cEvolverPtr evolver, ShowerInteraction::Type type) const { // inverse of old recon method if(_reconopt == 0) { - return deconstructGeneralSystem(tree,evolver,type); + return deconstructGeneralSystem(tree,type); } else if(_reconopt == 1) { - return deconstructColourSinglets(tree,evolver,type); + return deconstructColourSinglets(tree,type); } else if(_reconopt == 2) { throw Exception() << "Inverse reconstruction is not currently supported for ReconstructionOption Colour2 " << "in QTildeReconstructor::deconstructHardJets(). Please use one of the other options\n" << Exception::runerror; } else if(_reconopt == 3 || _reconopt == 4 ) { - return deconstructColourPartner(tree,evolver,type); + return deconstructColourPartner(tree,type); } else assert(false); } bool QTildeReconstructor:: -deconstructColourSinglets(HardTreePtr tree,cEvolverPtr evolver, - ShowerInteraction::Type type) const { +deconstructColourSinglets(HardTreePtr tree, + ShowerInteraction::Type type) const { // identify the colour singlet systems unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0); vector systems(identifySystems(tree->branchings(),nnun,nnii,nnif,nnf,nni)); // now decide what to do LorentzRotation toRest,fromRest; bool applyBoost(false); bool general(false); // initial-initial connection and final-state colour singlet systems // Drell-Yan type if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) { // reconstruct initial-initial system for(unsigned int ix=0;ix0&&nni==1)|| (nnif==2&& nni==0))) { for(unsigned int ix=0;ix0&&nni==2) { // only FS needed // but need to boost to rest frame if QED ISR Lorentz5Momentum ptotal; for(unsigned int ix=0;ixbranchingParticle()->momentum(); } toRest = LorentzRotation(ptotal.findBoostToCM()); fromRest = toRest; fromRest.invert(); if(type!=ShowerInteraction::QCD) { combineFinalState(systems); general=false; } } // general type else { general = true; } // final-state systems except for general recon if(!general) { for(unsigned int ix=0;ix::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) continue; if((**it).branchingParticle()->coloured()) (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } for(set::const_iterator it=tree->incoming().begin(); it!=tree->incoming().end();++it) { (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } return true; } else { - return deconstructGeneralSystem(tree,evolver,type); + return deconstructGeneralSystem(tree,type); } return true; } bool QTildeReconstructor:: -deconstructColourPartner(HardTreePtr tree,cEvolverPtr evolver, +deconstructColourPartner(HardTreePtr tree, ShowerInteraction::Type type) const { Lorentz5Momentum ptotal; HardBranchingPtr emitter; ColourSingletShower incomingShower,outgoingShower; for(set::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) { incomingShower.jets.push_back(*it); ptotal += (*it)->branchingParticle()->momentum(); // check for emitting particle if((**it).parent() ) { if(!emitter) emitter = *it; else throw Exception() << "Only one emitting particle allowed in " << "QTildeReconstructor::deconstructColourPartner()" << Exception::runerror; } } else if ((**it).status()==HardBranching::Outgoing) { outgoingShower.jets.push_back(*it); // check for emitting particle if(!(**it).children().empty() ) { if(!emitter) emitter = *it; else throw Exception() << "Only one emitting particle allowed in " << "QTildeReconstructor::deconstructColourPartner()" << Exception::runerror; } } } assert(emitter); assert(emitter->colourPartner()); ColourSingletShower system; system.jets.push_back(emitter); system.jets.push_back(emitter->colourPartner()); LorentzRotation toRest,fromRest; bool applyBoost(false); // identify the colour singlet system if(emitter->status() == HardBranching::Outgoing && emitter->colourPartner()->status() == HardBranching::Outgoing ) { system.type=F; // need to boost to rest frame if QED ISR if( !incomingShower.jets[0]->branchingParticle()->coloured() && !incomingShower.jets[1]->branchingParticle()->coloured() ) { Boost boost = ptotal.findBoostToCM(); toRest = LorentzRotation( boost); fromRest = LorentzRotation(-boost); } else findInitialBoost(ptotal,ptotal,toRest,fromRest); deconstructFinalStateSystem(toRest,fromRest,tree, - system.jets,evolver,type); + system.jets,type); } else if (emitter->status() == HardBranching::Incoming && emitter->colourPartner()->status() == HardBranching::Incoming) { system.type=II; deconstructInitialInitialSystem(applyBoost,toRest,fromRest,tree,system.jets,type); // make sure the recoil gets applied deconstructFinalStateSystem(toRest,fromRest,tree, - outgoingShower.jets,evolver,type); + outgoingShower.jets,type); } else if ((emitter->status() == HardBranching::Outgoing && emitter->colourPartner()->status() == HardBranching::Incoming ) || (emitter->status() == HardBranching::Incoming && emitter->colourPartner()->status() == HardBranching::Outgoing)) { system.type=IF; // enusre incoming first if(system.jets[0]->status() == HardBranching::Outgoing) swap(system.jets[0],system.jets[1]); - deconstructInitialFinalSystem(tree,system.jets,evolver,type); + deconstructInitialFinalSystem(tree,system.jets,type); } else { throw Exception() << "Unknown type of system in " << "QTildeReconstructor::deconstructColourPartner()" << Exception::runerror; } // only at this point that we can be sure all the reference vectors // are correct for(set::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()==HardBranching::Incoming) continue; if((**it).branchingParticle()->coloured()) (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } for(set::const_iterator it=tree->incoming().begin(); it!=tree->incoming().end();++it) { (**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false); } for(set::const_iterator it=tree->branchings().begin(); it!=tree->branchings().end();++it) { if((**it).status()!=HardBranching::Incoming) continue; if(*it==system.jets[0] || *it==system.jets[1]) continue; if((**it).branchingParticle()->momentum().z()>ZERO) { (**it).z((**it).branchingParticle()->momentum().plus()/(**it).beam()->momentum().plus()); } else { (**it).z((**it).branchingParticle()->momentum().minus()/(**it).beam()->momentum().minus()); } } return true; } void QTildeReconstructor:: reconstructInitialFinalSystem(vector jets) const { Lorentz5Momentum pin[2],pout[2],pbeam; for(unsigned int ix=0;ixprogenitor()->isFinalState()) { pout[0] +=jets[ix]->progenitor()->momentum(); _progenitor = jets[ix]->progenitor(); if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) { reconstructTimeLikeJet(jets[ix]->progenitor()); jets[ix]->reconstructed(ShowerProgenitor::done); } } // initial-state parton else { pin[0] +=jets[ix]->progenitor()->momentum(); if(jets[ix]->progenitor()->showerKinematics()) { pbeam = jets[ix]->progenitor()->showerBasis()->getBasis()[0]; } else { if ( jets[ix]->original()->parents().empty() ) { pbeam = jets[ix]->progenitor()->momentum(); } else { pbeam = jets[ix]->original()->parents()[0]->momentum(); } } if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) { reconstructSpaceLikeJet(jets[ix]->progenitor()); jets[ix]->reconstructed(ShowerProgenitor::done); } assert(!jets[ix]->original()->parents().empty()); } } // add intrinsic pt if needed addIntrinsicPt(jets); // momenta after showering for(unsigned int ix=0;ixprogenitor()->isFinalState()) pout[1] += jets[ix]->progenitor()->momentum(); else pin[1] += jets[ix]->progenitor()->momentum(); } // work out the boost to the Breit frame Lorentz5Momentum pa = pout[0]-pin[0]; Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if ( sinth > 1.e-9 ) rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); rot.boostZ( pa.e()/pa.vect().mag()); Lorentz5Momentum ptemp=rot*pbeam; Boost trans = -1./ptemp.e()*ptemp.vect(); trans.setZ(0.); if ( trans.mag2() - 1. >= 0. ) throw KinematicsReconstructionVeto(); rot.boost(trans); pa *=rot; // project and calculate rescaling // reference vectors Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z()); Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z()); Energy2 n1n2 = n1*n2; // decompose the momenta Lorentz5Momentum qbp=rot*pin[1],qcp=rot*pout[1]; qbp.rescaleMass(); qcp.rescaleMass(); double a[2],b[2]; a[0] = n2*qbp/n1n2; b[0] = n1*qbp/n1n2; Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2; b[1] = 0.5; a[1] = 0.5*(qcp.m2()-qperp.m2())/n1n2/b[1]; double kb; if(a[0]!=0.) { double A(0.5*a[0]),B(b[0]*a[0]-a[1]*b[1]-0.25),C(-0.5*b[0]); if(sqr(B)-4.*A*C<0.) throw KinematicsReconstructionVeto(); kb = 0.5*(-B+sqrt(sqr(B)-4.*A*C))/A; } else { kb = 0.5*b[0]/(b[0]*a[0]-a[1]*b[1]-0.25); } // changed to improve stability if(kb==0.) throw KinematicsReconstructionVeto(); if ( a[1]>b[1] && abs(a[1]) < 1e-12 ) throw KinematicsReconstructionVeto(); if ( a[1]<=b[1] && abs(0.5+b[0]/kb) < 1e-12 ) throw KinematicsReconstructionVeto(); double kc = (a[1]>b[1]) ? (a[0]*kb-0.5)/a[1] : b[1]/(0.5+b[0]/kb); if(kc==0.) throw KinematicsReconstructionVeto(); Lorentz5Momentum pnew[2] = { a[0]*kb*n1+b[0]/kb*n2+qperp, a[1]*kc*n1+b[1]/kc*n2+qperp}; LorentzRotation rotinv=rot.inverse(); for(unsigned int ix=0;ixprogenitor()->isFinalState()) { deepTransform(jets[ix]->progenitor(),rot); deepTransform(jets[ix]->progenitor(),solveBoost(pnew[1],qcp)); Energy delta = jets[ix]->progenitor()->momentum().m()-jets[ix]->progenitor()->momentum().mass(); if ( abs(delta) > MeV ) throw KinematicsReconstructionVeto(); deepTransform(jets[ix]->progenitor(),rotinv); } else { tPPtr parent; boostChain(jets[ix]->progenitor(),rot,parent); boostChain(jets[ix]->progenitor(),solveBoostZ(pnew[0],qbp),parent); // check the first boost worked, and if not apply small correction to // fix energy/momentum conservation // this is a kludge but it reduces momentum non-conservation dramatically Lorentz5Momentum pdiff = pnew[0]-jets[ix]->progenitor()->momentum(); Energy2 delta = sqr(pdiff.x())+sqr(pdiff.y())+sqr(pdiff.z())+sqr(pdiff.t()); unsigned int ntry=0; while(delta>1e-6*GeV2 && ntry<5 ) { ntry +=1; boostChain(jets[ix]->progenitor(),solveBoostZ(pnew[0],jets[ix]->progenitor()->momentum()),parent); pdiff = pnew[0]-jets[ix]->progenitor()->momentum(); delta = sqr(pdiff.x())+sqr(pdiff.y())+sqr(pdiff.z())+sqr(pdiff.t()); } // apply test in breit-frame Lorentz5Momentum ptest1 = parent->momentum(); Lorentz5Momentum ptest2 = rot*pbeam; if(ptest1.z()/ptest2.z()<0. || ptest1.z()/ptest2.z()>1.) throw KinematicsReconstructionVeto(); boostChain(jets[ix]->progenitor(),rotinv,parent); } } } bool QTildeReconstructor::addIntrinsicPt(vector jets) const { bool added=false; // add the intrinsic pt if needed for(unsigned int ix=0;ixprogenitor()->isFinalState()|| jets[ix]->hasEmitted()|| jets[ix]->reconstructed()==ShowerProgenitor::dontReconstruct) continue; if(_intrinsic.find(jets[ix])==_intrinsic.end()) continue; pair pt=_intrinsic[jets[ix]]; Energy etemp = jets[ix]->original()->parents()[0]->momentum().z(); Lorentz5Momentum p_basis(ZERO, ZERO, etemp, abs(etemp)), n_basis(ZERO, ZERO,-etemp, abs(etemp)); double alpha = jets[ix]->progenitor()->x(); double beta = 0.5*(sqr(jets[ix]->progenitor()->data().mass())+ sqr(pt.first))/alpha/(p_basis*n_basis); Lorentz5Momentum pnew=alpha*p_basis+beta*n_basis; pnew.setX(pt.first*cos(pt.second)); pnew.setY(pt.first*sin(pt.second)); pnew.rescaleMass(); jets[ix]->progenitor()->set5Momentum(pnew); added = true; } return added; } LorentzRotation QTildeReconstructor:: solveBoost(const double k, const Lorentz5Momentum & newq, const Lorentz5Momentum & oldp ) const { Energy q = newq.vect().mag(); Energy2 qs = sqr(q); Energy2 Q2 = newq.mass2(); Energy kp = k*(oldp.vect().mag()); Energy2 kps = sqr(kp); double betam = (q*newq.e() - kp*sqrt(kps + Q2))/(kps + qs + Q2); if ( abs(betam) - 1. >= 0. ) throw KinematicsReconstructionVeto(); Boost beta = -betam*(k/kp)*oldp.vect(); double gamma = 0.; if(Q2/sqr(oldp.e())>1e-4) { if(betam<0.5) { gamma = 1./sqrt(1.-sqr(betam)); } else { gamma = ( kps+ qs + Q2)/ sqrt(2.*kps*qs + kps*Q2 + qs*Q2 + sqr(Q2) + 2.*q*newq.e()*kp*sqrt(kps + Q2)); } } else { if(k>0) { gamma = 4.*kps*qs/sqr(kps +qs) + 2.*sqr(kps-qs)*Q2/pow<3,1>(kps +qs) - 0.25*( sqr(kps) + 14.*kps*qs + sqr(qs))*sqr(kps-qs)/(pow<4,1>(kps +qs)*kps*qs)*sqr(Q2); } else { gamma = 0.25*sqr(Q2)/(kps*qs)*(1. - 0.5*(kps+qs)/(kps*qs)*Q2); } if(gamma<=0.) throw KinematicsReconstructionVeto(); gamma = 1./sqrt(gamma); } // note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper. ThreeVector ax = newq.vect().cross( oldp.vect() ); double delta = newq.vect().angle( oldp.vect() ); LorentzRotation R; using Constants::pi; Energy2 scale1 = sqr(newq.x())+ sqr(newq.y())+sqr(newq.z()); Energy2 scale2 = sqr(oldp.x())+ sqr(oldp.y())+sqr(oldp.z()); if ( ax.mag2()/scale1/scale2 > 1e-28 ) { R.rotate( delta, unitVector(ax) ).boost( beta , gamma ); } else if(abs(delta-pi)/pi < 0.001) { double phi=2.*pi*UseRandom::rnd(); Axis axis(cos(phi),sin(phi),0.); axis.rotateUz(newq.vect().unit()); R.rotate(delta,axis).boost( beta , gamma ); } else { R.boost( beta , gamma ); } return R; } LorentzRotation QTildeReconstructor::solveBoost(const Lorentz5Momentum & q, const Lorentz5Momentum & p ) const { Energy modp = p.vect().mag(); Energy modq = q.vect().mag(); double betam = (p.e()*modp-q.e()*modq)/(sqr(modq)+sqr(modp)+p.mass2()); if ( abs(betam)-1. >= 0. ) throw KinematicsReconstructionVeto(); Boost beta = -betam*q.vect().unit(); ThreeVector ax = p.vect().cross( q.vect() ); double delta = p.vect().angle( q.vect() ); LorentzRotation R; using Constants::pi; if ( beta.mag2() - 1. >= 0. ) throw KinematicsReconstructionVeto(); if ( ax.mag2()/GeV2/MeV2 > 1e-16 ) { R.rotate( delta, unitVector(ax) ).boost( beta ); } else { R.boost( beta ); } return R; } LorentzRotation QTildeReconstructor::solveBoostZ(const Lorentz5Momentum & q, const Lorentz5Momentum & p ) const { static const double eps = 1e-6; LorentzRotation R; double beta; Energy2 mt2 = p.mass()eps) { double erat = (q.t()+q.z())/(p.t()+p.z()); Energy2 den = mt2*(erat+1./erat); Energy2 num = (q.z()-p.z())*(q.t()+p.t()) + (p.z()+q.z())*(p.t()-q.t()); beta = num/den; if ( abs(beta) - 1. >= 0. ) throw KinematicsReconstructionVeto(); R.boostZ(beta); } else { double er = sqr(p.t()/q.t()); double x = ratio+0.125*(er+10.+1./er)*sqr(ratio); beta = -(p.t()-q.t())*(p.t()+q.t())/(sqr(p.t())+sqr(q.t()))*(1.+x); double gamma = (4.*sqr(p.t()*q.t()) +sqr(p.t()-q.t())*sqr(p.t()+q.t())* (-2.*x+sqr(x)))/sqr(sqr(p.t())+sqr(q.t())); if ( abs(beta) - 1. >= 0. ) throw KinematicsReconstructionVeto(); gamma = 1./sqrt(gamma); R.boost(0.,0.,beta,gamma); } Lorentz5Momentum ptest = R*p; if(ptest.z()/q.z() < 0. || ptest.t()/q.t() < 0. ) { throw KinematicsReconstructionVeto(); } return R; } void QTildeReconstructor:: reconstructFinalStateSystem(bool applyBoost, const LorentzRotation & toRest, const LorentzRotation & fromRest, vector jets) const { LorentzRotation trans = applyBoost? toRest : LorentzRotation(); // special for case of individual particle if(jets.size()==1) { deepTransform(jets[0]->progenitor(),trans); deepTransform(jets[0]->progenitor(),fromRest); return; } bool radiated(false); // find the hard process centre-of-mass energy Lorentz5Momentum pcm; // check if radiated and calculate total momentum for(unsigned int ix=0;ixhasEmitted(); pcm += jets[ix]->progenitor()->momentum(); } if(applyBoost) pcm *= trans; // check if in CMF frame Boost beta_cm = pcm.findBoostToCM(); bool gottaBoost(false); if(beta_cm.mag() > 1e-12) { gottaBoost = true; trans.boost(beta_cm); } // collection of pointers to initial hard particle and jet momenta // for final boosts JetKinVect jetKinematics; vector::const_iterator cit; for(cit = jets.begin(); cit != jets.end(); cit++) { JetKinStruct tempJetKin; tempJetKin.parent = (*cit)->progenitor(); if(applyBoost || gottaBoost) { deepTransform(tempJetKin.parent,trans); } tempJetKin.p = (*cit)->progenitor()->momentum(); _progenitor=tempJetKin.parent; if((**cit).reconstructed()==ShowerProgenitor::notReconstructed) { radiated |= reconstructTimeLikeJet((*cit)->progenitor()); (**cit).reconstructed(ShowerProgenitor::done); } else { radiated |= !(*cit)->progenitor()->children().empty(); } tempJetKin.q = (*cit)->progenitor()->momentum(); jetKinematics.push_back(tempJetKin); } // default option rescale everything with the same factor if( _finalStateReconOption == 0 || jetKinematics.size() <= 2 ) { // find the rescaling factor double k = 0.0; if(radiated) { k = solveKfactor(pcm.m(), jetKinematics); // perform the rescaling and boosts for(JetKinVect::iterator it = jetKinematics.begin(); it != jetKinematics.end(); ++it) { LorentzRotation Trafo = solveBoost(k, it->q, it->p); deepTransform(it->parent,Trafo); } } } // different treatment of most off-shell else if ( _finalStateReconOption <= 4 ) { // sort the jets by virtuality std::sort(jetKinematics.begin(),jetKinematics.end(),JetOrdering()); // Bryan's procedures from FORTRAN if( _finalStateReconOption <=2 ) { // loop over the off-shell partons, _finalStateReconOption==1 only first ==2 all JetKinVect::const_iterator jend = _finalStateReconOption==1 ? jetKinematics.begin()+1 : jetKinematics.end(); for(JetKinVect::const_iterator jit=jetKinematics.begin(); jit!=jend;++jit) { // calculate the 4-momentum of the recoiling system Lorentz5Momentum psum; bool done = true; for(JetKinVect::const_iterator it=jetKinematics.begin();it!=jetKinematics.end();++it) { if(it==jit) { done = false; continue; } // first option put on-shell and sum 4-momenta if( _finalStateReconOption == 1 ) { LorentzRotation Trafo = solveBoost(1., it->q, it->p); deepTransform(it->parent,Trafo); psum += it->parent->momentum(); } // second option, sum momenta else { // already rescaled if(done) psum += it->parent->momentum(); // still needs to be rescaled else psum += it->p; } } // set the mass psum.rescaleMass(); // calculate the 3-momentum rescaling factor Energy2 s(pcm.m2()); Energy2 m1sq(jit->q.m2()),m2sq(psum.m2()); Energy4 num = sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq; if(nump.vect().mag2()) ); // boost the off-shell parton LorentzRotation B1 = solveBoost(k, jit->q, jit->p); deepTransform(jit->parent,B1); // boost everything else to rescale LorentzRotation B2 = solveBoost(k, psum, psum); for(JetKinVect::iterator it=jetKinematics.begin();it!=jetKinematics.end();++it) { if(it==jit) continue; deepTransform(it->parent,B2); it->p *= B2; it->q *= B2; } } } // Peter's C++ procedures else { reconstructFinalFinalOffShell(jetKinematics,pcm.m2(), _finalStateReconOption == 4); } } else assert(false); // apply the final boosts if(gottaBoost || applyBoost) { LorentzRotation finalBoosts; if(gottaBoost) finalBoosts.boost(-beta_cm); if(applyBoost) finalBoosts.transform(fromRest); for(JetKinVect::iterator it = jetKinematics.begin(); it != jetKinematics.end(); ++it) { deepTransform(it->parent,finalBoosts); } } } void QTildeReconstructor:: reconstructInitialInitialSystem(bool & applyBoost, LorentzRotation & toRest, LorentzRotation & fromRest, vector jets) const { bool radiated = false; Lorentz5Momentum pcm; // check whether particles radiated and calculate total momentum for( unsigned int ix = 0; ix < jets.size(); ++ix ) { radiated |= jets[ix]->hasEmitted(); pcm += jets[ix]->progenitor()->momentum(); if(jets[ix]->original()->parents().empty()) return; } pcm.rescaleMass(); // check if intrinsic pt to be added radiated |= !_intrinsic.empty(); // if no radiation return if(!radiated) { for(unsigned int ix=0;ixreconstructed()==ShowerProgenitor::notReconstructed) jets[ix]->reconstructed(ShowerProgenitor::done); } return; } // initial state shuffling applyBoost=false; vector p, pq, p_in; vector pts; for(unsigned int ix=0;ixprogenitor()->momentum()); // reconstruct the jet if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) { radiated |= reconstructSpaceLikeJet(jets[ix]->progenitor()); jets[ix]->reconstructed(ShowerProgenitor::done); } assert(!jets[ix]->original()->parents().empty()); Energy etemp = jets[ix]->original()->parents()[0]->momentum().z(); Lorentz5Momentum ptemp = Lorentz5Momentum(ZERO, ZERO, etemp, abs(etemp)); pq.push_back(ptemp); pts.push_back(jets[ix]->highestpT()); } // add the intrinsic pt if needed radiated |=addIntrinsicPt(jets); for(unsigned int ix=0;ixprogenitor()->momentum()); } double x1 = p_in[0].z()/pq[0].z(); double x2 = p_in[1].z()/pq[1].z(); vector beta=initialStateRescaling(x1,x2,p_in[0]+p_in[1],p,pq,pts); // if not need don't apply boosts if(!(radiated && p.size() == 2 && pq.size() == 2)) return; applyBoost=true; // apply the boosts Lorentz5Momentum newcmf; for(unsigned int ix=0;ixprogenitor(); Boost betaboost(0, 0, beta[ix]); tPPtr parent; boostChain(toBoost, LorentzRotation(0.,0.,beta[ix]),parent); if(parent->momentum().e()/pq[ix].e()>1.|| parent->momentum().z()/pq[ix].z()>1.) throw KinematicsReconstructionVeto(); newcmf+=toBoost->momentum(); } if(newcmf.m() jets, ShowerInteraction::Type) const { assert(jets.size()==2); // put beam with +z first if(jets[0]->beam()->momentum().z() pin,pq; for(unsigned int ix=0;ixbranchingParticle()->momentum()); Energy etemp = jets[ix]->beam()->momentum().z(); pq.push_back(Lorentz5Momentum(ZERO, ZERO,etemp, abs(etemp))); } // calculate the rescaling double x[2]; Lorentz5Momentum pcm=pin[0]+pin[1]; assert(pcm.mass2()>ZERO); pcm.rescaleMass(); vector boost = inverseInitialStateRescaling(x[0],x[1],pcm,pin,pq); set::const_iterator cjt=tree->incoming().begin(); HardBranchingPtr incoming[2]; incoming[0] = *cjt; ++cjt; incoming[1] = *cjt; if((*tree->incoming().begin())->beam()->momentum().z()/pq[0].z()<0.) swap(incoming[0],incoming[1]); // apply the boost the the particles unsigned int iswap[2]={1,0}; for(unsigned int ix=0;ix<2;++ix) { LorentzRotation R(0.,0.,-boost[ix]); incoming[ix]->pVector(pq[ix]); incoming[ix]->nVector(pq[iswap[ix]]); incoming[ix]->setMomenta(R,1.,Lorentz5Momentum()); jets[ix]->showerMomentum(x[ix]*jets[ix]->pVector()); } // and calculate the boosts applyBoost=true; // do one boost if(_initialBoost==0) { toRest = LorentzRotation(-pcm.boostVector()); } else if(_initialBoost==1) { // first the transverse boost Energy pT = sqrt(sqr(pcm.x())+sqr(pcm.y())); double beta = -pT/pcm.t(); toRest=LorentzRotation(Boost(beta*pcm.x()/pT,beta*pcm.y()/pT,0.)); // the longitudinal beta = pcm.z()/sqrt(pcm.m2()+sqr(pcm.z())); toRest.boost(Boost(0.,0.,-beta)); } else assert(false); fromRest = LorentzRotation((jets[0]->showerMomentum()+ jets[1]->showerMomentum()).boostVector()); } void QTildeReconstructor:: deconstructFinalStateSystem(const LorentzRotation & toRest, const LorentzRotation & fromRest, HardTreePtr tree, vector jets, - cEvolverPtr evolver, ShowerInteraction::Type type) const { LorentzRotation trans = toRest; if(jets.size()==1) { Lorentz5Momentum pnew = toRest*(jets[0]->branchingParticle()->momentum()); pnew *= fromRest; jets[0]-> original(pnew); jets[0]->showerMomentum(pnew); // find the colour partners ShowerParticleVector particles; vector ptemp; set::const_iterator cjt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { ptemp.push_back((**cjt).branchingParticle()->momentum()); (**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum()); particles.push_back((**cjt).branchingParticle()); } - evolver->showerModel()->partnerFinder() + dynamic_ptr_cast(ShowerHandler::currentHandler())->showerModel()->partnerFinder() ->setInitialEvolutionScales(particles,false,type,false); // calculate the reference vectors unsigned int iloc(0); set::iterator clt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { // reset the momentum (**cjt).branchingParticle()->set5Momentum(ptemp[iloc]); ++iloc; // sort out the partners tShowerParticlePtr partner = (*cjt)->branchingParticle()->partner(); if(!partner) continue; for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if((**clt).branchingParticle()==partner) { (**cjt).colourPartner(*clt); break; } } tHardBranchingPtr branch; for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if(clt==cjt) continue; if((*clt)->branchingParticle()==partner) { branch=*clt; break; } } } return; } vector::iterator cit; vector pout; vector mon; Lorentz5Momentum pin; for(cit=jets.begin();cit!=jets.end();++cit) { pout.push_back((*cit)->branchingParticle()->momentum()); mon.push_back(findMass(*cit)); pin+=pout.back(); } // boost all the momenta to the rest frame of the decaying particle pin.rescaleMass(); pin *=trans; Boost beta_cm = pin.findBoostToCM(); bool gottaBoost(false); if(beta_cm.mag() > 1e-12) { gottaBoost = true; trans.boost(beta_cm); pin.boost(beta_cm); } for(unsigned int ix=0;ixbranchingParticle()->momentum(); pvect.transform(trans); pvect /= lambda; pvect.setMass(mon[ix]); pvect.rescaleEnergy(); if(gottaBoost) pvect.boost(-beta_cm); pvect.transform(fromRest); jets[ix]->pVector(pvect); jets[ix]->showerMomentum(pvect); } // find the colour partners ShowerParticleVector particles; vector ptemp; set::const_iterator cjt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { ptemp.push_back((**cjt).branchingParticle()->momentum()); (**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum()); particles.push_back((**cjt).branchingParticle()); } - evolver->showerModel()->partnerFinder() + dynamic_ptr_cast(ShowerHandler::currentHandler())->showerModel()->partnerFinder() ->setInitialEvolutionScales(particles,false,type,false); // calculate the reference vectors unsigned int iloc(0); set::iterator clt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { // reset the momentum (**cjt).branchingParticle()->set5Momentum(ptemp[iloc]); ++iloc; } for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { // sort out the partners tShowerParticlePtr partner = (*cjt)->branchingParticle()->partner(); if(!partner) continue; for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if((**clt).branchingParticle()==partner) { (**cjt).colourPartner(*clt); break; } } tHardBranchingPtr branch; for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if(clt==cjt) continue; if((*clt)->branchingParticle()==partner) { branch=*clt; break; } } // compute the reference vectors // both incoming, should all ready be done if((**cjt).status()==HardBranching::Incoming && (**clt).status()==HardBranching::Incoming) { continue; } // both outgoing else if((**cjt).status()!=HardBranching::Incoming&& branch->status()==HardBranching::Outgoing) { Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM(); Lorentz5Momentum pcm = branch->pVector(); pcm.boost(boost); Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect()); nvect.boost( -boost); (**cjt).nVector(nvect); } else if((**cjt).status()==HardBranching::Incoming) { Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum(); Lorentz5Momentum pb = (**cjt).showerMomentum(); Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); rot.boostZ( pa.e()/pa.vect().mag()); pb*=rot; Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot.boost(trans); Energy scale=(**cjt).beam()->momentum().e(); Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale); Lorentz5Momentum pcm = rot*pbasis; rot.invert(); (**cjt).nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect())); tHardBranchingPtr branch2 = *cjt;; while (branch2->parent()) { branch2=branch2->parent(); branch2->nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect())); } } else if(branch->status()==HardBranching::Incoming) { (**cjt).nVector(Lorentz5Momentum(ZERO,branch->showerMomentum().vect())); } } // now compute the new momenta for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { if(!(*cjt)->branchingParticle()->isFinalState()) continue; Lorentz5Momentum qnew; if((*cjt)->branchingParticle()->partner()) { Energy2 dot=(*cjt)->pVector()*(*cjt)->nVector(); double beta = 0.5*((*cjt)->branchingParticle()->momentum().m2() -sqr((*cjt)->pVector().mass()))/dot; qnew=(*cjt)->pVector()+beta*(*cjt)->nVector(); qnew.rescaleMass(); } else { qnew = (*cjt)->pVector(); } // qnew is the unshuffled momentum in the rest frame of the p basis vectors, // for the simple case Z->q qbar g this was checked against analytic formulae. // compute the boost LorentzRotation R=solveBoost(qnew, toRest*(*cjt)->branchingParticle()->momentum())*toRest; (*cjt)->setMomenta(R,1.0,Lorentz5Momentum()); } } -Energy QTildeReconstructor::momConsEq(const double & k, +Energy QTildeReconstructor::momConsEq(double k, const Energy & root_s, const JetKinVect & jets) const { static const Energy2 eps=1e-8*GeV2; Energy dum = ZERO; for(JetKinVect::const_iterator it = jets.begin(); it != jets.end(); ++it) { Energy2 dum2 = (it->q).m2() + sqr(k)*(it->p).vect().mag2(); if(dum2 < ZERO) { if(dum2 < -eps) throw KinematicsReconstructionVeto(); dum2 = ZERO; } dum += sqrt(dum2); } return dum - root_s; } void QTildeReconstructor::boostChain(tPPtr p, const LorentzRotation &bv, tPPtr & parent) const { if(!p->parents().empty()) boostChain(p->parents()[0], bv,parent); else parent=p; p->transform(bv); if(p->children().size()==2) { if(dynamic_ptr_cast(p->children()[1])) deepTransform(p->children()[1],bv); } } namespace { bool sortJets(ShowerProgenitorPtr j1, ShowerProgenitorPtr j2) { return j1->highestpT()>j2->highestpT(); } } void QTildeReconstructor:: reconstructGeneralSystem(vector & ShowerHardJets) const { // find initial- and final-state systems ColourSingletSystem in,out; for(unsigned int ix=0;ixprogenitor()->isFinalState()) out.jets.push_back(ShowerHardJets[ix]); else in.jets.push_back(ShowerHardJets[ix]); } // reconstruct initial-initial system LorentzRotation toRest,fromRest; bool applyBoost(false); // reconstruct initial-initial system reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets); // reconstruct the final-state systems reconstructFinalStateSystem(applyBoost,toRest,fromRest,out.jets); } void QTildeReconstructor:: reconstructFinalFirst(vector & ShowerHardJets) const { static const Energy2 minQ2 = 1e-4*GeV2; map used; for(unsigned int ix=0;ix outgoing; // first find any particles with final state partners for(unsigned int ix=0;ixprogenitor()->isFinalState()&& ShowerHardJets[ix]->progenitor()->partner()&& ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) outgoing.insert(ShowerHardJets[ix]); } // then find the colour partners if(!outgoing.empty()) { set partners; for(set::const_iterator it=outgoing.begin();it!=outgoing.end();++it) { for(unsigned int ix=0;ixpartner()==ShowerHardJets[ix]->progenitor()) { partners.insert(ShowerHardJets[ix]); break; } } } outgoing.insert(partners.begin(),partners.end()); } // do the final-state reconstruction if needed if(!outgoing.empty()) { assert(outgoing.size()!=1); LorentzRotation toRest,fromRest; vector outgoingJets(outgoing.begin(),outgoing.end()); reconstructFinalStateSystem(false,toRest,fromRest,outgoingJets); } // Now do any initial-final systems which are needed vector IFSystems; // find the systems N.B. can have duplicates // find initial-state with FS partners or FS with IS partners for(unsigned int ix=0;ixprogenitor()->isFinalState()&& ShowerHardJets[ix]->progenitor()->partner()&& ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) { IFSystems.push_back(ColourSingletSystem(IF,ShowerHardJets[ix])); } else if(ShowerHardJets[ix]->progenitor()->isFinalState()&& ShowerHardJets[ix]->progenitor()->partner()&& !ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) { IFSystems.push_back(ColourSingletSystem(IF,ShowerHardJets[ix])); } } // then add the partners for(unsigned int is=0;isprogenitor()->partner()==ShowerHardJets[ix]->progenitor()) { IFSystems[is].jets.push_back(ShowerHardJets[ix]); } } // ensure incoming first if(IFSystems[is].jets[0]->progenitor()->isFinalState()) swap(IFSystems[is].jets[0],IFSystems[is].jets[1]); } if(!IFSystems.empty()) { unsigned int istart = UseRandom::irnd(IFSystems.size()); unsigned int istop=IFSystems.size(); for(unsigned int is=istart;is<=istop;++is) { if(is==IFSystems.size()) { if(istart!=0) { istop = istart-1; is=0; } else break; } // skip duplicates if(used[IFSystems[is].jets[0]] && used[IFSystems[is].jets[1]] ) continue; if(IFSystems[is].jets[0]->original()&&IFSystems[is].jets[0]->original()->parents().empty()) continue; Lorentz5Momentum psum; for(unsigned int ix=0;ixprogenitor()->isFinalState()) psum += IFSystems[is].jets[ix]->progenitor()->momentum(); else psum -= IFSystems[is].jets[ix]->progenitor()->momentum(); } if(-psum.m2()>minQ2) { reconstructInitialFinalSystem(IFSystems[is].jets); for(unsigned int ix=0;ixprogenitor()->isFinalState()) out.jets.push_back(ShowerHardJets[ix]); else in.jets.push_back(ShowerHardJets[ix]); } // reconstruct initial-initial system bool doRecon = false; for(unsigned int ix=0;ix & ShowerHardJets) const { static const Energy2 minQ2 = 1e-4*GeV2; // sort the vector by hardness of emission std::sort(ShowerHardJets.begin(),ShowerHardJets.end(),sortJets); // map between particles and progenitors for easy lookup map progenitorMap; for(unsigned int ix=0;ixprogenitor()] = ShowerHardJets[ix]; } // check that the IF systems can be reconstructed bool canReconstruct = true; for(unsigned int ix=0;ixprogenitor(); tShowerParticlePtr partner = progenitor->partner(); if(!partner) continue; else if((progenitor->isFinalState() && !partner->isFinalState()) || (!progenitor->isFinalState() && partner->isFinalState()) ) { vector jets(2); jets[0] = ShowerHardJets[ix]; jets[1] = progenitorMap[partner]; Lorentz5Momentum psum; for(unsigned int iy=0;iyprogenitor()->isFinalState()) psum += jets[iy]->progenitor()->momentum(); else psum -= jets[iy]->progenitor()->momentum(); } if(-psum.m2() used; for(unsigned int ix=0;ixreconstructed()==ShowerProgenitor::done) continue; // already reconstructed if(used[ShowerHardJets[ix]]) continue; // no partner continue tShowerParticlePtr progenitor = ShowerHardJets[ix]->progenitor(); tShowerParticlePtr partner = progenitor->partner(); if(!partner) { // check if there's a daughter tree which also needs boosting Lorentz5Momentum porig = progenitor->momentum(); map >::const_iterator tit; for(tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { // if there is, boost it if(tit->second.first && tit->second.second==progenitor) { Lorentz5Momentum pnew = tit->first->incomingLines().begin() ->first->progenitor()->momentum(); pnew *= tit->first->transform(); Lorentz5Momentum pdiff = porig-pnew; Energy2 test = sqr(pdiff.x()) + sqr(pdiff.y()) + sqr(pdiff.z()) + sqr(pdiff.t()); LorentzRotation rot; if(test>1e-6*GeV2) rot = solveBoost(porig,pnew); tit->first->transform(rot,false); _treeBoosts[tit->first].push_back(rot); } } ShowerHardJets[ix]->reconstructed(ShowerProgenitor::done); continue; } // do the reconstruction // final-final if(progenitor->isFinalState() && partner->isFinalState() ) { LorentzRotation toRest,fromRest; vector jets(2); jets[0] = ShowerHardJets[ix]; jets[1] = progenitorMap[partner]; if(_reconopt==4 && jets[1]->reconstructed()==ShowerProgenitor::notReconstructed) jets[1]->reconstructed(ShowerProgenitor::dontReconstruct); reconstructFinalStateSystem(false,toRest,fromRest,jets); if(_reconopt==4 && jets[1]->reconstructed()==ShowerProgenitor::dontReconstruct) jets[1]->reconstructed(ShowerProgenitor::notReconstructed); used[jets[0]] = true; if(_reconopt==3) used[jets[1]] = true; } // initial-final else if((progenitor->isFinalState() && !partner->isFinalState()) || (!progenitor->isFinalState() && partner->isFinalState()) ) { vector jets(2); jets[0] = ShowerHardJets[ix]; jets[1] = progenitorMap[partner]; if(jets[0]->progenitor()->isFinalState()) swap(jets[0],jets[1]); if(jets[0]->original()&&jets[0]->original()->parents().empty()) continue; Lorentz5Momentum psum; for(unsigned int iy=0;iyprogenitor()->isFinalState()) psum += jets[iy]->progenitor()->momentum(); else psum -= jets[iy]->progenitor()->momentum(); } if(_reconopt==4 && progenitorMap[partner]->reconstructed()==ShowerProgenitor::notReconstructed) progenitorMap[partner]->reconstructed(ShowerProgenitor::dontReconstruct); reconstructInitialFinalSystem(jets); if(_reconopt==4 && progenitorMap[partner]->reconstructed()==ShowerProgenitor::dontReconstruct) progenitorMap[partner]->reconstructed(ShowerProgenitor::notReconstructed); used[ShowerHardJets[ix]] = true; if(_reconopt==3) used[progenitorMap[partner]] = true; } // initial-initial else if(!progenitor->isFinalState() && !partner->isFinalState() ) { ColourSingletSystem in,out; in.jets.push_back(ShowerHardJets[ix]); in.jets.push_back(progenitorMap[partner]); for(unsigned int iy=0;iyprogenitor()->isFinalState()) out.jets.push_back(ShowerHardJets[iy]); } LorentzRotation toRest,fromRest; bool applyBoost(false); if(_reconopt==4 && in.jets[1]->reconstructed()==ShowerProgenitor::notReconstructed) in.jets[1]->reconstructed(ShowerProgenitor::dontReconstruct); reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets); if(_reconopt==4 && in.jets[1]->reconstructed()==ShowerProgenitor::dontReconstruct) in.jets[1]->reconstructed(ShowerProgenitor::notReconstructed); used[in.jets[0]] = true; if(_reconopt==3) used[in.jets[1]] = true; for(unsigned int iy=0;iyreconstructed()==ShowerProgenitor::notReconstructed) out.jets[iy]->reconstructed(ShowerProgenitor::dontReconstruct); } // reconstruct the final-state systems LorentzRotation finalBoosts; finalBoosts.transform( toRest); finalBoosts.transform(fromRest); for(unsigned int iy=0;iyprogenitor(),finalBoosts); } for(unsigned int iy=0;iyreconstructed()==ShowerProgenitor::dontReconstruct) out.jets[iy]->reconstructed(ShowerProgenitor::notReconstructed); } } } } bool QTildeReconstructor:: inverseDecayRescalingFactor(vector pout, vector mon,Energy roots, Lorentz5Momentum ppartner, Energy mbar, double & k1, double & k2) const { ThreeVector qtotal; vector pmag; for(unsigned int ix=0;ix1e10) return false; } while (abs(numer)>eps&&itry<100); k1 = abs(k1); k2 = a*k1; return itry<100; } void QTildeReconstructor:: deconstructInitialFinalSystem(HardTreePtr tree,vector jets, - cEvolverPtr evolver, ShowerInteraction::Type type) const { HardBranchingPtr incoming; Lorentz5Momentum pin[2],pout[2],pbeam; HardBranchingPtr initial; Energy mc(ZERO); for(unsigned int ix=0;ixstatus()==HardBranching::Outgoing) { pout[0] += jets[ix]->branchingParticle()->momentum(); mc = jets[ix]->branchingParticle()->thePEGBase() ? jets[ix]->branchingParticle()->thePEGBase()->mass() : jets[ix]->branchingParticle()->dataPtr()->mass(); } // initial-state parton else { pin[0] += jets[ix]->branchingParticle()->momentum(); initial = jets[ix]; pbeam = jets[ix]->beam()->momentum(); Energy scale=pbeam.t(); pbeam = Lorentz5Momentum(ZERO,pbeam.vect().unit()*scale); incoming = jets[ix]; while(incoming->parent()) incoming = incoming->parent(); } } if(jets.size()>2) { pout[0].rescaleMass(); mc = pout[0].mass(); } // work out the boost to the Breit frame Lorentz5Momentum pa = pout[0]-pin[0]; Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if(axis.perp2()>0.) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); rot.boostZ( pa.e()/pa.vect().mag()); } // transverse part Lorentz5Momentum paxis=rot*pbeam; Boost trans = -1./paxis.e()*paxis.vect(); trans.setZ(0.); rot.boost(trans); pa *= rot; // reference vectors Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z()); Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z()); Energy2 n1n2 = n1*n2; // decompose the momenta Lorentz5Momentum qbp=rot*pin[0],qcp= rot*pout[0]; double a[2],b[2]; a[0] = n2*qbp/n1n2; b[0] = n1*qbp/n1n2; a[1] = n2*qcp/n1n2; b[1] = n1*qcp/n1n2; Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2; // before reshuffling Energy Q = abs(pa.z()); double c = sqr(mc/Q); Lorentz5Momentum pb(ZERO,ZERO,0.5*Q*(1.+c),0.5*Q*(1.+c)); Lorentz5Momentum pc(ZERO,ZERO,0.5*Q*(c-1.),0.5*Q*(1.+c)); double anew[2],bnew[2]; anew[0] = pb*n2/n1n2; bnew[0] = 0.5*(qbp.m2()-qperp.m2())/n1n2/anew[0]; bnew[1] = pc*n1/n1n2; anew[1] = 0.5*qcp.m2()/bnew[1]/n1n2; Lorentz5Momentum qnewb = (anew[0]*n1+bnew[0]*n2+qperp); Lorentz5Momentum qnewc = (anew[1]*n1+bnew[1]*n2); // initial-state boost LorentzRotation rotinv=rot.inverse(); LorentzRotation transb=rotinv*solveBoostZ(qnewb,qbp)*rot; // final-state boost LorentzRotation transc=rotinv*solveBoost(qnewc,qcp)*rot; // this will need changing for more than one outgoing particle // set the pvectors for(unsigned int ix=0;ixstatus()==HardBranching::Incoming) { jets[ix]->pVector(pbeam); jets[ix]->showerMomentum(rotinv*pb); incoming->pVector(jets[ix]->pVector()); } else { jets[ix]->pVector(rotinv*pc); jets[ix]->showerMomentum(jets[ix]->pVector()); } } // find the colour partners ShowerParticleVector particles; vector ptemp; set::const_iterator cjt; for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { ptemp.push_back((**cjt).branchingParticle()->momentum()); (**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum()); particles.push_back((**cjt).branchingParticle()); } - evolver->showerModel()->partnerFinder() + dynamic_ptr_cast(ShowerHandler::currentHandler())->showerModel()->partnerFinder() ->setInitialEvolutionScales(particles,false,type,false); unsigned int iloc(0); for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) { // reset the momentum (**cjt).branchingParticle()->set5Momentum(ptemp[iloc]); ++iloc; } for(vector::const_iterator cjt=jets.begin(); cjt!=jets.end();++cjt) { // sort out the partners tShowerParticlePtr partner = (*cjt)->branchingParticle()->partner(); if(!partner) continue; tHardBranchingPtr branch; for(set::const_iterator clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) { if((**clt).branchingParticle()==partner) { (**cjt).colourPartner(*clt); branch=*clt; break; } } // compute the reference vectors // both incoming, should all ready be done if((**cjt).status()==HardBranching::Incoming && branch->status()==HardBranching::Incoming) { Energy etemp = (*cjt)->beam()->momentum().z(); Lorentz5Momentum nvect(ZERO, ZERO,-etemp, abs(etemp)); tHardBranchingPtr branch2 = *cjt; (**cjt).nVector(nvect); while (branch2->parent()) { branch2=branch2->parent(); branch2->nVector(nvect); } } // both outgoing else if((**cjt).status()==HardBranching::Outgoing&& branch->status()==HardBranching::Outgoing) { Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM(); Lorentz5Momentum pcm = branch->pVector(); pcm.boost(boost); Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect()); nvect.boost( -boost); (**cjt).nVector(nvect); } else if((**cjt).status()==HardBranching::Incoming) { Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum(); Lorentz5Momentum pb = (**cjt).showerMomentum(); Axis axis(pa.vect().unit()); LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if(axis.perp2()>1e-20) { rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); rot.rotateX(Constants::pi); } if(abs(1.-pa.e()/pa.vect().mag())>1e-6) rot.boostZ( pa.e()/pa.vect().mag()); pb*=rot; Boost trans = -1./pb.e()*pb.vect(); trans.setZ(0.); rot.boost(trans); Energy scale=(**cjt).beam()->momentum().t(); Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale); Lorentz5Momentum pcm = rot*pbasis; rot.invert(); Lorentz5Momentum nvect = rot*Lorentz5Momentum(ZERO,-pcm.vect()); (**cjt).nVector(nvect); tHardBranchingPtr branch2 = *cjt; while (branch2->parent()) { branch2=branch2->parent(); branch2->nVector(nvect); } } else if(branch->status()==HardBranching::Incoming) { Lorentz5Momentum nvect=Lorentz5Momentum(ZERO,branch->showerMomentum().vect()); (**cjt).nVector(nvect); } } // now compute the new momenta for(vector::const_iterator cjt=jets.begin(); cjt!=jets.end();++cjt) { if((**cjt).status()==HardBranching::Outgoing) { (**cjt).setMomenta(transc,1.,Lorentz5Momentum()); } } incoming->setMomenta(transb,1.,Lorentz5Momentum()); } void QTildeReconstructor::deepTransform(PPtr particle, const LorentzRotation & r, bool match, PPtr original) const { if(_boosts.find(particle)!=_boosts.end()) { _boosts[particle].push_back(r); } Lorentz5Momentum porig = particle->momentum(); if(!original) original = particle; for ( int i = 0, N = particle->children().size(); i < N; ++i ) { deepTransform(particle->children()[i],r, particle->children()[i]->id()==original->id()&&match,original); } particle->transform(r); // transform the p and n vectors ShowerParticlePtr sparticle = dynamic_ptr_cast(particle); if(sparticle && sparticle->showerBasis()) { sparticle->showerBasis()->transform(r); } if ( particle->next() ) deepTransform(particle->next(),r,match,original); if(!match) return; if(!particle->children().empty()) return; // force the mass shell if(particle->dataPtr()->stable()) { Lorentz5Momentum ptemp = particle->momentum(); ptemp.rescaleEnergy(); particle->set5Momentum(ptemp); } // check if there's a daughter tree which also needs boosting map >::const_iterator tit; for(tit = _currentTree->treelinks().begin(); tit != _currentTree->treelinks().end();++tit) { // if there is, boost it if(tit->second.first && tit->second.second==original) { Lorentz5Momentum pnew = tit->first->incomingLines().begin() ->first->progenitor()->momentum(); pnew *= tit->first->transform(); Lorentz5Momentum pdiff = porig-pnew; Energy2 test = sqr(pdiff.x()) + sqr(pdiff.y()) + sqr(pdiff.z()) + sqr(pdiff.t()); LorentzRotation rot; if(test>1e-6*GeV2) rot = solveBoost(porig,pnew); tit->first->transform(r*rot,false); _treeBoosts[tit->first].push_back(r*rot); } } } void QTildeReconstructor::reconstructFinalFinalOffShell(JetKinVect orderedJets, Energy2 s, bool recursive) const { JetKinVect::iterator jit; jit = orderedJets.begin(); ++jit; // 4-momentum of recoiling system Lorentz5Momentum psum; for( ; jit!=orderedJets.end(); ++jit) psum += jit->p; psum.rescaleMass(); // calculate the 3-momentum rescaling factor Energy2 m1sq(orderedJets.begin()->q.m2()),m2sq(psum.m2()); Energy4 num = sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq; if(nump.vect().mag2()) ); // boost the most off-shell LorentzRotation B1 = solveBoost(k, orderedJets.begin()->q, orderedJets.begin()->p); deepTransform(orderedJets.begin()->parent,B1); // boost everything else // first to rescale LorentzRotation B2 = solveBoost(k, psum, psum); // and then to rest frame of new system Lorentz5Momentum pnew = B2*psum; pnew.rescaleMass(); B2.transform(pnew.findBoostToCM()); // apply transform (calling routine ensures at least 3 elements) jit = orderedJets.begin(); ++jit; for(;jit!=orderedJets.end();++jit) { deepTransform(jit->parent,B2); jit->p *= B2; jit->q *= B2; } JetKinVect newJets(orderedJets.begin()+1,orderedJets.end()); // final reconstruction if(newJets.size()==2 || !recursive ) { // rescaling factor double k = solveKfactor(psum.m(), newJets); // rescale jets in the new CMF for(JetKinVect::iterator it = newJets.begin(); it != newJets.end(); ++it) { LorentzRotation Trafo = solveBoost(k, it->q, it->p); deepTransform(it->parent,Trafo); } } // recursive else { std::sort(newJets.begin(),newJets.end(),JetOrdering()); reconstructFinalFinalOffShell(newJets,psum.m2(),recursive); } // finally boost back from new CMF LorentzRotation back(-pnew.findBoostToCM()); for(JetKinVect::iterator it = newJets.begin(); it != newJets.end(); ++it) { deepTransform(it->parent,back); } } Energy QTildeReconstructor::findMass(HardBranchingPtr branch) const { // KH - 230909 - If the particle has no children then it will // not have showered and so it should be "on-shell" so we can // get it's mass from it's momentum. This means that the // inverseRescalingFactor doesn't give any nans or do things // it shouldn't if it gets e.g. two Z bosons generated with // off-shell masses. This is for sure not the best solution. // PR 1/1/10 modification to previous soln // PR 28/8/14 change to procedure and factorize into a function if(branch->children().empty()) { return branch->branchingParticle()->mass(); } else if(!branch->children().empty() && !branch->branchingParticle()->dataPtr()->stable() ) { for(unsigned int ix=0;ixchildren().size();++ix) { if(branch->branchingParticle()->id()== branch->children()[ix]->branchingParticle()->id()) return findMass(branch->children()[ix]); } } return branch->branchingParticle()->dataPtr()->mass(); } vector QTildeReconstructor::inverseInitialStateRescaling(double & x1, double & x2, const Lorentz5Momentum & pold, const vector & p, const vector & pq) const { // hadronic CMS Energy2 s = (pq[0] +pq[1] ).m2(); // partonic CMS Energy MDY = pold.m(); // find alpha, beta and pt Energy2 p12=pq[0]*pq[1]; double a[2],b[2]; Lorentz5Momentum pt[2]; for(unsigned int ix=0;ix<2;++ix) { a[ix] = p[ix]*pq[1]/p12; b [ix] = p[ix]*pq[0]/p12; pt[ix] = p[ix]-a[ix]*pq[0]-b[ix]*pq[1]; } // compute kappa // we always want to preserve the mass of the system double k1(1.),k2(1.); if(_initialStateReconOption==0) { double rap=pold.rapidity(); x2 = MDY/sqrt(s*exp(2.*rap)); x1 = sqr(MDY)/s/x2; k1=a[0]/x1; k2=b[1]/x2; } // longitudinal momentum else if(_initialStateReconOption==1) { double A = 1.; double C = -sqr(MDY)/s; double B = 2.*pold.z()/sqrt(s); if(abs(B)>1e-10) { double discrim = 1.-4.*A*C/sqr(B); if(discrim < 0.) throw KinematicsReconstructionVeto(); x1 = B>0. ? 0.5*B/A*(1.+sqrt(discrim)) : 0.5*B/A*(1.-sqrt(discrim)); } else { x1 = -C/A; if( x1 <= 0.) throw KinematicsReconstructionVeto(); x1 = sqrt(x1); } x2 = sqr(MDY)/s/x1; k1=a[0]/x1; k2=b[1]/x2; } // preserve mass and don't scale the softer system // to reproduce the dipole kinematics else if(_initialStateReconOption==2) { // in this case kp = k1 or k2 depending on who's the harder guy k1 = a[0]*b[1]*s/sqr(MDY); if ( pt[0].perp2() < pt[1].perp2() ) swap(k1,k2); x1 = a[0]/k1; x2 = b[1]/k2; } else assert(false); // decompose the momenta double anew[2] = {a[0]/k1,a[1]*k2}; double bnew[2] = {b[0]*k1,b[1]/k2}; vector boost(2); for(unsigned int ix=0;ix<2;++ix) { boost[ix] = getBeta(a [ix]+b [ix], a[ix] -b [ix], anew[ix]+bnew[ix], anew[ix]-bnew[ix]); } return boost; } vector QTildeReconstructor::initialStateRescaling(double x1, double x2, const Lorentz5Momentum & pold, const vector & p, const vector & pq, const vector& highestpts) const { Energy2 S = (pq[0]+pq[1]).m2(); // find alphas and betas in terms of desired basis Energy2 p12 = pq[0]*pq[1]; double a[2] = {p[0]*pq[1]/p12,p[1]*pq[1]/p12}; double b[2] = {p[0]*pq[0]/p12,p[1]*pq[0]/p12}; Lorentz5Momentum p1p = p[0] - a[0]*pq[0] - b[0]*pq[1]; Lorentz5Momentum p2p = p[1] - a[1]*pq[0] - b[1]*pq[1]; // compute kappa // we always want to preserve the mass of the system Energy MDY = pold.m(); Energy2 A = a[0]*b[1]*S; Energy2 B = Energy2(sqr(MDY)) - (a[0]*b[0]+a[1]*b[1])*S - (p1p+p2p).m2(); Energy2 C = a[1]*b[0]*S; double rad = 1.-4.*A*C/sqr(B); if(rad < 0.) throw KinematicsReconstructionVeto(); double kp = B/(2.*A)*(1.+sqrt(rad)); // now compute k1 // conserve rapidity double k1(0.); double k2(0.); if(_initialStateReconOption==0) { rad = kp*(b[0]+kp*b[1])/(kp*a[0]+a[1]); rad *= pq[0].z()1e-10) { double discrim = 1.-4.*a2*c2/sqr(b2); if(discrim < 0.) throw KinematicsReconstructionVeto(); k1 = b2>0. ? 0.5*b2/a2*(1.+sqrt(discrim)) : 0.5*b2/a2*(1.-sqrt(discrim)); } else { k1 = -c2/a2; if( k1 <= 0.) throw KinematicsReconstructionVeto(); k1 = sqrt(k1); } k2 = kp/k1; } // preserve mass and don't scale the softer system // to reproduce the dipole kinematics else if(_initialStateReconOption==2) { // in this case kp = k1 or k2 depending on who's the harder guy k1 = kp; k2 = 1.; if ( highestpts[0] < highestpts[1] ) swap(k1,k2); } else assert(false); // calculate the boosts vector beta(2); beta[0] = getBeta((a[0]+b[0]), (a[0]-b[0]), (k1*a[0]+b[0]/k1), (k1*a[0]-b[0]/k1)); beta[1] = getBeta((a[1]+b[1]), (a[1]-b[1]), (a[1]/k2+k2*b[1]), (a[1]/k2-k2*b[1])); if (pq[0].z() > ZERO) { beta[0] = -beta[0]; beta[1] = -beta[1]; } return beta; } void QTildeReconstructor:: reconstructColourSinglets(vector & ShowerHardJets, ShowerInteraction::Type type) const { // identify and catagorize the colour singlet systems unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0); vector systems(identifySystems(set(ShowerHardJets.begin(),ShowerHardJets.end()), nnun,nnii,nnif,nnf,nni)); // now decide what to do // initial-initial connection and final-state colour singlet systems LorentzRotation toRest,fromRest; bool applyBoost(false),general(false); // Drell-Yan type if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) { // reconstruct initial-initial system for(unsigned int ix=0;ix0&&nni==1)|| (nnif==2&& nni==0))) { // check these systems can be reconstructed for(unsigned int ix=0;ixprogenitor()->isFinalState()) q += systems[ix].jets[iy]->progenitor()->momentum(); else q -= systems[ix].jets[iy]->progenitor()->momentum(); } q.rescaleMass(); // check above cut if(abs(q.m())>=_minQ) continue; if(nnif==1&&nni==1) { throw KinematicsReconstructionVeto(); } else { general = true; break; } } if(!general) { for(unsigned int ix=0;ix0&&nni==2) { general = type !=ShowerInteraction::QCD; } // general type else { general = true; } // final-state systems except for general recon if(!general) { for(unsigned int ix=0;ix JetKinVect; + +/** + * Enum to identify types of colour singlet systems + */ +enum SystemType { UNDEFINED=-1, II, IF, F ,I }; + +/** + * Struct to store colour singlets + */ +template struct ColourSinglet { + + typedef vector > VecType; + + ColourSinglet() : type(UNDEFINED) {} + + ColourSinglet(SystemType intype,Value inpart) + : type(intype),jets(1,inpart) {} + + /** + * The type of system + */ + SystemType type; + + /** + * The jets in the system + */ + vector jets; + +}; + +/** + * Struct to store a colour singlet system of particles + */ +typedef ColourSinglet ColourSingletSystem; + +/** + * Struct to store a colour singlet shower + */ +typedef ColourSinglet ColourSingletShower; + +/** \ingroup Shower + * + * This class is responsible for the kinematical reconstruction + * after each showering step, and also for the necessary Lorentz boosts + * in order to preserve energy-momentum conservation in the overall collision, + * and also the invariant mass and the rapidity of the hard subprocess system. + * In the case of multi-step showering, there will be not unnecessary + * kinematical reconstructions. + * + * There is also the option of taking a set of momenta for the particles + * and inverting the reconstruction to give the evolution variables for the + * shower. + * + * Notice: + * - although we often use the term "jet" in either methods or variables names, + * or in comments, which could appear applicable only for QCD showering, + * there is indeed no "dynamics" represented in this class: only kinematics + * is involved, as the name of this class remainds. Therefore it can be used + * for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung). + * + * @see ShowerParticle + * @see ShowerKinematics + * @see \ref QTildeReconstructorInterfaces "The interfaces" + * defined for QTildeReconstructor. + */ +class QTildeReconstructor: public KinematicsReconstructor { + +public: + + /** + * Default constructor + */ + QTildeReconstructor() : _reconopt(0), _initialBoost(0), + _finalStateReconOption(0), + _initialStateReconOption(0), _minQ(MeV) {}; + + /** + * Methods to reconstruct the kinematics of a scattering or decay process + */ + //@{ + /** + * Given in input a vector of the particles which initiated the showers + * the method does the reconstruction of such jets, + * including the appropriate boosts (kinematics reshufflings) + * needed to conserve the total energy-momentum of the collision + * and preserving the invariant mass and the rapidity of the + * hard subprocess system. + */ + virtual bool reconstructHardJets(ShowerTreePtr hard, + const map > & pt, + ShowerInteraction::Type type, + bool switchRecon) const; + + /** + * Given in input a vector of the particles which initiated the showers + * the method does the reconstruction of such jets, + * including the appropriate boosts (kinematics reshufflings) + * needed to conserve the total energy-momentum of the collision + * and preserving the invariant mass and the rapidity of the + * hard subprocess system. + */ + virtual bool reconstructDecayJets(ShowerTreePtr decay, + ShowerInteraction::Type type) const; + //@} + + /** + * Methods to invert the reconstruction of the shower for + * a scattering or decay process and calculate + * the variables used to generate the + * shower given the particles produced. + * This is needed for the CKKW and POWHEG approaches + */ + //@{ + /** + * Given the particles, with a history which we wish to interpret + * as a shower reconstruct the variables used to generate the + * shower + */ + virtual bool deconstructDecayJets(HardTreePtr,ShowerInteraction::Type) const; + + /** + * Given the particles, with a history which we wish to interpret + * as a shower reconstruct the variables used to generate the shower + * for a hard process + */ + virtual bool deconstructHardJets(HardTreePtr,ShowerInteraction::Type) const; + //@} + +public: + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +protected: + + /** + * Methods to reconstruct the kinematics of individual jets + */ + //@{ + /** + * Given the particle (ShowerParticle object) that + * originates a forward (time-like) jet, this method reconstructs the kinematics + * of the jet. That is, by starting from the final grand-children (which + * originates directly or indirectly from particleJetParent, + * and which don't have children), and moving "backwards" (in a physical + * time picture), towards the particleJetParent, the + * ShowerKinematics objects associated with the various particles, + * which have been created during the showering, are now completed. + * In particular, at the end, we get the mass of the jet, which is the + * main information we want. + * This methods returns false if there was no radiation or rescaling required + */ + virtual bool reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent) const; + + /** + * Exactly similar to the previous one, but for a space-like jet. + * Also in this case we start from the final grand-children (which + * are childless) of the particle which originates the jet, but in + * this case we proceed "forward" (in the physical time picture) + * towards the particleJetParent. + * This methods returns false if there was no radiation or rescaling required + */ + bool reconstructSpaceLikeJet(const tShowerParticlePtr particleJetParent) const; + + /** + * Exactly similar to the previous one, but for a decay jet + * This methods returns false if there was no radiation or rescaling required + */ + bool reconstructDecayJet(const tShowerParticlePtr particleJetParent) const; + //@} + + /** + * Methods to perform the reconstruction of various types of colour + * singlet systems + */ + //@{ + /** + * Perform the reconstruction of a system with one incoming and at least one + * outgoing particle + */ + void reconstructInitialFinalSystem(vector) const; + + /** + * Perform the reconstruction of a system with only final-state + * particles + */ + void reconstructFinalStateSystem(bool applyBoost, + const LorentzRotation & toRest, + const LorentzRotation & fromRest, + vector) const; + + /** + * Reconstruction of a general coloured system + */ + void reconstructGeneralSystem(vector & ShowerHardJets) const; + + /** + * Reconstruction of a general coloured system doing + * final-final, then initial-final and then initial-initial + */ + void reconstructFinalFirst(vector & ShowerHardJets) const; + + /** + * Reconstruction of a general coloured system doing + * colour parners + */ + void reconstructColourPartner(vector & ShowerHardJets) const; + + /** + * Reconstruction based on colour singlet systems + */ + void reconstructColourSinglets(vector & ShowerHardJets, + ShowerInteraction::Type type) const; + + /** + * Perform the reconstruction of a system with only final-state + * particles + */ + void reconstructInitialInitialSystem(bool & applyBoost, + LorentzRotation & toRest, + LorentzRotation & fromRest, + vector) const; + //@} + + /** + * Methods to perform the inverse reconstruction of various types of + * colour singlet systems + */ + //@{ + /** + * Perform the inverse reconstruction of a system with only final-state + * particles + */ + void deconstructFinalStateSystem(const LorentzRotation & toRest, + const LorentzRotation & fromRest, + HardTreePtr, + vector, + ShowerInteraction::Type) const; + + /** + * Perform the inverse reconstruction of a system with only initial-state + * particles + */ + void deconstructInitialInitialSystem(bool & applyBoost, + LorentzRotation & toRest, + LorentzRotation & fromRest, + HardTreePtr, + vector, + ShowerInteraction::Type ) const; + + /** + * Perform the inverse reconstruction of a system with only initial-state + * particles + */ + void deconstructInitialFinalSystem(HardTreePtr, + vector, + ShowerInteraction::Type ) const; + + bool deconstructGeneralSystem(HardTreePtr, + ShowerInteraction::Type) const; + + bool deconstructColourSinglets(HardTreePtr, + ShowerInteraction::Type) const; + + bool deconstructColourPartner(HardTreePtr, + ShowerInteraction::Type) const; + //@} + + /** + * Recursively treat the most off-shell paricle seperately + * for final-final reconstruction + */ + void reconstructFinalFinalOffShell(JetKinVect orderedJets, Energy2 s, + bool recursive) const; + + /** + * Various methods for the Lorentz transforms needed to do the + * rescalings + */ + //@{ + /** + * Compute the boost to get from the the old momentum to the new + */ + LorentzRotation solveBoost(const double k, + const Lorentz5Momentum & newq, + const Lorentz5Momentum & oldp) const; + + /** + * Compute the boost to get from the the old momentum to the new + */ + LorentzRotation solveBoost(const Lorentz5Momentum & newq, + const Lorentz5Momentum & oldq) const; + + /** + * Compute the boost to get from the the old momentum to the new + */ + LorentzRotation solveBoostZ(const Lorentz5Momentum & newq, + const Lorentz5Momentum & oldq) const; + + /** + * Recursively boost the initial-state shower + * @param p The particle + * @param bv The boost + * @param parent The parent of the chain + */ + void boostChain(tPPtr p, const LorentzRotation & bv, tPPtr & parent) const; + + /** + * Given a 5-momentum and a scale factor, the method returns the + * Lorentz boost that transforms the 3-vector vec{momentum} ---> + * k*vec{momentum}. The method returns the null boost in the case no + * solution exists. This will only work in the case where the + * outgoing jet-momenta are parallel to the momenta of the particles + * leaving the hard subprocess. + */ + Boost solveBoostBeta( const double k, const Lorentz5Momentum & newq, + const Lorentz5Momentum & oldp); + + /** + * Compute boost parameter along z axis to get (Ep, any perp, qp) + * from (E, same perp, q). + */ + double getBeta(const double E, const double q, + const double Ep, const double qp) const + {return (q*E-qp*Ep)/(sqr(qp)+sqr(E));} + //@} + + /** + * Methods to calculate the various scaling factors + */ + //@{ + /** + * Given a vector of 5-momenta of jets, where the 3-momenta are the initial + * ones before showering and the masses are reconstructed after the showering, + * this method returns the overall scaling factor for the 3-momenta of the + * vector of particles, vec{P}_i -> k * vec{P}_i, such to preserve energy- + * momentum conservation, i.e. after the rescaling the center of mass 5-momentum + * is equal to the one specified in input, cmMomentum. + * The method returns 0 if such factor cannot be found. + * @param root_s Centre-of-mass energy + * @param jets The jets + */ + double solveKfactor( const Energy & root_s, const JetKinVect & jets ) const; + + /** + * Calculate the rescaling factors for the jets in a particle decay where + * there was initial-state radiation + * @param mb The mass of the decaying particle + * @param n The reference vector for the initial state radiation + * @param pjet The momentum of the initial-state jet + * @param jetKinematics The JetKinStruct objects for the jets + * @param partner The colour partner + * @param ppartner The momentum of the colour partner of the decaying particle + * before and after radiation + * @param k1 The rescaling parameter for the partner + * @param k2 The rescaling parameter for the outgoing singlet + * @param qt The transverse momentum vector + */ + bool solveDecayKFactor(Energy mb, + const Lorentz5Momentum & n, + const Lorentz5Momentum & pjet, + const JetKinVect & jetKinematics, + ShowerParticlePtr partner, + Lorentz5Momentum ppartner[2], + double & k1, + double & k2, + Lorentz5Momentum & qt) const; + + /** + * Compute the momentum rescaling factor needed to invert the shower + * @param pout The momenta of the outgoing particles + * @param mon The on-shell masses + * @param roots The mass of the decaying particle + */ + double inverseRescalingFactor(vector pout, + vector mon,Energy roots) const; + + /** + * Compute the momentum rescaling factor needed to invert the shower + * @param pout The momenta of the outgoing particles + * @param mon The on-shell masses + * @param roots The mass of the decaying particle + * @param ppartner The momentum of the colour partner + * @param mbar The mass of the decaying particle + * @param k1 The first scaling factor + * @param k2 The second scaling factor + */ + bool inverseDecayRescalingFactor(vector pout, + vector mon,Energy roots, + Lorentz5Momentum ppartner, Energy mbar, + double & k1, double & k2) const; + + /** + * Check the rescaling conserves momentum + * @param k The rescaling + * @param root_s The centre-of-mass energy + * @param jets The jets + */ + Energy momConsEq(double k, const Energy & root_s, + const JetKinVect & jets) const; + + + void findInitialBoost(const Lorentz5Momentum & pold, const Lorentz5Momentum & pnew, + LorentzRotation & toRest, LorentzRotation & fromRest) const; + //@} + + /** + * Find the colour partners of a particle to identify the colour singlet + * systems for the reconstruction. + */ + template void findPartners(Value branch,set & done, + const set & branchings, + vector & jets) const; + + /** + * Add the intrinsic \f$p_T\f$ to the system if needed + */ + bool addIntrinsicPt(vector) const; + + /** + * Apply a transform to the particle and any child, including child ShowerTree + * objects + * @param particle The particle + * @param r The Lorentz transformation + * @param match Whether or not to look at children etc + * @param original The original particle + */ + void deepTransform(PPtr particle,const LorentzRotation & r, + bool match=true,PPtr original=PPtr()) const; + + /** + * Find the mass of a particle in the hard branching + */ + Energy findMass(HardBranchingPtr) const; + + /** + * Calculate the initial-state rescaling factors + */ + vector initialStateRescaling(double x1, double x2, + const Lorentz5Momentum & pold, + const vector & p, + const vector & pq, + const vector& highespts) const; + + /** + * Calculate the inverse of the initial-state rescaling factor + */ + vector inverseInitialStateRescaling(double & x1, double & x2, + const Lorentz5Momentum & pold, + const vector & p, + const vector & pq) const; + + /** + * Find the colour singlet systems + */ + template + typename ColourSinglet::VecType identifySystems(set jets, + unsigned int & nnun,unsigned int & nnii, + unsigned int & nnif,unsigned int & nnf, + unsigned int & nni) const; + + /** + * Combine final-state colour systems + */ + template + void combineFinalState(vector > & systems) const; + +protected: + + /** @name Clone Methods. */ + //@{ + /** + * Make a simple clone of this object. + * @return a pointer to the new object. + */ + virtual IBPtr clone() const {return new_ptr(*this);} + + /** Make a clone of this object, possibly modifying the cloned object + * to make it sane. + * @return a pointer to the new object. + */ + virtual IBPtr fullclone() const {return new_ptr(*this);} + //@} + +protected: + + /** @name Standard Interfaced functions. */ + //@{ + /** + * Initialize this object after the setup phase before saving an + * EventGenerator to disk. + * @throws InitException if object could not be initialized properly. + */ + virtual void doinit(); + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + QTildeReconstructor & operator=(const QTildeReconstructor &); + +private: + + /** + * Option for handling the reconstruction + */ + unsigned int _reconopt; + + /** + * Option for the boost for initial-initial reconstruction + */ + unsigned int _initialBoost; + + /** + * Option for the reconstruction of final state systems + */ + unsigned int _finalStateReconOption; + + /** + * Option for the initial state reconstruction + */ + unsigned int _initialStateReconOption; + + /** + * Minimum invariant mass for initial-final dipoles to allow the + * reconstruction + */ + Energy _minQ; + + /** + * The progenitor of the jet currently being reconstructed + */ + mutable tShowerParticlePtr _progenitor; + + /** + * Storage of the intrinsic \f$p_T\f$ + */ + mutable map > _intrinsic; + + /** + * Current ShowerTree + */ + mutable tShowerTreePtr _currentTree; + + /** + * Particles which shouldn't have their masses rescaled as + * vector for the interface + */ + PDVector _noRescaleVector; + + /** + * Particles which shouldn't have their masses rescaled as + * set for quick access + */ + set _noRescale; + + /** + * Storage of the boosts applied to enable resetting after failure + */ + mutable map > _boosts; + + /** + * Storage of the boosts applied to enable resetting after failure + */ + mutable map > _treeBoosts; +}; + +} + +#include "QTildeReconstructor.tcc" +#endif /* HERWIG_QTildeReconstructor_H */ diff --git a/Shower/Default/QTildeReconstructor.tcc b/Shower/QTilde/Default/QTildeReconstructor.tcc rename from Shower/Default/QTildeReconstructor.tcc rename to Shower/QTilde/Default/QTildeReconstructor.tcc diff --git a/Shower/QTilde/Default/QTildeShowerKinematics1to2.cc b/Shower/QTilde/Default/QTildeShowerKinematics1to2.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Default/QTildeShowerKinematics1to2.cc @@ -0,0 +1,133 @@ +// -*- C++ -*- +// +// QTildeShowerKinematics1to2.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 QTildeShowerKinematics1to2 class. +// + +#include "QTildeShowerKinematics1to2.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" +#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" +#include "ThePEG/Helicity/LorentzSpinorBar.h" + +using namespace Herwig; +using namespace ThePEG::Helicity; + +vector QTildeShowerKinematics1to2::getBasis() const { + vector dum; + dum.push_back( _pVector ); + dum.push_back( _nVector ); + return dum; +} + +void QTildeShowerKinematics1to2::setBasis(const Lorentz5Momentum &p, + const Lorentz5Momentum & n, + Frame inframe) { + _pVector=p; + _nVector=n; + frame(inframe); + Boost beta_bb; + if(frame()==BackToBack) { + beta_bb = -(_pVector + _nVector).boostVector(); + } + else if(frame()==Rest) { + beta_bb = -pVector().boostVector(); + } + else + assert(false); + Lorentz5Momentum p_bb = pVector(); + Lorentz5Momentum n_bb = nVector(); + p_bb.boost( beta_bb ); + n_bb.boost( beta_bb ); + // rotate to have z-axis parallel to p/n + Axis axis; + if(frame()==BackToBack) { + axis = p_bb.vect().unit(); + } + else if(frame()==Rest) { + axis = n_bb.vect().unit(); + } + else + assert(false); + LorentzRotation rot; + if(axis.perp2()>1e-10) { + double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); + rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); + } + else if(axis.z()<0.) { + rot.rotate(Constants::pi,Axis(1.,0.,0.)); + } + _xPerp=LorentzVector(1.,0.,0.,0.); + _yPerp=LorentzVector(0.,1.,0.,0.); + _xPerp.transform(rot); + _yPerp.transform(rot); + // boost back + _xPerp.boost( -beta_bb ); + _yPerp.boost( -beta_bb ); +} + +void QTildeShowerKinematics1to2::setMomentum(tShowerParticlePtr particle, + bool timeLike) const { + Energy mass = particle->mass() > ZERO ? particle->mass() : particle->data().mass(); + // calculate the momentum of the assuming on-shell + Energy2 pt2 = sqr(particle->showerParameters().pt); + double alpha = timeLike ? particle->showerParameters().alpha : particle->x(); + double beta = 0.5*(sqr(mass) + pt2 - sqr(alpha)*pVector().m2())/(alpha*p_dot_n()); + Lorentz5Momentum porig=sudakov2Momentum(alpha,beta, + particle->showerParameters().ptx, + particle->showerParameters().pty); + porig.setMass(mass); + particle->set5Momentum(porig); +} + +void QTildeShowerKinematics1to2::constructSpinInfo(tShowerParticlePtr particle, + bool timeLike) const { + // now construct the required spininfo and calculate the basis states + PDT::Spin spin(particle->dataPtr()->iSpin()); + if(spin==PDT::Spin0) { + ScalarWaveFunction::constructSpinInfo(particle,outgoing,timeLike); + } + // calculate the basis states and construct the SpinInfo for a spin-1/2 particle + else if(spin==PDT::Spin1Half) { + // outgoing particle + if(particle->id()>0) { + vector > stemp; + SpinorBarWaveFunction::calculateWaveFunctions(stemp,particle,outgoing); + SpinorBarWaveFunction::constructSpinInfo(stemp,particle,outgoing,timeLike); + } + // outgoing antiparticle + else { + vector > stemp; + SpinorWaveFunction::calculateWaveFunctions(stemp,particle,outgoing); + SpinorWaveFunction::constructSpinInfo(stemp,particle,outgoing,timeLike); + } + } + // calculate the basis states and construct the SpinInfo for a spin-1 particle + else if(spin==PDT::Spin1) { + bool massless(particle->id()==ParticleID::g||particle->id()==ParticleID::gamma); + vector vtemp; + VectorWaveFunction::calculateWaveFunctions(vtemp,particle,outgoing,massless); + VectorWaveFunction::constructSpinInfo(vtemp,particle,outgoing,timeLike,massless); + } + else { + throw Exception() << "Spins higher than 1 are not yet implemented in " + << "FS_QtildaShowerKinematics1to2::constructVertex() " + << Exception::runerror; + } +} +void QTildeShowerKinematics1to2::transform(const LorentzRotation & r) { + _pVector *= r; + _nVector *= r; + _xPerp *= r; + _yPerp *= r; +} diff --git a/Shower/QTilde/Default/QTildeShowerKinematics1to2.h b/Shower/QTilde/Default/QTildeShowerKinematics1to2.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Default/QTildeShowerKinematics1to2.h @@ -0,0 +1,132 @@ +// -*- C++ -*- +// +// QTildeShowerKinematics1to2.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_QTildeShowerKinematics1to2_H +#define HERWIG_QTildeShowerKinematics1to2_H +// +// This is the declaration of the QTildeShowerKinematics1to2 class. +// + +#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" +#include "ThePEG/Vectors/Lorentz5Vector.h" +#include "QTildeShowerKinematics1to2.fh" + +namespace Herwig { + +using namespace ThePEG; + +/** \ingroup Shower + * + * This abstract class describes the common features for initial and final + * state radiation kinematics for \f$1\to2\f$ branchings and for + * the choice of \f$\tilde{q}\f$ as evolution variable. + * + * @see ShowerKinematics + * @see IS_QTildeShowerKinematics1to2 + * @see FS_QTildeShowerKinematics1to2 + * @see KinematicsReconstructor + */ +class QTildeShowerKinematics1to2: public ShowerKinematics { + +public: + + /** + * Implementation of the virtual function returning a set of basis vectors, specific to + * the type of evolution. This function will be used by the + * ForwardShowerEvolver in order to access \f$p\f$ + * and \f$n\f$. + */ + virtual vector getBasis() const; + + /** + * Access to the \f$p\f$ vector used to describe the kinematics. + */ + const Lorentz5Momentum & pVector() const {return _pVector;} + + /** + * Access to the \f$n\f$ vector used to describe the kinematics. + */ + const Lorentz5Momentum & nVector() const {return _nVector;} + + /** + * Dot product of thew basis vectors + */ + Energy2 p_dot_n() const {return _pVector*_nVector;} + + /** + * Converts a Sudakov parametrization of a momentum w.r.t. the given + * basis \f$p\f$ and \f$n\f$ into a 5 momentum. + * @param alpha The \f$\alpha\f$ parameter of the Sudakov parameterisation + * @param beta The \f$\beta\f$ parameter of the Sudakov parameterisation + * @param px The \f$x\f$-component of the transverse momentum in the Sudakov + * parameterisation + * @param py The \f$x\f$-component of the transverse momentum in the Sudakov + * parameterisation + */ + Lorentz5Momentum sudakov2Momentum(double alpha, double beta, + Energy px, Energy py) const { + return alpha*_pVector + beta*_nVector + px*_xPerp+py*_yPerp; + } + + /** + * Transform the shower kinematics (usually the reference vectors) + */ + virtual void transform(const LorentzRotation & r); + +protected: + + /** + * Set the basis vectors + */ + void setBasis(const Lorentz5Momentum &p, const Lorentz5Momentum & n, + Frame frame); + + /** + * Set a preliminary momentum for the particle + */ + void setMomentum(tShowerParticlePtr,bool timelike) const; + + /** + * Construct the spin info object for a shower particle + */ + void constructSpinInfo(tShowerParticlePtr,bool timelike) const; + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + QTildeShowerKinematics1to2 & operator=(const QTildeShowerKinematics1to2 &); + +private: + + /** + * The \f$p\f$ reference vector + */ + Lorentz5Momentum _pVector; + + /** + * The \f$n\f$ reference vector + */ + Lorentz5Momentum _nVector; + + /** + * x \f$q_\perp\f$ reference vector + */ + LorentzVector _xPerp; + + /** + * y \f$q_\perp\f$reference vector + */ + LorentzVector _yPerp; +}; + +} + +#endif /* HERWIG_QTildeShowerKinematics1to2_H */ diff --git a/Shower/Default/QTildeSudakov.cc b/Shower/QTilde/Default/QTildeSudakov.cc rename from Shower/Default/QTildeSudakov.cc rename to Shower/QTilde/Default/QTildeSudakov.cc --- a/Shower/Default/QTildeSudakov.cc +++ b/Shower/QTilde/Default/QTildeSudakov.cc @@ -1,1062 +1,1060 @@ // -*- 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 "Herwig/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h" +#include "Herwig/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h" +#include "Herwig/Shower/QTilde/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" +#include "Herwig/Shower/QTilde/Base/ShowerVertex.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/QTildeShowerHandler.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/ShowerModel.h" +#include "Herwig/Shower/QTilde/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, - const double & detune) { + double detune) { Energy2 told = t; // calculate limits on z and if lower>upper return if(!computeTimeLikeLimits(t)) return false; // guess values of t and z t = guesst(told,0,ids_,enhance,ids_[1]==ids_[2],detune); z(guessz(0,ids_)); // actual values for z-limits if(!computeTimeLikeLimits(t)) return false; if(tupper return if(!computeSpaceLikeLimits(t,x)) return false; // guess values of t and z t = guesst(told,1,ids_,enhance,ids_[1]==ids_[2],detune); z(guessz(1,ids_)); // actual values for z-limits if(!computeSpaceLikeLimits(t,x)) return false; if(t zLimits().second) return true; Energy2 q2 = z()*(1.-z())*t; if(ids_[0]->id()!=ParticleID::g && ids_[0]->id()!=ParticleID::gamma ) q2 += masssquared_[0]; if(q2>maxQ2) return true; // compute the pts Energy2 pt2 = z()*(1.-z())*q2 - masssquared_[1]*(1.-z()) - masssquared_[2]*z(); // if pt2<0 veto if(pt2 min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax); // no shower variations to calculate if(ShowerHandler::currentHandler()->showerVariations().empty()){ // Without variations do the usual Veto algorithm // No need for more if-statements in this loop. do { if(!guessTimeLike(t,tmin,enhance,detuning)) break; } while(PSVeto(t,maxQ2) || SplittingFnVeto(z()*(1.-z())*t,ids,true,rho,detuning) || alphaSVeto(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t)); } - else{ + else { bool alphaRew(true),PSRew(true),SplitRew(true); do { if(!guessTimeLike(t,tmin,enhance,detuning)) break; PSRew=PSVeto(t,maxQ2); if (PSRew) continue; SplitRew=SplittingFnVeto(z()*(1.-z())*t,ids,true,rho,detuning); alphaRew=alphaSVeto(splittingFn()->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,detuning); - ShowerHandlerPtr ch = ShowerHandler::currentHandler(); + tShowerHandlerPtr ch = ShowerHandler::currentHandler(); if( !(SplitRew || alphaRew) ) { //Emission q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if (q_ <= ZERO) break; } - for ( map::const_iterator var = + 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,detuning); double varied; if ( SplitRew || alphaRew ) { // No Emission varied = (1. - newfactor) / (1. - factor); } else { // Emission varied = newfactor / factor; } map::iterator wi = ch->currentWeights().find(var->first); if ( wi != ch->currentWeights().end() ) wi->second *= varied; else { assert(false); //ch->currentWeights()[var->first] = varied; } } } } while(PSRew || SplitRew || alphaRew); } q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if(q_ < ZERO) return ShoKinPtr(); // return the ShowerKinematics object return createFinalStateBranching(q_,z(),phi(),pT()); } ShoKinPtr QTildeSudakov:: generateNextSpaceBranching(const Energy startingQ, const IdList &ids, double x, const RhoDMatrix & rho, double enhance, Ptr::transient_const_pointer beam, double detuning) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to the method. q_ = ZERO; z(0.); phi(0.); // perform the initialization Energy2 tmax(sqr(startingQ)),tmin; initialize(ids,tmin); // check max > min if(tmax<=tmin) return ShoKinPtr(); // calculate next value of t using veto algorithm Energy2 t(tmax),pt2(ZERO); // no shower variations if(ShowerHandler::currentHandler()->showerVariations().empty()) { // Without variations do the usual Veto algorithm // No need for more if-statements in this loop. do { if(!guessSpaceLike(t,tmin,x,enhance,detuning)) break; pt2=sqr(1.-z())*t-z()*masssquared_[2]; } while(pt2 < pT2min()|| z() > zLimits().second|| - SplittingFnVeto((1.-z())*t/z(),ids,true,rho,detuning)|| + SplittingFnVeto((1.-z())*t/z(),ids,false,rho,detuning)|| alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t)|| PDFVeto(t,x,ids[0],ids[1],beam)); } // shower variations - else{ + else { bool alphaRew(true),PDFRew(true),ptRew(true),zRew(true),SplitRew(true); do { if(!guessSpaceLike(t,tmin,x,enhance,detuning)) break; pt2=sqr(1.-z())*t-z()*masssquared_[2]; ptRew=pt2 < pT2min(); zRew=z() > zLimits().second; if (ptRew||zRew) continue; - SplitRew=SplittingFnVeto((1.-z())*t/z(),ids,true,rho,detuning); + SplitRew=SplittingFnVeto((1.-z())*t/z(),ids,false,rho,detuning); 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,detuning); + SplittingFnVetoRatio((1.-z())*t/z(),ids,false,rho,detuning); - ShowerHandlerPtr ch = ShowerHandler::currentHandler(); + tShowerHandlerPtr ch = ShowerHandler::currentHandler(); if( !(PDFRew || SplitRew || alphaRew) ) { //Emission q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV; if (q_ <= ZERO) break; } - for ( map::const_iterator var = + 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,detuning); + *SplittingFnVetoRatio((1.-z())*t/z(),ids,false,rho,detuning); double varied; if( PDFRew || SplitRew || alphaRew) { // No Emission varied = (1. - newfactor) / (1. - factor); } else { // Emission varied = newfactor / factor; } map::iterator wi = ch->currentWeights().find(var->first); if ( wi != ch->currentWeights().end() ) - wi->second *= varied; + 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, double detuning) { // First reset the internal kinematics variables that can // have been eventually set in the previous call to this method. q_ = Constants::MaxEnergy; z(0.); phi(0.); // perform initialisation Energy2 tmax(sqr(stoppingScale)),tmin; initialize(ids,tmin); tmin=sqr(startingScale); // check some branching possible if(tmax<=tmin) return ShoKinPtr(); // perform the evolution Energy2 t(tmin),pt2(-MeV2); do { if(!guessDecay(t,tmax,minmass,enhance,detuning)) break; pt2 = sqr(1.-z())*(t-masssquared_[0])-z()*masssquared_[2]; } while(SplittingFnVeto((1.-z())*t/z(),ids,true,rho,detuning)|| alphaSVeto(splittingFn()->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, const double & detune) { + double enhance, double detune) { // 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()) + if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy2 t = z*(1.-z)*sqr(kinematics->scale()); Energy pT = kinematics->pT(); // if soft correlations Energy2 pipj,pik; bool canBeSoft[2] = {ids[1]->id()==ParticleID::g || ids[1]->id()==ParticleID::gamma, ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma }; 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()&& + bool softAllowed = dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()&& (canBeSoft[0] || canBeSoft[1]); if(softAllowed) { // find the partner for the soft correlations tShowerParticlePtr partner=findCorrelationPartner(particle,true,splittingFn()->interactionType()); // remember we want the softer gluon bool swapOrder = !canBeSoft[1] || (canBeSoft[0] && canBeSoft[1] && z < 0.5); double zFact = !swapOrder ? (1.-z) : z; // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); Boost beta_bb; if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) { beta_bb = -(pVect + nVect).boostVector(); } else if(particle.showerBasis()->frame()==ShowerBasis::Rest) { beta_bb = -pVect.boostVector(); } else assert(false); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis; if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) { axis = pVect.vect().unit(); } else if(particle.showerBasis()->frame()==ShowerBasis::Rest) { axis = nVect.vect().unit(); } else assert(false); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect, m2 = pVect.m2(); double alpha0 = particle.showerParameters().alpha; double beta0 = 0.5/alpha0/pn* (sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt)); Lorentz5Momentum qperp0(particle.showerParameters().ptx, particle.showerParameters().pty,ZERO,ZERO); assert(partner); Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; // compute the two phi independent dot products pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn ) +0.5*sqr(pT)/zFact; Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; Energy2 dot3 = pj*qperp0; pipj = alpha0*dot1+beta0*dot2+dot3; // compute the constants for the phi dependent dot product pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*dot2/pn/zFact/alpha0; pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT; pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT; m12 = sqr(particle.dataPtr()->mass()); m22 = sqr(partner->dataPtr()->mass()); if(swapOrder) { pjk[1] *= -1.; pjk[2] *= -1.; } Ek[0] = zFact*(alpha0*pVect.t()-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0; Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT; Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT; if(swapOrder) { Ek[1] *= -1.; Ek[2] *= -1.; } Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2])); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); double phi0 = atan2(-pjk[2],-pjk[1]); if(phi0<0.) phi0 += Constants::twopi; double phi1 = atan2(-Ek[2],-Ek[1]); if(phi1<0.) phi1 += Constants::twopi; double xi_min = pik/Ei/(Ek[0]+mag2), xi_max = pik/Ei/(Ek[0]-mag2), xi_ij = pipj/Ei/Ej; if(xi_min>xi_max) swap(xi_min,xi_max); if(xi_min>xi_ij) softAllowed = false; Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2])); - if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { + if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } - else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { + else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { double A = (pipj*Ek[0]- Ej*pik)/Ej/sqr(Ej); double B = -sqrt(sqr(pipj)*(sqr(Ek[1])+sqr(Ek[2])))/Ej/sqr(Ej); double C = pjk[0]/sqr(Ej); double D = -sqrt(sqr(pjk[1])+sqr(pjk[2]))/sqr(Ej); pair minima = softPhiMin(phi0,phi1,A,B,C,D); aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + max(Ej*(A+B*cos(minima.first -phi1))/(C+D*cos(minima.first -phi0)), Ej*(A+B*cos(minima.second-phi1))/(C+D*cos(minima.second-phi0)))); } else assert(false); } // if spin correlations - vector > wgts; - if(ShowerHandler::currentHandler()->evolver()->spinCorrelations()) { + vector > wgts; + if(dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations()) { // calculate the weights wgts = splittingFn()->generatePhiForward(z,t,ids,rho); } else { wgts = vector >(1,make_pair(0,1.)); } // generate the azimuthal angle double phi,wgt; static const Complex ii(0.,1.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); // first the spin correlations bit (gives 1 if correlations off) Complex spinWgt = 0.; for(unsigned int ix=0;ix1e-10) { generator()->log() << "Forward spin weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; generator()->log() << "Weights \n"; for(unsigned int ix=0;ixlog() << wgts[ix].first << " " << wgts[ix].second << "\n"; } // soft correlations bit double aziWgt = 1.; if(softAllowed) { Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi); if(pipj*Eg>pik*Ej) { - if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { + if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } - else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { + else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { aziWgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax); } if(aziWgt-1.>1e-10||aziWgt<-1e-10) { generator()->log() << "Forward soft weight problem " << aziWgt << " " << aziWgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } } else { aziWgt = 0.; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi in forward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double QTildeSudakov::generatePhiBackward(ShowerParticle & particle, const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho) { // no correlations, return flat phi - if(! ShowerHandler::currentHandler()->evolver()->correlations()) + if(! dynamic_ptr_cast(ShowerHandler::currentHandler())->correlations()) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy2 t = (1.-z)*sqr(kinematics->scale())/z; Energy pT = kinematics->pT(); // if soft correlations - bool softAllowed = ShowerHandler::currentHandler()->evolver()->softCorrelations() && + bool softAllowed = dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations() && (ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma); Energy2 pipj,pik,m12(ZERO),m22(ZERO); 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) { + if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } - else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { + else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { Ek = alpha0*zFact/(1.-zFact)*pVect.t()+beta2*nVect.t(); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); if(pipj*Ek> Ej*pik) { aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik + (pipj*Ek- Ej*pik)/(pjk[0]-mag)); } else { aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik); } } else { - assert(ShowerHandler::currentHandler()->evolver()->softCorrelations()==0); + assert(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==0); } } // if spin correlations vector > wgts; - if(ShowerHandler::currentHandler()->evolver()->spinCorrelations()) { - // get the spin density matrix and the mapping + if(dynamic_ptr_cast(ShowerHandler::currentHandler())->spinCorrelations()) { // get the weights wgts = splittingFn()->generatePhiBackward(z,t,ids,rho); } else { wgts = vector >(1,make_pair(0,1.)); } // generate the azimuthal angle double phi,wgt; static const Complex ii(0.,1.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); Complex spinWgt = 0.; for(unsigned int ix=0;ix1e-10) { generator()->log() << "Backward weight problem " << wgt << " " << wgt-1. - << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << z << " " << phi << "\n"; + << " " << 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) { + if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } - else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { + else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { aziWgt = max(ZERO,0.5/pik/Ek*(Ei-m12*Ek/pik + pipj*Ek/dot - Ej*pik/dot)/aziMax); } if(aziWgt-1.>1e-10||aziWgt<-1e-10) { generator()->log() << "Backward soft weight problem " << aziWgt << " " << aziWgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } } wgt *= aziWgt; if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi in backward evolution\n"; phi = phiMax; } // return the azimuthal angle return phi; } double 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() && + if( !(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations() && (ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma ))) return Constants::twopi*UseRandom::rnd(); // get the kinematic variables double z = kinematics->z(); Energy pT = kinematics->pT(); // if soft correlations // find the partner for the soft correlations tShowerParticlePtr partner = findCorrelationPartner(particle,true,splittingFn()->interactionType()); double zFact(1.-z); // compute the transforms to the shower reference frame // first the boost Lorentz5Momentum pVect = particle.showerBasis()->pVector(); Lorentz5Momentum nVect = particle.showerBasis()->nVector(); assert(particle.showerBasis()->frame()==ShowerBasis::Rest); Boost beta_bb = -pVect.boostVector(); pVect.boost(beta_bb); nVect.boost(beta_bb); Axis axis = nVect.vect().unit(); // and then the rotation LorentzRotation rot; if(axis.perp2()>0.) { double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); } else if(axis.z()<0.) { rot.rotate(Constants::pi,Axis(1.,0.,0.)); } rot.invert(); pVect *= rot; nVect *= rot; // shower parameters Energy2 pn = pVect*nVect; Energy2 m2 = pVect.m2(); double alpha0 = particle.showerParameters().alpha; double beta0 = 0.5/alpha0/pn* (sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt)); Lorentz5Momentum qperp0(particle.showerParameters().ptx, particle.showerParameters().pty,ZERO,ZERO); Lorentz5Momentum pj = partner->momentum(); pj.boost(beta_bb); pj *= rot; // compute the two phi independent dot products Energy2 pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn ) +0.5*sqr(pT)/zFact; Energy2 dot1 = pj*pVect; Energy2 dot2 = pj*nVect; Energy2 dot3 = pj*qperp0; Energy2 pipj = alpha0*dot1+beta0*dot2+dot3; // compute the constants for the phi dependent dot product 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) { + if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag); } - else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { + else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { Ek[0] = zFact*(alpha0*pVect.t()+-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0)) +0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0; Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT; Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT; Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2])); Ei = alpha0*pVect.t()+beta0*nVect.t(); Ej = pj.t(); aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + pipj*(Ek[0]+mag2)/(pjk[0]-mag) - Ej*pik/(pjk[0]-mag) ); } else - assert(ShowerHandler::currentHandler()->evolver()->softCorrelations()==0); + assert(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==0); // generate the azimuthal angle double phi,wgt(0.); unsigned int ntry(0); double phiMax(0.),wgtMax(0.); do { phi = Constants::twopi*UseRandom::rnd(); Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi); - if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==1) { + if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==1) { wgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax; } - else if(ShowerHandler::currentHandler()->evolver()->softCorrelations()==2) { + else if(dynamic_ptr_cast(ShowerHandler::currentHandler())->softCorrelations()==2) { if(qperp0.m2()==ZERO) { wgt = 1.; } else { Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi); wgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax); } } if(wgt-1.>1e-10||wgt<-1e-10) { generator()->log() << "Decay soft weight problem " << wgt << " " << wgt-1. << " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n"; } if(wgt>wgtMax) { phiMax = phi; wgtMax = wgt; } ++ntry; } while(wgtlog() << "Too many tries to generate phi\n"; } // return the azimuthal angle return phi; } Energy 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/Default/QTildeSudakov.h b/Shower/QTilde/Default/QTildeSudakov.h rename from Shower/Default/QTildeSudakov.h rename to Shower/QTilde/Default/QTildeSudakov.h --- a/Shower/Default/QTildeSudakov.h +++ b/Shower/QTilde/Default/QTildeSudakov.h @@ -1,291 +1,291 @@ // -*- C++ -*- // // QTildeSudakov.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef HERWIG_QTildeSudakov_H #define HERWIG_QTildeSudakov_H // // This is the declaration of the QTildeSudakov class. // -#include "Herwig/Shower/Base/SudakovFormFactor.h" +#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * The QTildeSudakov class implements the Sudakov form factor for evolution in * \f$\tilde{q}^2\f$ using the veto algorithm. * * @see \ref QTildeSudakovInterfaces "The interfaces" * defined for QTildeSudakov. */ class QTildeSudakov: public SudakovFormFactor { public: /** * The default constructor. */ inline QTildeSudakov() {} /** * Members to generate the scale of the next branching */ //@{ /** * Return the scale of the next time-like branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param ids The PDG codes of the particles in the splitting * @param 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, double detuning, Energy2 maxQ2); /** * Return the scale of the next space-like decay branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param stoppingScale stopping scale for the evolution * @param minmass The minimum mass allowed for the spake-like particle. * @param ids The PDG codes of the particles in the splitting * defined. * @param enhance The radiation enhancement factor */ virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale, const Energy stoppingScale, const Energy minmass, const IdList &ids, const RhoDMatrix & rho, double enhance, double detuning); /** * Return the scale of the next space-like branching. If there is no * branching then it returns ZERO. * @param startingScale starting scale for the evolution * @param ids The PDG codes of the particles in the splitting * @param x The fraction of the beam momentum * defined. * @param enhance The radiation enhancement factor * @param beam The beam particle */ virtual ShoKinPtr generateNextSpaceBranching(const Energy startingScale, const IdList &ids,double x, const RhoDMatrix & rho, double enhance, tcBeamPtr beam, double detuning); //@} /** * Generate the azimuthal angle of the branching for forward branching * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiForward(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho); /** * Generate the azimuthal angle of the branching for backward branching * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiBackward(ShowerParticle & particle,const IdList & ids, - ShoKinPtr kinematics, + ShoKinPtr kinematics, const RhoDMatrix & rho); /** * Generate the azimuthal angle of the branching for ISR in decays * @param particle The branching particle * @param ids The PDG codes of the particles in the branchings * @param The Shower kinematics */ virtual double generatePhiDecay(ShowerParticle & particle,const IdList & ids, ShoKinPtr kinematics, const RhoDMatrix & rho); /** * Method to return the evolution scale given the * transverse momentum, \f$p_T\f$ and \f$z\f$. */ virtual Energy calculateScale(double z, Energy pt, IdList ids,unsigned int iopt); /** * Method to create the ShowerKinematics object for a final-state branching */ virtual ShoKinPtr createFinalStateBranching(Energy scale,double z, double phi, Energy pt); /** * Method to create the ShowerKinematics object for an initial-state branching */ virtual ShoKinPtr createInitialStateBranching(Energy scale,double z, double phi, Energy pt); /** * Method to create the ShowerKinematics object for a decay branching */ virtual ShoKinPtr createDecayBranching(Energy scale,double z, double phi, Energy pt); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * Methods to provide the next value of the scale before the vetos * are applied. */ //@{ /** * Value of the energy fraction and scale for time-like branching * @param t The scale * @param tmin The minimum scale * @param enhance The radiation enhancement factor * @return False if scale less than minimum, true otherwise */ - bool guessTimeLike(Energy2 &t, Energy2 tmin, double enhance, const double & detune); + bool guessTimeLike(Energy2 &t, Energy2 tmin, double enhance, double detune); /** * Value of the energy fraction and scale for time-like branching * @param t The scale * @param tmax The maximum scale * @param minmass The minimum mass of the particle after the branching * @param enhance The radiation enhancement factor */ bool guessDecay(Energy2 &t, Energy2 tmax,Energy minmass, - double enhance, const double & detune); + double enhance, double detune); /** * Value of the energy fraction and scale for space-like branching * @param t The scale * @param tmin The minimum scale * @param x Fraction of the beam momentum. * @param enhance The radiation enhancement factor */ bool guessSpaceLike(Energy2 &t, Energy2 tmin, const double x, - double enhance, const double & detune); + double enhance, double detune); //@} /** * Initialize the values of the cut-offs and scales * @param tmin The minimum scale * @param ids The ids of the partics in the branching */ void initialize(const IdList & ids,Energy2 &tmin); /** * Phase Space veto member to implement the \f$\Theta\f$ function as a veto * so that the emission is within the allowed phase space. * @param t The scale * @param maxQ2 The maximum virtuality * @return true if vetoed */ bool PSVeto(const Energy2 t,const Energy2 maxQ2); /** * Compute the limits on \f$z\f$ for time-like branching * @param scale The scale of the particle * @return True if lower limit less than upper, otherwise false */ bool computeTimeLikeLimits(Energy2 & scale); /** * Compute the limits on \f$z\f$ for space-like branching * @param scale The scale of the particle * @param x The energy fraction of the parton * @return True if lower limit less than upper, otherwise false */ bool computeSpaceLikeLimits(Energy2 & scale, double x); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ inline virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ inline virtual IBPtr fullclone() const {return new_ptr(*this);} //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeSudakov & operator=(const QTildeSudakov &); private: /** * The evolution scale, \f$\tilde{q}\f$. */ Energy q_; /** * The Ids of the particles in the current branching */ IdList ids_; /** * The masses of the particles in the current branching */ vector masses_; /** * The mass squared of the particles in the current branching */ vector masssquared_; }; } #endif /* HERWIG_QTildeSudakov_H */ diff --git a/Shower/Makefile.am b/Shower/QTilde/Makefile.am copy from Shower/Makefile.am copy to Shower/QTilde/Makefile.am --- a/Shower/Makefile.am +++ b/Shower/QTilde/Makefile.am @@ -1,50 +1,28 @@ SUBDIRS = Matching . pkglib_LTLIBRARIES = HwShower.la -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_LDFLAGS = $(AM_LDFLAGS) -module -version-info 22:0:0 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 \ +QTildeShowerHandler.h QTildeShowerHandler.fh QTildeShowerHandler.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 +Base/ShowerVeto.h Base/ShowerVeto.fh Base/ShowerVeto.cc \ +Base/FullShowerVeto.h Base/FullShowerVeto.fh Base/FullShowerVeto.cc diff --git a/Shower/Matching/CKKWTree.cc b/Shower/QTilde/Matching/CKKWTree.cc rename from Shower/Matching/CKKWTree.cc rename to Shower/QTilde/Matching/CKKWTree.cc diff --git a/Shower/Matching/CKKWTree.fh b/Shower/QTilde/Matching/CKKWTree.fh rename from Shower/Matching/CKKWTree.fh rename to Shower/QTilde/Matching/CKKWTree.fh diff --git a/Shower/Matching/CKKWTree.h b/Shower/QTilde/Matching/CKKWTree.h rename from Shower/Matching/CKKWTree.h rename to Shower/QTilde/Matching/CKKWTree.h --- a/Shower/Matching/CKKWTree.h +++ b/Shower/QTilde/Matching/CKKWTree.h @@ -1,149 +1,149 @@ // -*- C++ -*- #ifndef HERWIG_CKKWTree_H #define HERWIG_CKKWTree_H // // This is the declaration of the CKKWTree class. // -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/QTilde/Base/HardTree.h" #include "CKKWTree.fh" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the CKKWTree class. */ class CKKWTree: public HardTree { public: /** * The default constructor. */ CKKWTree(vector, vector, ShowerInteraction::Type); public: /** * Returns true if all spacelike lines are ordered in x */ bool checkXOrdering(); /** * Get lowest Pt in which ever jet definition from the hardtree momentum */ Energy lowestPtMomentum( int jetMeasureMode, int cutOption ); /** * Returns true if all lines in tree are ordered in /tilde(q) */ bool checkHardOrdering(); /** * Returns sum of pts of all branchings in tree */ Energy totalPt() { return totalpT_; } /** * Calls recursive function to fill externals and nodes * then finds the internal lines from the nodes */ void findNodes(); /** * Access the nodal branchings */ map< HardBranchingPtr, Energy > & getNodes() { return nodes_; } /** * Get LowestPt in which ever jet definition from the shower variables */ Energy lowestPt( int jetMeasureMode, Energy2 s ); /** * Is the tree ordered? */ bool ordered() const {return ordered_;} protected: /** * Recursive function to find the lowest jet measure in a hardtree from clustered momenta **/ void getLowestJetMeasure( HardBranchingPtr branch, int jetMeasureMode, int cutOption ); /** * Function for finding the hadronic jet measure of two partons **/ Energy hadronJetMeasure( const Lorentz5Momentum & p1, const Lorentz5Momentum & p2, bool final ); /** * Function for finding the Durham or LUCLUS jet measures of two partons **/ Energy getJetMeasure( const Lorentz5Momentum & p1, const Lorentz5Momentum & p2, int jetMeasureMode ); /** * Function to determine whether a branching consists of external partons **/ bool externalBranching( HardBranchingPtr a, HardBranchingPtr b ); /** * Function to recursively find the hard line scales **/ void fillHardScales( HardBranchingPtr branch, vector< pair< Energy, double > > & currentLine ); /** * Recursive function to fill externals, nodes and intermediates from the time-like showers */ bool fillNodes( HardBranchingPtr ); /** * Recursive function to fix the parent assignments */ bool fixParents( HardBranchingPtr ); private: /** * Map containing all nodes with the ingoing partons and their scale * (this is the the intermediates and their ending node). */ map< HardBranchingPtr, Energy > nodes_; /** * Scales and z along each hard line to check ordering */ vector< vector< pair< Energy, double > > > hardLineScales_; /** * The lowest pt of the branchings in the hardtree in whatever * jet measure according to the hardtree momenta (not the shower variables) */ Energy lowestpTMomentum_; /** * The sum of the pts of all branchings */ Energy totalpT_; /** * The hardBranching of softest branching * This is found by looking at tree end points in fillNodes */ HardBranchingPtr lowestpT_; /** * Is the tree ordered */ bool ordered_; }; } #endif /* HERWIG_CKKWTree_H */ diff --git a/Shower/Matching/Makefile.am b/Shower/QTilde/Matching/Makefile.am rename from Shower/Matching/Makefile.am rename to Shower/QTilde/Matching/Makefile.am diff --git a/Shower/QTilde/Matching/MatchingHandler.cc b/Shower/QTilde/Matching/MatchingHandler.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Matching/MatchingHandler.cc @@ -0,0 +1,1088 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the MatchingHandler class. +// + +#include "MatchingHandler.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Interface/Reference.h" +#include "ThePEG/Interface/Switch.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" +#include "ThePEG/PDF/PartonExtractor.h" +#include "ThePEG/PDF/BeamParticleData.h" +#include "ThePEG/PDF/PDF.h" +#include "ThePEG/Cuts/Cuts.h" +#include "Herwig/PDF/HwRemDecayer.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "ThePEG/MatrixElement/Tree2toNDiagram.h" +#include "ThePEG/Utilities/Throw.h" + +using namespace Herwig; + +namespace { +struct ParticleOrdering { + bool operator()(tcPDPtr p1, tcPDPtr p2) { + return abs(p1->id()) > abs(p2->id()) || + ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || + ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); + } +}; +} + +MatchingHandler::MatchingHandler(bool reWeight) + : reWeight_(reWeight), rejectNonAO_( true ), rejectNOHistories_( true ), + includeDecays_(false) +{} + +void MatchingHandler::persistentOutput(PersistentOStream & os) const { + os << alphaS_ << matrixElement_ << HWmatrixElement_ << includeDecays_ + << partonExtractor_ << cuts_ << rejectNonAO_ << rejectNOHistories_ + << allowedInitial_ << allowedFinal_; +} + +void MatchingHandler::persistentInput(PersistentIStream & is, int) { + is >> alphaS_ >> matrixElement_ >> HWmatrixElement_ >> includeDecays_ + >> partonExtractor_ >> cuts_ >> rejectNonAO_ >> rejectNOHistories_ + >> allowedInitial_ >> allowedFinal_; +} + +// *** Attention *** The following static variable is needed for the type +// description system in ThePEG. Please check that the template arguments +// are correct (the class and its base class), and that the constructor +// arguments are correct (the class name and the name of the dynamically +// loadable library where the class implementation can be found). +DescribeAbstractClass +describeHerwigMatchingHandler("Herwig::MatchingHandler", "HwMatching.so"); + +void MatchingHandler::Init() { + + static ClassDocumentation documentation + ("The MatchingHandler class is the base class implementating" + " many of the features needed for matching."); + + static Reference interfaceMatrixElement + ("MatrixElement", + "The matrix element class for the core 2->2 process", + &MatchingHandler::matrixElement_, false, false, true, true, false); + + static Reference interfacePartonExtractor + ("PartonExtractor", + "The PartonExtractor object used to construct remnants. If no object is " + "provided the LesHouchesEventHandler object must provide one instead.", + &MatchingHandler::partonExtractor_, true, false, true, false, false); + + static Reference interfaceCuts + ("Cuts", + "The Cuts object to be used for this reader. Note that these " + "must not be looser cuts than those used in the actual generation. " + "If no object is provided the LesHouchesEventHandler object must " + "provide one instead.", + &MatchingHandler::cuts_, true, false, true, false, false); + + static Reference interfaceShowerAlpha + ("ShowerAlpha", + "The object calculating the strong coupling constant", + &MatchingHandler::alphaS_, false, false, true, true, false); + + static Switch interfaceReject + ("RejectNonOrdered", + "Whether to reject non angular ordered cluster histories", + &MatchingHandler::rejectNonAO_, true, false, false); + static SwitchOption interfaceRejectYes + (interfaceReject, + "Reject", + "Reject all non angular ordered events", + true); + static SwitchOption interfaceRejectNo + (interfaceReject, + "Select", + "Select a history for non angular ordered events", + false); + + static Switch interfaceRejectNoHist + ("RejectNoHistories", + "Whether to reject events with no shower interpretation", + &MatchingHandler::rejectNOHistories_, true, false, false); + static SwitchOption interfaceRejectNoHistYes + (interfaceRejectNoHist, + "Reject", + "Reject all events with no shower interpretation", + true); + static SwitchOption interfaceRejectNoHistNo + (interfaceRejectNoHist, + "Shower", + "Shower events with no shower interpretation directly", + false); + + static Switch interfaceDecayingParticles + ("IncludeDecayingParticles", + "Separate production of decay of unstable particles", + &MatchingHandler::includeDecays_, false, false, false); + static SwitchOption interfaceDecayingParticlesYes + (interfaceDecayingParticles, + "Yes", + "Separate them", + true); + static SwitchOption interfaceDecayingParticlesNo + (interfaceDecayingParticles, + "No", + "Don't separate them", + false); + +} + +void MatchingHandler::doinit() { + ShowerHandler::doinit(); + HWmatrixElement_ = dynamic_ptr_cast(matrixElement_); + + + // check + if(reWeight_ && !alphaS_) { + throw Exception() << "ShowerAlpha must be set in MatchingHandler if " + << "reweighting events" + << Exception::runerror; + } + // extract the allowed branchings + // final-state + for(BranchingList::const_iterator + it = splittingGenerator()->finalStateBranchings().begin(); + it != splittingGenerator()->finalStateBranchings().end(); ++it) { + pair prod(make_pair(it->second.second[1],it->second.second[2])); + allowedFinal_.insert(make_pair(prod,it->second)); + swap(prod.first,prod.second); + allowedFinal_.insert(make_pair(prod,it->second)); + } + // initial-state + for(BranchingList::const_iterator + it = splittingGenerator()->initialStateBranchings().begin(); + it != splittingGenerator()->initialStateBranchings().end(); ++it) { + allowedInitial_.insert(make_pair(it->second.second[0],it->second)); + } +} + +void MatchingHandler::fillProtoTrees( ProtoTreePtr currentProtoTree ) { + if(currentProtoTree->branchings().size()==4) return; + for( set::const_iterator + ita = currentProtoTree->branchings().begin(); + ita!=currentProtoTree->branchings().end();++ita) { + for( set::const_iterator + itb = currentProtoTree->branchings().begin(); + itb!=ita;++itb) { + // can't merge two incoming branchings + if( (**ita).status() == HardBranching::Incoming && + (**itb).status() == HardBranching::Incoming ) continue; + // get a new branching for this pair + ProtoBranchingPtr currentBranching = getCluster(*ita,*itb); + if( ! currentBranching ) continue; + // branching allowed so make a new Tree out of these branchings + set< tProtoBranchingPtr > newTreeBranchings = currentProtoTree->branchings(); + newTreeBranchings.erase(*ita); + newTreeBranchings.erase(*itb); + newTreeBranchings.insert(currentBranching); + ProtoTreePtr newProtoTree = new_ptr( ProtoTree( newTreeBranchings ) ); + // remove duplicate trees + if( ! repeatProtoTree( newProtoTree ) ) protoTrees().insert( newProtoTree ); + // remove the current tree if it hasn't already been removed + if( protoTrees().find( currentProtoTree ) != protoTrees().end() ) + protoTrees().erase( currentProtoTree ); + // do recursion + fillProtoTrees( newProtoTree ); + } + } +} + +tProtoBranchingPtr MatchingHandler::getCluster( tProtoBranchingPtr b1, + tProtoBranchingPtr b2 ) { + //look for the clustered pair in protoBranchings_ + for(set::const_iterator cit = protoBranchings().begin(); + cit != protoBranchings().end(); ++cit) { + // both outgoing + if(b1->status()==HardBranching::Outgoing && + b2->status()==HardBranching::Outgoing) { + if((**cit).status()!=HardBranching::Outgoing|| + (**cit).children().empty()) continue; + if( ( b1 == (**cit).children()[0] && b2 == (**cit).children()[1] ) || + ( b1 == (**cit).children()[1] && b2 == (**cit).children()[0] ) ) + return *cit; + } + // first incoming + else if(b1->status()==HardBranching::Incoming) { + if((**cit).backChildren().empty() ) continue; + if(b1!=(**cit).backChildren()[0]) continue; + if(b2==(**cit).backChildren()[1]) return *cit; + } + // second incoming + else if(b2->status()==HardBranching::Incoming) { + if((**cit).backChildren().empty() ) continue; + if(b2!=(**cit).backChildren()[0]) continue; + if(b1==(**cit).backChildren()[1]) return *cit; + } + } + // is branching incoming or outgoing + bool incoming = b1->status()==HardBranching::Incoming || + b2->status()==HardBranching::Incoming; + // get the branching + BranchingElement theBranching; + if( !incoming ) theBranching = allowedFinalStateBranching( b1, b2 ); + else theBranching = allowedInitialStateBranching( b1, b2 ); + + //if branching is not allowed return null ProtoBrancing + if( !theBranching.first ) return ProtoBranchingPtr(); + + // get the PArticleData object for the new branching + tcPDPtr particle_data = incoming ? + getParticleData( theBranching.second[1] ) : getParticleData( theBranching.second[0] ); + + // create clustered ProtoBranching + ProtoBranchingPtr clusteredBranch; + // outgoing + if( !incoming ){ + Lorentz5Momentum pairMomentum = b1->momentum() + b2->momentum(); + pairMomentum.setMass(ZERO); + clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Outgoing, + pairMomentum, theBranching.first)); + } + // incoming + else { + Lorentz5Momentum pairMomentum = b1->momentum() - b2->momentum(); + pairMomentum.setMass( ZERO ); + // check for CC + if( particle_data->CC() && + ( b1->id() != theBranching.second[0] || + b2->id() != theBranching.second[2] ) ) { + particle_data = particle_data->CC(); + } + clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Incoming, + pairMomentum,theBranching.first)); + } + protoBranchings().insert(clusteredBranch); + //set children relations + // outgoing + if( !incoming ){ + clusteredBranch->addChild( b1 ); + clusteredBranch->addChild( b2 ); + } + else { + clusteredBranch->addBackChild( b1 ); + clusteredBranch->addBackChild( b2 ); + } + return clusteredBranch; +} + +BranchingElement MatchingHandler:: +allowedFinalStateBranching( tProtoBranchingPtr & b1, tProtoBranchingPtr & b2) { + // check with normal ID's + pair< long, long > ptest = make_pair( b1->id(), b2->id() ); + map< pair< long, long >, pair< SudakovPtr, IdList > >::const_iterator + split = allowedFinal_.find(ptest); + if( split != allowedFinal_.end() ) { + if( split->second.second[1] != ptest.first ) swap( b1, b2 ); + return split->second; + } + // check with CC + if( b1->particle()->CC() ) ptest.first *= -1; + if( b2->particle()->CC() ) ptest.second *= -1; + split = allowedFinal_.find( ptest ); + if( split != allowedFinal_.end() ) { + // cc the idlist only be for qbar g clusterings + BranchingElement ccBranch = split->second; + if( getParticleData( ccBranch.second[0] )->CC() ) ccBranch.second[0] *= -1; + if( getParticleData( ccBranch.second[1] )->CC() ) ccBranch.second[1] *= -1; + if( getParticleData( ccBranch.second[2] )->CC() ) ccBranch.second[2] *= -1; + if( split->second.second[1] != ptest.first ) swap( b1, b2); + return ccBranch; + } + // not found found null pointer + return make_pair( SudakovPtr(), IdList() ); +} + +BranchingElement MatchingHandler:: +allowedInitialStateBranching( tProtoBranchingPtr & b1, + tProtoBranchingPtr & b2) { + if(b2->status()==HardBranching::Incoming) swap(b1,b2); + // is initial parton an antiparticle + bool cc = b1->id() < 0; + //gives range of allowedInitial_ with matching first abs( id ) + pair< multimap< long, pair< SudakovPtr, IdList > >::const_iterator, + multimap< long, pair< SudakovPtr, IdList > >::const_iterator > + location = allowedInitial_.equal_range( abs( b1->id() ) ); + //iterates over this range + for( multimap< long, pair< SudakovPtr, IdList> >::const_iterator it = location.first; + it != location.second; ++it ) { + //test id for second particle in pair + long idtest = it->second.second[2]; + //if it is antiparticle *= -1 + if( cc && getParticleData( idtest )->CC() ) idtest *= -1; + // does second id match the test + if( idtest == b2->id() ) return it->second; + //if the the IS parton is a gluon and charge conjugate of second parton mathes accept + if( idtest == -b2->id() && + ! b1->particle()->CC() ) return it->second; + } + // not found found null pointer + return make_pair(SudakovPtr(),IdList()); +} + + +bool MatchingHandler::repeatProtoTree( ProtoTreePtr currentProtoTree ) { + // loop over all prototrees and see + // how many ProtoBranchings of current ProtoTree are found in each + for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); + cit != protoTrees().end(); ++cit ) { + unsigned int no_matches = 0; + for( set< tProtoBranchingPtr >::const_iterator ckt + = currentProtoTree->branchings().begin(); + ckt != currentProtoTree->branchings().end(); ckt++ ) { + if( (*cit)->branchings().find( *ckt ) != (*cit)->branchings().end() ) + ++no_matches; + } + // return true if all match + if( no_matches == currentProtoTree->branchings().size() ) + return true; + } + return false; +} + +double MatchingHandler::getDiagram(PotentialTree & tree) { + if(tree.diagrams().empty()) { + set::const_iterator cit; + tcPDPair incoming; + multiset outgoing; + //get the incoming and outgoing partons involved in hard process + for( cit = tree.tree()->branchings().begin(); + cit != tree.tree()->branchings().end(); ++cit ){ + if( (*cit)->status() ==HardBranching::Incoming) { + HardBranchingPtr parent = *cit; + while(parent->parent()) parent = parent->parent(); + if( parent->branchingParticle()->momentum().z()>ZERO ) + incoming.first = (*cit)->branchingParticle()->dataPtr(); + else + incoming.second = (*cit)->branchingParticle()->dataPtr(); + } + else { + outgoing.insert( (*cit)->branchingParticle()->dataPtr() ); + } + } + if(!incoming.first || !incoming.second) return 0.; + pair tag; + tag.first = incoming.first ->PDGName() + "," + incoming.second->PDGName() + "->"; + tag.second = incoming.second ->PDGName() + "," + incoming.first ->PDGName() + "->"; + + string tag_out; + for ( multiset::iterator i = outgoing.begin(); + i != outgoing.end(); ++i ) { + if ( i != outgoing.begin() ) tag_out += ","; + tag_out += (**i).PDGName(); + } + tag.first += tag_out; + tag.second += tag_out; + // find the diagrams + for ( int i = 0, N = matrixElement()->diagrams().size(); i < N; ++i ) { + string temp = matrixElement()->diagrams()[i]->getTag(); + if ( temp == tag.first || temp == tag.second ) + tree.diagrams().push_back(matrixElement()->diagrams()[i]); + } + } + if(tree.diagrams().empty()) return 0.; + // construct a set of on-shell momenta for the hard collison + vector meMomenta; + vector mePartonData; + PVector particles; + set::const_iterator it; + // incoming particles + for( it = tree.tree()->branchings().begin();it != tree.tree()->branchings().end(); ++it ) { + if( (**it).status() == HardBranching::Incoming ) { + meMomenta.push_back( (**it).branchingParticle()->momentum() ); + mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); + particles.push_back( (**it).branchingParticle() ); + } + } + assert(particles.size()==2); + for( it = tree.tree()->branchings().begin(); it != tree.tree()->branchings().end(); ++it ) { + if( (**it).status() == HardBranching::Outgoing ) { + meMomenta.push_back( (**it).branchingParticle()->momentum() ); + mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); + particles.push_back( (**it).branchingParticle() ); + } + } + const cPDVector partons = tree.diagrams()[0]->partons(); + // order of the incoming partons + if(mePartonData[0] != partons[0]) { + swap( mePartonData[0], mePartonData[1] ); + swap( meMomenta[0], meMomenta[1] ); + swap( particles[0], particles[1] ); + } + // order of the outgoing partons + for(unsigned int ix=2;ix0.) { + R.rotateZ(-axis.phi()); + R.rotateY(-acos(axis.z())); + } + for( unsigned int ix = 0; ix < meMomenta.size(); ++ix ) + meMomenta[ix].transform(R); + // now rescale to put on shell + Energy Ebeam = 0.5 * ( max(meMomenta[0].e(),abs(meMomenta[0].z())) + + max(meMomenta[1].e(),abs(meMomenta[1].z())) ); + for( unsigned int i = 0; i < 2; ++i ) { + meMomenta[i].setZ( meMomenta[i].z() / abs(meMomenta[i].z()) * Ebeam ); + meMomenta[i].setT( Ebeam ); + } + Energy2 s = 4.0 * sqr(Ebeam); + Energy m1 = mePartonData[2]->mass(); + Energy m2 = mePartonData[3]->mass(); + // \todo need to improve this + if(m1+m2>sqrt(s)) return 0.; + double lambda = 0.25/Ebeam/meMomenta[2].rho() * + sqrt( ( s - sqr(m1+m2) ) * ( s - sqr(m1-m2) ) ); + for( unsigned int i = 2; i < meMomenta.size(); ++i ) { + meMomenta[i] *= lambda; + meMomenta[i].setMass(mePartonData[i]->mass()); + meMomenta[i].rescaleEnergy(); + } + // incoming pair + PPair in( mePartonData[0]->produceParticle( meMomenta[0] ), + mePartonData[1]->produceParticle( meMomenta[1] ) ); + // outgoing + PVector out; + for(unsigned int ix=2;ixproduceParticle(meMomenta[ix])); + } + // call the matrix element to initialize + + matrixElement()->setKinematics(in,out); + if(HWMatrixElement()) { + vector momenta; + cPDVector data; + data.push_back(in. first->dataPtr()); + momenta.push_back(in. first->momentum()); + data.push_back(in.second->dataPtr()); + momenta.push_back(in.second->momentum()); + for(unsigned int ix=0;ixdataPtr()); + momenta.push_back(out[ix]->momentum()); + } + HWMatrixElement()->rescaleMomenta(momenta,data); + } + if(!cuts()->scale(matrixElement()->scale())) { + return 0.; + } + matrixElement()->dSigHatDR(); + + // select the diagram + if(!tree.diagram()) + tree.diagram(tree.diagrams()[matrixElement()->diagram(tree.diagrams())]); + // get the colour structure + if(!tree.colourLines()) { + Selector sel = matrixElement()->colourGeometries(tree.diagram()); + tree.colourLines(sel.select(rnd())); + } + PVector slike; + tPVector ret; + slike.push_back(particles[0]); + Ptr::const_pointer diagram2 = + dynamic_ptr_cast::const_pointer>(tree.diagram()); + for ( int i = 1; i < diagram2->nSpace() - 1; ++i ) + slike.push_back(diagram2->allPartons()[i]->produceParticle()); + slike.push_back(particles[1]); + ret = tPVector(slike.begin(), slike.end()); + int io = particles.size(); + PVector tlike(diagram2->allPartons().size() - diagram2->nSpace()); + for ( int i = diagram2->allPartons().size() - 1; i >= diagram2->nSpace(); --i ) { + int it = i - diagram2->nSpace(); + pair ch = diagram2->children(i); + bool iso = ch.first < 0; + if ( iso ) { + tlike[it] = particles[--io]; + } + else { + Lorentz5Momentum p = tlike[ch.first - diagram2->nSpace()]->momentum() + + tlike[ch.second - diagram2->nSpace()]->momentum(); + tlike[it] = diagram2->allPartons()[i]->produceParticle(p); + } + } + ret.insert( ret.end(), tlike.begin(), tlike.end() ); + tree.colourLines()->connect(ret); + for( unsigned int ix = 0; ix < ret.size(); ++ix ) { + PVector::iterator it = find( particles.begin(), particles.end(),ret[ix] ); + if( it == particles.end() ) { + ColinePtr line = ret[ix]->colourLine(); + if(line) line->removeColoured(ret[ix]); + line = ret[ix]->antiColourLine(); + if(line) line->removeAntiColoured(ret[ix]); + } + } + // now the colours of the rest of the particles + // for( set::const_iterator it = tree.tree()->branchings().begin(); + // it!=tree.tree()->branchings().end(); ++it ) (**it).fixColours(); + // now make the colour connections in the tree + ShowerParticleVector branchingParticles; + map branchingMap; + for( set< HardBranchingPtr >::iterator it = tree.tree()->branchings().begin(); + it != tree.tree()->branchings().end(); ++it ) { + branchingParticles.push_back((**it).branchingParticle()); + branchingMap.insert(make_pair((**it).branchingParticle(),*it)); + } + // find the colour partners + showerModel()->partnerFinder() + ->setInitialEvolutionScales(branchingParticles,false, + ShowerInteraction::QCD,true); + for(unsigned int ix=0;ixpartner()) { + HardBranchingPtr partner = branchingMap[branchingParticles[ix]->partner()]; + branchingMap[branchingParticles[ix]]->colourPartner(partner); + } + } + double weight = 1.; + // calculate the weight if needed + if(reWeight_) { + if(matrixElement()->orderInAlphaS()>0) { + weight = pow(alphaS_->value( max(matrixElement()->scale(),sqr(pdfScale_)) ) + / alphaSMG_, int(matrixElement()->orderInAlphaS())); + } + } + // return the weight + return weight; +} + +bool MatchingHandler::updateSubProcess() { + assert( hardTree().diagram() && hardTree().tree() ); + PPair beams = lastXCombPtr()->lastParticles(); + + // PPair remnants; + // // remove children of beams + // PVector beam_children = beams.first->children(); + // for( unsigned int ix = 0; ix != beam_children.size(); ix++ ){ + // if (abs(beam_children[ix]->id())==82) + // remnants.first=beam_children[ix]; + // beams.first->abandonChild( beam_children[ix] ); + // } + // beam_children = beams.second->children(); + // for( unsigned int ix = 0; ix != beam_children.size(); ix++ ){ + // if (abs(beam_children[ix]->id())==82) + // remnants.second=beam_children[ix]; + // beams.second->abandonChild( beam_children[ix] ); + // } + + // remove children of beams + PVector beam_children = beams.first->children(); + for( unsigned int ix = 0; ix != beam_children.size(); ix++ ) + beams.first->abandonChild( beam_children[ix] ); + beam_children = beams.second->children(); + for( unsigned int ix = 0; ix != beam_children.size(); ix++ ) + beams.second->abandonChild( beam_children[ix] ); + + if( (**hardTree().tree()->incoming().begin()).branchingParticle()->momentum().z() / + beams.first->momentum().z() < 0.) + swap( beams.first, beams.second ); + Ptr::const_pointer diagram = + dynamic_ptr_cast::const_pointer>(hardTree().diagram()); + assert(diagram); + set::const_iterator it; + map< ColinePtr, ColinePtr> colourMap; + PPair incoming; + // loop over the branchings and sort out incoming particles + for( it = hardTree().tree()->branchings().begin(); + it != hardTree().tree()->branchings().end(); ++it) { + if( (*it)->status() == HardBranching::Outgoing ) continue; + PPtr newParticle = new_ptr( Particle( (**it).branchingParticle()->dataPtr() ) ); + newParticle->set5Momentum( (**it).showerMomentum() ); + if( (**it).branchingParticle()->colourLine() ) { + map< ColinePtr, ColinePtr>::iterator loc + = colourMap.find( (**it).branchingParticle()->colourLine() ); + if( loc != colourMap.end() ) { + loc->second->addColoured( newParticle ); + } + else { + ColinePtr newLine = new_ptr( ColourLine() ); + colourMap[ (**it).branchingParticle()->colourLine() ] = newLine; + newLine->addColoured( newParticle ); + } + } + if( (**it).branchingParticle()->antiColourLine() ) { + map< ColinePtr, ColinePtr> ::iterator loc + = colourMap.find( (**it).branchingParticle()->antiColourLine() ); + if( loc != colourMap.end() ) { + loc->second->addAntiColoured( newParticle ); + } + else { + ColinePtr newLine = new_ptr( ColourLine() ); + colourMap[ (**it).branchingParticle()->antiColourLine() ] = newLine; + newLine->addAntiColoured( newParticle ); + } + } + if( lastXCombPtr()->subProcess()->incoming().first->momentum().z() / + newParticle->momentum().z() > 0. ) + incoming.first = newParticle; + else + incoming.second = newParticle; + } + bool mirror = + incoming.first ->dataPtr() != diagram->partons()[0] && + incoming.second->dataPtr() != diagram->partons()[1]; + // create the new subprocess + SubProPtr newSubProcess = + new_ptr( SubProcess( incoming, lastXCombPtr()->subProcess()->collision(), + lastXCombPtr()->subProcess()->handler() ) ); + // add the spacelike intermediates + PVector slike; + slike.push_back( !mirror ? incoming.first : incoming.second); + for ( int i = 1; i < diagram->nSpace() - 1; ++i ) + slike.push_back(diagram->allPartons()[i]->produceParticle()); + slike.push_back( !mirror ? incoming.second : incoming.first); + tPVector ret = tPVector(slike.begin(), slike.end()); + for ( size_t i = 1; i < slike.size() - 1; ++i ) { + slike[i-1]->addChild(slike[i]); + newSubProcess->addIntermediate(slike[ mirror ? i: slike.size() - 1 - i], false); + } + // get the parton bins from the parton extractor if first time + static bool first = true; + if(first) { + first = false; + Energy e1 = lastXCombPtr()->lastParticles().first ->momentum().e(); + Energy e2 = lastXCombPtr()->lastParticles().second->momentum().e(); + Energy emax = 2.0*sqrt(e1*e2); + cPDPair inData = make_pair(lastXCombPtr()->lastParticles().first ->dataPtr(), + lastXCombPtr()->lastParticles().second->dataPtr()); + cuts()->initialize(sqr(emax),0.5*log(e1/e2)); + partonBins(partonExtractor()->getPartons(emax, inData, *cuts())); + } + // get the parton bins for this event + tcPBPair sel; + for ( int i = 0, N = partonBins().size(); i < N; ++i ) { + tcPBPtr bin = partonBins()[i].first; + tPPtr p = incoming.first; + while ( bin && p ) { + if ( p->dataPtr() != bin->parton() ) break; + bin = bin->incoming(); + p = p != lastXCombPtr()->lastParticles().first ? + lastXCombPtr()->lastParticles().first : PPtr(); + } + if ( bin || p ) continue; + bin = partonBins()[i].second; + p = incoming.second; + while ( bin && p ) { + if ( p->dataPtr() != bin->parton() ) break; + bin = bin->incoming(); + p = p != lastXCombPtr()->lastParticles().second ? + lastXCombPtr()->lastParticles().second : PPtr(); + } + if ( bin || p ) continue; + sel = partonBins()[i]; + break; + } + if ( !sel.first || !sel.second ) Throw() + << "Could not find appropriate " + << "PartonBin objects for event in " + << "MatchingHandler " << Exception::runerror; + // create the new parton bin instances + Direction<0> dir(true); + PBIPair partonBinInstances; + // temporary mother/daugther settings + // to get parton bin instances correct + lastXCombPtr()->lastParticles().first ->addChild(incoming.first ); + lastXCombPtr()->lastParticles().second->addChild(incoming.second); + // make the parton bin instances + partonBinInstances.first = + new_ptr(PartonBinInstance(incoming.first, sel.first, + lastXCombPtr()->partonBinInstances().first->scale())); + dir.reverse(); + partonBinInstances.second = + new_ptr(PartonBinInstance(incoming.second, sel.second, + lastXCombPtr()->partonBinInstances().second->scale())); + // remove temporary mother/daugther settings + lastXCombPtr()->lastParticles().first ->abandonChild(incoming.first ); + lastXCombPtr()->lastParticles().second->abandonChild(incoming.second); + // set the parton bin instances + lastXCombPtr()->setPartonBinInstances(partonBinInstances, + lastXCombPtr()->lastScale()); + // momenta of the time like partons + vector meMomenta; + vector mePartonData; + vector branchings; + for( it = hardTree().tree()->branchings().begin(); + it != hardTree().tree()->branchings().end(); ++it ) { + if( (**it).status() == HardBranching::Outgoing ) { + meMomenta.push_back( (**it).showerMomentum() ); + mePartonData.push_back( (**it).branchingParticle()->dataPtr() ); + branchings.push_back(*it); + } + } + // order of the outgoing partons + for(int ix=2;ixpartons().size());++ix) { + for(int iy=ix-2;iypartons()[ix]==mePartonData[iy]) { + if(ix!=iy) { + swap(mePartonData[ix-2],mePartonData[iy]); + swap(meMomenta [ix-2],meMomenta [iy]); + swap(branchings [ix-2],branchings [iy]); + } + break; + } + } + } + // time like particles + int io = meMomenta.size(); + PVector tlike(diagram->allPartons().size() - diagram->nSpace()); + vector tBranchings; + tPVector out; + for ( int i = diagram->allPartons().size() - 1; i >= diagram->nSpace(); --i ) { + int it = i - diagram->nSpace(); + pair ch = diagram->children(i); + bool iso = ch.first < 0; + if ( iso ) { + tlike[it] = diagram->allPartons()[i]->produceParticle(meMomenta[--io]); + } + else { + Lorentz5Momentum p = tlike[ch.first - diagram->nSpace()]->momentum() + + tlike[ch.second - diagram->nSpace()]->momentum(); + tlike[it] = diagram->allPartons()[i]->produceParticle(p); + } + if ( diagram->parent(i) < diagram->nSpace() ) { + slike[diagram->parent(i)]->addChild(tlike[it]); + if ( diagram->parent(i) == diagram->nSpace() - 2 ) + slike[diagram->parent(i) + 1]->addChild(tlike[it]); + } + if ( !iso ) { + tlike[it]->addChild(tlike[ch.first - diagram->nSpace()]); + tlike[it]->addChild(tlike[ch.second - diagram->nSpace()]); + } + if ( iso ) { + out.push_back(tlike[it]); + tBranchings.push_back(branchings[io]); + } + else + newSubProcess->addIntermediate(tlike[it], false); + } + ret.insert(ret.end(), tlike.begin(), tlike.end()); + // select the colour structure now + const ColourLines & cl = matrixElement()->selectColourGeometry(hardTree().diagram()); + cl.connect(ret); + // add the particles + for ( int i = 0, N = out.size(); i < N; ++i ) { + tPPtr particle = out[mirror ? i: out.size() - i - 1]; + // if not including decays add as outgoing + if(!includeDecays_) { + newSubProcess->addOutgoing(particle, false); + continue; + } + HardBranchingPtr branching = tBranchings[mirror ? i: out.size() - i - 1]; + // move to end of chain for time-like branchings + while(!branching->children().empty()) { + bool found=false; + for(unsigned int ix=0;ixchildren().size();++ix) { + if(branching->children()[ix]->branchingParticle()->id()== + branching->branchingParticle()->id()) { + found = true; + branching = branching->children()[ix]; + break; + } + } + if(!found) break; + } + // check if from decay + map::const_iterator pit = parent(branching->branchingParticle()); + // if not add as outgoing + if(pit==decayingParticles_.end()) { + newSubProcess->addOutgoing(particle, false); + continue; + } + LorentzRotation decayBoost = branching->showerBoost(); + // final boost if FSR + Lorentz5Momentum pShower = decayBoost*(pit->first->momentum()); + decayBoost = LorentzRotation(-pShower.boostVector())*decayBoost; + decayBoost = LorentzRotation(particle->momentum().boostVector())*decayBoost; + // add decayed particle as intermediate + newSubProcess->addIntermediate(particle,false); + // add decay products + addDecayProducts(newSubProcess,particle,pit,decayBoost); + } + for ( PVector::size_type i = 0; i < slike.size() - 2; ++i ) { + pair ch = diagram->children(i); + slike[ch.first]->set5Momentum(slike[i]->momentum() - + tlike[ch.second - diagram->nSpace()]->momentum()); + } + + + + // // set parents of incoming particles?? + // PPair inParents = lastXCombPtr()->lastParticles(); + // if( incoming.first->momentum().z() / inParents.first->momentum().z() < 0.) + // swap( inParents.first, inParents.second ); + // if( remnants.first->momentum().z() / inParents.first->momentum().z() < 0.) + // swap( remnants.first, remnants.second ); + // if (incoming.first ->parents().empty()) { + // inParents.first ->addChild(incoming.first ); + // inParents.first ->addChild(remnants.first ); + // } + // if (incoming.second->parents().empty()){ + // inParents.second->addChild(incoming.second); + // inParents.second->addChild(remnants.second); + // } + + // set the subprocess + lastXCombPtr()->subProcess( newSubProcess ); + decayingParticles_.clear(); + return true; +} + +void MatchingHandler::findDecayingParticles(PPtr parent) { + ParticleVector decayProducts; + for(unsigned int ix=0;ixchildren().size();++ix) { + decayProducts.push_back(parent->children()[ix]); + if(!parent->children()[ix]->children().empty()) + findDecayingParticles(parent->children()[ix]); + } + if(decayingParticles_.find(parent)==decayingParticles_.end()) + decayingParticles_[parent] = decayProducts; +} + +PotentialTree MatchingHandler::doClustering() { + noShowerHists_ = false; + // clear storage of the protoTrees + protoBranchings().clear(); + protoTrees().clear(); + nonOrderedTrees_.clear(); + hardTrees_.clear(); + assert( matrixElement() ); + // get particles from the XComb object + ParticleVector outgoing = lastXCombPtr()->subProcess()->outgoing(); + PPair incoming = lastXCombPtr()->subProcess()->incoming(); + // storage of decayed particles + decayingParticles_.clear(); + // all outgoing particles as a set for checking + set outgoingset(outgoing.begin(),outgoing.end()); + // loop through the FS particles and create ProtoBranchings + for( unsigned int i = 0; i < outgoing.size(); ++i) { + tPPtr parent = outgoing[i]->parents()[0]; + bool decayProd = decayProduct(parent,lastXCombPtr()->subProcess()); + if(!decayProd||!includeDecays_) { + ProtoBranchingPtr currentBranching = + new_ptr(ProtoBranching(outgoing[i]->dataPtr(),HardBranching::Outgoing, + outgoing[i]->momentum(),tSudakovPtr())); + protoBranchings().insert(currentBranching); + } + else { + bool isHard = true; + PPtr newParent = findParent(parent,isHard,outgoingset,false, + lastXCombPtr()->subProcess()); + assert(newParent); + if(decayingParticles_.find(newParent)==decayingParticles_.end()) { + ProtoBranchingPtr currentBranching = + new_ptr(ProtoBranching(newParent->dataPtr(),HardBranching::Outgoing, + newParent->momentum(),tSudakovPtr())); + protoBranchings().insert(currentBranching); + findDecayingParticles(newParent); + } + } + } + // add IS hardBranchings + ProtoBranchingPtr currentBranching = + new_ptr(ProtoBranching(incoming.first ->dataPtr(),HardBranching::Incoming, + incoming.first ->momentum(),tSudakovPtr())); + protoBranchings().insert(currentBranching); + currentBranching = + new_ptr(ProtoBranching(incoming.second->dataPtr(),HardBranching::Incoming, + incoming.second->momentum(),tSudakovPtr())); + protoBranchings().insert(currentBranching); + //create and initialise the first tree + ProtoTreePtr initialProtoTree = new_ptr( ProtoTree() ); + for(set::const_iterator it=protoBranchings().begin(); + it!=protoBranchings().end();++it) { + initialProtoTree->addBranching(*it); + } + //fill _proto_trees with all possible trees + protoTrees().insert(initialProtoTree ); + fillProtoTrees( initialProtoTree ); + double totalWeight = 0., nonOrderedWeight = 0.; + // create a HardTree from each ProtoTree and fill hardTrees() + for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); + cit != protoTrees().end(); ++cit ) { + PotentialTree newTree; + newTree.tree((**cit).createHardTree()); + // check the created CKKWTree corresponds to an allowed LO configuration + // (does matrix element have a corresponding diagram) + double meWgt = getDiagram( newTree ); + if( !newTree.diagram() ) continue; + // set the beam particles + PPair beams = lastXCombPtr()->lastParticles(); + // remove children of beams + PVector beam_children = beams.first->children(); + if( (**newTree.tree()->incoming().begin()).branchingParticle()->momentum().z() / + beams.first->momentum().z() < 0.) + swap( beams.first, beams.second ); + set::iterator it = newTree.tree()->incoming().begin(); + HardBranchingPtr br = *it; + br->beam( beams.first ); + while ( !br->children().empty() ) { + for(unsigned int ix = 0; ix < br->children().size(); ++ix ) { + if( br->children()[ix]->status() == HardBranching::Incoming ) { + br = br->children()[ix]; + break; + } + } + br->beam( beams.first ); + } + ++it; + br = *it; + br->beam( beams.second ); + while ( !br->children().empty() ) { + for( unsigned int ix = 0; ix < br->children().size(); ++ix ) { + if( br->children()[ix]->status() == HardBranching::Incoming ) { + br = br->children()[ix]; + break; + } + } + br->beam( beams.second ); + } + // do inverse momentum reconstruction + if( !showerModel()->kinematicsReconstructor() + ->deconstructHardJets( newTree.tree(), evolver(), ShowerInteraction::QCD ) ) + continue; + newTree.tree()->findNodes(); + if( newTree.tree()->ordered() ) { + // find the wgt and fill hardTrees() map + double treeWeight = 1.; + if(reWeight_) treeWeight = meWgt*sudakovWeight( newTree.tree() ); + newTree.weight(treeWeight); + hardTrees_.push_back( make_pair( newTree, treeWeight ) ); + totalWeight += treeWeight; + } + else { + nonOrderedTrees_.push_back( make_pair( newTree, 1. ) ); + nonOrderedWeight += 1.; + } + } + // if rejecting non-ordered trees return + if( hardTrees_.empty() && rejectNonAO_ ) return PotentialTree(); + + // select the tree + PotentialTree chosen_hardTree=chooseHardTree(totalWeight, + nonOrderedWeight); + protoBranchings().clear(); + protoTrees().clear(); + nonOrderedTrees_.clear(); + hardTrees_.clear(); + if(! chosen_hardTree.tree() ) { + noShowerHists_ = true; + return PotentialTree(); + } + else + return chosen_hardTree; +} + +void MatchingHandler::initialiseMatching(int minMult, int maxMult) { + if (!matrixElement_){ + tStdXCombPtr lastXC = dynamic_ptr_cast(lastXCombPtr()); + tStdXCombPtr headXC = lastXC->head(); + if (headXC) + matrixElement_ = dynamic_ptr_cast(headXC->matrixElement()); + else if (lastXC) + matrixElement_ = dynamic_ptr_cast(lastXC->matrixElement()); + } + + HWmatrixElement_ = dynamic_ptr_cast(matrixElement_); + + assert(matrixElement_); + + // check multiplicity of FS partons + int nOut = lastXCombPtr()->subProcess()->outgoing().size(); + // is it the lowest multiplicity + lowestMult_ = nOut == minMult; + // or the highest + highestMult_ = nOut == maxMult; + // centre-of-mass energy + sHat(lastXCombPtr()->lastSHat()); + // scale for the PDFs + pdfScale(sqrt(lastXCombPtr()->lastScale())); + // alphaS value used by the ME generate + alphaSMG(lastXCombPtr()->lastAlphaS()); + // create a hard tree by clustering the event + hardTree(doClustering()); +} + +map::const_iterator MatchingHandler::parent(PPtr parent) { + long id = parent->id(); + for(map::const_iterator it = decayingParticles_.begin(); + it!=decayingParticles_.end();++it) { + if(id!=it->first->id()) continue; + Energy2 diff = + sqr(it->first->momentum().x()-parent->momentum().x()) + + sqr(it->first->momentum().y()-parent->momentum().y()) + + sqr(it->first->momentum().z()-parent->momentum().z()) + + sqr(it->first->momentum().t()-parent->momentum().t()); + Energy2 sum = + sqr(it->first->momentum().x()+parent->momentum().x()) + + sqr(it->first->momentum().y()+parent->momentum().y()) + + sqr(it->first->momentum().z()+parent->momentum().z()) + + sqr(it->first->momentum().t()+parent->momentum().t()); + double ratio = diff/sum; + if(ratio<1e-10) return it; + } + return decayingParticles_.end(); +} + +void MatchingHandler::addDecayProducts(SubProPtr subProcess, PPtr parent, + map::const_iterator decay, + const LorentzRotation & boost) const { + // map colours of the parent + map cmap; + if(parent->colourLine()) + cmap.insert(make_pair(decay->first-> colourLine(), + parent-> colourLine())); + if(parent->antiColourLine()) + cmap.insert(make_pair(decay->first->antiColourLine(), + parent->antiColourLine())); + // add the decay products + for(unsigned int ix=0;ixsecond.size();++ix) { + Lorentz5Momentum pnew = boost*decay->second[ix]->momentum(); + PPtr newParticle = decay->second[ix]->dataPtr()->produceParticle(pnew); + parent->addChild(newParticle); + if(decay->second[ix]->colourLine()) { + if(cmap.find(decay->second[ix]->colourLine())==cmap.end()) { + ColinePtr newLine(new_ptr(ColourLine())); + cmap.insert(make_pair(decay->second[ix]->colourLine(),newLine)); + } + cmap[decay->second[ix]->colourLine()]->addColoured(newParticle); + } + if(decay->second[ix]->antiColourLine()) { + if(cmap.find(decay->second[ix]->antiColourLine())==cmap.end()) { + ColinePtr newLine(new_ptr(ColourLine())); + cmap.insert(make_pair(decay->second[ix]->antiColourLine(),newLine)); + } + cmap[decay->second[ix]->antiColourLine()]->addAntiColoured(newParticle); + } + map::const_iterator pit = + decayingParticles_.find(decay->second[ix]); + if(pit!=decayingParticles_.end()) { + subProcess->addIntermediate(newParticle, false); + addDecayProducts(subProcess,newParticle,pit,boost); + } + else { + subProcess->addOutgoing(newParticle, false); + } + } +} diff --git a/Shower/Matching/MatchingHandler.h b/Shower/QTilde/Matching/MatchingHandler.h rename from Shower/Matching/MatchingHandler.h rename to Shower/QTilde/Matching/MatchingHandler.h --- a/Shower/Matching/MatchingHandler.h +++ b/Shower/QTilde/Matching/MatchingHandler.h @@ -1,448 +1,448 @@ // -*- C++ -*- #ifndef Herwig_MatchingHandler_H #define Herwig_MatchingHandler_H // // This is the declaration of the MatchingHandler class. // #include "Herwig/Shower/ShowerHandler.h" #include "ThePEG/MatrixElement/MEBase.h" #include "Herwig/MatrixElement/HwMEBase.h" #include "ThePEG/MatrixElement/DiagramBase.fh" #include "ThePEG/PDF/PartonExtractor.h" -#include "Herwig/Shower/Base/HardBranching.h" +#include "Herwig/Shower/QTilde/Base/HardBranching.h" #include "ProtoTree.h" #include "PotentialTree.h" namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the MatchingHandler class. * * @see \ref MatchingHandlerInterfaces "The interfaces" * defined for MatchingHandler. */ class MatchingHandler: public ShowerHandler { public: /** * The default constructor. */ MatchingHandler(bool reWeight = false); /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly 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: /** * Access to the core matrix element */ MEPtr matrixElement() const {return matrixElement_;} /** * Access to the core Hw++ matrix element */ HwMEBasePtr HWMatrixElement() const {return HWmatrixElement_;} /** * The PartonExtractor object used to construct remnants. */ PExtrPtr partonExtractor() { return partonExtractor_;} /** * The pairs of PartonBin objects describing the partons which can * be extracted by the PartonExtractor object. */ PartonPairVec partonBins() {return partonBins_;} /** * The pairs of PartonBin objects describing the partons which can * be extracted by the PartonExtractor object. */ void partonBins(PartonPairVec bins) {partonBins_ = bins;} /** * The Cuts object to be used for this reader. */ CutsPtr & cuts() {return cuts_;} /** * Initialise the matching */ void initialiseMatching(int minMult, int maxMult); protected: /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alphaS() {return alphaS_;} /** * whether to just reject event if there are no angular ordered histories (true) * or to choose one of the non angular ordered histories (false) */ bool rejectNonAngularOrdered() {return rejectNonAO_;} /** * whether to reject events (true) for which there is no parton shower interpretation * or just shower them with no reweighting */ bool rejectNoShowerHistory() {return rejectNOHistories_;} /** * Access to basic info on the event */ //@{ /** * Centre of mass energy */ Energy2 sHat() const {return sHat_;} /** * Centre of mass energy */ void sHat(Energy2 in) {sHat_ = in;} /** * The fixed factorization scale used in the MEs. */ Energy pdfScale() const {return pdfScale_;} /** * The fixed factorization scale used in the MEs. */ void pdfScale(Energy in) {pdfScale_ = in;} /** * The fixed alphaS value that was used to generate parton configurations */ double alphaSMG() const {return alphaSMG_;} /** * The fixed alphaS value that was used to generate parton configurations */ void alphaSMG(double in) {alphaSMG_ = in;} /** * Whether we are treating an event with no shower interpretation */ bool noShowerHistory() {return noShowerHists_;} /** * whether the current event is a highest multiplicity event. */ bool highestMult() const {return highestMult_;} /** * whether the current event is a lowest multiplicity event */ bool lowestMult() const {return lowestMult_;} //@} /** * Storage of potential shower interpretations */ //@{ /** * Access to the potential branchings */ set & protoBranchings() {return protoBranchings_;} /** * The ProtoTrees which will become CKKWTrees */ set< ProtoTreePtr > & protoTrees() {return protoTrees_;} /** * Access to the select tree */ PotentialTree & hardTree() {return hardTree_;} /** * Access to the select tree */ void hardTree(PotentialTree in) {hardTree_ = in;} /** * access to the hard tree object */ CKKWTreePtr getCKKWTree() const {return hardTree_.tree();} /** * The possible shower configurations that are angular-ordered */ vector< pair< PotentialTree, double > > & hardTrees() { return hardTrees_; } /** * The possible shower configurations that are not angular-ordered */ vector< pair< PotentialTree, double > > & nonOrderedTrees() { return nonOrderedTrees_; } //@} /** * Returns the diagram corresponding to the (leading-order) hardTree */ double getDiagram(PotentialTree &); /** * Recursive function to find all possible clustered trees. * Does not produce any repeated trees. */ void fillProtoTrees( ProtoTreePtr ); /** * update sub process based on the CKKWTree and Diagram */ bool updateSubProcess(); /** * Creates all (ordered) cluster histories and selects one. */ PotentialTree doClustering(); /** * Calculate the Sudakov weight */ virtual double sudakovWeight( CKKWTreePtr ) = 0; /** * Select the hard tree */ virtual PotentialTree chooseHardTree(double totalWeight, double nonOrderedWeight) = 0; /** * Function looks to see if a cluster of the branchings already exists * in protoBranchings_ if so returns the pointer to that protoBranching * if not creates the hardBranchings, adds it * to protoBranchings and returns the pointer */ tProtoBranchingPtr getCluster( tProtoBranchingPtr, tProtoBranchingPtr ); /** * Checks whether a ProtoTree containing the same branchings already * exists in protoTrees_ in which case the current tree is a repeat * and should be removed (and not recursed) */ bool repeatProtoTree( ProtoTreePtr currentProtoTree ); /** * Returns the branching element for an FS-FS clustering */ BranchingElement allowedFinalStateBranching( tProtoBranchingPtr &, tProtoBranchingPtr &); /** * Returns the branching element for an IS-FS clustering */ BranchingElement allowedInitialStateBranching( tProtoBranchingPtr & , tProtoBranchingPtr &); /** * Find decaying particles */ void findDecayingParticles(PPtr parent); /** * Check if a decayed particle */ map::const_iterator parent(PPtr parent); /** * Add the decay products of a particle to the new SubProcess */ void addDecayProducts(SubProPtr subProcess, PPtr parent, map::const_iterator decay, const LorentzRotation & boost) const; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MatchingHandler & operator=(const MatchingHandler &); private: /** * Whether or not to reweight */ bool reWeight_; /** * whether to just reject event if there are no angular ordered histories (true) * or to choose one of the non angular ordered histories (false) */ bool rejectNonAO_; /** * whether to reject events (true) for which there is no parton shower interpretation * or just shower them with no reweighting */ bool rejectNOHistories_; /** * Include decaying particles */ bool includeDecays_; /** * The matrix element for the core process */ MEPtr matrixElement_; /** * The cast matrix element */ HwMEBasePtr HWmatrixElement_; /** * The PartonExtractor object used to construct remnants. */ PExtrPtr partonExtractor_; /** * The pairs of PartonBin objects describing the partons which can * be extracted by the PartonExtractor object. */ PartonPairVec partonBins_; /** * The Cuts object to be used for this reader. */ CutsPtr cuts_; /** * Centre of mass energy */ Energy2 sHat_; /** * Pointer to the object calculating the strong coupling */ ShowerAlphaPtr alphaS_; /** * The fixed factorization scale used in the MEs. */ Energy pdfScale_; /** * The fixed alphaS value that was used to generate parton configurations */ double alphaSMG_; private: /** * Storage of the potential shower interpretation */ //@{ /** * All the Protobranchings used in finding the shower histories */ set protoBranchings_; /** * The ProtoTrees which will become CKKWTrees */ set< ProtoTreePtr > protoTrees_; /** * The chosen hard tree */ PotentialTree hardTree_; /** * The possible shower configurations that are angular-ordered */ vector< pair< PotentialTree, double > > hardTrees_; /** * The possible shower configurations that are not angular-ordered */ vector< pair< PotentialTree, double > > nonOrderedTrees_; /** * Any decays */ map decayingParticles_; /** * Whether we are treating an event with no shower interpretation */ bool noShowerHists_; /** * Whether we are treating the highest multiplicity contribution */ bool highestMult_; /** * Whether we are treating the lowest multiplicity contribution */ bool lowestMult_; //@} /** * Which branchings are allowed? */ //@{ /** * The allowed final-state branchings */ map,pair > allowedFinal_; /** * The allowed initial-state branchings */ multimap > allowedInitial_; //@} }; } #endif /* Herwig_MatchingHandler_H */ diff --git a/Shower/Matching/PotentialTree.h b/Shower/QTilde/Matching/PotentialTree.h rename from Shower/Matching/PotentialTree.h rename to Shower/QTilde/Matching/PotentialTree.h diff --git a/Shower/QTilde/Matching/PowhegHandler.cc b/Shower/QTilde/Matching/PowhegHandler.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/Matching/PowhegHandler.cc @@ -0,0 +1,167 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the PowhegHandler class. +// + +#include "PowhegHandler.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Interface/Switch.h" +#include "ThePEG/Interface/Parameter.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" +#include "ThePEG/PDF/PartonExtractor.h" +#include "ThePEG/PDF/BeamParticleData.h" +#include "ThePEG/PDF/PDF.h" +#include "ThePEG/Cuts/Cuts.h" +#include "Herwig/PDF/HwRemDecayer.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.h" + +using namespace Herwig; + +IBPtr PowhegHandler::clone() const { + return new_ptr(*this); +} + +IBPtr PowhegHandler::fullclone() const { + return new_ptr(*this); +} + +void PowhegHandler::persistentOutput(PersistentOStream & os) const { + os << pTDefinition_ << ounit(maxpT_,GeV); +} + +void PowhegHandler::persistentInput(PersistentIStream & is, int) { + is >> pTDefinition_ >> iunit(maxpT_,GeV); +} + + +// *** Attention *** The following static variable is needed for the type +// description system in ThePEG. Please check that the template arguments +// are correct (the class and its base class), and that the constructor +// arguments are correct (the class name and the name of the dynamically +// loadable library where the class implementation can be found). +DescribeClass +describeHerwigPowhegHandler("Herwig::PowhegHandler", "HwMatching.so"); + +void PowhegHandler::Init() { + + static ClassDocumentation documentation + ("The PowhegHandler class handles the generation of the shower, including truncated" + "showers for external processes using the POWHEG scheme."); + + static Switch interfacepTDefinition + ("pTDefinition", + "The choice of the definition of the pT for the maximum emission in the shower", + &PowhegHandler::pTDefinition_, 0, false, false); + static SwitchOption interfacepTDefinitionScale + (interfacepTDefinition, + "Scale", + "Use the value of the lastScale(), which if reading Les Houches events is SCALUP", + 0); + static SwitchOption interfacepTDefinitionScaleAndpT + (interfacepTDefinition, + "ScaleAndpT", + "Use the same choice as scale for non-emission events but the pT of the" + " emitted particle for emission events", + 1); + static SwitchOption interfacepTDefinitionmaxpTAndpT + (interfacepTDefinition, + "maxpTAndpT", + "Use the maxPt value fo non-emission events and the pT of the" + " emitted particle for emission events", + 2); + + static Parameter interfacemaxpT + ("maxpT", + "Maximum pT for emission from non-emission events.", + &PowhegHandler::maxpT_, GeV, 1.0*GeV, 0.0*GeV, 10.0*GeV, + false, false, Interface::limited); + +} + +double PowhegHandler::reweightCKKW(int minMult, int maxMult) { + // as not reweighting skip if in initialisation + if(generator()->state()==InterfacedBase::initializing) + return 1.; + initialiseMatching(minMult,maxMult); + if( ! hardTree().tree() ) return 1.; + // update sub process based on hardTree() + updateSubProcess(); + return 1.; +} + +HardTreePtr PowhegHandler::generateCKKW(ShowerTreePtr tree) const { + + //get com energy from the progenitors + Energy2 s = + (tree->incomingLines(). begin()->first->progenitor()->momentum() + + tree->incomingLines().rbegin()->first->progenitor()->momentum()).m2(); + // Get the HardTree from the CKKW handler. + CKKWTreePtr hardtree = getCKKWTree(); + + // if no hard tree return + if( ! hardtree ) return HardTreePtr(); + // check the trees match + if( ! hardtree->connect(tree) ) return HardTreePtr(); + // choice of the veto pT + Energy veto_pt = sqrt( s ); + // use the scale + if(pTDefinition_==0) { + veto_pt = sqrt(lastXCombPtr()->lastScale()); + } + // otherwise pT of emission if emitted + else if(!lowestMult()) { + veto_pt = hardtree->lowestPt( 1, s ); + for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it + = tree->outgoingLines().begin(); + it != tree->outgoingLines().end(); ++it ) { + if( ! it->second->coloured() ) continue; + it->first->maximumpT( veto_pt, ShowerInteraction::QCD ); + } + for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it + = tree->incomingLines().begin(); + it != tree->incomingLines().end(); ++it ) { + if( ! it->second->coloured() ) continue; + it->first->maximumpT( veto_pt, ShowerInteraction::QCD ); + } + } + else if(pTDefinition_==1) { + veto_pt = sqrt(lastXCombPtr()->lastScale()); + } + else if(pTDefinition_==2) { + veto_pt = maxpT_; + } + else + assert(false); + // that's it + return hardtree; +} + +PotentialTree PowhegHandler::chooseHardTree(double,double) { + PotentialTree chosen_hardTree; + Energy min_pt = Constants::MaxEnergy; + if( !hardTrees().empty() ){ + for(unsigned int ix = 0; ix < hardTrees().size(); ix++ ){ + if( hardTrees()[ix].first.tree()->totalPt() < min_pt ) { + min_pt = hardTrees()[ix].first.tree()->totalPt(); + chosen_hardTree = hardTrees()[ix].first; + } + } + } + else { + for(unsigned int ix = 0; ix < nonOrderedTrees().size(); ix++ ){ + if( nonOrderedTrees()[ix].first.tree()->totalPt() < min_pt ){ + min_pt = nonOrderedTrees()[ix].first.tree()->totalPt(); + chosen_hardTree=nonOrderedTrees()[ix].first; + } + } + } + return chosen_hardTree; +} diff --git a/Shower/Matching/PowhegHandler.h b/Shower/QTilde/Matching/PowhegHandler.h rename from Shower/Matching/PowhegHandler.h rename to Shower/QTilde/Matching/PowhegHandler.h diff --git a/Shower/Matching/PowhegShowerHandler.cc b/Shower/QTilde/Matching/PowhegShowerHandler.cc rename from Shower/Matching/PowhegShowerHandler.cc rename to Shower/QTilde/Matching/PowhegShowerHandler.cc --- a/Shower/Matching/PowhegShowerHandler.cc +++ b/Shower/QTilde/Matching/PowhegShowerHandler.cc @@ -1,1110 +1,1109 @@ // -*- C++ -*- // // PowhegShowerHandler.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 PowhegShowerHandler class. // #include #include "PowhegShowerHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/DescribeClass.h" // include theses to have complete types -#include "Herwig/Shower/Base/Evolver.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/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/Shower/QTilde/Base/ShowerTree.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" #include "Herwig/PDF/HwRemDecayer.h" -#include "Herwig/Shower/Base/ShowerProgenitor.h" -#include "Herwig/Shower/Base/HardBranching.h" -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h" +#include "Herwig/Shower/QTilde/Base/HardBranching.h" +#include "Herwig/Shower/QTilde/Base/HardTree.h" #include "Herwig/MatrixElement/HwMEBase.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/MatrixElement/DiagramBase.fh" #include "ThePEG/PDF/PartonExtractor.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "Herwig/MatrixElement/Matchbox/Utility/DiagramDrawer.h" using namespace Herwig; namespace { struct ParticleOrdering { bool operator()(tcPDPtr p1, tcPDPtr p2) { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; } IBPtr PowhegShowerHandler::clone() const { return new_ptr(*this); } IBPtr PowhegShowerHandler::fullclone() const { return new_ptr(*this); } HardTreePtr PowhegShowerHandler::generateCKKW(ShowerTreePtr showerTree) const { // hard subprocess tSubProPtr sub = lastXCombPtr()->subProcess(); // real emission sub-process tSubProPtr real = Factory()->hardTreeSubprocess(); // born emitter emitter_ = Factory()->hardTreeEmitter(); spectator_ = Factory()->hardTreeSpectator(); // if no hard emission return if ( !(real && emitter_>-1) ) return HardTreePtr(); // check emission if(sub->outgoing().size()>=real->outgoing().size()) return HardTreePtr(); // check if decay has radiated don't add it if(showerTree->outgoingLines().size() != sub->outgoing().size()) { // loop over the decay trees for(map >::const_iterator tit=showerTree->treelinks().begin(); tit != showerTree->treelinks().end(); ++tit) { if(tit->first->outgoingLines().empty()) continue; // match the particles set decayProducts; set outgoing(real->outgoing().begin(),real->outgoing().end()); for(map::const_iterator oit=tit->first->outgoingLines().begin(); oit!=tit->first->outgoingLines().end();++oit) { tPPtr decayProd; Energy2 dmin( 1e30*GeV2 ); tPPtr part = oit->second->original(); for( set::const_iterator it = outgoing.begin(); it != outgoing.end(); ++it ) { if((**it).id()!=part->id()) continue; Energy2 dtest = sqr( part->momentum().x() - (**it).momentum().x() ) + sqr( part->momentum().y() - (**it).momentum().y() ) + sqr( part->momentum().z() - (**it).momentum().z() ) + sqr( part->momentum().t() - (**it).momentum().t() ); dtest += 1e10*sqr(part->momentum().m()-(**it).momentum().m()); if( dtest < dmin ) { decayProd = *it; dmin = dtest; } } if(!decayProd) { throw Exception() << "PowhegShowerHandler::generateCKKW(). Can't match shower and hard trees." << Exception::eventerror; } outgoing .erase (decayProd); decayProducts.insert(decayProd); } bool coloured = false, foundParent = true; tPPtr parent,emitted; unsigned int nprod(0); for( set::const_iterator it = decayProducts.begin(); it != decayProducts.end(); ++it ) { coloured |= (**it).dataPtr()->coloured(); tPPtr newParent = !(**it).parents().empty() ? (**it).parents()[0] : tPPtr(); ++nprod; // check if from emission if(newParent->id()==(**it).id()) { if(newParent->children().size()!=2) foundParent=false; bool foundChild(false), foundGluon(false); for(unsigned int ix=0;ixchildren().size();++ix) { if(newParent->children()[ix]==*it) { foundChild = true; continue; } else if(newParent->children()[ix]->id()==ParticleID::g) { foundGluon = true; continue; } } if(foundChild && foundGluon) { newParent = !newParent->parents().empty() ? newParent->parents()[0] : tPPtr(); ++nprod; } else foundParent = false; } if(!newParent) { foundParent = false; } else if(!parent) { parent = newParent; } else { if(parent!=newParent) foundParent = false; } } if(nprod!=tit->first->outgoingLines().size()&&foundParent) { if(decayRadiation_==0) { throw Exception() << "The radiation generated in this event\n " << *real << "\n has been interepted as occuring in the " << "decay \nof a colour-singlet object and cannot be handled " << "you can either not simulated this process, " << "veto this class of events by using\n" << "set " << fullName() << ":DecayRadiation VetoEvent\n" << "or throw the hard radiation away using \n" << "set " << fullName() << ":DecayRadiation VetoRadiation\n" << "Please contact us at herwig@hepforge.org for advice\n" << "on how to simulate this process\n" << Exception::runerror; } else if(decayRadiation_==1) { throw Exception() << "The radiation generated in this event\n " << *real << "\n has been interepted as occuring in the " << "decay \nof a colour-singlet object and cannot be handled " << "vetoing event\n" << Exception::eventerror; } else if(decayRadiation_==2) { generator()->log() << "The radiation generated in this event\n " << *real << "\n has been interepted as occuring in the " << "decay \nof a colour-singlet object and cannot be handled " << "vetoing radiation\n"; return HardTreePtr(); } else assert(false); } } } tStdXCombPtr lastXC = dynamic_ptr_cast(lastXCombPtr()); tStdXCombPtr headXC = lastXC->head(); if (headXC) matrixElement_ = dynamic_ptr_cast(headXC->matrixElement()); else if (lastXC) matrixElement_ = dynamic_ptr_cast(lastXC->matrixElement()); if (lastXC){ tStdXCombPtr projector= lastXC->lastProjector(); if (projector){ matrixElement_ = dynamic_ptr_cast(projector->matrixElement()); setSubtractionIntegral(true); } else setSubtractionIntegral(false); } assert(matrixElement_); // create a hard tree by clustering the event try { hardTree(doClustering(real,showerTree)); } catch(exception &e) { throw Exception() << "Caught a problem in PowhegShowerHandler::doClustering " << e.what() << Exception::eventerror; } // Get the HardTree from the CKKW handler. CKKWTreePtr hardtree = hardTree().tree(); // zero to avoid MPI problems Factory()->setHardTreeEmitter(-1); Factory()->setHardTreeSubprocess(SubProPtr()); return hardtree; } PotentialTree PowhegShowerHandler::doClustering(tSubProPtr real,ShowerTreePtr showerTree) const { // clear storage of the protoTrees protoBranchings().clear(); protoTrees().clear(); hardTrees_.clear(); assert( matrixElement() ); // extract the XComb for the Born process tStdXCombPtr lastXC; if (subtractionIntegral()){ tStdXCombPtr lastXCReal = dynamic_ptr_cast(lastXCombPtr()); lastXC = lastXCReal->lastProjector(); } else lastXC = dynamic_ptr_cast(lastXCombPtr()); const StandardXComb xc= *lastXC; // get the particles for the born process PPair incomingBorn = xc.subProcess()->incoming(); ParticleVector outgoingBorn = xc.subProcess()->outgoing(); // get particles from the XComb object for the real process ParticleVector outgoing = real->outgoing(); PPair incoming = real->incoming(); // loop through the FS particles and create ProtoBranchings for( unsigned int i = 0; i < outgoing.size(); ++i) { tPPtr parent = outgoing[i]->parents()[0]; ProtoBranchingPtr currentBranching = new_ptr(ProtoBranching(outgoing[i]->dataPtr(),HardBranching::Outgoing, outgoing[i]->momentum(),tSudakovPtr())); currentBranching-> colourLine(outgoing[i]-> colourLine()); currentBranching->antiColourLine(outgoing[i]->antiColourLine()); protoBranchings().insert(currentBranching); } // add IS hardBranchings ProtoBranchingPtr currentBranching = new_ptr(ProtoBranching(incoming.first ->dataPtr(),HardBranching::Incoming, incoming.first ->momentum(),tSudakovPtr())); currentBranching-> colourLine(incoming.first-> colourLine()); currentBranching->antiColourLine(incoming.first->antiColourLine()); protoBranchings().insert(currentBranching); currentBranching = new_ptr(ProtoBranching(incoming.second->dataPtr(),HardBranching::Incoming, incoming.second->momentum(),tSudakovPtr())); currentBranching-> colourLine(incoming.second-> colourLine()); currentBranching->antiColourLine(incoming.second->antiColourLine()); protoBranchings().insert(currentBranching); // create and initialise the first tree ProtoTreePtr initialProtoTree = new_ptr( ProtoTree() ); for(set::const_iterator it=protoBranchings().begin(); it!=protoBranchings().end();++it) { initialProtoTree->addBranching(*it); } // fill _proto_trees with all possible trees protoTrees().insert(initialProtoTree ); fillProtoTrees( initialProtoTree , xc.mePartonData()[emitter_]->id() ); // create a HardTree from each ProtoTree and fill hardTrees() for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); cit != protoTrees().end(); ++cit ) { set bornParticles(outgoingBorn.begin(),outgoingBorn.end()); bornParticles.insert(incomingBorn.first ); bornParticles.insert(incomingBorn.second); PotentialTree newTree; newTree.tree((**cit).createHardTree()); // new check based on the colour structure map cmap; // make the colour connections in the tree ShowerParticleVector branchingParticles; map branchingMap; bool matched(true); int iemitter(-1); HardBranchingPtr emitter; map locMap; for( set< HardBranchingPtr >::iterator it = newTree.tree()->branchings().begin(); it != newTree.tree()->branchings().end(); ++it ) { matched = true; // map the particle to the branching for future use branchingParticles.push_back((**it).branchingParticle()); branchingMap.insert(make_pair((**it).branchingParticle(),*it)); tPPtr bornPartner; if((**it).status()==HardBranching::Incoming) { HardBranchingPtr parent=*it; while(parent->parent()) { parent = parent->parent(); }; if(parent->branchingParticle()->momentum().z()/incomingBorn.first->momentum().z()>0.) { bornPartner = incomingBorn.first; if(!parent->children().empty()) { iemitter = 0; emitter = *it; } locMap[0] = *it; } else { bornPartner = incomingBorn.second; if(!parent->children().empty()) { iemitter = 1; emitter = *it; } locMap[1] = *it; } } else { Energy2 dmin( 1e30*GeV2 ); for(set::const_iterator bit=bornParticles.begin();bit!=bornParticles.end(); ++bit) { if((**it).branchingParticle()->id()!=(**bit).id()) continue; if(*bit==incomingBorn.first||*bit==incomingBorn.second) continue; Energy2 dtest = sqr( (**bit).momentum().x() - (**it).branchingParticle()->momentum().x() ) + sqr( (**bit).momentum().y() - (**it).branchingParticle()->momentum().y() ) + sqr( (**bit).momentum().z() - (**it).branchingParticle()->momentum().z() ) + sqr( (**bit).momentum().t() - (**it).branchingParticle()->momentum().t() ); dtest += 1e10*sqr((**bit).momentum().m()-(**it).branchingParticle()->momentum().m()); if( dtest < dmin ) { bornPartner = *bit; dmin = dtest; } } // find the map int iloc(-1); for(unsigned int ix=0;ixcolourLine()) { if(cmap.find((**it).branchingParticle()->colourLine())!=cmap.end()) { if(cmap[(**it).branchingParticle()->colourLine()]!=bornPartner->colourLine()) { matched=false; } } else { cmap[(**it).branchingParticle()->colourLine()] = bornPartner->colourLine(); } } if((**it).branchingParticle()->antiColourLine()) { if(cmap.find((**it).branchingParticle()->antiColourLine())!=cmap.end()) { if(cmap[(**it).branchingParticle()->antiColourLine()]!=bornPartner->antiColourLine()) { matched=false; } } else { cmap[(**it).branchingParticle()->antiColourLine()] = bornPartner->antiColourLine(); } } // require a match if(!matched) break; } // if no match continue if(!matched) continue; // now sort out any decays if(showerTree->outgoingLines().size()+showerTree->incomingLines().size() != newTree.tree()->branchings().size()) { if(showerTree->treelinks().empty()) { matched = false; continue; } // loop over the decay trees for(map >::const_iterator tit=showerTree->treelinks().begin(); tit != showerTree->treelinks().end(); ++tit) { if(tit->first->outgoingLines().empty()) continue; set decayProducts; set branchings = newTree.tree()->branchings(); // match the particles for(map::const_iterator oit=tit->first->outgoingLines().begin(); oit!=tit->first->outgoingLines().end();++oit) { HardBranchingPtr decayProd; Energy2 dmin( 1e30*GeV2 ); tPPtr part = oit->second->original(); for( set< HardBranchingPtr >::iterator it = branchings.begin(); it != branchings.end(); ++it ) { if((**it).status()==HardBranching::Incoming ) continue; if((**it).branchingParticle()->id()!=part->id()) continue; Energy2 dtest = sqr( part->momentum().x() - (**it).branchingParticle()->momentum().x() ) + sqr( part->momentum().y() - (**it).branchingParticle()->momentum().y() ) + sqr( part->momentum().z() - (**it).branchingParticle()->momentum().z() ) + sqr( part->momentum().t() - (**it).branchingParticle()->momentum().t() ); dtest += 1e10*sqr(part->momentum().m()-(**it).branchingParticle()->momentum().m()); if( dtest < dmin ) { decayProd = *it; dmin = dtest; } } if(!decayProd) { throw Exception() << "PowhegShowerHandler::generateCKKW(). Can't match shower and hard trees." << Exception::eventerror; } branchings .erase (decayProd); decayProducts.insert(decayProd); } // erase the decay products Lorentz5Momentum pnew,pshower; for(set::iterator it = decayProducts.begin(); it!=decayProducts.end(); ++it) { newTree.tree()->branchings().erase(*it); pnew += (**it).branchingParticle()->momentum(); pshower += (**it).showerMomentum(); } pnew .setMass(tit->second.second->mass()); pshower.setMass(tit->second.second->mass()); pnew .rescaleEnergy(); pshower.rescaleEnergy(); // create the decaying particle ShowerParticlePtr particle = new_ptr( ShowerParticle( tit->second.second->dataPtr() , true ) ); particle->set5Momentum( pnew ); HardBranchingPtr newBranch = new_ptr( HardBranching( particle, tSudakovPtr(), HardBranchingPtr(), HardBranching::Outgoing ) ); newBranch->showerMomentum(pshower); newTree.tree()->branchings().insert(newBranch); } } // if no match continue if(!matched) continue; // find the colour partners try { - evolver()->showerModel()->partnerFinder() + showerModel()->partnerFinder() ->setInitialEvolutionScales(branchingParticles,false, ShowerInteraction::QCD,true); } catch( Exception & e ) { generator()->log() << "Problem in set evolution scales in " << "PowhegShowerHandler::doClustering(). Exception was" << e.what(); continue; } for(unsigned int ix=0;ixpartner()) { HardBranchingPtr partner = branchingMap[branchingParticles[ix]->partner()]; branchingMap[branchingParticles[ix]]->colourPartner(partner); } } if(forcePartners_) { locMap[emitter_ ]->colourPartner(locMap[spectator_]); locMap[spectator_]->colourPartner(locMap[emitter_ ]); locMap[emitter_ ]->branchingParticle()->partner(locMap[spectator_]->branchingParticle()); locMap[spectator_]->branchingParticle()->partner(locMap[emitter_ ]->branchingParticle()); } newTree.tree()->partnersSet(true); // set the beam particles PPair beams = lastXCombPtr()->lastParticles(); // remove children of beams PVector beam_children = beams.first->children(); if( (**newTree.tree()->incoming().begin()).branchingParticle()->momentum().z() / beams.first->momentum().z() < 0.) swap( beams.first, beams.second ); set::iterator it = newTree.tree()->incoming().begin(); HardBranchingPtr br = *it; br->beam( beams.first ); while ( !br->children().empty() ) { for(unsigned int ix = 0; ix < br->children().size(); ++ix ) { if( br->children()[ix]->status() == HardBranching::Incoming ) { br = br->children()[ix]; break; } } br->beam( beams.first ); } ++it; br = *it; br->beam( beams.second ); while ( !br->children().empty() ) { for( unsigned int ix = 0; ix < br->children().size(); ++ix ) { if( br->children()[ix]->status() == HardBranching::Incoming ) { br = br->children()[ix]; break; } } br->beam( beams.second ); } // check the emitter and the spectator some how if(iemitter!=emitter_) continue; //do inverse momentum reconstruction - if( !evolver()->showerModel()->kinematicsReconstructor() - ->deconstructHardJets( newTree.tree(), evolver(), ShowerInteraction::QCD ) ) continue; + if( !showerModel()->kinematicsReconstructor() + ->deconstructHardJets( newTree.tree(), ShowerInteraction::QCD ) ) continue; newTree.tree()->findNodes(); newTree.weight(1.); hardTrees_.push_back( make_pair( newTree, 1. ) ); } // select the tree PotentialTree chosen_hardTree; if (hardTrees_.size()==1) { chosen_hardTree = hardTrees_[0].first; } else { // if multiple trees pick the one with matching // intermediate particle momenta for (unsigned int il=0; il > particles; PotentialTree testTree = hardTrees_[il].first; CKKWTreePtr check = testTree.tree(); // get id and momenta of particles in hard tree for (set< HardBranchingPtr >::iterator it=check->branchings().begin(); it!=check->branchings().end(); ++it) { particles.push_back(make_pair((*it)->branchingParticle()->id(), (*it)->branchingParticle()->momentum())); if (!(*it)->children().empty()){ for (unsigned int ic=0; ic<(*it)->children().size(); ++ic) particles.push_back(make_pair((*it)->children()[ic]->branchingParticle()->id(), (*it)->children()[ic]->branchingParticle()->momentum())); } if ((*it)->parent()){ particles.push_back(make_pair((*it)->parent()->branchingParticle()->id(), (*it)->parent()->branchingParticle()->momentum())); if (!(*it)->parent()->children().empty()) { for (unsigned int ic=0; ic<(*it)->parent()->children().size(); ++ic) { if(*it==(*it)->parent()->children()[ic]) continue; particles.push_back(make_pair((*it)->parent()->children()[ic]->branchingParticle()->id(), (*it)->parent()->children()[ic]->branchingParticle()->momentum())); } } } } // loop through and match to particles in real subprocess vector >::iterator part = particles.begin(); // incoming for (; part!=particles.end(); ++part){ if ((*part).first==real->incoming().first->id() && fuzzyEqual((*part).second, real->incoming().first->momentum())) break; } if (part!=particles.end()) particles.erase(part); part = particles.begin(); for (; part!=particles.end(); ++part){ if ((*part).first==real->incoming().second->id() && fuzzyEqual((*part).second, real->incoming().second->momentum())) break; } if (part!=particles.end()) particles.erase(part); // outgoing for (unsigned int io=0; iooutgoing().size(); ++io){ part = particles.begin(); for (; part!=particles.end(); ++part){ if ((*part).first==real->outgoing()[io]->id() && fuzzyEqual((*part).second, real->outgoing()[io]->momentum())) break; } if (part!=particles.end()) particles.erase(part); } // intermediate for (unsigned int ii=0; iiintermediates().size(); ++ii){ part = particles.begin(); for (; part!=particles.end(); ++part){ if ((*part).first==real->intermediates()[ii]->id() && fuzzyEqual((*part).second, real->intermediates()[ii]->momentum())) break; } if (part!=particles.end()) particles.erase(part); } // intermediate CC with -1*momentum for (unsigned int ii=0; iiintermediates().size(); ++ii){ part = particles.begin(); for (; part!=particles.end(); ++part){ if (!real->intermediates()[ii]->coloured() || (real->intermediates()[ii]->hasColour() && real->intermediates()[ii]->hasAntiColour())){ if ((*part).first==real->intermediates()[ii]->id() && fuzzyEqual((*part).second, -1.*real->intermediates()[ii]->momentum()) ) break; } else { if ((*part).first==-1.*real->intermediates()[ii]->id() && fuzzyEqual((*part).second, -1.*real->intermediates()[ii]->momentum()) ) break; } } if (part!=particles.end()) particles.erase(part); } // if all particles match, set as hardtree if (particles.empty()){ chosen_hardTree = testTree; break; } } } protoBranchings().clear(); protoTrees().clear(); hardTrees_.clear(); if(! chosen_hardTree.tree() ) { return PotentialTree(); } else return chosen_hardTree; } bool PowhegShowerHandler::checkDiagram(PotentialTree & tree, tcDiagPtr loDiagram) const { set::const_iterator cit; tcPDPair incoming; multiset outgoing; //get the incoming and outgoing partons involved in hard process for( cit = tree.tree()->branchings().begin(); cit != tree.tree()->branchings().end(); ++cit ){ if( (*cit)->status() ==HardBranching::Incoming) { HardBranchingPtr parent = *cit; while(parent->parent()) parent = parent->parent(); if( parent->branchingParticle()->momentum().z()>ZERO ) incoming.first = (*cit)->branchingParticle()->dataPtr(); else incoming.second = (*cit)->branchingParticle()->dataPtr(); } else { outgoing.insert( (*cit)->branchingParticle()->dataPtr() ); } } if(!incoming.first || !incoming.second) return 0.; pair tag; tag.first = incoming.first ->PDGName() + "," + incoming.second->PDGName() + "->"; tag.second = incoming.second ->PDGName() + "," + incoming.first ->PDGName() + "->"; string tag_out; for ( multiset::iterator i = outgoing.begin(); i != outgoing.end(); ++i ) { if ( i != outgoing.begin() ) tag_out += ","; tag_out += (**i).PDGName(); } tag.first += tag_out; tag.second += tag_out; // find the diagrams if( tag.first == loDiagram->getTag() || tag.second == loDiagram->getTag() ) tree.diagram(loDiagram); // check this is allowed return tree.diagram(); } void PowhegShowerHandler::fillProtoTrees( ProtoTreePtr currentProtoTree,long id ) const { if(currentProtoTree->branchings().size()==(lastXCombPtr()->subProcess()->outgoing().size()+2)) return; for( set::const_iterator ita = currentProtoTree->branchings().begin(); ita!=currentProtoTree->branchings().end();++ita) { for( set::const_iterator itb = currentProtoTree->branchings().begin(); itb!=ita;++itb) { // can't merge two incoming branchings if( (**ita).status() == HardBranching::Incoming && (**itb).status() == HardBranching::Incoming ) continue; // if branching must be outgoing, skip incoming if(emitter_>=2 && ( (**ita).status() == HardBranching::Incoming || (**itb).status() == HardBranching::Incoming )) continue; // if branching must be incoming, skip outgoing if(emitter_<2 && ( (**ita).status() != HardBranching::Incoming && (**itb).status() != HardBranching::Incoming )) continue; // get a new branching for this pair ProtoBranchingPtr currentBranching = getCluster(*ita,*itb); // check branching with the right PID if( ! currentBranching || currentBranching->id() != id) continue; // branching allowed so make a new Tree out of these branchings set< tProtoBranchingPtr > newTreeBranchings = currentProtoTree->branchings(); newTreeBranchings.erase(*ita); newTreeBranchings.erase(*itb); newTreeBranchings.insert(currentBranching); ProtoTreePtr newProtoTree = new_ptr( ProtoTree( newTreeBranchings ) ); // remove duplicate trees if( ! repeatProtoTree( newProtoTree ) ) protoTrees().insert( newProtoTree ); // remove the current tree if it hasn't already been removed if( protoTrees().find( currentProtoTree ) != protoTrees().end() ) protoTrees().erase( currentProtoTree ); // do recursion fillProtoTrees( newProtoTree , id); } } } bool PowhegShowerHandler::repeatProtoTree( ProtoTreePtr currentProtoTree ) const { // loop over all prototrees and see // how many ProtoBranchings of current ProtoTree are found in each for( set< ProtoTreePtr >::const_iterator cit = protoTrees().begin(); cit != protoTrees().end(); ++cit ) { unsigned int no_matches = 0; for( set< tProtoBranchingPtr >::const_iterator ckt = currentProtoTree->branchings().begin(); ckt != currentProtoTree->branchings().end(); ckt++ ) { if( (*cit)->branchings().find( *ckt ) != (*cit)->branchings().end() ) ++no_matches; } // return true if all match if( no_matches == currentProtoTree->branchings().size() ) return true; } return false; } tProtoBranchingPtr PowhegShowerHandler::getCluster( tProtoBranchingPtr b1, tProtoBranchingPtr b2 ) const { // look for the clustered pair in protoBranchings_ for(set::const_iterator cit = protoBranchings().begin(); cit != protoBranchings().end(); ++cit) { // both outgoing if(b1->status()==HardBranching::Outgoing && b2->status()==HardBranching::Outgoing) { if((**cit).status()!=HardBranching::Outgoing|| (**cit).children().empty()) continue; if( ( b1 == (**cit).children()[0] && b2 == (**cit).children()[1] ) || ( b1 == (**cit).children()[1] && b2 == (**cit).children()[0] ) ) return *cit; } // first incoming else if(b1->status()==HardBranching::Incoming) { if((**cit).backChildren().empty() ) continue; if(b1!=(**cit).backChildren()[0]) continue; if(b2==(**cit).backChildren()[1]) return *cit; } // second incoming else if(b2->status()==HardBranching::Incoming) { if((**cit).backChildren().empty() ) continue; if(b2!=(**cit).backChildren()[0]) continue; if(b1==(**cit).backChildren()[1]) return *cit; } } // is branching incoming or outgoing bool incoming = b1->status()==HardBranching::Incoming || b2->status()==HardBranching::Incoming; // get the branching BranchingElement theBranching; if( !incoming ) theBranching = allowedFinalStateBranching( b1, b2 ); else theBranching = allowedInitialStateBranching( b1, b2 ); //if branching is not allowed return null ProtoBrancing if( !theBranching.sudakov ) return ProtoBranchingPtr(); // get the ParticleData object for the new branching tcPDPtr particle_data = incoming ? theBranching.particles[1] : theBranching.particles[0]; // create clustered ProtoBranching ProtoBranchingPtr clusteredBranch; // outgoing if( !incoming ) { Lorentz5Momentum pairMomentum = b1->momentum() + b2->momentum(); pairMomentum.setMass(ZERO); clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Outgoing, pairMomentum, theBranching.sudakov)); if(particle_data->iColour()==PDT::Colour0) return ProtoBranchingPtr(); else if(particle_data->iColour()==PDT::Colour3) { if(b1->particle()->iColour()==PDT::Colour3 && b2->particle()->iColour()==PDT::Colour8) { if(b1->colourLine()!=b2->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch->colourLine(b2->colourLine()); } else if(b2->particle()->iColour()==PDT::Colour3 && b1->particle()->iColour()==PDT::Colour8) { if(b2->colourLine()!=b1->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b1->colourLine()); } else assert(false); clusteredBranch->type(ShowerPartnerType::QCDColourLine); } else if(particle_data->iColour()==PDT::Colour3bar) { if(b1->particle()->iColour()==PDT::Colour3bar && b2->particle()->iColour()==PDT::Colour8) { if(b1->antiColourLine()!=b2->colourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b2->antiColourLine()); } else if(b2->particle()->iColour()==PDT::Colour3bar && b1->particle()->iColour()==PDT::Colour8) { if(b2->antiColourLine()!=b1->colourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b1->antiColourLine()); } else assert(false); clusteredBranch->type(ShowerPartnerType::QCDAntiColourLine); } else if(particle_data->iColour()==PDT::Colour8) { tProtoBranchingPtr coloured,antiColoured; if(b1->particle()->iColour()==PDT::Colour3 && b2->particle()->iColour()==PDT::Colour3bar) { coloured = b1; antiColoured = b2; } else if(b2->particle()->iColour()==PDT::Colour3 && b1->particle()->iColour()==PDT::Colour3bar) { coloured = b2; antiColoured = b1; } else if(b1->particle()->iColour()==PDT::Colour8 && b2->particle()->iColour()==PDT::Colour8 ) { if(b1->colourLine()==b2->antiColourLine()) { coloured = b2; antiColoured = b1; } else if(b2->colourLine()==b1->antiColourLine()) { coloured = b1; antiColoured = b2; } else return ProtoBranchingPtr(); } else assert(false); // can't have colour self connected gluons if(coloured-> colourLine()==antiColoured->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch-> colourLine( coloured-> colourLine()); clusteredBranch->antiColourLine(antiColoured->antiColourLine()); // softest particle is the emitted if(coloured->momentum().t()>antiColoured->momentum().t()) { clusteredBranch->type(ShowerPartnerType::QCDAntiColourLine); } else { clusteredBranch->type(ShowerPartnerType::QCDColourLine); } } else assert(false); } // incoming else { Lorentz5Momentum pairMomentum = b1->momentum() - b2->momentum(); pairMomentum.setMass( ZERO ); // check for CC if( particle_data->CC() && ( b1->id() != theBranching.particles[0]->id() || b2->id() != theBranching.particles[2]->id() ) ) { particle_data = particle_data->CC(); } clusteredBranch = new_ptr(ProtoBranching(particle_data,HardBranching::Incoming, pairMomentum,theBranching.sudakov)); // work out the type of branching if(b1->particle()->iColour()==PDT::Colour3) { b1->type(ShowerPartnerType::QCDColourLine); if(b2->particle()->iColour()==PDT::Colour3 && particle_data->iColour()==PDT::Colour8) { if(b1->colourLine()==b2->colourLine()) return ProtoBranchingPtr(); clusteredBranch-> colourLine(b1->colourLine()); clusteredBranch->antiColourLine(b2->colourLine()); } else if(b2->particle()->iColour()==PDT::Colour8 && particle_data->iColour()==PDT::Colour3) { if(b1->colourLine()!=b2->colourLine()) return ProtoBranchingPtr(); clusteredBranch->colourLine(b2->antiColourLine()); } else assert(false); } else if(b1->particle()->iColour()==PDT::Colour3bar) { b1->type(ShowerPartnerType::QCDAntiColourLine); if(b2->particle()->iColour()==PDT::Colour3bar && particle_data->iColour()==PDT::Colour8) { if(b1->antiColourLine()==b2->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch-> colourLine(b2->antiColourLine()); clusteredBranch->antiColourLine(b1->antiColourLine()); } else if(b2->particle()->iColour()==PDT::Colour8 && particle_data->iColour()==PDT::Colour3bar) { if(b1->antiColourLine()!=b2->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b2->colourLine()); } else assert(false); } else if(b1->particle()->iColour()==PDT::Colour8) { if(b2->particle()->iColour()==PDT::Colour3) { if(b1->colourLine()!=b2->colourLine()) return ProtoBranchingPtr(); clusteredBranch->antiColourLine(b1->antiColourLine()); b1->type(ShowerPartnerType::QCDColourLine); } else if(b2->particle()->iColour()==PDT::Colour3bar) { if(b1->antiColourLine()!=b2->antiColourLine()) return ProtoBranchingPtr(); clusteredBranch-> colourLine(b1->colourLine()); b1->type(ShowerPartnerType::QCDAntiColourLine); } else if(b2->particle()->iColour()==PDT::Colour8) { if(b1->colourLine()==b2->colourLine()) { b1->type(ShowerPartnerType::QCDColourLine); clusteredBranch->antiColourLine(b1->antiColourLine()); clusteredBranch->colourLine(b2->antiColourLine()); } else if(b1->antiColourLine()==b2->antiColourLine()) { b1->type(ShowerPartnerType::QCDAntiColourLine); clusteredBranch-> colourLine(b1->colourLine()); clusteredBranch->antiColourLine(b2->colourLine()); } else { return ProtoBranchingPtr(); } } else assert(false); } else assert(false); } protoBranchings().insert(clusteredBranch); //set children relations // outgoing if( !incoming ){ clusteredBranch->addChild( b1 ); clusteredBranch->addChild( b2 ); } else { clusteredBranch->addBackChild( b1 ); clusteredBranch->addBackChild( b2 ); } return clusteredBranch; } BranchingElement PowhegShowerHandler:: allowedFinalStateBranching( tProtoBranchingPtr & b1, tProtoBranchingPtr & b2) const { // check with normal ID's pair< long, long > ptest = make_pair( b1->id(), b2->id() ); map< pair< long, long >, BranchingElement >::const_iterator split = allowedFinal_.find(ptest); if( split != allowedFinal_.end() ) { if( split->second.particles[1]->id() != ptest.first ) swap( b1, b2 ); return split->second; } // check with CC if( b1->particle()->CC() ) ptest.first *= -1; if( b2->particle()->CC() ) ptest.second *= -1; split = allowedFinal_.find( ptest ); if( split != allowedFinal_.end() ) { // cc the idlist only be for qbar g clusterings BranchingElement ccBranch = split->second; swap(ccBranch.particles,ccBranch.conjugateParticles); if( split->second.particles[1]->id() != ptest.first ) swap( b1, b2); return ccBranch; } // not found found null pointer return BranchingElement(); } BranchingElement PowhegShowerHandler::allowedInitialStateBranching( tProtoBranchingPtr & b1, tProtoBranchingPtr & b2) const { if(b2->status()==HardBranching::Incoming) swap(b1,b2); // is initial parton an antiparticle bool cc = b1->id() < 0; //gives range of allowedInitial_ with matching first abs( id ) pair< multimap< long, BranchingElement >::const_iterator, - multimap< long, BranchingElement >::const_iterator > + multimap< long, BranchingElement >::const_iterator > location = allowedInitial_.equal_range( abs( b1->id() ) ); //iterates over this range for( multimap< long, BranchingElement >::const_iterator it = location.first; it != location.second; ++it ) { //test id for second particle in pair long idtest = cc ? it->second.conjugateParticles[2]->id() : it->second.particles[2]->id(); // does second id match the test if( idtest == b2->id() ) return it->second; //if the the IS parton is a gluon and charge conjugate of second parton mathes accept if( idtest == -b2->id() && ! b1->particle()->CC() ) return it->second; } // not found found null pointer return BranchingElement(); } bool PowhegShowerHandler::fuzzyEqual(Lorentz5Momentum a, Lorentz5Momentum b) const{ // check momenta are within 1% of each other if ( (a.e()==ZERO && b.e()==ZERO) || (a.e()/b.e()>0.99 && a.e()/b.e()<1.01) ){ if ((a.x()==ZERO && b.x()==ZERO) || (a.x()/b.x()>0.99 && a.x()/b.x()<1.01) ){ if ((a.y()==ZERO && b.y()==ZERO) || (a.y()/b.y()>0.99 && a.y()/b.y()<1.01) ){ if ((a.z()==ZERO && b.z()==ZERO) || (a.z()/b.z()>0.99 && a.z()/b.z()<1.01) ) return true; } } } return false; } void PowhegShowerHandler::doinit() { - ShowerHandler::doinit(); + QTildeShowerHandler::doinit(); // extract the allowed branchings // final-state for(BranchingList::const_iterator - it = evolver()->splittingGenerator()->finalStateBranchings().begin(); - it != evolver()->splittingGenerator()->finalStateBranchings().end(); ++it) { + it = splittingGenerator()->finalStateBranchings().begin(); + it != splittingGenerator()->finalStateBranchings().end(); ++it) { pair prod(make_pair(it->second.particles[1]->id(), it->second.particles[2]->id())); allowedFinal_.insert(make_pair(prod,it->second)); swap(prod.first,prod.second); allowedFinal_.insert(make_pair(prod,it->second)); } // initial-state for(BranchingList::const_iterator - it = evolver()->splittingGenerator()->initialStateBranchings().begin(); - it != evolver()->splittingGenerator()->initialStateBranchings().end(); ++it) { + it = splittingGenerator()->initialStateBranchings().begin(); + it != splittingGenerator()->initialStateBranchings().end(); ++it) { allowedInitial_.insert(make_pair(it->second.particles[0]->id(),it->second)); } } void PowhegShowerHandler::persistentOutput(PersistentOStream & os) const { os << theFactory << allowedInitial_ << allowedFinal_ << subtractionIntegral_ << enforceColourConsistency_ << forcePartners_ << decayRadiation_; } void PowhegShowerHandler::persistentInput(PersistentIStream & is, int) { is >> theFactory >> allowedInitial_ >> allowedFinal_ >> subtractionIntegral_ >> enforceColourConsistency_ >> forcePartners_ >> decayRadiation_; } // Static variable needed for the type description system in ThePEG. -DescribeClass +DescribeClass describeHerwigPowhegShowerHandler("Herwig::PowhegShowerHandler", "HwMatchbox.so HwMatching.so"); void PowhegShowerHandler::Init() { static ClassDocumentation documentation ("The PowhegShowerHandler class"); static Reference interfaceFactory ("Factory", "The factory object to use.", &PowhegShowerHandler::theFactory, false, false, true, false, false); static Switch interfaceEnforceColourConsistency ("EnforceColourConsistency", "Force the Born and real emission colour flows to be consistent", &PowhegShowerHandler::enforceColourConsistency_, false, false, false); static SwitchOption interfaceEnforceColourConsistencyYes (interfaceEnforceColourConsistency, "Yes", "Enforce the consistency", true); static SwitchOption interfaceEnforceColourConsistencyNo (interfaceEnforceColourConsistency, "No", "Don't enforce consistency", false); static Switch interfaceForcePartners ("ForcePartners", "Whether or not to force the partners to be those from the kinematic generation", &PowhegShowerHandler::forcePartners_, false, false, false); static SwitchOption interfaceForcePartnersYes (interfaceForcePartners, "Yes", "Force them", true); static SwitchOption interfaceForcePartnersNo (interfaceForcePartners, "No", "Don't force them", false); static Switch interfaceDecayRadiation ("DecayRadiation", "Handling of radiation which is interpretted as having come from decays", &PowhegShowerHandler::decayRadiation_, 0, false,false); static SwitchOption interfaceDecayRadiationNotAllowed (interfaceDecayRadiation, "NotAllowed", "Not allowed at all, run error will be thrown", 0); static SwitchOption interfaceDecayRadiationVetoEvent (interfaceDecayRadiation, "VetoEvent", "Veto the whole event", 1); static SwitchOption interfaceDecayRadiationVetoRadiation (interfaceDecayRadiation, "VetoRadiation", "Throw the radiation away but keep the event", 2); } diff --git a/Shower/Matching/PowhegShowerHandler.h b/Shower/QTilde/Matching/PowhegShowerHandler.h rename from Shower/Matching/PowhegShowerHandler.h rename to Shower/QTilde/Matching/PowhegShowerHandler.h --- a/Shower/Matching/PowhegShowerHandler.h +++ b/Shower/QTilde/Matching/PowhegShowerHandler.h @@ -1,306 +1,306 @@ // -*- C++ -*- // // PowhegShowerHandler.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_PowhegShowerHandler_H #define HERWIG_PowhegShowerHandler_H // // This is the declaration of the PowhegShowerHandler class. // -#include "Herwig/Shower/ShowerHandler.h" +#include "Herwig/Shower/QTilde/QTildeShowerHandler.h" #include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" #include "Herwig/MatrixElement/HwMEBase.h" -#include "Herwig/Shower/Base/HardBranching.h" +#include "Herwig/Shower/QTilde/Base/HardBranching.h" -#include "Herwig/Shower/Matching/CKKWTree.h" -#include "Herwig/Shower/Matching/ProtoTree.h" -#include "Herwig/Shower/Matching/ProtoBranching.h" -#include "Herwig/Shower/Matching/PotentialTree.h" +#include "Herwig/Shower/QTilde/Matching/CKKWTree.h" +#include "Herwig/Shower/QTilde/Matching/ProtoTree.h" +#include "Herwig/Shower/QTilde/Matching/ProtoBranching.h" +#include "Herwig/Shower/QTilde/Matching/PotentialTree.h" #include "ThePEG/MatrixElement/DiagramBase.fh" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/PDF/PartonExtractor.h" -#include "Herwig/Shower/Base/HardTree.h" +#include "Herwig/Shower/QTilde/Base/HardTree.h" -// #include "Herwig/Shower/SplittingFunctions/SplittingGenerator.h" -// #include "Herwig/Shower/Base/ShowerModel.h" +// #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.h" +// #include "Herwig/Shower/QTilde/Base/ShowerModel.h" // #include "ThePEG/PDF/BeamParticleData.h" -// #include "Herwig/Shower/Base/ShowerTree.h" -// #include "Herwig/Shower/Base/ShowerProgenitor.fh" -// #include "Herwig/Shower/ShowerHandler.fh" -// #include "Herwig/Shower/Base/Branching.h" -// #include "Herwig/Shower/Base/ShowerVeto.h" +// #include "Herwig/Shower/QTilde/Base/ShowerTree.h" +// #include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh" +// #include "Herwig/Shower/QTilde/QTildeShowerHandler.fh" +// #include "Herwig/Shower/QTilde/Base/Branching.h" +// #include "Herwig/Shower/QTilde/Base/ShowerVeto.h" // #include "ThePEG/Handlers/XComb.h" // #include "Herwig/Decay/HwDecayerBase.h" namespace Herwig { using namespace ThePEG; -class PowhegShowerHandler: public ShowerHandler { +class PowhegShowerHandler: public QTildeShowerHandler { public: /** * The default constructor. */ PowhegShowerHandler() : subtractionIntegral_(false), enforceColourConsistency_(false), forcePartners_(false), decayRadiation_(0) {} public: Ptr::ptr Factory(){return theFactory;} Ptr::ptr Factory() const {return theFactory;} /** * Return true, if the shower handler can generate a truncated * shower for POWHEG style events generated using Matchbox */ virtual bool canHandleMatchboxTrunc() const { return true; } protected: /** * Generate hard emissions for CKKW etc */ virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const; protected: /** * Access to the core matrix element */ MEPtr matrixElement() const {return matrixElement_;} /** * Creates all (ordered) cluster histories and selects one. */ PotentialTree doClustering(tSubProPtr sub,ShowerTreePtr showerTree) const; /** * Access to the select tree */ PotentialTree & hardTree() {return hardTree_;} const PotentialTree & hardTree() const {return hardTree_;} /** * Access to the select tree */ void hardTree(PotentialTree in) const {hardTree_ = in;} /** * Check if two momenta are equal within 1% */ bool fuzzyEqual(Lorentz5Momentum a, Lorentz5Momentum b) const; /** * Access to the potential branchings */ set & protoBranchings() const {return protoBranchings_;} /** * The ProtoTrees which will become CKKWTrees */ set< ProtoTreePtr > & protoTrees() const {return protoTrees_;} /** * Recursive function to find all possible clustered trees. * Does not produce any repeated trees. */ void fillProtoTrees( ProtoTreePtr , long id ) const; /** * Function looks to see if a cluster of the branchings already exists * in protoBranchings_ if so returns the pointer to that protoBranching * if not creates the hardBranchings, adds it * to protoBranchings and returns the pointer */ tProtoBranchingPtr getCluster( tProtoBranchingPtr, tProtoBranchingPtr ) const; /** * Checks whether a ProtoTree containing the same branchings already * exists in protoTrees_ in which case the current tree is a repeat * and should be removed (and not recursed) */ bool repeatProtoTree( ProtoTreePtr currentProtoTree ) const; /** * Returns the branching element for an FS-FS clustering */ BranchingElement allowedFinalStateBranching( tProtoBranchingPtr &, tProtoBranchingPtr &) const; /** * Returns the branching element for an IS-FS clustering */ BranchingElement allowedInitialStateBranching( tProtoBranchingPtr & , tProtoBranchingPtr &) const; /** * Returns the diagram corresponding to the (leading-order) hardTree */ bool checkDiagram(PotentialTree &,tcDiagPtr) const; bool subtractionIntegral() const {return subtractionIntegral_;} void setSubtractionIntegral(bool subInt) const { subtractionIntegral_=subInt;} private: /** * The factory object to fetch splitting channels from */ Ptr::ptr theFactory; /** * The matrix element for the core process */ mutable MEPtr matrixElement_; /** * The chosen hard tree */ mutable PotentialTree hardTree_; /** * All the Protobranchings used in finding the shower histories */ mutable set protoBranchings_; /** * The ProtoTrees which will become CKKWTrees */ mutable set< ProtoTreePtr > protoTrees_; /** * The possible shower configurations that are angular-ordered */ mutable vector< pair< PotentialTree, double > > hardTrees_; /** * Which branchings are allowed? */ //@{ /** * The allowed final-state branchings */ mutable map,BranchingElement > allowedFinal_; /** * The allowed initial-state branchings */ mutable multimap allowedInitial_; //@} 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: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ PowhegShowerHandler & operator=(const PowhegShowerHandler &); private: /** * Emitter particle from the original generation */ mutable int emitter_; /** * Spectator particle from the original generation */ mutable int spectator_; /** * Whether or not a subtraction integral */ mutable bool subtractionIntegral_; /** * Whether or not do enforce consistency of the Born and real colour flows */ bool enforceColourConsistency_; /** * Force emitter and spectator partners */ bool forcePartners_; /** * Handling of radiation in decays */ unsigned int decayRadiation_; }; } #endif /* HERWIG_PowhegShowerHandler_H */ diff --git a/Shower/Matching/ProtoBranching.h b/Shower/QTilde/Matching/ProtoBranching.h rename from Shower/Matching/ProtoBranching.h rename to Shower/QTilde/Matching/ProtoBranching.h diff --git a/Shower/Matching/ProtoTree.h b/Shower/QTilde/Matching/ProtoTree.h rename from Shower/Matching/ProtoTree.h rename to Shower/QTilde/Matching/ProtoTree.h diff --git a/Shower/QTilde/QTildeShowerHandler.cc b/Shower/QTilde/QTildeShowerHandler.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/QTildeShowerHandler.cc @@ -0,0 +1,3736 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the QTildeShowerHandler class. +// + +#include "QTildeShowerHandler.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/Interface/Switch.h" +#include "ThePEG/Interface/Reference.h" +#include "ThePEG/Interface/RefVector.h" +#include "ThePEG/Interface/Parameter.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" +#include "ThePEG/Utilities/EnumIO.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/PDF/MPIPDF.h" +#include "Herwig/PDF/MinBiasPDF.h" +#include "Herwig/Shower/QTilde/Base/ShowerTree.h" +#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h" +#include "Herwig/Shower/QTilde/Base/PartnerFinder.h" +#include "Herwig/PDF/HwRemDecayer.h" +#include "Herwig/Shower/QTilde/Base/ShowerVertex.h" +#include "ThePEG/Repository/CurrentGenerator.h" +#include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" +#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" +#include "ThePEG/PDF/PartonExtractor.h" +#include "Herwig/Shower/RealEmissionProcess.h" + +using namespace Herwig; + +namespace { + + /** + * A struct to order the particles in the same way as in the DecayMode's + */ + struct ParticleOrdering { + /** + * Operator for the ordering + * @param p1 The first ParticleData object + * @param p2 The second ParticleData object + */ + bool operator() (tcPDPtr p1, tcPDPtr p2) { + return abs(p1->id()) > abs(p2->id()) || + ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || + ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); + } + }; + typedef multiset OrderedParticles; + + /** + * Cached lookup of decay modes. + * Generator::findDecayMode() is not efficient. + */ + tDMPtr findDecayMode(const string & tag) { + static map cache; + map::const_iterator pos = cache.find(tag); + + if ( pos != cache.end() ) + return pos->second; + + tDMPtr dm = CurrentGenerator::current().findDecayMode(tag); + cache[tag] = dm; + return dm; + } +} + +bool QTildeShowerHandler::_hardEmissionWarn = true; +bool QTildeShowerHandler::_missingTruncWarn = true; + +QTildeShowerHandler::QTildeShowerHandler() : + _maxtry(100), _meCorrMode(1), _reconOpt(0), + _hardVetoReadOption(false), + _iptrms(ZERO), _beta(0.), _gamma(ZERO), _iptmax(), + _limitEmissions(0), _initialenhance(1.), _finalenhance(1.), + _nReWeight(100), _reWeight(false), + interaction_(ShowerInteraction::QEDQCD), + _trunc_Mode(true), _hardEmission(1), + _spinOpt(1), _softOpt(2), _hardPOWHEG(false), muPt(ZERO), + _maxTryFSR(100000), _maxFailFSR(100), _fracFSR(0.001), + _nFSR(0), _nFailedFSR(0) +{} + +QTildeShowerHandler::~QTildeShowerHandler() {} + +IBPtr QTildeShowerHandler::clone() const { + return new_ptr(*this); +} + +IBPtr QTildeShowerHandler::fullclone() const { + return new_ptr(*this); +} + +void QTildeShowerHandler::persistentOutput(PersistentOStream & os) const { + os << _model << _splittingGenerator << _maxtry + << _meCorrMode << _hardVetoReadOption + << _limitEmissions << _spinOpt << _softOpt << _hardPOWHEG + << ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV) + << _vetoes << _fullShowerVetoes << _nReWeight << _reWeight + << _trunc_Mode << _hardEmission << _reconOpt + << ounit(muPt,GeV) + << oenum(interaction_) << _maxTryFSR << _maxFailFSR << _fracFSR; +} + +void QTildeShowerHandler::persistentInput(PersistentIStream & is, int) { + is >> _model >> _splittingGenerator >> _maxtry + >> _meCorrMode >> _hardVetoReadOption + >> _limitEmissions >> _spinOpt >> _softOpt >> _hardPOWHEG + >> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV) + >> _vetoes >> _fullShowerVetoes >> _nReWeight >> _reWeight + >> _trunc_Mode >> _hardEmission >> _reconOpt + >> iunit(muPt,GeV) + >> ienum(interaction_) >> _maxTryFSR >> _maxFailFSR >> _fracFSR; +} + + +// The following static variable is needed for the type +// description system in ThePEG. +DescribeClass +describeHerwigQTildeShowerHandler("Herwig::QTildeShowerHandler", "HwShower.so"); + +void QTildeShowerHandler::Init() { + + static ClassDocumentation documentation + ("TheQTildeShowerHandler class is the main class" + " for the angular-ordered parton shower", + "The Shower evolution was performed using an algorithm described in " + "\\cite{Marchesini:1983bm,Marchesini:1987cf,Gieseke:2003rz,Bahr:2008pv}.", + "%\\cite{Marchesini:1983bm}\n" + "\\bibitem{Marchesini:1983bm}\n" + " G.~Marchesini and B.~R.~Webber,\n" + " ``Simulation Of QCD Jets Including Soft Gluon Interference,''\n" + " Nucl.\\ Phys.\\ B {\\bf 238}, 1 (1984).\n" + " %%CITATION = NUPHA,B238,1;%%\n" + "%\\cite{Marchesini:1987cf}\n" + "\\bibitem{Marchesini:1987cf}\n" + " G.~Marchesini and B.~R.~Webber,\n" + " ``Monte Carlo Simulation of General Hard Processes with Coherent QCD\n" + " Radiation,''\n" + " Nucl.\\ Phys.\\ B {\\bf 310}, 461 (1988).\n" + " %%CITATION = NUPHA,B310,461;%%\n" + "%\\cite{Gieseke:2003rz}\n" + "\\bibitem{Gieseke:2003rz}\n" + " S.~Gieseke, P.~Stephens and B.~Webber,\n" + " ``New formalism for QCD parton showers,''\n" + " JHEP {\\bf 0312}, 045 (2003)\n" + " [arXiv:hep-ph/0310083].\n" + " %%CITATION = JHEPA,0312,045;%%\n" + ); + + static Reference + interfaceSplitGen("SplittingGenerator", + "A reference to the SplittingGenerator object", + &Herwig::QTildeShowerHandler::_splittingGenerator, + false, false, true, false); + + static Reference interfaceShowerModel + ("ShowerModel", + "The pointer to the object which defines the shower evolution model.", + &QTildeShowerHandler::_model, false, false, true, false, false); + + static Parameter interfaceMaxTry + ("MaxTry", + "The maximum number of attempts to generate the shower from a" + " particular ShowerTree", + &QTildeShowerHandler::_maxtry, 100, 1, 100000, + false, false, Interface::limited); + + static Parameter interfaceNReWeight + ("NReWeight", + "The number of attempts for the shower when reweighting", + &QTildeShowerHandler::_nReWeight, 100, 10, 10000, + false, false, Interface::limited); + + static Switch ifaceMECorrMode + ("MECorrMode", + "Choice of the ME Correction Mode", + &QTildeShowerHandler::_meCorrMode, 1, false, false); + static SwitchOption on + (ifaceMECorrMode,"HardPlusSoft","hard+soft on", 1); + static SwitchOption hard + (ifaceMECorrMode,"Hard","only hard on", 2); + static SwitchOption soft + (ifaceMECorrMode,"Soft","only soft on", 3); + + static Switch ifaceHardVetoReadOption + ("HardVetoReadOption", + "Apply read-in scale veto to all collisions or just the primary one?", + &QTildeShowerHandler::_hardVetoReadOption, false, false, false); + static SwitchOption AllCollisions + (ifaceHardVetoReadOption, + "AllCollisions", + "Read-in pT veto applied to primary and secondary collisions.", + false); + static SwitchOption PrimaryCollision + (ifaceHardVetoReadOption, + "PrimaryCollision", + "Read-in pT veto applied to primary but not secondary collisions.", + true); + + static Parameter ifaceiptrms + ("IntrinsicPtGaussian", + "RMS of intrinsic pT of Gaussian distribution:\n" + "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", + &QTildeShowerHandler::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV, + false, false, Interface::limited); + + static Parameter ifacebeta + ("IntrinsicPtBeta", + "Proportion of inverse quadratic distribution in generating intrinsic pT.\n" + "(1-Beta) is the proportion of Gaussian distribution", + &QTildeShowerHandler::_beta, 0, 0, 1, + false, false, Interface::limited); + + static Parameter ifacegamma + ("IntrinsicPtGamma", + "Parameter for inverse quadratic:\n" + "2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))", + &QTildeShowerHandler::_gamma,GeV, ZERO, ZERO, 100000.0*GeV, + false, false, Interface::limited); + + static Parameter ifaceiptmax + ("IntrinsicPtIptmax", + "Upper bound on intrinsic pT for inverse quadratic", + &QTildeShowerHandler::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV, + false, false, Interface::limited); + + static RefVector ifaceVetoes + ("Vetoes", + "The vetoes to be checked during showering", + &QTildeShowerHandler::_vetoes, -1, + false,false,true,true,false); + + static RefVector interfaceFullShowerVetoes + ("FullShowerVetoes", + "The vetos to be appliede on the full final state of the shower", + &QTildeShowerHandler::_fullShowerVetoes, -1, false, false, true, false, false); + + static Switch interfaceLimitEmissions + ("LimitEmissions", + "Limit the number and type of emissions for testing", + &QTildeShowerHandler::_limitEmissions, 0, false, false); + static SwitchOption interfaceLimitEmissionsNoLimit + (interfaceLimitEmissions, + "NoLimit", + "Allow an arbitrary number of emissions", + 0); + static SwitchOption interfaceLimitEmissionsOneInitialStateEmission + (interfaceLimitEmissions, + "OneInitialStateEmission", + "Allow one emission in the initial state and none in the final state", + 1); + static SwitchOption interfaceLimitEmissionsOneFinalStateEmission + (interfaceLimitEmissions, + "OneFinalStateEmission", + "Allow one emission in the final state and none in the initial state", + 2); + static SwitchOption interfaceLimitEmissionsHardOnly + (interfaceLimitEmissions, + "HardOnly", + "Only allow radiation from the hard ME correction", + 3); + static SwitchOption interfaceLimitEmissionsOneEmission + (interfaceLimitEmissions, + "OneEmission", + "Allow one emission in either the final state or initial state, but not both", + 4); + + static Switch interfaceTruncMode + ("TruncatedShower", "Include the truncated shower?", + &QTildeShowerHandler::_trunc_Mode, 1, false, false); + static SwitchOption interfaceTruncMode0 + (interfaceTruncMode,"No","Truncated Shower is OFF", 0); + static SwitchOption interfaceTruncMode1 + (interfaceTruncMode,"Yes","Truncated Shower is ON", 1); + + static Switch interfaceHardEmission + ("HardEmission", + "Whether to use ME corrections or POWHEG for the hardest emission", + &QTildeShowerHandler::_hardEmission, 0, false, false); + static SwitchOption interfaceHardEmissionNone + (interfaceHardEmission, + "None", + "No Corrections", + 0); + static SwitchOption interfaceHardEmissionMECorrection + (interfaceHardEmission, + "MECorrection", + "Old fashioned ME correction", + 1); + static SwitchOption interfaceHardEmissionPOWHEG + (interfaceHardEmission, + "POWHEG", + "Powheg style hard emission", + 2); + + static Switch interfaceInteraction + ("Interaction", + "The interactions to be used in the shower", + &QTildeShowerHandler::interaction_, ShowerInteraction::QEDQCD, false, false); + static SwitchOption interfaceInteractionsQCD + (interfaceInteraction, + "QCD", + "Only QCD radiation", + ShowerInteraction::QCD); + static SwitchOption interfaceInteractionsQED + (interfaceInteraction, + "QED", + "Only QEd radiation", + ShowerInteraction::QED); + static SwitchOption interfaceInteractionEWOnly + (interfaceInteraction, + "EWOnly", + "Only EW", + ShowerInteraction::EW); + static SwitchOption interfaceInteractionQEDQCD + (interfaceInteraction, + "QEDQCD", + "QED and QCD", + ShowerInteraction::QEDQCD); + static SwitchOption interfaceInteractionALL + (interfaceInteraction, + "ALL", + "QED, QCD and EW", + ShowerInteraction::ALL); + + static Switch interfaceReconstructionOption + ("ReconstructionOption", + "Treatment of the reconstruction of the transverse momentum of " + "a branching from the evolution scale.", + &QTildeShowerHandler::_reconOpt, 0, false, false); + static SwitchOption interfaceReconstructionOptionCutOff + (interfaceReconstructionOption, + "CutOff", + "Use the cut-off masses in the calculation", + 0); + static SwitchOption interfaceReconstructionOptionOffShell + (interfaceReconstructionOption, + "OffShell", + "Use the off-shell masses in the calculation veto the emission of the parent," + " no veto in generation of emissions from children", + 1); + static SwitchOption interfaceReconstructionOptionOffShell2 + (interfaceReconstructionOption, + "OffShell2", + "Use the off-shell masses in the calculation veto the emissions from the children." + " no veto in generation of emissions from children", + 2); + static SwitchOption interfaceReconstructionOptionOffShell3 + (interfaceReconstructionOption, + "OffShell3", + "Use the off-shell masses in the calculation veto the emissions from the children." + " veto in generation of emissions from children using cut-off for second parton", + 3); + static SwitchOption interfaceReconstructionOptionOffShell4 + (interfaceReconstructionOption, + "OffShell4", + "Ass OffShell3 but with a restriction on the mass of final-state" + " jets produced via backward evolution.", + 4); + + static Switch interfaceSpinCorrelations + ("SpinCorrelations", + "Treatment of spin correlations in the parton shower", + &QTildeShowerHandler::_spinOpt, 1, false, false); + static SwitchOption interfaceSpinCorrelationsOff + (interfaceSpinCorrelations, + "No", + "No spin correlations", + 0); + static SwitchOption interfaceSpinCorrelationsSpin + (interfaceSpinCorrelations, + "Yes", + "Include the azimuthal spin correlations only", + 1); + + static Switch interfaceSoftCorrelations + ("SoftCorrelations", + "Option for the treatment of soft correlations in the parton shower", + &QTildeShowerHandler::_softOpt, 2, false, false); + static SwitchOption interfaceSoftCorrelationsNone + (interfaceSoftCorrelations, + "No", + "No soft correlations", + 0); + static SwitchOption interfaceSoftCorrelationsFull + (interfaceSoftCorrelations, + "Full", + "Use the full eikonal", + 1); + static SwitchOption interfaceSoftCorrelationsSingular + (interfaceSoftCorrelations, + "Singular", + "Use original Webber-Marchisini form", + 2); + + static Switch interfaceHardPOWHEG + ("HardPOWHEG", + "Treatment of powheg emissions which are too hard to have a shower interpretation", + &QTildeShowerHandler::_hardPOWHEG, false, false, false); + static SwitchOption interfaceHardPOWHEGAsShower + (interfaceHardPOWHEG, + "AsShower", + "Still interpret as shower emissions", + false); + static SwitchOption interfaceHardPOWHEGRealEmission + (interfaceHardPOWHEG, + "RealEmission", + "Generate shower from the real emmission configuration", + true); + + static Parameter interfaceMaxTryFSR + ("MaxTryFSR", + "The maximum number of attempted FSR emissions in" + " the generation of the FSR", + &QTildeShowerHandler::_maxTryFSR, 100000, 10, 100000000, + false, false, Interface::limited); + + static Parameter interfaceMaxFailFSR + ("MaxFailFSR", + "Maximum number of failures generating the FSR", + &QTildeShowerHandler::_maxFailFSR, 100, 1, 100000000, + false, false, Interface::limited); + + static Parameter interfaceFSRFailureFraction + ("FSRFailureFraction", + "Maximum fraction of events allowed to fail due to too many FSR emissions", + &QTildeShowerHandler::_fracFSR, 0.001, 1e-10, 1, + false, false, Interface::limited); + +} + +tPPair QTildeShowerHandler::cascade(tSubProPtr sub, + XCPtr xcomb) { + // use me for reference in tex file etc + useMe(); + prepareCascade(sub); + // set things up in the base class + resetWeights(); + hard_=ShowerTreePtr(); + decay_.clear(); + done_.clear(); + // check if anything needs doing + if ( !doFSR() && ! doISR() ) + return sub->incoming(); + // start of the try block for the whole showering process + unsigned int countFailures=0; + while (countFailuresoutgoing().begin(), + currentSubProcess()->outgoing().end()), + hard,decay); + ShowerTree::constructTrees(hard_,decay_,hard,decay); + // if no hard process + if(!hard_) throw Exception() << "Shower starting with a decay" + << "is not implemented" + << Exception::runerror; + // perform the shower for the hard process + showerHardProcess(hard_,xcomb); + done_.push_back(hard_); + hard_->updateAfterShower(decay_); + // if no decaying particles to shower break out of the loop + if(decay_.empty()) break; + // shower the decay products + while(!decay_.empty()) { + // find particle whose production process has been showered + ShowerDecayMap::iterator dit = decay_.begin(); + while(!dit->second->parent()->hasShowered() && dit!=decay_.end()) ++dit; + assert(dit!=decay_.end()); + // get the particle + ShowerTreePtr decayingTree = dit->second; + // remove it from the multimap + decay_.erase(dit); + // make sure the particle has been decayed + QTildeShowerHandler::decay(decayingTree,decay_); + // now shower the decay + showerDecay(decayingTree); + done_.push_back(decayingTree); + decayingTree->updateAfterShower(decay_); + } + // suceeded break out of the loop + break; + } + catch (KinematicsReconstructionVeto) { + resetWeights(); + ++countFailures; + } + } + // 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(incomingBeams().first ) && + !isResolvedHadron(incomingBeams().second) ) + return incomingBeams(); + // remake the remnants (needs to be after the colours are sorted + // out in the insertion into the event record) + if ( firstInteraction() ) return remakeRemnant(sub->incoming()); + //Return the new pair of incoming partons. remakeRemnant is not + //necessary here, because the secondary interactions are not yet + //connected to the remnants. + return make_pair(findFirstParton(sub->incoming().first ), + findFirstParton(sub->incoming().second)); +} + +void QTildeShowerHandler::fillEventRecord() { + // create a new step + StepPtr pstep = newStep(); + assert(!done_.empty()); + assert(done_[0]->isHard()); + // insert the steps + for(unsigned int ix=0;ixfillEventRecord(pstep,doISR(),doFSR()); + } +} + +HardTreePtr QTildeShowerHandler::generateCKKW(ShowerTreePtr ) const { + return HardTreePtr(); +} + +void QTildeShowerHandler::doinit() { + ShowerHandler::doinit(); + // interactions may have been changed through a setup file so we + // clear it up here + // calculate max no of FSR vetos + _maxFailFSR = max(int(_maxFailFSR), int(_fracFSR*double(generator()->N()))); + // check on the reweighting + for(unsigned int ix=0;ix<_fullShowerVetoes.size();++ix) { + if(_fullShowerVetoes[ix]->behaviour()==1) { + _reWeight = true; + break; + } + } + if(_reWeight && maximumTries()<_nReWeight) { + throw Exception() << "Reweight being performed in the shower but the number of attempts for the" + << "shower is less than that for the reweighting.\n" + << "Maximum number of attempt for the shower " + << fullName() << ":MaxTry is " << maximumTries() << "\nand for reweighting is " + << fullName() << ":NReWeight is " << _nReWeight << "\n" + << "we recommend the number of attempts is 10 times the number for reweighting\n" + << Exception::runerror; + } +} + +void QTildeShowerHandler::generateIntrinsicpT(vector particlesToShower) { + _intrinsic.clear(); + if ( !ipTon() || !doISR() ) return; + // don't do anything for the moment for secondary scatters + if( !firstInteraction() ) return; + // generate intrinsic pT + for(unsigned int ix=0;ixprogenitor()->isFinalState()) continue; + if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue; + Energy ipt; + if(UseRandom::rnd() > _beta) { + ipt=_iptrms*sqrt(-log(UseRandom::rnd())); + } + else { + ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.); + } + pair pt = make_pair(ipt,UseRandom::rnd(Constants::twopi)); + _intrinsic[particlesToShower[ix]] = pt; + } +} + +void QTildeShowerHandler::setupMaximumScales(const vector & p, + XCPtr xcomb) { + // let POWHEG events radiate freely + if(_hardEmission==2&&hardTree()) { + vector::const_iterator ckt = p.begin(); + for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy); + return; + } + // return if no vetos + if (!restrictPhasespace()) return; + // find out if hard partonic subprocess. + bool isPartonic(false); + map::const_iterator + cit = _currenttree->incomingLines().begin(); + Lorentz5Momentum pcm; + for(; cit!=currentTree()->incomingLines().end(); ++cit) { + pcm += cit->first->progenitor()->momentum(); + isPartonic |= cit->first->progenitor()->coloured(); + } + // find minimum pt from hard process, the maximum pt from all outgoing + // coloured lines (this is simpler and more general than + // 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will + // be transverse mass. + Energy ptmax = generator()->maximumCMEnergy(); + // general case calculate the scale + if ( !hardScaleIsMuF() || (hardVetoReadOption()&&!firstInteraction()) ) { + // scattering process + if(currentTree()->isHard()) { + assert(xcomb); + // coloured incoming particles + if (isPartonic) { + map::const_iterator + cjt = currentTree()->outgoingLines().begin(); + for(; cjt!=currentTree()->outgoingLines().end(); ++cjt) { + if (cjt->first->progenitor()->coloured()) + ptmax = min(ptmax,cjt->first->progenitor()->momentum().mt()); + } + } + if (ptmax == generator()->maximumCMEnergy() ) ptmax = pcm.m(); + if(hardScaleIsMuF()&&hardVetoReadOption()&& + !firstInteraction()) { + ptmax=min(ptmax,sqrt(xcomb->lastShowerScale())); + } + } + // decay, incoming() is the decaying particle. + else { + ptmax = currentTree()->incomingLines().begin()->first + ->progenitor()->momentum().mass(); + } + } + // hepeup.SCALUP is written into the lastXComb by the + // LesHouchesReader itself - use this by user's choice. + // Can be more general than this. + else { + if(currentTree()->isHard()) { + assert(xcomb); + ptmax = sqrt( xcomb->lastShowerScale() ); + } + else { + ptmax = currentTree()->incomingLines().begin()->first + ->progenitor()->momentum().mass(); + } + } + ptmax *= hardScaleFactor(); + // set maxHardPt for all progenitors. For partonic processes this + // is now the max pt in the FS, for non-partonic processes or + // processes with no coloured FS the invariant mass of the IS + vector::const_iterator ckt = p.begin(); + for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax); +} + +void QTildeShowerHandler::setupHardScales(const vector & p, + XCPtr xcomb) { + if ( hardScaleIsMuF() && + (!hardVetoReadOption() || firstInteraction()) ) { + Energy hardScale = ZERO; + if(currentTree()->isHard()) { + assert(xcomb); + hardScale = sqrt( xcomb->lastShowerScale() ); + } + else { + hardScale = currentTree()->incomingLines().begin()->first + ->progenitor()->momentum().mass(); + } + hardScale *= hardScaleFactor(); + vector::const_iterator ckt = p.begin(); + for (; ckt != p.end(); ckt++) (*ckt)->hardScale(hardScale); + muPt = hardScale; + } +} + +void QTildeShowerHandler::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) { + _hardme = HwMEBasePtr(); + // extract the matrix element + tStdXCombPtr lastXC = dynamic_ptr_cast(xcomb); + if(lastXC) { + _hardme = dynamic_ptr_cast(lastXC->matrixElement()); + } + _decayme = HwDecayerBasePtr(); + // set the current tree + currentTree(hard); + hardTree(HardTreePtr()); + // work out the type of event + currentTree()->xcombPtr(dynamic_ptr_cast(xcomb)); + currentTree()->identifyEventType(); + checkFlags(); + // generate the showering + doShowering(true,xcomb); +} + +RealEmissionProcessPtr QTildeShowerHandler::hardMatrixElementCorrection(bool hard) { + // set the initial enhancement factors for the soft correction + _initialenhance = 1.; + _finalenhance = 1.; + // see if we can get the correction from the matrix element + // or decayer + RealEmissionProcessPtr real; + if(hard) { + if(_hardme&&_hardme->hasMECorrection()) { + _hardme->initializeMECorrection(_currenttree->perturbativeProcess(), + _initialenhance,_finalenhance); + if(hardMEC()) + real = + _hardme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess()); + } + } + else { + if(_decayme&&_decayme->hasMECorrection()) { + _decayme->initializeMECorrection(_currenttree->perturbativeProcess(), + _initialenhance,_finalenhance); + if(hardMEC()) + real = _decayme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess()); + } + } + return real; +} + +ShowerParticleVector QTildeShowerHandler::createTimeLikeChildren(tShowerParticlePtr, IdList ids) { + // Create the ShowerParticle objects for the two children of + // the emitting particle; set the parent/child relationship + // if same as definition create particles, otherwise create cc + ShowerParticleVector children; + for(unsigned int ix=0;ix<2;++ix) { + children.push_back(new_ptr(ShowerParticle(ids[ix+1],true))); + if(children[ix]->id()==_progenitor->id()&&!ids[ix+1]->stable()) + children[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass())); + else + children[ix]->set5Momentum(Lorentz5Momentum(ids[ix+1]->mass())); + } + return children; +} + +bool QTildeShowerHandler::timeLikeShower(tShowerParticlePtr particle, + ShowerInteraction::Type type, + Branching fb, bool first) { + // don't do anything if not needed + if(_limitEmissions == 1 || hardOnly() || + ( _limitEmissions == 2 && _nfs != 0) || + ( _limitEmissions == 4 && _nfs + _nis != 0) ) { + if(particle->spinInfo()) particle->spinInfo()->develop(); + return false; + } + // too many tries + if(_nFSR>=_maxTryFSR) { + ++_nFailedFSR; + // too many failed events + if(_nFailedFSR>=_maxFailFSR) + throw Exception() << "Too many events have failed due to too many shower emissions, in\n" + << "QTildeShowerHandler::timeLikeShower(). Terminating run\n" + << Exception::runerror; + throw Exception() << "Too many attempted emissions in QTildeShowerHandler::timeLikeShower()\n" + << Exception::eventerror; + } + // generate the emission + ShowerParticleVector children; + int ntry=0; + // generate the emission + if(!fb.kinematics) + fb = selectTimeLikeBranching(particle,type,HardBranchingPtr()); + // no emission, return + if(!fb.kinematics) { + if(particle->spinInfo()) particle->spinInfo()->develop(); + return false; + } + Branching fc[2]; + bool setupChildren = true; + while (ntry<50) { + fc[0] = Branching(); + fc[1] = Branching(); + ++ntry; + assert(fb.kinematics); + // has emitted + // Assign the shower kinematics to the emitting particle. + if(setupChildren) { + ++_nFSR; + particle->showerKinematics(fb.kinematics); + // check highest pT + if(fb.kinematics->pT()>progenitor()->highestpT()) + progenitor()->highestpT(fb.kinematics->pT()); + // create the children + children = createTimeLikeChildren(particle,fb.ids); + // update the children + particle->showerKinematics()-> + updateChildren(particle, children,fb.type,_reconOpt>=3); + // update number of emissions + ++_nfs; + if(_limitEmissions!=0) { + if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); + if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); + if(particle->spinInfo()) particle->spinInfo()->develop(); + return true; + } + setupChildren = false; + } + // select branchings for children + fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); + fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); + // old default + if(_reconOpt==0) { + // shower the first particle + if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); + if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); + // shower the second particle + if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); + if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); + break; + } + // Herwig default + else if(_reconOpt==1) { + // shower the first particle + if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); + if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); + // shower the second particle + if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); + if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); + // branching has happened + particle->showerKinematics()->updateParent(particle, children,fb.type); + // clean up the vetoed emission + if(particle->virtualMass()==ZERO) { + particle->showerKinematics(ShoKinPtr()); + for(unsigned int ix=0;ixabandonChild(children[ix]); + children.clear(); + if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); + particle->vetoEmission(fb.type,fb.kinematics->scale()); + // generate the new emission + fb = selectTimeLikeBranching(particle,type,HardBranchingPtr()); + // no emission, return + if(!fb.kinematics) { + if(particle->spinInfo()) particle->spinInfo()->develop(); + return false; + } + setupChildren = true; + continue; + } + else + break; + } + // veto children + else if(_reconOpt>=2) { + // cut-off masses for the branching + const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); + // compute the masses of the children + Energy masses[3]; + for(unsigned int ix=0;ix<2;++ix) { + if(fc[ix].kinematics) { + const vector & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids); + Energy2 q2 = + fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale()); + if(fc[ix].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); + masses[ix+1] = sqrt(q2); + } + else { + masses[ix+1] = virtualMasses[ix+1]; + } + } + masses[0] = fb.ids[0]->id()!=ParticleID::g ? virtualMasses[0] : ZERO; + double z = fb.kinematics->z(); + Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale()) + sqr(masses[0])) + - sqr(masses[1])*(1.-z) - sqr(masses[2])*z; + if(pt2>=ZERO) { + break; + } + else { + // reset the scales for the children + for(unsigned int ix=0;ix<2;++ix) { + if(fc[ix].kinematics) + children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); + else + children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); + children[ix]->virtualMass(ZERO); + } + } + } + }; + if(_reconOpt>=2) { + // shower the first particle + if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false); + if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); + // shower the second particle + if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false); + if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); + // branching has happened + particle->showerKinematics()->updateParent(particle, children,fb.type); + } + if(first&&!children.empty()) + particle->showerKinematics()->resetChildren(particle,children); + if(particle->spinInfo()) particle->spinInfo()->develop(); + return true; +} + +bool +QTildeShowerHandler::spaceLikeShower(tShowerParticlePtr particle, PPtr beam, + ShowerInteraction::Type type) { + //using the pdf's associated with the ShowerHandler assures, that + //modified pdf's are used for the secondary interactions via + //CascadeHandler::resetPDFs(...) + tcPDFPtr pdf; + if(firstPDF().particle() == _beam) + pdf = firstPDF().pdf(); + if(secondPDF().particle() == _beam) + pdf = secondPDF().pdf(); + Energy freeze = pdfFreezingScale(); + // don't do anything if not needed + if(_limitEmissions == 2 || hardOnly() || + ( _limitEmissions == 1 && _nis != 0 ) || + ( _limitEmissions == 4 && _nis + _nfs != 0 ) ) { + if(particle->spinInfo()) particle->spinInfo()->develop(); + return false; + } + Branching bb; + // generate branching + while (true) { + bb=_splittingGenerator->chooseBackwardBranching(*particle,beam, + _initialenhance, + _beam,type, + pdf,freeze); + // return if no emission + if(!bb.kinematics) { + if(particle->spinInfo()) particle->spinInfo()->develop(); + return false; + } + // if not vetoed break + if(!spaceLikeVetoed(bb,particle)) break; + // otherwise reset scale and continue + particle->vetoEmission(bb.type,bb.kinematics->scale()); + if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); + } + // assign the splitting function and shower kinematics + particle->showerKinematics(bb.kinematics); + if(bb.kinematics->pT()>progenitor()->highestpT()) + progenitor()->highestpT(bb.kinematics->pT()); + // For the time being we are considering only 1->2 branching + // particles as in Sudakov form factor + tcPDPtr part[2]={bb.ids[0],bb.ids[2]}; + // Now create the actual particles, make the otherChild a final state + // particle, while the newParent is not + ShowerParticlePtr newParent = new_ptr(ShowerParticle(part[0],false)); + ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true)); + ShowerParticleVector theChildren; + theChildren.push_back(particle); + theChildren.push_back(otherChild); + //this updates the evolution scale + particle->showerKinematics()-> + updateParent(newParent, theChildren,bb.type); + // update the history if needed + _currenttree->updateInitialStateShowerProduct(_progenitor,newParent); + _currenttree->addInitialStateBranching(particle,newParent,otherChild); + // for the reconstruction of kinematics, parent/child + // relationships are according to the branching process: + // now continue the shower + ++_nis; + bool emitted = _limitEmissions==0 ? + spaceLikeShower(newParent,beam,type) : false; + if(newParent->spinInfo()) newParent->spinInfo()->develop(); + // now reconstruct the momentum + if(!emitted) { + if(_intrinsic.find(_progenitor)==_intrinsic.end()) { + bb.kinematics->updateLast(newParent,ZERO,ZERO); + } + else { + pair kt=_intrinsic[_progenitor]; + bb.kinematics->updateLast(newParent, + kt.first*cos(kt.second), + kt.first*sin(kt.second)); + } + } + particle->showerKinematics()-> + updateChildren(newParent, theChildren,bb.type,_reconOpt>=4); + if(_limitEmissions!=0) { + if(particle->spinInfo()) particle->spinInfo()->develop(); + return true; + } + // perform the shower of the final-state particle + timeLikeShower(otherChild,type,Branching(),true); + updateHistory(otherChild); + if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop(); + // return the emitted + if(particle->spinInfo()) particle->spinInfo()->develop(); + return true; +} + +void QTildeShowerHandler::showerDecay(ShowerTreePtr decay) { + // work out the type of event + currentTree()->xcombPtr(StdXCombPtr()); + currentTree()->identifyEventType(); + _decayme = HwDecayerBasePtr(); + _hardme = HwMEBasePtr(); + // find the decayer + // try the normal way if possible + tDMPtr dm = decay->incomingLines().begin()->first->original() ->decayMode(); + if(!dm) dm = decay->incomingLines().begin()->first->copy() ->decayMode(); + if(!dm) dm = decay->incomingLines().begin()->first->progenitor()->decayMode(); + // otherwise make a string and look it up + if(!dm) { + string tag = decay->incomingLines().begin()->first->original()->dataPtr()->name() + + "->"; + OrderedParticles outgoing; + for(map::const_iterator + it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) { + if(abs(decay->incomingLines().begin()->first->original()->id()) == ParticleID::t && + abs(it->first->original()->id())==ParticleID::Wplus && + decay->treelinks().size() == 1) { + ShowerTreePtr Wtree = decay->treelinks().begin()->first; + for(map::const_iterator + it2=Wtree->outgoingLines().begin();it2!=Wtree->outgoingLines().end();++it2) { + outgoing.insert(it2->first->original()->dataPtr()); + } + } + else { + outgoing.insert(it->first->original()->dataPtr()); + } + } + for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) { + if(it!=outgoing.begin()) tag += ","; + tag +=(**it).name(); + } + tag += ";"; + dm = findDecayMode(tag); + } + if(dm) _decayme = dynamic_ptr_cast(dm->decayer()); + // set the ShowerTree to be showered + currentTree(decay); + decay->applyTransforms(); + hardTree(HardTreePtr()); + // generate the showering + doShowering(false,XCPtr()); + // if no vetos + // force calculation of spin correlations + SpinPtr spInfo = decay->incomingLines().begin()->first->progenitor()->spinInfo(); + if(spInfo) { + if(!spInfo->developed()) spInfo->needsUpdate(); + spInfo->develop(); + } +} + +bool QTildeShowerHandler::spaceLikeDecayShower(tShowerParticlePtr particle, + const ShowerParticle::EvolutionScales & maxScales, + Energy minmass,ShowerInteraction::Type type, + Branching fb) { + // too many tries + if(_nFSR>=_maxTryFSR) { + ++_nFailedFSR; + // too many failed events + if(_nFailedFSR>=_maxFailFSR) + throw Exception() << "Too many events have failed due to too many shower emissions, in\n" + << "QTildeShowerHandler::timeLikeShower(). Terminating run\n" + << Exception::runerror; + throw Exception() << "Too many attempted emissions in QTildeShowerHandler::timeLikeShower()\n" + << Exception::eventerror; + } + // generate the emission + ShowerParticleVector children; + int ntry=0; + // generate the emission + if(!fb.kinematics) + fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type, + HardBranchingPtr()); + // no emission, return + if(!fb.kinematics) return false; + Branching fc[2]; + bool setupChildren = true; + while (ntry<50) { + if(particle->virtualMass()==ZERO) + particle->virtualMass(_progenitor->progenitor()->mass()); + fc[0] = Branching(); + fc[1] = Branching(); + ++ntry; + assert(fb.kinematics); + // has emitted + // Assign the shower kinematics to the emitting particle. + if(setupChildren) { + ++_nFSR; + // Assign the shower kinematics to the emitting particle. + particle->showerKinematics(fb.kinematics); + if(fb.kinematics->pT()>progenitor()->highestpT()) + progenitor()->highestpT(fb.kinematics->pT()); + // create the ShowerParticle objects for the two children + children = createTimeLikeChildren(particle,fb.ids); + // updateChildren the children + particle->showerKinematics()-> + updateChildren(particle, children, fb.type,_reconOpt>=3); + setupChildren = false; + } + // select branchings for children + fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass, + type,HardBranchingPtr()); + fc[1] = selectTimeLikeBranching (children[1],type,HardBranchingPtr()); + // old default + if(_reconOpt==0) { + // shower the first particle + _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); + _currenttree->addInitialStateBranching(particle,children[0],children[1]); + if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); + // shower the second particle + if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); + updateHistory(children[1]); + // branching has happened + break; + } + // Herwig default + else if(_reconOpt==1) { + // shower the first particle + _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); + _currenttree->addInitialStateBranching(particle,children[0],children[1]); + if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); + // shower the second particle + if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); + updateHistory(children[1]); + // branching has happened + particle->showerKinematics()->updateParent(particle, children,fb.type); + // clean up the vetoed emission + if(particle->virtualMass()==ZERO) { + particle->showerKinematics(ShoKinPtr()); + for(unsigned int ix=0;ixabandonChild(children[ix]); + children.clear(); + particle->vetoEmission(fb.type,fb.kinematics->scale()); + // generate the new emission + fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type, + HardBranchingPtr()); + // no emission, return + if(!fb.kinematics) { + return false; + } + setupChildren = true; + continue; + } + else + break; + } + else if(_reconOpt>=2) { + // cut-off masses for the branching + const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); + // compute the masses of the children + Energy masses[3]; + // space-like children + masses[1] = children[0]->virtualMass(); + // time-like child + if(fc[1].kinematics) { + const vector & vm = fc[1].sudakov->virtualMasses(fc[1].ids); + Energy2 q2 = + fc[1].kinematics->z()*(1.-fc[1].kinematics->z())*sqr(fc[1].kinematics->scale()); + if(fc[1].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); + masses[2] = sqrt(q2); + } + else { + masses[2] = virtualMasses[2]; + } + masses[0]=particle->virtualMass(); + double z = fb.kinematics->z(); + Energy2 pt2 = (1.-z)*(z*sqr(masses[0])-sqr(masses[1])-z/(1.-z)*sqr(masses[2])); + if(pt2>=ZERO) { + break; + } + else { + // reset the scales for the children + for(unsigned int ix=0;ix<2;++ix) { + if(fc[ix].kinematics) + children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); + else { + if(ix==0) + children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,Constants::MaxEnergy); + else + children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); + } + } + children[0]->virtualMass(_progenitor->progenitor()->mass()); + children[1]->virtualMass(ZERO); + } + } + }; + if(_reconOpt>=2) { + // In the case of splittings which involves coloured particles, + // set properly the colour flow of the branching. + // update the history if needed + _currenttree->updateInitialStateShowerProduct(_progenitor,children[0]); + _currenttree->addInitialStateBranching(particle,children[0],children[1]); + // shower the first particle + if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching()); + // shower the second particle + if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true); + updateHistory(children[1]); + // branching has happened + particle->showerKinematics()->updateParent(particle, children,fb.type); + } + // branching has happened + return true; +} + +vector QTildeShowerHandler::setupShower(bool hard) { + RealEmissionProcessPtr real; + // generate hard me if needed + if(_hardEmission==1) { + real = hardMatrixElementCorrection(hard); + if(real&&!real->outgoing().empty()) setupMECorrection(real); + } + // generate POWHEG hard emission if needed + else if(_hardEmission==2) + hardestEmission(hard); + // set the initial colour partners + setEvolutionPartners(hard,interaction_,false); + // get the particles to be showered + vector particlesToShower = + currentTree()->extractProgenitors(); + // return the answer + return particlesToShower; +} + +void QTildeShowerHandler::setEvolutionPartners(bool hard,ShowerInteraction::Type type, + bool clear) { + // match the particles in the ShowerTree and hardTree + if(hardTree() && !hardTree()->connect(currentTree())) + throw Exception() << "Can't match trees in " + << "QTildeShowerHandler::setEvolutionPartners()" + << Exception::eventerror; + // extract the progenitors + vector particles = + currentTree()->extractProgenitorParticles(); + // clear the partners if needed + if(clear) { + for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); + particles[ix]->clearPartners(); + } + } + // sort out the colour partners + if(hardTree()) { + // find the partner + for(unsigned int ix=0;ixparticles()[particles[ix]]->branchingParticle()->partner(); + if(!partner) continue; + for(map::const_iterator + it=hardTree()->particles().begin(); + it!=hardTree()->particles().end();++it) { + if(it->second->branchingParticle()==partner) { + particles[ix]->partner(it->first); + break; + } + } + if(!particles[ix]->partner()) + throw Exception() << "Can't match partners in " + << "QTildeShowerHandler::setEvolutionPartners()" + << Exception::eventerror; + } + } + + // Set the initial evolution scales + showerModel()->partnerFinder()-> + setInitialEvolutionScales(particles,!hard,interaction_,!_hardtree); + if(hardTree() && _hardPOWHEG) { + bool tooHard=false; + map::const_iterator + eit=hardTree()->particles().end(); + for(unsigned int ix=0;ix::const_iterator + mit = hardTree()->particles().find(particles[ix]); + Energy hardScale(ZERO); + ShowerPartnerType::Type type(ShowerPartnerType::Undefined); + // final-state + if(particles[ix]->isFinalState()) { + if(mit!= eit && !mit->second->children().empty()) { + hardScale = mit->second->scale(); + type = mit->second->type(); + } + } + // initial-state + else { + if(mit!= eit && mit->second->parent()) { + hardScale = mit->second->parent()->scale(); + type = mit->second->parent()->type(); + } + } + if(type!=ShowerPartnerType::Undefined) { + if(type==ShowerPartnerType::QED) { + tooHard |= particles[ix]->scales().QED_noAOscales().QCD_c_noAOscales().QCD_ac_noAOscales().EWchildren().empty()) { + ShowerParticleVector theChildren; + for(unsigned int ix=0;ixchildren().size();++ix) { + ShowerParticlePtr part = dynamic_ptr_cast + (particle->children()[ix]); + theChildren.push_back(part); + } + // update the history if needed + if(particle==_currenttree->getFinalStateShowerProduct(_progenitor)) + _currenttree->updateFinalStateShowerProduct(_progenitor, + particle,theChildren); + _currenttree->addFinalStateBranching(particle,theChildren); + for(unsigned int ix=0;ixprogenitor()->initializeFinalState(); + if(!progenitor()->progenitor()->partner()) return false; + if(hardTree()) { + map::const_iterator + eit=hardTree()->particles().end(), + mit = hardTree()->particles().find(progenitor()->progenitor()); + if( mit != eit && !mit->second->children().empty() ) { + bool output=truncatedTimeLikeShower(progenitor()->progenitor(), + mit->second ,type,Branching(),true); + if(output) updateHistory(progenitor()->progenitor()); + return output; + } + } + // do the shower + bool output = hardOnly() ? false : + timeLikeShower(progenitor()->progenitor() ,type,Branching(),true) ; + if(output) updateHistory(progenitor()->progenitor()); + return output; +} + +bool QTildeShowerHandler::startSpaceLikeShower(PPtr parent, ShowerInteraction::Type type) { + // initialise the basis vectors + progenitor()->progenitor()->initializeInitialState(parent); + if(!progenitor()->progenitor()->partner()) return false; + if(hardTree()) { + map::const_iterator + eit =hardTree()->particles().end(), + mit = hardTree()->particles().find(progenitor()->progenitor()); + if( mit != eit && mit->second->parent() ) { + return truncatedSpaceLikeShower( progenitor()->progenitor(), + parent, mit->second->parent(), type ); + } + } + // perform the shower + return hardOnly() ? false : + spaceLikeShower(progenitor()->progenitor(),parent,type); +} + +bool QTildeShowerHandler:: +startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, + Energy minimumMass,ShowerInteraction::Type type) { + _nFSR = 0; + // set up the particle basis vectors + progenitor()->progenitor()->initializeDecay(); + if(!progenitor()->progenitor()->partner()) return false; + if(hardTree()) { + map::const_iterator + eit =hardTree()->particles().end(), + mit = hardTree()->particles().find(progenitor()->progenitor()); + if( mit != eit && mit->second->parent() ) { + HardBranchingPtr branch=mit->second; + while(branch->parent()) branch=branch->parent(); + return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxScales, + minimumMass, branch ,type, Branching()); + } + } + // perform the shower + return hardOnly() ? false : + spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type,Branching()); +} + +bool QTildeShowerHandler::timeLikeVetoed(const Branching & fb, + ShowerParticlePtr particle) { + // work out type of interaction + ShowerInteraction::Type type = convertInteraction(fb.type); + // check whether emission was harder than largest pt of hard subprocess + if ( restrictPhasespace() && fb.kinematics->pT() > _progenitor->maxHardPt() ) + return true; + // soft matrix element correction veto + if( softMEC()) { + if(_hardme && _hardme->hasMECorrection()) { + if(_hardme->softMatrixElementVeto(_progenitor,particle,fb)) + return true; + } + else if(_decayme && _decayme->hasMECorrection()) { + if(_decayme->softMatrixElementVeto(_progenitor,particle,fb)) + return true; + } + } + // veto on maximum pt + if(fb.kinematics->pT()>_progenitor->maximumpT(type)) return true; + // general vetos + if (fb.kinematics && !_vetoes.empty()) { + bool vetoed=false; + for (vector::iterator v = _vetoes.begin(); + v != _vetoes.end(); ++v) { + bool test = (**v).vetoTimeLike(_progenitor,particle,fb); + switch((**v).vetoType()) { + case ShowerVeto::Emission: + vetoed |= test; + break; + case ShowerVeto::Shower: + if(test) throw VetoShower(); + break; + case ShowerVeto::Event: + if(test) throw Veto(); + break; + } + } + if(vetoed) return true; + } + if ( firstInteraction() && + profileScales() ) { + double weight = + profileScales()-> + hardScaleProfile(_progenitor->hardScale(),fb.kinematics->pT()); + if ( UseRandom::rnd() > weight ) + return true; + } + return false; +} + +bool QTildeShowerHandler::spaceLikeVetoed(const Branching & bb, + ShowerParticlePtr particle) { + // work out type of interaction + ShowerInteraction::Type type = convertInteraction(bb.type); + // check whether emission was harder than largest pt of hard subprocess + if (restrictPhasespace() && bb.kinematics->pT() > _progenitor->maxHardPt()) + return true; + // apply the soft correction + if( softMEC() && _hardme && _hardme->hasMECorrection() ) { + if(_hardme->softMatrixElementVeto(_progenitor,particle,bb)) + return true; + } + // the more general vetos + + // check vs max pt for the shower + if(bb.kinematics->pT()>_progenitor->maximumpT(type)) return true; + + if (!_vetoes.empty()) { + bool vetoed=false; + for (vector::iterator v = _vetoes.begin(); + v != _vetoes.end(); ++v) { + bool test = (**v).vetoSpaceLike(_progenitor,particle,bb); + switch ((**v).vetoType()) { + case ShowerVeto::Emission: + vetoed |= test; + break; + case ShowerVeto::Shower: + if(test) throw VetoShower(); + break; + case ShowerVeto::Event: + if(test) throw Veto(); + break; + } + } + if (vetoed) return true; + } + if ( firstInteraction() && + profileScales() ) { + double weight = + profileScales()-> + hardScaleProfile(_progenitor->hardScale(),bb.kinematics->pT()); + if ( UseRandom::rnd() > weight ) + return true; + } + return false; +} + +bool QTildeShowerHandler::spaceLikeDecayVetoed( const Branching & fb, + ShowerParticlePtr particle) { + // work out type of interaction + ShowerInteraction::Type type = convertInteraction(fb.type); + // apply the soft correction + if( softMEC() && _decayme && _decayme->hasMECorrection() ) { + if(_decayme->softMatrixElementVeto(_progenitor,particle,fb)) + return true; + } + // veto on hardest pt in the shower + if(fb.kinematics->pT()> _progenitor->maximumpT(type)) return true; + // general vetos + if (!_vetoes.empty()) { + bool vetoed=false; + for (vector::iterator v = _vetoes.begin(); + v != _vetoes.end(); ++v) { + bool test = (**v).vetoSpaceLike(_progenitor,particle,fb); + switch((**v).vetoType()) { + case ShowerVeto::Emission: + vetoed |= test; + break; + case ShowerVeto::Shower: + if(test) throw VetoShower(); + break; + case ShowerVeto::Event: + if(test) throw Veto(); + break; + } + if (vetoed) return true; + } + } + return false; +} + +void QTildeShowerHandler::hardestEmission(bool hard) { + HardTreePtr ISRTree; + // internal POWHEG in production or decay + if( (( _hardme && _hardme->hasPOWHEGCorrection()!=0 ) || + ( _decayme && _decayme->hasPOWHEGCorrection()!=0 ) ) ) { + RealEmissionProcessPtr real; + unsigned int type(0); + // production + if(_hardme) { + assert(hard); + real = _hardme->generateHardest( currentTree()->perturbativeProcess(), + interaction_); + type = _hardme->hasPOWHEGCorrection(); + } + // decay + else { + assert(!hard); + real = _decayme->generateHardest( currentTree()->perturbativeProcess() ); + type = _decayme->hasPOWHEGCorrection(); + } + if(real) { + // set up ther hard tree + if(!real->outgoing().empty()) _hardtree = new_ptr(HardTree(real)); + // set up the vetos + currentTree()->setVetoes(real->pT(),type); + } + // store initial state POWHEG radiation + if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1) + ISRTree = _hardtree; + } + else if (hard) { + // Get minimum pT cutoff used in shower approximation + Energy maxpt = 1.*GeV; + + if ( currentTree()->showerApproximation() ) { + int colouredIn = 0; + int colouredOut = 0; + for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it + = currentTree()->outgoingLines().begin(); + it != currentTree()->outgoingLines().end(); ++it ) { + if( it->second->coloured() ) ++colouredOut; + } + for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it + = currentTree()->incomingLines().begin(); + it != currentTree()->incomingLines().end(); ++it ) { + if( it->second->coloured() ) ++colouredIn; + } + if ( currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->fiPtCut() && + currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->iiPtCut() ) + maxpt = currentTree()->showerApproximation()->ffPtCut(); + else if ( colouredIn == 2 && colouredOut == 0 ) + maxpt = currentTree()->showerApproximation()->iiPtCut(); + else if ( colouredIn == 0 && colouredOut > 1 ) + maxpt = currentTree()->showerApproximation()->ffPtCut(); + else if ( colouredIn == 2 && colouredOut == 1 ) + maxpt = min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()); + else if ( colouredIn == 1 && colouredOut > 1 ) + maxpt = min(currentTree()->showerApproximation()->ffPtCut(), currentTree()->showerApproximation()->fiPtCut()); + else + maxpt = min(min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()), + currentTree()->showerApproximation()->ffPtCut()); + } + + // Generate hardtree from born and real emission subprocesses + _hardtree = generateCKKW(currentTree()); + + // Find transverse momentum of hardest emission + if (_hardtree){ + for(set::iterator it=_hardtree->branchings().begin(); + it!=_hardtree->branchings().end();++it) { + if ((*it)->parent() && (*it)->status()==HardBranching::Incoming) + maxpt=(*it)->branchingParticle()->momentum().perp(); + if ((*it)->children().size()==2 && (*it)->status()==HardBranching::Outgoing){ + if ((*it)->branchingParticle()->id()!=21 && + abs((*it)->branchingParticle()->id())>5 ){ + if ((*it)->children()[0]->branchingParticle()->id()==21 || + abs((*it)->children()[0]->branchingParticle()->id())<6) + maxpt=(*it)->children()[0]->branchingParticle()->momentum().perp(); + else if ((*it)->children()[1]->branchingParticle()->id()==21 || + abs((*it)->children()[1]->branchingParticle()->id())<6) + maxpt=(*it)->children()[1]->branchingParticle()->momentum().perp(); + } + else { + if ( abs((*it)->branchingParticle()->id())<6){ + if (abs((*it)->children()[0]->branchingParticle()->id())<6) + maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); + else + maxpt = (*it)->children()[0]->branchingParticle()->momentum().perp(); + } + else maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp(); + } + } + } + } + + + // Hardest (pt) emission should be the first powheg emission. + maxpt=min(sqrt(lastXCombPtr()->lastShowerScale()),maxpt); + + // set maximum pT for subsequent emissions from S events + if ( currentTree()->isPowhegSEvent() ) { + for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it + = currentTree()->outgoingLines().begin(); + it != currentTree()->outgoingLines().end(); ++it ) { + if( ! it->second->coloured() ) continue; + it->first->maximumpT(maxpt, ShowerInteraction::QCD ); + } + for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it + = currentTree()->incomingLines().begin(); + it != currentTree()->incomingLines().end(); ++it ) { + if( ! it->second->coloured() ) continue; + it->first->maximumpT(maxpt, ShowerInteraction::QCD ); + } + } + } + else + _hardtree = generateCKKW(currentTree()); + + // if hard me doesn't have a FSR powheg + // correction use decay powheg correction + if (_hardme && _hardme->hasPOWHEGCorrection()<2) { + addFSRUsingDecayPOWHEG(ISRTree); + } + // connect the trees + if(_hardtree) { + connectTrees(currentTree(),_hardtree,hard); + } +} + +void QTildeShowerHandler::addFSRUsingDecayPOWHEG(HardTreePtr ISRTree) { + // check for intermediate colour singlet resonance + const ParticleVector inter = _hardme->subProcess()->intermediates(); + if (inter.size()!=1 || inter[0]->momentum().m2()/GeV2 < 0 || + inter[0]->dataPtr()->iColour()!=PDT::Colour0) { + return; + } + + // ignore cases where outgoing particles are not coloured + map out = currentTree()->outgoingLines(); + if (out.size() != 2 || + out. begin()->second->dataPtr()->iColour()==PDT::Colour0 || + out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) { + return; + } + + // look up decay mode + tDMPtr dm; + string tag; + string inParticle = inter[0]->dataPtr()->name() + "->"; + vector outParticles; + outParticles.push_back(out.begin ()->first->progenitor()->dataPtr()->name()); + outParticles.push_back(out.rbegin()->first->progenitor()->dataPtr()->name()); + for (int it=0; it<2; ++it){ + tag = inParticle + outParticles[it] + "," + outParticles[(it+1)%2] + ";"; + dm = generator()->findDecayMode(tag); + if(dm) break; + } + + // get the decayer + HwDecayerBasePtr decayer; + if(dm) decayer = dynamic_ptr_cast(dm->decayer()); + // check if decayer has a FSR POWHEG correction + if (!decayer || decayer->hasPOWHEGCorrection()<2) { + return; + } + // generate the hardest emission + // create RealEmissionProcess + PPtr in = new_ptr(*inter[0]); + RealEmissionProcessPtr newProcess(new_ptr(RealEmissionProcess())); + newProcess->bornIncoming().push_back(in); + newProcess->bornOutgoing().push_back(out.begin ()->first->progenitor()); + newProcess->bornOutgoing().push_back(out.rbegin()->first->progenitor()); + // generate the FSR + newProcess = decayer->generateHardest(newProcess); + HardTreePtr FSRTree; + if(newProcess) { + // set up ther hard tree + if(!newProcess->outgoing().empty()) FSRTree = new_ptr(HardTree(newProcess)); + // set up the vetos + currentTree()->setVetoes(newProcess->pT(),2); + } + if(!FSRTree) return; + + // if there is no ISRTree make _hardtree from FSRTree + if (!ISRTree){ + vector inBranch,hardBranch; + for(map::const_iterator + cit =currentTree()->incomingLines().begin(); + cit!=currentTree()->incomingLines().end();++cit ) { + inBranch.push_back(new_ptr(HardBranching(cit->second,SudakovPtr(), + HardBranchingPtr(), + HardBranching::Incoming))); + inBranch.back()->beam(cit->first->original()->parents()[0]); + hardBranch.push_back(inBranch.back()); + } + if(inBranch[0]->branchingParticle()->dataPtr()->coloured()) { + inBranch[0]->colourPartner(inBranch[1]); + inBranch[1]->colourPartner(inBranch[0]); + } + for(set::iterator it=FSRTree->branchings().begin(); + it!=FSRTree->branchings().end();++it) { + if((**it).branchingParticle()->id()!=in->id()) + hardBranch.push_back(*it); + } + hardBranch[2]->colourPartner(hardBranch[3]); + hardBranch[3]->colourPartner(hardBranch[2]); + HardTreePtr newTree = new_ptr(HardTree(hardBranch,inBranch, + ShowerInteraction::QCD)); + _hardtree = newTree; + } + + // Otherwise modify the ISRTree to include the emission in FSRTree + else { + vector FSROut, ISROut; + set::iterator itFSR, itISR; + // get outgoing particles + for(itFSR =FSRTree->branchings().begin(); + itFSR!=FSRTree->branchings().end();++itFSR){ + if ((**itFSR).status()==HardBranching::Outgoing) + FSROut.push_back((*itFSR)->branchingParticle()); + } + for(itISR =ISRTree->branchings().begin(); + itISR!=ISRTree->branchings().end();++itISR){ + if ((**itISR).status()==HardBranching::Outgoing) + ISROut.push_back((*itISR)->branchingParticle()); + } + + // find COM frame formed by outgoing particles + LorentzRotation eventFrameFSR, eventFrameISR; + eventFrameFSR = ((FSROut[0]->momentum()+FSROut[1]->momentum()).findBoostToCM()); + eventFrameISR = ((ISROut[0]->momentum()+ISROut[1]->momentum()).findBoostToCM()); + + // find rotation between ISR and FSR frames + int j=0; + if (ISROut[0]->id()!=FSROut[0]->id()) j=1; + eventFrameISR.rotateZ( (eventFrameFSR*FSROut[0]->momentum()).phi()- + (eventFrameISR*ISROut[j]->momentum()).phi() ); + eventFrameISR.rotateY( (eventFrameFSR*FSROut[0]->momentum()).theta()- + (eventFrameISR*ISROut[j]->momentum()).theta() ); + eventFrameISR.invert(); + + for (itFSR=FSRTree->branchings().begin(); + itFSR!=FSRTree->branchings().end();++itFSR){ + if ((**itFSR).branchingParticle()->id()==in->id()) continue; + for (itISR =ISRTree->branchings().begin(); + itISR!=ISRTree->branchings().end();++itISR){ + if ((**itISR).status()==HardBranching::Incoming) continue; + if ((**itFSR).branchingParticle()->id()== + (**itISR).branchingParticle()->id()){ + // rotate FSRTree particle to ISRTree event frame + (**itISR).branchingParticle()->setMomentum(eventFrameISR* + eventFrameFSR* + (**itFSR).branchingParticle()->momentum()); + (**itISR).branchingParticle()->rescaleMass(); + // add the children of the FSRTree particles to the ISRTree + if(!(**itFSR).children().empty()){ + (**itISR).addChild((**itFSR).children()[0]); + (**itISR).addChild((**itFSR).children()[1]); + // rotate momenta to ISRTree event frame + (**itISR).children()[0]->branchingParticle()->setMomentum(eventFrameISR* + eventFrameFSR* + (**itFSR).children()[0]->branchingParticle()->momentum()); + (**itISR).children()[1]->branchingParticle()->setMomentum(eventFrameISR* + eventFrameFSR* + (**itFSR).children()[1]->branchingParticle()->momentum()); + } + } + } + } + _hardtree = ISRTree; + } +} + +bool QTildeShowerHandler::truncatedTimeLikeShower(tShowerParticlePtr particle, + HardBranchingPtr branch, + ShowerInteraction::Type type, + Branching fb, bool first) { + // select a branching if we don't have one + if(!fb.kinematics) + fb = selectTimeLikeBranching(particle,type,branch); + // must be an emission, the forced one it not a truncated one + assert(fb.kinematics); + ShowerParticleVector children; + int ntry=0; + Branching fc[2]; + bool setupChildren = true; + while (ntry<50) { + if(!fc[0].hard) fc[0] = Branching(); + if(!fc[1].hard) fc[1] = Branching(); + ++ntry; + // Assign the shower kinematics to the emitting particle. + if(setupChildren) { + ++_nFSR; + // Assign the shower kinematics to the emitting particle. + particle->showerKinematics(fb.kinematics); + if(fb.kinematics->pT()>progenitor()->highestpT()) + progenitor()->highestpT(fb.kinematics->pT()); + // create the children + children = createTimeLikeChildren(particle,fb.ids); + // update the children + particle->showerKinematics()-> + updateChildren(particle, children,fb.type,_reconOpt>=3); + setupChildren = false; + } + // select branchings for children + if(!fc[0].kinematics) { + // select branching for first particle + if(!fb.hard && fb.iout ==1 ) + fc[0] = selectTimeLikeBranching(children[0],type,branch); + else if(fb.hard && !branch->children()[0]->children().empty() ) + fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); + else + fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); + } + // select branching for the second particle + if(!fc[1].kinematics) { + // select branching for first particle + if(!fb.hard && fb.iout ==2 ) + fc[1] = selectTimeLikeBranching(children[1],type,branch); + else if(fb.hard && !branch->children()[1]->children().empty() ) + fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); + else + fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); + } + // old default + if(_reconOpt==0 || (_reconOpt==1 && fb.hard) ) { + // shower the first particle + if(fc[0].kinematics) { + // the parent has truncated emission and following line + if(!fb.hard && fb.iout == 1) + truncatedTimeLikeShower(children[0],branch,type,fc[0],false); + // hard emission and subsquent hard emissions + else if(fb.hard && !branch->children()[0]->children().empty() ) + truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); + // normal shower + else + timeLikeShower(children[0],type,fc[0],false); + } + if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); + // shower the second particle + if(fc[1].kinematics) { + // the parent has truncated emission and following line + if(!fb.hard && fb.iout == 2) + truncatedTimeLikeShower(children[1],branch,type,fc[1],false); + // hard emission and subsquent hard emissions + else if(fb.hard && !branch->children()[1]->children().empty() ) + truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false); + else + timeLikeShower(children[1],type,fc[1],false); + } + if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); + // branching has happened + particle->showerKinematics()->updateParent(particle, children,fb.type); + break; + } + // H7 default + else if(_reconOpt==1) { + // shower the first particle + if(fc[0].kinematics) { + // the parent has truncated emission and following line + if(!fb.hard && fb.iout == 1) + truncatedTimeLikeShower(children[0],branch,type,fc[0],false); + else + timeLikeShower(children[0],type,fc[0],false); + } + if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); + // shower the second particle + if(fc[1].kinematics) { + // the parent has truncated emission and following line + if(!fb.hard && fb.iout == 2) + truncatedTimeLikeShower(children[1],branch,type,fc[1],false); + else + timeLikeShower(children[1],type,fc[1],false); + } + if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); + // branching has happened + particle->showerKinematics()->updateParent(particle, children,fb.type); + // clean up the vetoed emission + if(particle->virtualMass()==ZERO) { + particle->showerKinematics(ShoKinPtr()); + for(unsigned int ix=0;ixabandonChild(children[ix]); + children.clear(); + if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); + particle->vetoEmission(fb.type,fb.kinematics->scale()); + // generate the new emission + fb = selectTimeLikeBranching(particle,type,branch); + // must be at least hard emission + assert(fb.kinematics); + setupChildren = true; + continue; + } + else + break; + } + else if(_reconOpt>=2) { + // cut-off masses for the branching + const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); + // compute the masses of the children + Energy masses[3]; + for(unsigned int ix=0;ix<2;++ix) { + if(fc[ix].kinematics) { + const vector & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids); + Energy2 q2 = + fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale()); + if(fc[ix].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); + masses[ix+1] = sqrt(q2); + } + else { + masses[ix+1] = virtualMasses[ix+1]; + } + } + masses[0] = fb.ids[0]->id()!=ParticleID::g ? virtualMasses[0] : ZERO; + double z = fb.kinematics->z(); + Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale()) + sqr(masses[0])) + - sqr(masses[1])*(1.-z) - sqr(masses[2])*z; + if(pt2>=ZERO) { + break; + } + // if only the hard emission have to accept it + else if ((fc[0].hard && !fc[1].kinematics) || + (fc[1].hard && !fc[0].kinematics) ) { + break; + } + else { + // reset the scales for the children + for(unsigned int ix=0;ix<2;++ix) { + if(fc[ix].hard) continue; + if(fc[ix].kinematics && ! fc[ix].hard ) + children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); + else + children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); + children[ix]->virtualMass(ZERO); + } + } + } + }; + if(_reconOpt>=2) { + // shower the first particle + if(fc[0].kinematics) { + // the parent has truncated emission and following line + if(!fb.hard && fb.iout == 1) + truncatedTimeLikeShower(children[0],branch,type,fc[0],false); + // hard emission and subsquent hard emissions + else if(fb.hard && !branch->children()[0]->children().empty() ) + truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); + // normal shower + else + timeLikeShower(children[0],type,fc[0],false); + } + if(children[0]->spinInfo()) children[0]->spinInfo()->develop(); + // shower the second particle + if(fc[1].kinematics) { + // the parent has truncated emission and following line + if(!fb.hard && fb.iout == 2) + truncatedTimeLikeShower(children[1],branch,type,fc[1],false); + // hard emission and subsquent hard emissions + else if(fb.hard && !branch->children()[1]->children().empty() ) + truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false); + else + timeLikeShower(children[1],type,fc[1],false); + } + if(children[1]->spinInfo()) children[1]->spinInfo()->develop(); + // branching has happened + particle->showerKinematics()->updateParent(particle, children,fb.type); + } + if(first&&!children.empty()) + particle->showerKinematics()->resetChildren(particle,children); + if(particle->spinInfo()) particle->spinInfo()->develop(); + return true; +} + +bool QTildeShowerHandler::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam, + HardBranchingPtr branch, + ShowerInteraction::Type type) { + tcPDFPtr pdf; + if(firstPDF().particle() == beamParticle()) + pdf = firstPDF().pdf(); + if(secondPDF().particle() == beamParticle()) + pdf = secondPDF().pdf(); + Energy freeze = pdfFreezingScale(); + Branching bb; + // parameters of the force branching + double z(0.); + HardBranchingPtr timelike; + for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) { + if( branch->children()[ix]->status() ==HardBranching::Outgoing) { + timelike = branch->children()[ix]; + } + if( branch->children()[ix]->status() ==HardBranching::Incoming ) + z = branch->children()[ix]->z(); + } + // generate truncated branching + tcPDPtr part[2]; + if(z>=0.&&z<=1.) { + while (true) { + if( !isTruncatedShowerON() || hardOnly() ) break; + bb = splittingGenerator()->chooseBackwardBranching( *particle, + beam, 1., beamParticle(), + type , pdf,freeze); + if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) { + bb = Branching(); + break; + } + // particles as in Sudakov form factor + part[0] = bb.ids[0]; + part[1] = bb.ids[2]; + double zsplit = bb.kinematics->z(); + // apply the vetos for the truncated shower + // if doesn't carry most of momentum + ShowerInteraction::Type type2 = convertInteraction(bb.type); + if(type2==branch->sudakov()->interactionType() && + zsplit < 0.5) { + particle->vetoEmission(bb.type,bb.kinematics->scale()); + continue; + } + // others + if( part[0]->id() != particle->id() || // if particle changes type + bb.kinematics->pT() > progenitor()->maximumpT(type2) || // pt veto + bb.kinematics->scale() < branch->scale()) { // angular ordering veto + particle->vetoEmission(bb.type,bb.kinematics->scale()); + continue; + } + // and those from the base class + if(spaceLikeVetoed(bb,particle)) { + particle->vetoEmission(bb.type,bb.kinematics->scale()); + continue; + } + break; + } + } + if( !bb.kinematics ) { + //do the hard emission + ShoKinPtr kinematics = + branch->sudakov()->createInitialStateBranching( branch->scale(), z, branch->phi(), + branch->children()[0]->pT() ); + // assign the splitting function and shower kinematics + particle->showerKinematics( kinematics ); + if(kinematics->pT()>progenitor()->highestpT()) + progenitor()->highestpT(kinematics->pT()); + // For the time being we are considering only 1->2 branching + // Now create the actual particles, make the otherChild a final state + // particle, while the newParent is not + ShowerParticlePtr newParent = + new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) ); + ShowerParticlePtr otherChild = + new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(), + true, true ) ); + ShowerParticleVector theChildren; + theChildren.push_back( particle ); + theChildren.push_back( otherChild ); + particle->showerKinematics()-> + updateParent( newParent, theChildren, branch->type()); + // update the history if needed + currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); + currentTree()->addInitialStateBranching( particle, newParent, otherChild ); + // for the reconstruction of kinematics, parent/child + // relationships are according to the branching process: + // now continue the shower + bool emitted=false; + if(!hardOnly()) { + if( branch->parent() ) { + emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type); + } + else { + emitted = spaceLikeShower( newParent, beam , type); + } + } + if( !emitted ) { + if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { + kinematics->updateLast( newParent, ZERO, ZERO ); + } + else { + pair kt = intrinsicpT()[progenitor()]; + kinematics->updateLast( newParent, + kt.first*cos( kt.second ), + kt.first*sin( kt.second ) ); + } + } + particle->showerKinematics()-> + updateChildren( newParent, theChildren,bb.type,false); + if(hardOnly()) return true; + // perform the shower of the final-state particle + if( timelike->children().empty() ) { + timeLikeShower( otherChild , type,Branching(),true); + } + else { + truncatedTimeLikeShower( otherChild, timelike , type,Branching(), true); + } + updateHistory(otherChild); + // return the emitted + return true; + } + // assign the splitting function and shower kinematics + particle->showerKinematics( bb.kinematics ); + if(bb.kinematics->pT()>progenitor()->highestpT()) + progenitor()->highestpT(bb.kinematics->pT()); + // For the time being we are considering only 1->2 branching + // Now create the actual particles, make the otherChild a final state + // particle, while the newParent is not + ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) ); + ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) ); + ShowerParticleVector theChildren; + theChildren.push_back( particle ); + theChildren.push_back( otherChild ); + particle->showerKinematics()-> + updateParent( newParent, theChildren, bb.type); + // update the history if needed + currentTree()->updateInitialStateShowerProduct( progenitor(), newParent ); + currentTree()->addInitialStateBranching( particle, newParent, otherChild ); + // for the reconstruction of kinematics, parent/child + // relationships are according to the branching process: + // now continue the shower + bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type); + // now reconstruct the momentum + if( !emitted ) { + if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) { + bb.kinematics->updateLast( newParent, ZERO, ZERO ); + } + else { + pair kt = intrinsicpT()[ progenitor() ]; + bb.kinematics->updateLast( newParent, + kt.first*cos( kt.second ), + kt.first*sin( kt.second ) ); + } + } + particle->showerKinematics()-> + updateChildren( newParent, theChildren, bb.type,false); + // perform the shower of the final-state particle + timeLikeShower( otherChild , type,Branching(),true); + updateHistory(otherChild); + // return the emitted + return true; +} + +bool QTildeShowerHandler:: +truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, + const ShowerParticle::EvolutionScales & maxScales, + Energy minmass, HardBranchingPtr branch, + ShowerInteraction::Type type, Branching fb) { + // select a branching if we don't have one + if(!fb.kinematics) + fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch); + // must be an emission, the forced one it not a truncated one + assert(fb.kinematics); + ShowerParticleVector children; + int ntry=0; + Branching fc[2]; + bool setupChildren = true; + while (ntry<50) { + if(!fc[0].hard) fc[0] = Branching(); + if(!fc[1].hard) fc[1] = Branching(); + ++ntry; + if(setupChildren) { + ++_nFSR; + // Assign the shower kinematics to the emitting particle. + particle->showerKinematics(fb.kinematics); + if(fb.kinematics->pT()>progenitor()->highestpT()) + progenitor()->highestpT(fb.kinematics->pT()); + // create the ShowerParticle objects for the two children + children = createTimeLikeChildren(particle,fb.ids); + // updateChildren the children + particle->showerKinematics()-> + updateChildren(particle, children, fb.type,_reconOpt>=3); + setupChildren = false; + } + // select branchings for children + if(!fc[0].kinematics) { + if(children[0]->id()==particle->id()) { + // select branching for first particle + if(!fb.hard) + fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type,branch); + else if(fb.hard && ! branch->children()[0]->children().empty() ) + fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, + branch->children()[0]); + else + fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type, + HardBranchingPtr()); + } + else { + // select branching for first particle + if(fb.hard && !branch->children()[0]->children().empty() ) + fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]); + else + fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr()); + } + } + // select branching for the second particle + if(!fc[1].kinematics) { + if(children[1]->id()==particle->id()) { + // select branching for first particle + if(!fb.hard) + fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type,branch); + else if(fb.hard && ! branch->children()[1]->children().empty() ) + fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, + branch->children()[1]); + else + fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type, + HardBranchingPtr()); + } + else { + if(fb.hard && !branch->children()[1]->children().empty() ) + fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]); + else + fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr()); + } + } + // old default + if(_reconOpt==0 || (_reconOpt==1 && fb.hard) ) { + // update the history if needed + currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); + currentTree()->addInitialStateBranching(particle,children[0],children[1]); + // shower the first particle + if(fc[0].kinematics) { + if(children[0]->id()==particle->id()) { + if(!fb.hard) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch,type,fc[0]); + else if(fb.hard && ! branch->children()[0]->children().empty() ) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch->children()[0],type,fc[0]); + else + spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); + } + else { + if(fb.hard && !branch->children()[0]->children().empty() ) + truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); + // normal shower + else + timeLikeShower(children[0],type,fc[0],false); + } + } + // shower the second particle + if(fc[1].kinematics) { + if(children[0]->id()==particle->id()) { + if(!fb.hard) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch,type,fc[1]); + else if(fb.hard && ! branch->children()[0]->children().empty() ) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch->children()[0],type,fc[1]); + else + spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); + } + else { + if(fb.hard && !branch->children()[0]->children().empty() ) + truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); + // normal shower + else + timeLikeShower(children[0],type,fc[1],false); + } + } + updateHistory(children[1]); + // branching has happened + break; + } + // H7 default + else if(_reconOpt==1) { + // update the history if needed + currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); + currentTree()->addInitialStateBranching(particle,children[0],children[1]); + // shower the first particle + if(fc[0].kinematics) { + if(children[0]->id()==particle->id()) { + if(!fb.hard) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch,type,fc[0]); + else if(fb.hard && ! branch->children()[0]->children().empty() ) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch->children()[0],type,fc[0]); + else + spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); + } + else { + if(fb.hard && !branch->children()[0]->children().empty() ) + truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); + // normal shower + else + timeLikeShower(children[0],type,fc[0],false); + } + } + // shower the second particle + if(fc[1].kinematics) { + if(children[0]->id()==particle->id()) { + if(!fb.hard) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch,type,fc[1]); + else if(fb.hard && ! branch->children()[0]->children().empty() ) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch->children()[0],type,fc[1]); + else + spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); + } + else { + if(fb.hard && !branch->children()[0]->children().empty() ) + truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); + // normal shower + else + timeLikeShower(children[0],type,fc[1],false); + } + } + // clean up the vetoed emission + if(particle->virtualMass()==ZERO) { + particle->showerKinematics(ShoKinPtr()); + for(unsigned int ix=0;ixabandonChild(children[ix]); + children.clear(); + particle->vetoEmission(fb.type,fb.kinematics->scale()); + // generate the new emission + fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch); + // must be at least hard emission + assert(fb.kinematics); + setupChildren = true; + continue; + } + else { + updateHistory(children[1]); + break; + } + } + else if(_reconOpt>=2) { + // cut-off masses for the branching + const vector & virtualMasses = fb.sudakov->virtualMasses(fb.ids); + // compute the masses of the children + Energy masses[3]; + // space-like children + masses[1] = children[0]->virtualMass(); + // time-like child + if(fc[1].kinematics) { + const vector & vm = fc[1].sudakov->virtualMasses(fc[1].ids); + Energy2 q2 = + fc[1].kinematics->z()*(1.-fc[1].kinematics->z())*sqr(fc[1].kinematics->scale()); + if(fc[1].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]); + masses[2] = sqrt(q2); + } + else { + masses[2] = virtualMasses[2]; + } + masses[0]=particle->virtualMass(); + double z = fb.kinematics->z(); + Energy2 pt2 = (1.-z)*(z*sqr(masses[0])-sqr(masses[1])-z/(1.-z)*sqr(masses[2])); + if(pt2>=ZERO) { + break; + } + else { + // reset the scales for the children + for(unsigned int ix=0;ix<2;++ix) { + if(fc[ix].kinematics) + children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale()); + else { + if(ix==0) + children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,Constants::MaxEnergy); + else + children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO); + } + } + children[0]->virtualMass(_progenitor->progenitor()->mass()); + children[1]->virtualMass(ZERO); + } + } + }; + if(_reconOpt>=2) { + // update the history if needed + currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]); + currentTree()->addInitialStateBranching(particle,children[0],children[1]); + // shower the first particle + if(fc[0].kinematics) { + if(children[0]->id()==particle->id()) { + if(!fb.hard) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch,type,fc[0]); + else if(fb.hard && ! branch->children()[0]->children().empty() ) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch->children()[0],type,fc[0]); + else + spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]); + } + else { + if(fb.hard && !branch->children()[0]->children().empty() ) + truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false); + // normal shower + else + timeLikeShower(children[0],type,fc[0],false); + } + } + // shower the second particle + if(fc[1].kinematics) { + if(children[0]->id()==particle->id()) { + if(!fb.hard) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch,type,fc[1]); + else if(fb.hard && ! branch->children()[0]->children().empty() ) + truncatedSpaceLikeDecayShower( children[0],maxScales,minmass, + branch->children()[0],type,fc[1]); + else + spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]); + } + else { + if(fb.hard && !branch->children()[0]->children().empty() ) + truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false); + // normal shower + else + timeLikeShower(children[0],type,fc[1],false); + } + } + updateHistory(children[1]); + } + return true; +} + +void QTildeShowerHandler::connectTrees(ShowerTreePtr showerTree, + HardTreePtr hardTree, bool hard ) { + ShowerParticleVector particles; + // find the Sudakovs + for(set::iterator cit=hardTree->branchings().begin(); + cit!=hardTree->branchings().end();++cit) { + // Sudakovs for ISR + if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) { + ++_nis; + vector br(3); + br[0] = (**cit).parent()->branchingParticle()->id(); + br[1] = (**cit). branchingParticle()->id(); + br[2] = (**cit).parent()->children()[0]==*cit ? + (**cit).parent()->children()[1]->branchingParticle()->id() : + (**cit).parent()->children()[0]->branchingParticle()->id(); + BranchingList branchings = splittingGenerator()->initialStateBranchings(); + if(br[1]<0&&br[0]==br[1]) { + br[0] = abs(br[0]); + br[1] = abs(br[1]); + } + else if(br[1]<0) { + br[1] = -br[1]; + br[2] = -br[2]; + } + long index = abs(br[1]); + SudakovPtr sudakov; + for(BranchingList::const_iterator cjt = branchings.lower_bound(index); + cjt != branchings.upper_bound(index); ++cjt ) { + IdList ids = cjt->second.particles; + if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { + sudakov=cjt->second.sudakov; + break; + } + } + if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in " + << "QTildeShowerHandler::connectTrees() for ISR" + << Exception::runerror; + (**cit).parent()->sudakov(sudakov); + } + // Sudakovs for FSR + else if(!(**cit).children().empty()) { + ++_nfs; + vector br(3); + br[0] = (**cit) .branchingParticle()->id(); + br[1] = (**cit).children()[0]->branchingParticle()->id(); + br[2] = (**cit).children()[1]->branchingParticle()->id(); + BranchingList branchings = splittingGenerator()->finalStateBranchings(); + if(br[0]<0) { + br[0] = abs(br[0]); + br[1] = abs(br[1]); + br[2] = abs(br[2]); + } + long index = br[0]; + SudakovPtr sudakov; + for(BranchingList::const_iterator cjt = branchings.lower_bound(index); + cjt != branchings.upper_bound(index); ++cjt ) { + IdList ids = cjt->second.particles; + if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) { + sudakov=cjt->second.sudakov; + break; + } + } + if(!sudakov) { + throw Exception() << "Can't find Sudakov for the hard emission in " + << "QTildeShowerHandler::connectTrees()" + << Exception::runerror; + } + (**cit).sudakov(sudakov); + } + } + // calculate the evolution scale + for(set::iterator cit=hardTree->branchings().begin(); + cit!=hardTree->branchings().end();++cit) { + particles.push_back((*cit)->branchingParticle()); + } + showerModel()->partnerFinder()-> + setInitialEvolutionScales(particles,!hard,interaction_,true); + hardTree->partnersSet(true); + // inverse reconstruction + if(hard) { + showerModel()->kinematicsReconstructor()-> + deconstructHardJets(hardTree,interaction_); + } + else + showerModel()->kinematicsReconstructor()-> + deconstructDecayJets(hardTree,interaction_); + // now reset the momenta of the showering particles + vector particlesToShower=showerTree->extractProgenitors(); + // match them + map partners; + for(set::const_iterator bit=hardTree->branchings().begin(); + bit!=hardTree->branchings().end();++bit) { + Energy2 dmin( 1e30*GeV2 ); + ShowerProgenitorPtr partner; + for(vector::const_iterator pit=particlesToShower.begin(); + pit!=particlesToShower.end();++pit) { + if(partners.find(*pit)!=partners.end()) continue; + if( (**bit).branchingParticle()->id() != (**pit).progenitor()->id() ) continue; + if( (**bit).branchingParticle()->isFinalState() != + (**pit).progenitor()->isFinalState() ) continue; + if( (**pit).progenitor()->isFinalState() ) { + Energy2 dtest = + sqr( (**pit).progenitor()->momentum().x() - (**bit).showerMomentum().x() ) + + sqr( (**pit).progenitor()->momentum().y() - (**bit).showerMomentum().y() ) + + sqr( (**pit).progenitor()->momentum().z() - (**bit).showerMomentum().z() ) + + sqr( (**pit).progenitor()->momentum().t() - (**bit).showerMomentum().t() ); + // add mass difference for identical particles (e.g. Z0 Z0 production) + dtest += 1e10*sqr((**pit).progenitor()->momentum().m()-(**bit).showerMomentum().m()); + if( dtest < dmin ) { + partner = *pit; + dmin = dtest; + } + } + else { + // ensure directions are right + if((**pit).progenitor()->momentum().z()/(**bit).showerMomentum().z()>ZERO) { + partner = *pit; + break; + } + } + } + if(!partner) throw Exception() << "Failed to match shower and hard trees in QTildeShowerHandler::hardestEmission" + << Exception::eventerror; + partners[partner] = *bit; + } + for(vector::const_iterator pit=particlesToShower.begin(); + pit!=particlesToShower.end();++pit) { + HardBranchingPtr partner = partners[*pit]; + if((**pit).progenitor()->dataPtr()->stable()) { + (**pit).progenitor()->set5Momentum(partner->showerMomentum()); + (**pit).copy()->set5Momentum(partner->showerMomentum()); + } + else { + Lorentz5Momentum oldMomentum = (**pit).progenitor()->momentum(); + Lorentz5Momentum newMomentum = partner->showerMomentum(); + LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); + (**pit).progenitor()->transform(boost); + (**pit).copy() ->transform(boost); + boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); + (**pit).progenitor()->transform(boost); + (**pit).copy() ->transform(boost); + } + } + // correction boosts for daughter trees + for(map >::const_iterator + tit = showerTree->treelinks().begin(); + tit != showerTree->treelinks().end();++tit) { + ShowerTreePtr decayTree = tit->first; + map::const_iterator + cit = decayTree->incomingLines().begin(); + // reset the momentum of the decay particle + Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum(); + Lorentz5Momentum newMomentum = tit->second.second->momentum(); + LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); + decayTree->transform(boost,true); + boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); + decayTree->transform(boost,true); + } +} + +void QTildeShowerHandler::doShowering(bool hard,XCPtr xcomb) { + // zero number of emissions + _nis = _nfs = 0; + // if MC@NLO H event and limited emissions + // indicate both final and initial state emission + if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) { + _nis = _nfs = 1; + } + // extract particles to shower + vector particlesToShower(setupShower(hard)); + // check if we should shower + bool colCharge = false; + for(unsigned int ix=0;ixprogenitor()->dataPtr()->coloured() || + particlesToShower[ix]->progenitor()->dataPtr()->charged()) { + colCharge = true; + break; + } + } + if(!colCharge) { + _currenttree->hasShowered(true); + return; + } + // setup the maximum scales for the shower + if (restrictPhasespace()) setupMaximumScales(particlesToShower,xcomb); + // set the hard scales for the profiles + setupHardScales(particlesToShower,xcomb); + // specific stuff for hard processes and decays + Energy minmass(ZERO), mIn(ZERO); + // hard process generate the intrinsic p_T once and for all + if(hard) { + generateIntrinsicpT(particlesToShower); + } + // decay compute the minimum mass of the final-state + else { + for(unsigned int ix=0;ixprogenitor()->isFinalState()) { + if(particlesToShower[ix]->progenitor()->dataPtr()->stable()) + minmass += particlesToShower[ix]->progenitor()->dataPtr()->constituentMass(); + else + minmass += particlesToShower[ix]->progenitor()->mass(); + } + else { + mIn = particlesToShower[ix]->progenitor()->mass(); + } + } + // throw exception if decay can't happen + if ( minmass > mIn ) { + throw Exception() << "QTildeShowerHandler.cc: Mass of decaying particle is " + << "below constituent masses of decay products." + << Exception::eventerror; + } + } + // setup for reweighted + bool reWeighting = _reWeight && hard && ShowerHandler::currentHandler()->firstInteraction(); + double eventWeight=0.; + unsigned int nTryReWeight(0); + // create random particle vector (only need to do once) + vector tmp; + unsigned int nColouredIncoming = 0; + while(particlesToShower.size()>0){ + unsigned int xx=UseRandom::irnd(particlesToShower.size()); + tmp.push_back(particlesToShower[xx]); + particlesToShower.erase(particlesToShower.begin()+xx); + } + particlesToShower=tmp; + for(unsigned int ix=0;ixprogenitor()->isFinalState() && + particlesToShower[ix]->progenitor()->coloured()) ++nColouredIncoming; + } + bool switchRecon = hard && nColouredIncoming !=1; + // main shower loop + unsigned int ntry(0); + bool reconstructed = false; + do { + // clear results of last attempt if needed + if(ntry!=0) { + currentTree()->clear(); + setEvolutionPartners(hard,interaction_,true); + _nis = _nfs = 0; + // if MC@NLO H event and limited emissions + // indicate both final and initial state emission + if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) { + _nis = _nfs = 1; + } + for(unsigned int ix=0; ixprogenitor()->spinInfo(); + if(spin && spin->decayVertex() && + dynamic_ptr_cast(spin->decayVertex())) { + spin->decayVertex(VertexPtr()); + } + } + } + // loop over particles + for(unsigned int ix=0;ixprogenitor()->isFinalState()) { + if(!doFSR()) continue; + // perform shower + progenitor()->hasEmitted(startTimeLikeShower(interaction_)); + } + // initial-state radiation + else { + if(!doISR()) continue; + // hard process + if(hard) { + // get the PDF + setBeamParticle(_progenitor->beam()); + assert(beamParticle()); + // perform the shower + // set the beam particle + tPPtr beamparticle=progenitor()->original(); + if(!beamparticle->parents().empty()) + beamparticle=beamparticle->parents()[0]; + // generate the shower + progenitor()->hasEmitted(startSpaceLikeShower(beamparticle, + interaction_)); + } + // decay + else { + // skip colour and electrically neutral particles + if(!progenitor()->progenitor()->dataPtr()->coloured() && + !progenitor()->progenitor()->dataPtr()->charged()) { + progenitor()->hasEmitted(false); + continue; + } + // perform shower + // set the scales correctly. The current scale is the maximum scale for + // emission not the starting scale + ShowerParticle::EvolutionScales maxScales(progenitor()->progenitor()->scales()); + progenitor()->progenitor()->scales() = ShowerParticle::EvolutionScales(); + if(progenitor()->progenitor()->dataPtr()->charged()) { + progenitor()->progenitor()->scales().QED = progenitor()->progenitor()->mass(); + progenitor()->progenitor()->scales().QED_noAO = progenitor()->progenitor()->mass(); + } + if(progenitor()->progenitor()->hasColour()) { + progenitor()->progenitor()->scales().QCD_c = progenitor()->progenitor()->mass(); + progenitor()->progenitor()->scales().QCD_c_noAO = progenitor()->progenitor()->mass(); + } + if(progenitor()->progenitor()->hasAntiColour()) { + progenitor()->progenitor()->scales().QCD_ac = progenitor()->progenitor()->mass(); + progenitor()->progenitor()->scales().QCD_ac_noAO = progenitor()->progenitor()->mass(); + } + // perform the shower + progenitor()->hasEmitted(startSpaceLikeDecayShower(maxScales,minmass, + interaction_)); + } + } + } + // do the kinematic reconstruction, checking if it worked + reconstructed = hard ? + showerModel()->kinematicsReconstructor()-> + reconstructHardJets (currentTree(),intrinsicpT(),interaction_, + switchRecon && ntry>maximumTries()/2) : + showerModel()->kinematicsReconstructor()-> + reconstructDecayJets(currentTree(),interaction_); + if(!reconstructed) continue; + // apply vetos on the full shower + for(vector::const_iterator it=_fullShowerVetoes.begin(); + it!=_fullShowerVetoes.end();++it) { + int veto = (**it).applyVeto(currentTree()); + if(veto<0) continue; + // veto the shower + if(veto==0) { + reconstructed = false; + break; + } + // veto the shower and reweight + else if(veto==1) { + reconstructed = false; + break; + } + // veto the event + else if(veto==2) { + throw Veto(); + } + } + if(reWeighting) { + if(reconstructed) eventWeight += 1.; + reconstructed=false; + ++nTryReWeight; + if(nTryReWeight==_nReWeight) { + reWeighting = false; + if(eventWeight==0.) throw Veto(); + } + } + } + while(!reconstructed&&maximumTries()>++ntry); + // check if failed to generate the shower + if(ntry==maximumTries()) { + if(hard) + throw ShowerHandler::ShowerTriesVeto(ntry); + else + throw Exception() << "Failed to generate the shower after " + << ntry << " attempts in QTildeShowerHandler::showerDecay()" + << Exception::eventerror; + } + // handle the weights and apply any reweighting required + if(nTryReWeight>0) { + tStdEHPtr seh = dynamic_ptr_cast(generator()->currentEventHandler()); + static bool first = true; + if(seh) { + seh->reweight(eventWeight/double(nTryReWeight)); + } + else if(first) { + generator()->log() << "Reweighting the shower only works with internal Herwig7 processes" + << "Presumably you are showering Les Houches Events. These will not be" + << "reweighted\n"; + first = false; + } + } + // tree has now showered + _currenttree->hasShowered(true); + hardTree(HardTreePtr()); +} + +void QTildeShowerHandler:: convertHardTree(bool hard,ShowerInteraction::Type type) { + map cmap; + // incoming particles + for(map::const_iterator + cit=currentTree()->incomingLines().begin();cit!=currentTree()->incomingLines().end();++cit) { + map::const_iterator + mit = hardTree()->particles().find(cit->first->progenitor()); + // put the colour lines in the map + ShowerParticlePtr oldParticle = cit->first->progenitor(); + ShowerParticlePtr newParticle = mit->second->branchingParticle(); + ColinePtr cLine = oldParticle-> colourLine(); + ColinePtr aLine = oldParticle->antiColourLine(); + if(newParticle->colourLine() && + cmap.find(newParticle-> colourLine())==cmap.end()) + cmap[newParticle-> colourLine()] = cLine; + if(newParticle->antiColourLine() && + cmap.find(newParticle->antiColourLine())==cmap.end()) + cmap[newParticle->antiColourLine()] = aLine; + // check whether or not particle emits + bool emission = mit->second->parent(); + if(emission) { + if(newParticle->colourLine()) { + ColinePtr ctemp = newParticle-> colourLine(); + ctemp->removeColoured(newParticle); + } + if(newParticle->antiColourLine()) { + ColinePtr ctemp = newParticle->antiColourLine(); + ctemp->removeAntiColoured(newParticle); + } + newParticle = mit->second->parent()->branchingParticle(); + } + // get the new colour lines + ColinePtr newCLine,newALine; + // sort out colour lines + if(newParticle->colourLine()) { + ColinePtr ctemp = newParticle-> colourLine(); + ctemp->removeColoured(newParticle); + if(cmap.find(ctemp)!=cmap.end()) { + newCLine = cmap[ctemp]; + } + else { + newCLine = new_ptr(ColourLine()); + cmap[ctemp] = newCLine; + } + } + // and anticolour lines + if(newParticle->antiColourLine()) { + ColinePtr ctemp = newParticle->antiColourLine(); + ctemp->removeAntiColoured(newParticle); + if(cmap.find(ctemp)!=cmap.end()) { + newALine = cmap[ctemp]; + } + else { + newALine = new_ptr(ColourLine()); + cmap[ctemp] = newALine; + } + } + // remove colour lines from old particle + if(aLine) { + aLine->removeAntiColoured(cit->first->copy()); + aLine->removeAntiColoured(cit->first->progenitor()); + } + if(cLine) { + cLine->removeColoured(cit->first->copy()); + cLine->removeColoured(cit->first->progenitor()); + } + // add particle to colour lines + if(newCLine) newCLine->addColoured (newParticle); + if(newALine) newALine->addAntiColoured(newParticle); + // insert new particles + cit->first->copy(newParticle); + ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,false))); + cit->first->progenitor(sp); + currentTree()->incomingLines()[cit->first]=sp; + cit->first->perturbative(!emission); + // and the emitted particle if needed + if(emission) { + ShowerParticlePtr newOut = mit->second->parent()->children()[1]->branchingParticle(); + if(newOut->colourLine()) { + ColinePtr ctemp = newOut-> colourLine(); + ctemp->removeColoured(newOut); + assert(cmap.find(ctemp)!=cmap.end()); + cmap[ctemp]->addColoured (newOut); + } + if(newOut->antiColourLine()) { + ColinePtr ctemp = newOut->antiColourLine(); + ctemp->removeAntiColoured(newOut); + assert(cmap.find(ctemp)!=cmap.end()); + cmap[ctemp]->addAntiColoured(newOut); + } + ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); + ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); + out->perturbative(false); + currentTree()->outgoingLines().insert(make_pair(out,sout)); + } + if(hard) { + // sort out the value of x + if(mit->second->beam()->momentum().z()>ZERO) { + sp->x(newParticle->momentum(). plus()/mit->second->beam()->momentum(). plus()); + } + else { + sp->x(newParticle->momentum().minus()/mit->second->beam()->momentum().minus()); + } + } + } + // outgoing particles + for(map::const_iterator + cit=currentTree()->outgoingLines().begin();cit!=currentTree()->outgoingLines().end();++cit) { + map >::const_iterator tit; + for(tit = currentTree()->treelinks().begin(); + tit != currentTree()->treelinks().end();++tit) { + if(tit->second.first && tit->second.second==cit->first->progenitor()) + break; + } + map::const_iterator + mit = hardTree()->particles().find(cit->first->progenitor()); + if(mit==hardTree()->particles().end()) continue; + // put the colour lines in the map + ShowerParticlePtr oldParticle = cit->first->progenitor(); + ShowerParticlePtr newParticle = mit->second->branchingParticle(); + ShowerParticlePtr newOut; + ColinePtr cLine = oldParticle-> colourLine(); + ColinePtr aLine = oldParticle->antiColourLine(); + if(newParticle->colourLine() && + cmap.find(newParticle-> colourLine())==cmap.end()) + cmap[newParticle-> colourLine()] = cLine; + if(newParticle->antiColourLine() && + cmap.find(newParticle->antiColourLine())==cmap.end()) + cmap[newParticle->antiColourLine()] = aLine; + // check whether or not particle emits + bool emission = !mit->second->children().empty(); + if(emission) { + if(newParticle->colourLine()) { + ColinePtr ctemp = newParticle-> colourLine(); + ctemp->removeColoured(newParticle); + } + if(newParticle->antiColourLine()) { + ColinePtr ctemp = newParticle->antiColourLine(); + ctemp->removeAntiColoured(newParticle); + } + newParticle = mit->second->children()[0]->branchingParticle(); + newOut = mit->second->children()[1]->branchingParticle(); + if(newParticle->id()!=oldParticle->id()&&newParticle->id()==newOut->id()) + swap(newParticle,newOut); + } + // get the new colour lines + ColinePtr newCLine,newALine; + // sort out colour lines + if(newParticle->colourLine()) { + ColinePtr ctemp = newParticle-> colourLine(); + ctemp->removeColoured(newParticle); + if(cmap.find(ctemp)!=cmap.end()) { + newCLine = cmap[ctemp]; + } + else { + newCLine = new_ptr(ColourLine()); + cmap[ctemp] = newCLine; + } + } + // and anticolour lines + if(newParticle->antiColourLine()) { + ColinePtr ctemp = newParticle->antiColourLine(); + ctemp->removeAntiColoured(newParticle); + if(cmap.find(ctemp)!=cmap.end()) { + newALine = cmap[ctemp]; + } + else { + newALine = new_ptr(ColourLine()); + cmap[ctemp] = newALine; + } + } + // remove colour lines from old particle + if(aLine) { + aLine->removeAntiColoured(cit->first->copy()); + aLine->removeAntiColoured(cit->first->progenitor()); + } + if(cLine) { + cLine->removeColoured(cit->first->copy()); + cLine->removeColoured(cit->first->progenitor()); + } + // special for unstable particles + if(newParticle->id()==oldParticle->id() && + (tit!=currentTree()->treelinks().end()||!oldParticle->dataPtr()->stable())) { + Lorentz5Momentum oldMomentum = oldParticle->momentum(); + Lorentz5Momentum newMomentum = newParticle->momentum(); + LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass()); + if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); + oldParticle->transform(boost); + boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass()); + oldParticle->transform(boost); + if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false); + newParticle=oldParticle; + } + // add particle to colour lines + if(newCLine) newCLine->addColoured (newParticle); + if(newALine) newALine->addAntiColoured(newParticle); + // insert new particles + cit->first->copy(newParticle); + ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,true))); + cit->first->progenitor(sp); + currentTree()->outgoingLines()[cit->first]=sp; + cit->first->perturbative(!emission); + // and the emitted particle if needed + if(emission) { + if(newOut->colourLine()) { + ColinePtr ctemp = newOut-> colourLine(); + ctemp->removeColoured(newOut); + assert(cmap.find(ctemp)!=cmap.end()); + cmap[ctemp]->addColoured (newOut); + } + if(newOut->antiColourLine()) { + ColinePtr ctemp = newOut->antiColourLine(); + ctemp->removeAntiColoured(newOut); + assert(cmap.find(ctemp)!=cmap.end()); + cmap[ctemp]->addAntiColoured(newOut); + } + ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true)); + ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout)); + out->perturbative(false); + currentTree()->outgoingLines().insert(make_pair(out,sout)); + } + // update any decay products + if(tit!=currentTree()->treelinks().end()) + currentTree()->updateLink(tit->first,make_pair(cit->first,sp)); + } + // reset the tree + currentTree()->resetShowerProducts(); + // reextract the particles and set the colour partners + vector particles = + currentTree()->extractProgenitorParticles(); + // clear the partners + for(unsigned int ix=0;ixpartner(ShowerParticlePtr()); + particles[ix]->clearPartners(); + } + // clear the tree + hardTree(HardTreePtr()); + // Set the initial evolution scales + showerModel()->partnerFinder()-> + setInitialEvolutionScales(particles,!hard,type,!_hardtree); +} + +Branching QTildeShowerHandler::selectTimeLikeBranching(tShowerParticlePtr particle, + ShowerInteraction::Type type, + HardBranchingPtr branch) { + Branching fb; + unsigned int iout=0; + while (true) { + // break if doing truncated shower and no truncated shower needed + if(branch && (!isTruncatedShowerON()||hardOnly())) break; + fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type); + // no emission break + if(!fb.kinematics) break; + // special for truncated shower + if(branch) { + // check haven't evolved too far + if(fb.kinematics->scale() < branch->scale()) { + fb=Branching(); + break; + } + // find the truncated line + iout=0; + if(fb.ids[1]->id()!=fb.ids[2]->id()) { + if(fb.ids[1]->id()==particle->id()) iout=1; + else if (fb.ids[2]->id()==particle->id()) iout=2; + } + else if(fb.ids[1]->id()==particle->id()) { + if(fb.kinematics->z()>0.5) iout=1; + else iout=2; + } + // apply the vetos for the truncated shower + // no flavour changing branchings + if(iout==0) { + particle->vetoEmission(fb.type,fb.kinematics->scale()); + continue; + } + double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); + // only if same interaction for forced branching + ShowerInteraction::Type type2 = convertInteraction(fb.type); + // and evolution + if(type2==branch->sudakov()->interactionType()) { + if(zsplit < 0.5 || // hardest line veto + fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto + particle->vetoEmission(fb.type,fb.kinematics->scale()); + continue; + } + } + // pt veto + if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { + particle->vetoEmission(fb.type,fb.kinematics->scale()); + continue; + } + } + // standard vetos for all emissions + if(timeLikeVetoed(fb,particle)) { + particle->vetoEmission(fb.type,fb.kinematics->scale()); + if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); + continue; + } + // special for already decayed particles + // don't allow flavour changing branchings + bool vetoDecay = false; + for(map >::const_iterator tit = currentTree()->treelinks().begin(); + tit != currentTree()->treelinks().end();++tit) { + if(tit->second.first == progenitor()) { + map::const_iterator + it = currentTree()->outgoingLines().find(progenitor()); + if(it!=currentTree()->outgoingLines().end() && particle == it->second && + fb.ids[0]!=fb.ids[1] && fb.ids[1]!=fb.ids[2]) { + vetoDecay = true; + break; + } + } + } + if(vetoDecay) { + particle->vetoEmission(fb.type,fb.kinematics->scale()); + if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr()); + continue; + } + break; + } + // normal case + if(!branch) { + if(fb.kinematics) fb.hard = false; + return fb; + } + // truncated emission + if(fb.kinematics) { + fb.hard = false; + fb.iout = iout; + return fb; + } + // otherwise need to return the hard emission + // construct the kinematics for the hard emission + ShoKinPtr showerKin= + branch->sudakov()->createFinalStateBranching(branch->scale(), + branch->children()[0]->z(), + branch->phi(), + branch->children()[0]->pT()); + IdList idlist(3); + idlist[0] = particle->dataPtr(); + idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); + idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); + fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() ); + fb.hard = true; + fb.iout=0; + // return it + return fb; +} + +Branching QTildeShowerHandler::selectSpaceLikeDecayBranching(tShowerParticlePtr particle, + const ShowerParticle::EvolutionScales & maxScales, + Energy minmass,ShowerInteraction::Type type, + HardBranchingPtr branch) { + Branching fb; + unsigned int iout=0; + while (true) { + // break if doing truncated shower and no truncated shower needed + if(branch && (!isTruncatedShowerON()||hardOnly())) break; + // select branching + fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass, + _initialenhance,type); + // return if no radiation + if(!fb.kinematics) break; + // special for truncated shower + if(branch) { + // check haven't evolved too far + if(fb.kinematics->scale() < branch->scale()) { + fb=Branching(); + break; + } + // find the truncated line + iout=0; + if(fb.ids[1]->id()!=fb.ids[2]->id()) { + if(fb.ids[1]->id()==particle->id()) iout=1; + else if (fb.ids[2]->id()==particle->id()) iout=2; + } + else if(fb.ids[1]->id()==particle->id()) { + if(fb.kinematics->z()>0.5) iout=1; + else iout=2; + } + // apply the vetos for the truncated shower + // no flavour changing branchings + if(iout==0) { + particle->vetoEmission(fb.type,fb.kinematics->scale()); + continue; + } + ShowerInteraction::Type type2 = convertInteraction(fb.type); + double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z(); + if(type2==branch->sudakov()->interactionType()) { + if(zsplit < 0.5 || // hardest line veto + fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto + particle->vetoEmission(fb.type,fb.kinematics->scale()); + continue; + } + } + // pt veto + if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) { + particle->vetoEmission(fb.type,fb.kinematics->scale()); + continue; + } + } + // if not vetoed break + if(spaceLikeDecayVetoed(fb,particle)) { + // otherwise reset scale and continue + particle->vetoEmission(fb.type,fb.kinematics->scale()); + continue; + } + break; + } + // normal case + if(!branch) { + if(fb.kinematics) fb.hard = false; + return fb; + } + // truncated emission + if(fb.kinematics) { + fb.hard = false; + fb.iout = iout; + return fb; + } + // otherwise need to return the hard emission + // construct the kinematics for the hard emission + ShoKinPtr showerKin= + branch->sudakov()->createDecayBranching(branch->scale(), + branch->children()[0]->z(), + branch->phi(), + branch->children()[0]->pT()); + IdList idlist(3); + idlist[0] = particle->dataPtr(); + idlist[1] = branch->children()[0]->branchingParticle()->dataPtr(); + idlist[2] = branch->children()[1]->branchingParticle()->dataPtr(); + // create the branching + fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine ); + fb.hard=true; + fb.iout=0; + // return it + return fb; +} + +void QTildeShowerHandler::checkFlags() { + string error = "Inconsistent hard emission set-up in QTildeShowerHandler::showerHardProcess(). "; + if ( ( currentTree()->isMCatNLOSEvent() || currentTree()->isMCatNLOHEvent() ) ) { + if (_hardEmission ==2 ) + throw Exception() << error + << "Cannot generate POWHEG matching with MC@NLO shower " + << "approximation. Add 'set QTildeShowerHandler:HardEmission 0' to input file." + << Exception::runerror; + if ( canHandleMatchboxTrunc() ) + throw Exception() << error + << "Cannot use truncated qtilde shower with MC@NLO shower " + << "approximation. Set LHCGenerator:EventHandler" + << ":CascadeHandler to '/Herwig/Shower/ShowerHandler' or " + << "'/Herwig/Shower/Dipole/DipoleShowerHandler'." + << Exception::runerror; + } + else if ( ((currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) ) && + _hardEmission != 2){ + if ( canHandleMatchboxTrunc()) + throw Exception() << error + << "Unmatched events requested for POWHEG shower " + << "approximation. Set QTildeShowerHandler:HardEmission to " + << "'POWHEG'." + << Exception::runerror; + else if (_hardEmissionWarn) { + _hardEmissionWarn = false; + _hardEmission=2; + throw Exception() << error + << "Unmatched events requested for POWHEG shower " + << "approximation. Changing QTildeShowerHandler:HardEmission from " + << _hardEmission << " to 2" + << Exception::warning; + } + } + + if ( currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) { + if (currentTree()->showerApproximation()->needsTruncatedShower() && + !canHandleMatchboxTrunc() ) + throw Exception() << error + << "Current shower handler cannot generate truncated shower. " + << "Set Generator:EventHandler:CascadeHandler to " + << "'/Herwig/Shower/PowhegShowerHandler'." + << Exception::runerror; + } + else if ( currentTree()->truncatedShower() && _missingTruncWarn) { + _missingTruncWarn=false; + throw Exception() << "Warning: POWHEG shower approximation used without " + << "truncated shower. Set Generator:EventHandler:" + << "CascadeHandler to '/Herwig/Shower/PowhegShowerHandler' and " + << "'MEMatching:TruncatedShower Yes'." + << Exception::warning; + } + // else if ( !dipme && _hardEmissionMode > 1 && + // firstInteraction()) + // throw Exception() << error + // << "POWHEG matching requested for LO events. Include " + // << "'set Factory:ShowerApproximation MEMatching' in input file." + // << Exception::runerror; +} + + +tPPair QTildeShowerHandler::remakeRemnant(tPPair oldp){ + // get the parton extractor + PartonExtractor & pex = *lastExtractor(); + // get the new partons + tPPair newp = make_pair(findFirstParton(oldp.first ), + findFirstParton(oldp.second)); + // if the same do nothing + if(newp == oldp) return oldp; + // Creates the new remnants and returns the new PartonBinInstances + // ATTENTION Broken here for very strange configuration + PBIPair newbins = pex.newRemnants(oldp, newp, newStep()); + newStep()->addIntermediate(newp.first); + newStep()->addIntermediate(newp.second); + // return the new partons + return newp; +} + +PPtr QTildeShowerHandler::findFirstParton(tPPtr seed) const{ + if(seed->parents().empty()) return seed; + tPPtr parent = seed->parents()[0]; + //if no parent there this is a loose end which will + //be connected to the remnant soon. + if(!parent || parent == incomingBeams().first || + parent == incomingBeams().second ) return seed; + else return findFirstParton(parent); +} + +void QTildeShowerHandler::decay(ShowerTreePtr tree, ShowerDecayMap & decay) { + // must be one incoming particle + assert(tree->incomingLines().size()==1); + // apply any transforms + tree->applyTransforms(); + // if already decayed return + if(!tree->outgoingLines().empty()) return; + // now we need to replace the particle with a new copy after the shower + // find particle after the shower + map >::const_iterator + tit = tree->parent()->treelinks().find(tree); + assert(tit!=tree->parent()->treelinks().end()); + ShowerParticlePtr newparent=tit->second.second; + PerturbativeProcessPtr newProcess = new_ptr(PerturbativeProcess()); + newProcess->incoming().push_back(make_pair(newparent,PerturbativeProcessPtr())); + DecayProcessMap decayMap; + ShowerHandler::decay(newProcess,decayMap); + ShowerTree::constructTrees(tree,decay,newProcess,decayMap); +} + +namespace { + + ShowerProgenitorPtr + findFinalStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) { + map::iterator partner; + Energy2 dmin(1e30*GeV2); + for(map::iterator + cit =tree->outgoingLines().begin(); cit!=tree->outgoingLines().end(); ++cit) { + if(cit->second->id()!=id) continue; + Energy2 test = + sqr(cit->second->momentum().x()-momentum.x())+ + sqr(cit->second->momentum().y()-momentum.y())+ + sqr(cit->second->momentum().z()-momentum.z())+ + sqr(cit->second->momentum().t()-momentum.t()); + if(testfirst; + } + + ShowerProgenitorPtr + findInitialStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) { + map::iterator partner; + Energy2 dmin(1e30*GeV2); + for(map::iterator + cit =tree->incomingLines().begin(); cit!=tree->incomingLines().end(); ++cit) { + if(cit->second->id()!=id) continue; + Energy2 test = + sqr(cit->second->momentum().x()-momentum.x())+ + sqr(cit->second->momentum().y()-momentum.y())+ + sqr(cit->second->momentum().z()-momentum.z())+ + sqr(cit->second->momentum().t()-momentum.t()); + if(testfirst; + } + + void fixSpectatorColours(PPtr newSpect,ShowerProgenitorPtr oldSpect, + ColinePair & cline,ColinePair & aline, bool reconnect) { + cline.first = oldSpect->progenitor()->colourLine(); + cline.second = newSpect->colourLine(); + aline.first = oldSpect->progenitor()->antiColourLine(); + aline.second = newSpect->antiColourLine(); + if(!reconnect) return; + if(cline.first) { + cline.first ->removeColoured(oldSpect->copy()); + cline.first ->removeColoured(oldSpect->progenitor()); + cline.second->removeColoured(newSpect); + cline.first ->addColoured(newSpect); + } + if(aline.first) { + aline.first ->removeAntiColoured(oldSpect->copy()); + aline.first ->removeAntiColoured(oldSpect->progenitor()); + aline.second->removeAntiColoured(newSpect); + aline.first ->addAntiColoured(newSpect); + } + } + + void fixInitialStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter, + ColinePair cline,ColinePair aline,double x) { + // sort out the colours + if(emitted->dataPtr()->iColour()==PDT::Colour8) { + // emitter + if(cline.first && cline.first == emitter->progenitor()->antiColourLine() && + cline.second !=newEmit->antiColourLine()) { + // sort out not radiating line + ColinePtr col = emitter->progenitor()->colourLine(); + if(col) { + col->removeColoured(emitter->copy()); + col->removeColoured(emitter->progenitor()); + newEmit->colourLine()->removeColoured(newEmit); + col->addColoured(newEmit); + } + } + else if(aline.first && aline.first == emitter->progenitor()->colourLine() && + aline.second !=newEmit->colourLine()) { + // sort out not radiating line + ColinePtr anti = emitter->progenitor()->antiColourLine(); + if(anti) { + anti->removeAntiColoured(emitter->copy()); + anti->removeAntiColoured(emitter->progenitor()); + newEmit->colourLine()->removeAntiColoured(newEmit); + anti->addAntiColoured(newEmit); + } + } + else + assert(false); + // emitted + if(cline.first && cline.second==emitted->colourLine()) { + cline.second->removeColoured(emitted); + cline.first->addColoured(emitted); + } + else if(aline.first && aline.second==emitted->antiColourLine()) { + aline.second->removeAntiColoured(emitted); + aline.first->addAntiColoured(emitted); + } + else + assert(false); + } + else { + if(emitter->progenitor()->antiColourLine() ) { + ColinePtr col = emitter->progenitor()->antiColourLine(); + col->removeAntiColoured(emitter->copy()); + col->removeAntiColoured(emitter->progenitor()); + if(newEmit->antiColourLine()) { + newEmit->antiColourLine()->removeAntiColoured(newEmit); + col->addAntiColoured(newEmit); + } + else if (emitted->colourLine()) { + emitted->colourLine()->removeColoured(emitted); + col->addColoured(emitted); + } + else + assert(false); + } + if(emitter->progenitor()->colourLine() ) { + ColinePtr col = emitter->progenitor()->colourLine(); + col->removeColoured(emitter->copy()); + col->removeColoured(emitter->progenitor()); + if(newEmit->colourLine()) { + newEmit->colourLine()->removeColoured(newEmit); + col->addColoured(newEmit); + } + else if (emitted->antiColourLine()) { + emitted->antiColourLine()->removeAntiColoured(emitted); + col->addAntiColoured(emitted); + } + else + assert(false); + } + } + // update the emitter + emitter->copy(newEmit); + ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,false)); + sp->x(x); + emitter->progenitor(sp); + tree->incomingLines()[emitter]=sp; + emitter->perturbative(false); + // add emitted + sp=new_ptr(ShowerParticle(*emitted,1,true)); + ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(),emitted,sp)); + gluon->perturbative(false); + tree->outgoingLines().insert(make_pair(gluon,sp)); + } + + void fixFinalStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter, + ColinePair cline,ColinePair aline) { + map >::const_iterator tit; + // special case if decayed + for(tit = tree->treelinks().begin(); tit != tree->treelinks().end();++tit) { + if(tit->second.first && tit->second.second==emitter->progenitor()) + break; + } + // sort out the colour lines + if(cline.first && cline.first == emitter->progenitor()->antiColourLine() && + cline.second !=newEmit->antiColourLine()) { + // sort out not radiating line + ColinePtr col = emitter->progenitor()->colourLine(); + if(col) { + col->removeColoured(emitter->copy()); + col->removeColoured(emitter->progenitor()); + newEmit->colourLine()->removeColoured(newEmit); + col->addColoured(newEmit); + } + } + else if(aline.first && aline.first == emitter->progenitor()->colourLine() && + aline.second !=newEmit->colourLine()) { + // sort out not radiating line + ColinePtr anti = emitter->progenitor()->antiColourLine(); + if(anti) { + anti->removeAntiColoured(emitter->copy()); + anti->removeAntiColoured(emitter->progenitor()); + newEmit->colourLine()->removeAntiColoured(newEmit); + anti->addAntiColoured(newEmit); + } + } + else + assert(false); + // update the emitter + emitter->copy(newEmit); + ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,true)); + emitter->progenitor(sp); + tree->outgoingLines()[emitter]=sp; + emitter->perturbative(false); + // update for decaying particles + if(tit!=tree->treelinks().end()) + tree->updateLink(tit->first,make_pair(emitter,sp)); + // add the emitted particle + // sort out the colour + if(cline.first && cline.second==emitted->antiColourLine()) { + cline.second->removeAntiColoured(emitted); + cline.first->addAntiColoured(emitted); + } + else if(aline.first && aline.second==emitted->colourLine()) { + aline.second->removeColoured(emitted); + aline.first->addColoured(emitted); + } + else + assert(false); + sp=new_ptr(ShowerParticle(*emitted,1,true)); + ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(), + emitted,sp)); + gluon->perturbative(false); + tree->outgoingLines().insert(make_pair(gluon,sp)); + } + +} + +void QTildeShowerHandler::setupMECorrection(RealEmissionProcessPtr real) { + assert(real); + currentTree()->hardMatrixElementCorrection(true); + // II emission + if(real->emitter() < real->incoming().size() && + real->spectator() < real->incoming().size()) { + // recoiling system + for( map::const_iterator + cjt= currentTree()->outgoingLines().begin(); + cjt != currentTree()->outgoingLines().end();++cjt ) { + cjt->first->progenitor()->transform(real->transformation()); + cjt->first->copy()->transform(real->transformation()); + } + // the the radiating system + ShowerProgenitorPtr emitter,spectator; + unsigned int iemit = real->emitter(); + unsigned int ispect = real->spectator(); + int ig = int(real->emitted())-int(real->incoming().size()); + emitter = findInitialStateLine(currentTree(), + real->bornIncoming()[iemit]->id(), + real->bornIncoming()[iemit]->momentum()); + spectator = findInitialStateLine(currentTree(), + real->bornIncoming()[ispect]->id(), + real->bornIncoming()[ispect]->momentum()); + // sort out the colours + ColinePair cline,aline; + fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true); + // update the spectator + spectator->copy(real->incoming()[ispect]); + ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false))); + sp->x(ispect ==0 ? real->x().first :real->x().second); + spectator->progenitor(sp); + currentTree()->incomingLines()[spectator]=sp; + spectator->perturbative(true); + // now for the emitter + fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig], + emitter,cline,aline,iemit ==0 ? real->x().first :real->x().second); + } + // FF emission + else if(real->emitter() >= real->incoming().size() && + real->spectator() >= real->incoming().size()) { + assert(real->outgoing()[real->emitted()-real->incoming().size()]->id()==ParticleID::g); + // find the emitter and spectator in the shower tree + ShowerProgenitorPtr emitter,spectator; + int iemit = int(real->emitter())-int(real->incoming().size()); + emitter = findFinalStateLine(currentTree(), + real->bornOutgoing()[iemit]->id(), + real->bornOutgoing()[iemit]->momentum()); + int ispect = int(real->spectator())-int(real->incoming().size()); + spectator = findFinalStateLine(currentTree(), + real->bornOutgoing()[ispect]->id(), + real->bornOutgoing()[ispect]->momentum()); + map >::const_iterator tit; + // first the spectator + // special case if decayed + for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { + if(tit->second.first && tit->second.second==spectator->progenitor()) + break; + } + // sort out the colours + ColinePair cline,aline; + fixSpectatorColours(real->outgoing()[ispect],spectator,cline,aline,true); + // update the spectator + spectator->copy(real->outgoing()[ispect]); + ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect],1,true))); + spectator->progenitor(sp); + currentTree()->outgoingLines()[spectator]=sp; + spectator->perturbative(true); + // update for decaying particles + if(tit!=currentTree()->treelinks().end()) + currentTree()->updateLink(tit->first,make_pair(spectator,sp)); + // now the emitting particle + int ig = int(real->emitted())-int(real->incoming().size()); + fixFinalStateEmitter(currentTree(),real->outgoing()[iemit], + real->outgoing()[ig], + emitter,cline,aline); + } + // IF emission + else { + // scattering process + if(real->incoming().size()==2) { + ShowerProgenitorPtr emitter,spectator; + unsigned int iemit = real->emitter(); + unsigned int ispect = real->spectator(); + int ig = int(real->emitted())-int(real->incoming().size()); + ColinePair cline,aline; + // incoming spectator + if(ispect<2) { + spectator = findInitialStateLine(currentTree(), + real->bornIncoming()[ispect]->id(), + real->bornIncoming()[ispect]->momentum()); + fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true); + // update the spectator + spectator->copy(real->incoming()[ispect]); + ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false))); + sp->x(ispect ==0 ? real->x().first :real->x().second); + spectator->progenitor(sp); + currentTree()->incomingLines()[spectator]=sp; + spectator->perturbative(true); + } + // outgoing spectator + else { + spectator = findFinalStateLine(currentTree(), + real->bornOutgoing()[ispect-real->incoming().size()]->id(), + real->bornOutgoing()[ispect-real->incoming().size()]->momentum()); + // special case if decayed + map >::const_iterator tit; + for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) { + if(tit->second.first && tit->second.second==spectator->progenitor()) + break; + } + fixSpectatorColours(real->outgoing()[ispect-real->incoming().size()],spectator,cline,aline,true); + // update the spectator + spectator->copy(real->outgoing()[ispect-real->incoming().size()]); + ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect-real->incoming().size()],1,true))); + spectator->progenitor(sp); + currentTree()->outgoingLines()[spectator]=sp; + spectator->perturbative(true); + // update for decaying particles + if(tit!=currentTree()->treelinks().end()) + currentTree()->updateLink(tit->first,make_pair(spectator,sp)); + } + // incoming emitter + if(iemit<2) { + emitter = findInitialStateLine(currentTree(), + real->bornIncoming()[iemit]->id(), + real->bornIncoming()[iemit]->momentum()); + fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig], + emitter,aline,cline,iemit ==0 ? real->x().first :real->x().second); + } + // outgoing emitter + else { + emitter = findFinalStateLine(currentTree(), + real->bornOutgoing()[iemit-real->incoming().size()]->id(), + real->bornOutgoing()[iemit-real->incoming().size()]->momentum()); + fixFinalStateEmitter(currentTree(),real->outgoing()[iemit-real->incoming().size()], + real->outgoing()[ig],emitter,aline,cline); + } + } + // decay process + else { + assert(real->spectator()==0); + unsigned int iemit = real->emitter()-real->incoming().size(); + int ig = int(real->emitted())-int(real->incoming().size()); + ColinePair cline,aline; + // incoming spectator + ShowerProgenitorPtr spectator = findInitialStateLine(currentTree(), + real->bornIncoming()[0]->id(), + real->bornIncoming()[0]->momentum()); + fixSpectatorColours(real->incoming()[0],spectator,cline,aline,false); + // find the emitter + ShowerProgenitorPtr emitter = + findFinalStateLine(currentTree(), + real->bornOutgoing()[iemit]->id(), + real->bornOutgoing()[iemit]->momentum()); + // recoiling system + for( map::const_iterator + cjt= currentTree()->outgoingLines().begin(); + cjt != currentTree()->outgoingLines().end();++cjt ) { + if(cjt->first==emitter) continue; + cjt->first->progenitor()->transform(real->transformation()); + cjt->first->copy()->transform(real->transformation()); + } + // sort out the emitter + fixFinalStateEmitter(currentTree(),real->outgoing()[iemit], + real->outgoing()[ig],emitter,aline,cline); + } + } + // clean up the shower tree + _currenttree->resetShowerProducts(); +} diff --git a/Shower/QTilde/QTildeShowerHandler.fh b/Shower/QTilde/QTildeShowerHandler.fh new file mode 100644 --- /dev/null +++ b/Shower/QTilde/QTildeShowerHandler.fh @@ -0,0 +1,22 @@ +// -*- C++ -*- +// +// This is the forward declaration of the QTildeShowerHandler class. +// +#ifndef Herwig_QTildeShowerHandler_FH +#define Herwig_QTildeShowerHandler_FH + +#include "ThePEG/Config/ThePEG.h" + +namespace Herwig { + +class QTildeShowerHandler; + +} + +namespace ThePEG { + +ThePEG_DECLARE_POINTERS(Herwig::QTildeShowerHandler,QTildeShowerHandlerPtr); + +} + +#endif diff --git a/Shower/QTilde/QTildeShowerHandler.h b/Shower/QTilde/QTildeShowerHandler.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/QTildeShowerHandler.h @@ -0,0 +1,846 @@ +// -*- C++ -*- +#ifndef Herwig_QTildeShowerHandler_H +#define Herwig_QTildeShowerHandler_H +// +// This is the declaration of the QTildeShowerHandler class. +// + +#include "QTildeShowerHandler.fh" +#include "Herwig/Shower/ShowerHandler.h" +#include "Herwig/Shower/QTilde/Base/ShowerModel.h" +#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.h" +#include "Herwig/Shower/QTilde/Base/ShowerTree.h" +#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh" +#include "Herwig/Shower/QTilde/Base/HardTree.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/QTilde/Base/ShowerVeto.h" +#include "Herwig/Shower/QTilde/Base/FullShowerVeto.h" +#include "Herwig/MatrixElement/HwMEBase.h" +#include "Herwig/Decay/HwDecayerBase.h" +#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" +#include "Herwig/Shower/RealEmissionProcess.h" +#include "Herwig/Utilities/Statistic.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * The QTildeShowerHandler class. + * + * @see \ref QTildeShowerHandlerInterfaces "The interfaces" + * defined for QTildeShowerHandler. + */ +class QTildeShowerHandler: public ShowerHandler { + +public: + + /** + * Pointer to an XComb object + */ + typedef Ptr::pointer XCPtr; + +public: + + /** @name Standard constructors and destructors. */ + //@{ + /** + * The default constructor. + */ + QTildeShowerHandler(); + + /** + * The destructor. + */ + virtual ~QTildeShowerHandler(); + //@} + +public: + + /** + * At the end of the Showering, transform ShowerParticle objects + * into ThePEG particles and fill the event record with them. + * Notice that the parent/child relationships and the + * transformation from ShowerColourLine objects into ThePEG + * ColourLine ones must be properly handled. + */ + void fillEventRecord(); + + /** + * Return the relevant hard scale to be used in the profile scales + */ + virtual Energy hardScale() const { + return muPt; + } + + /** + * Generate hard emissions for CKKW etc + */ + virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const; + + /** + * Members to perform the shower + */ + //@{ + /** + * Perform the shower of the hard process + */ + virtual void showerHardProcess(ShowerTreePtr,XCPtr); + + /** + * Perform the shower of a decay + */ + virtual void showerDecay(ShowerTreePtr); + //@} + + /** + * Access to the flags and shower variables + */ + //@{ + /** + * Get the ShowerModel + */ + ShowerModelPtr showerModel() const {return _model;} + + /** + * Get the SplittingGenerator + */ + tSplittingGeneratorPtr splittingGenerator() const { return _splittingGenerator; } + + /** + * Mode for hard emissions + */ + int hardEmission() const {return _hardEmission;} + //@} + + /** + * Connect the Hard and Shower trees + */ + virtual void connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ); + + /** + * Access to switches for spin correlations + */ + //@{ + /** + * Spin Correlations + */ + unsigned int spinCorrelations() const { + return _spinOpt; + } + + /** + * Soft correlations + */ + unsigned int softCorrelations() const { + return _softOpt; + } + + /** + * Any correlations + */ + bool correlations() const { + return _spinOpt!=0||_softOpt!=0; + } + //@} + +protected: + + /** + * Perform the shower + */ + void doShowering(bool hard,XCPtr); + + /** + * Generate the hard matrix element correction + */ + virtual RealEmissionProcessPtr hardMatrixElementCorrection(bool); + + /** + * Generate the hardest emission + */ + virtual void hardestEmission(bool hard); + + /** + * Set up for applying a matrix element correction + */ + void setupMECorrection(RealEmissionProcessPtr real); + + /** + * Extract the particles to be showered, set the evolution scales + * and apply the hard matrix element correction + * @param hard Whether this is a hard process or decay + * @return The particles to be showered + */ + virtual vector setupShower(bool hard); + + /** + * set the colour partners + */ + virtual void setEvolutionPartners(bool hard,ShowerInteraction::Type, + bool clear); + + /** + * Methods to perform the evolution of an individual particle, including + * recursive calling on the products + */ + //@{ + /** + * It does the forward evolution of the time-like input particle + * (and recursively for all its radiation products). + * accepting only emissions which conforms to the showerVariables + * and soft matrix element correction. + * If at least one emission has occurred then the method returns true. + * @param particle The particle to be showered + */ + virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction::Type, + Branching fb, bool first); + + /** + * It does the backward evolution of the space-like input particle + * (and recursively for all its time-like radiation products). + * accepting only emissions which conforms to the showerVariables. + * If at least one emission has occurred then the method returns true + * @param particle The particle to be showered + * @param beam The beam particle + */ + virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam, + ShowerInteraction::Type); + + /** + * If does the forward evolution of the input on-shell particle + * involved in a decay + * (and recursively for all its time-like radiation products). + * accepting only emissions which conforms to the showerVariables. + * @param particle The particle to be showered + * @param maxscale The maximum scale for the shower. + * @param minimumMass The minimum mass of the final-state system + */ + virtual bool + spaceLikeDecayShower(tShowerParticlePtr particle, + const ShowerParticle::EvolutionScales & maxScales, + Energy minimumMass,ShowerInteraction::Type, + Branching fb); + + /** + * Truncated shower from a time-like particle + */ + virtual bool truncatedTimeLikeShower(tShowerParticlePtr particle, + HardBranchingPtr branch, + ShowerInteraction::Type type, + Branching fb, bool first); + + /** + * Truncated shower from a space-like particle + */ + virtual bool truncatedSpaceLikeShower(tShowerParticlePtr particle,PPtr beam, + HardBranchingPtr branch, + ShowerInteraction::Type type); + + /** + * Truncated shower from a time-like particle + */ + virtual bool truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, + const ShowerParticle::EvolutionScales & maxScales, + Energy minimumMass, HardBranchingPtr branch, + ShowerInteraction::Type type, Branching fb); + //@} + + /** + * Switches for matrix element corrections + */ + //@{ + /** + * Any ME correction? + */ + bool MECOn() const { + return _hardEmission == 1; + } + + /** + * Any hard ME correction? + */ + bool hardMEC() const { + return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode == 2); + } + + /** + * Any soft ME correction? + */ + bool softMEC() const { + return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode > 2); + } + //@} + + /** + * Is the truncated shower on? + */ + bool isTruncatedShowerON() const {return _trunc_Mode;} + + /** + * Switch for intrinsic pT + */ + //@{ + /** + * Any intrinsic pT? + */ + bool ipTon() const { + return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO ); + } + //@} + + /**@name Additional shower vetoes */ + //@{ + /** + * Insert a veto. + */ + void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); } + + /** + * Remove a veto. + */ + void removeVeto (ShowerVetoPtr v) { + vector::iterator vit = find(_vetoes.begin(),_vetoes.end(),v); + if (vit != _vetoes.end()) + _vetoes.erase(vit); + } + + //@} + + /** + * Switches for vetoing hard emissions + */ + //@{ + /** + * Returns true if the hard veto read-in is to be applied to only + * the primary collision and false otherwise. + */ + bool hardVetoReadOption() const {return _hardVetoReadOption;} + //@} + + /** + * Enhancement factors for radiation needed to generate the soft matrix + * element correction. + */ + //@{ + /** + * Access the enhancement factor for initial-state radiation + */ + double initialStateRadiationEnhancementFactor() const { return _initialenhance; } + + /** + * Access the enhancement factor for final-state radiation + */ + double finalStateRadiationEnhancementFactor() const { return _finalenhance; } + + /** + * Set the enhancement factor for initial-state radiation + */ + void initialStateRadiationEnhancementFactor(double in) { _initialenhance=in; } + + /** + * Set the enhancement factor for final-state radiation + */ + void finalStateRadiationEnhancementFactor(double in) { _finalenhance=in; } + //@} + + /** + * Access to set/get the HardTree currently beinging showered + */ + //@{ + /** + * The HardTree currently being showered + */ + tHardTreePtr hardTree() {return _hardtree;} + + /** + * The HardTree currently being showered + */ + void hardTree(tHardTreePtr in) {_hardtree = in;} + //@} + + /** + * Access/set the beam particle for the current initial-state shower + */ + //@{ + /** + * Get the beam particle data + */ + Ptr::const_pointer beamParticle() const { return _beam; } + + /** + * Set the beam particle data + */ + void setBeamParticle(Ptr::const_pointer in) { _beam=in; } + //@} + + /** + * Set/Get the current tree being evolverd for inheriting classes + */ + //@{ + /** + * Get the tree + */ + tShowerTreePtr currentTree() { return _currenttree; } + + /** + * Set the tree + */ + void currentTree(tShowerTreePtr tree) { _currenttree=tree; } + + //@} + + /** + * Access the maximum number of attempts to generate the shower + */ + unsigned int maximumTries() const { return _maxtry; } + + /** + * Set/Get the ShowerProgenitor for the current shower + */ + //@{ + /** + * Access the progenitor + */ + ShowerProgenitorPtr progenitor() { return _progenitor; } + + /** + * Set the progenitor + */ + void progenitor(ShowerProgenitorPtr in) { _progenitor=in; } + //@} + + /** + * Calculate the intrinsic \f$p_T\f$. + */ + virtual void generateIntrinsicpT(vector); + + /** + * Access to the intrinsic \f$p_T\f$ for inheriting classes + */ + map > & intrinsicpT() { return _intrinsic; } + + /** + * find the maximally allowed pt acc to the hard process. + */ + void setupMaximumScales(const vector &,XCPtr); + + /** + * find the relevant hard scales for profile scales. + */ + void setupHardScales(const vector &,XCPtr); + + /** + * Convert the HardTree into an extra shower emission + */ + void convertHardTree(bool hard,ShowerInteraction::Type type); + +protected: + + /** + * Find the parton extracted from the incoming particle after ISR + */ + PPtr findFirstParton(tPPtr seed) const; + + /** + * Fix Remnant connections after ISR + */ + tPPair remakeRemnant(tPPair oldp); + +protected: + + /** + * Start the shower of a timelike particle + */ + virtual bool startTimeLikeShower(ShowerInteraction::Type); + + /** + * Update of the time-like stuff + */ + void updateHistory(tShowerParticlePtr particle); + + /** + * Start the shower of a spacelike particle + */ + virtual bool startSpaceLikeShower(PPtr,ShowerInteraction::Type); + + /** + * Start the shower of a spacelike particle + */ + virtual bool + startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, + Energy minimumMass,ShowerInteraction::Type); + + /** + * Select the branching for the next time-like emission + */ + Branching selectTimeLikeBranching(tShowerParticlePtr particle, + ShowerInteraction::Type type, + HardBranchingPtr branch); + + /** + * Select the branching for the next space-like emission in a decay + */ + Branching selectSpaceLikeDecayBranching(tShowerParticlePtr particle, + const ShowerParticle::EvolutionScales & maxScales, + Energy minmass,ShowerInteraction::Type type, + HardBranchingPtr branch); + /** + * Create the timelike child of a branching + */ + ShowerParticleVector createTimeLikeChildren(tShowerParticlePtr particle, + IdList ids); + + /** + * Vetos for the timelike shower + */ + virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr); + + /** + * Vetos for the spacelike shower + */ + virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr); + + /** + * Vetos for the spacelike shower + */ + virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr); + + /** + * Only generate the hard emission, for testing only. + */ + bool hardOnly() const {return _limitEmissions==3;} + + /** + * Check the flags + */ + void checkFlags(); + + /** + * + */ + void addFSRUsingDecayPOWHEG(HardTreePtr ISRTree); + +public: + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +protected: + + /** + * The main method which manages the showering of a subprocess. + */ + virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb); + + /** + * Decay a ShowerTree + */ + void decay(ShowerTreePtr tree, ShowerDecayMap & decay); + +protected: + + /** @name Clone Methods. */ + //@{ + /** + * Make a simple clone of this object. + * @return a pointer to the new object. + */ + virtual IBPtr clone() const; + + /** Make a clone of this object, possibly modifying the cloned object + * to make it sane. + * @return a pointer to the new object. + */ + virtual IBPtr fullclone() const; + //@} + +protected: + + /** @name Standard Interfaced functions. */ + //@{ + /** + * Initialize this object after the setup phase before saving an + * EventGenerator to disk. + * @throws InitException if object could not be initialized properly. + */ + virtual void doinit(); + //@} + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + QTildeShowerHandler & operator=(const QTildeShowerHandler &); + +private: + + + /** + * Stuff from the ShowerHandler + */ + //@{ + + /** + * The ShowerTree for the hard process + */ + ShowerTreePtr hard_; + + /** + * The ShowerTree for the decays + */ + ShowerDecayMap decay_; + + /** + * The ShowerTrees for which the initial shower + */ + vector done_; + //@} + +private : + + /** + * Pointer to the model for the shower evolution model + */ + ShowerModelPtr _model; + + /** + * Pointer to the splitting generator + */ + SplittingGeneratorPtr _splittingGenerator; + + /** + * Maximum number of tries to generate the shower of a particular tree + */ + unsigned int _maxtry; + + /** + * Matrix element correction switch + */ + unsigned int _meCorrMode; + + /** + * Control of the reconstruction option + */ + unsigned int _reconOpt; + + /** + * If hard veto pT scale is being read-in this determines + * whether the read-in value is applied to primary and + * secondary (MPI) scatters or just the primary one, with + * the usual computation of the veto being performed for + * the secondary (MPI) scatters. + */ + bool _hardVetoReadOption; + + /** + * rms intrinsic pT of Gaussian distribution + */ + Energy _iptrms; + + /** + * Proportion of inverse quadratic intrinsic pT distribution + */ + double _beta; + + /** + * Parameter for inverse quadratic: 2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT)) + */ + Energy _gamma; + + /** + * Upper bound on intrinsic pT for inverse quadratic + */ + Energy _iptmax; + + /** + * Limit the number of emissions for testing + */ + unsigned int _limitEmissions; + + /** + * The progenitor of the current shower + */ + ShowerProgenitorPtr _progenitor; + + /** + * Matrix element + */ + HwMEBasePtr _hardme; + + /** + * Decayer + */ + HwDecayerBasePtr _decayme; + + /** + * The ShowerTree currently being showered + */ + ShowerTreePtr _currenttree; + + /** + * The HardTree currently being showered + */ + HardTreePtr _hardtree; + + /** + * Radiation enhancement factors for use with the veto algorithm + * if needed by the soft matrix element correction + */ + //@{ + /** + * Enhancement factor for initial-state radiation + */ + double _initialenhance; + + /** + * Enhancement factor for final-state radiation + */ + double _finalenhance; + //@} + + /** + * The beam particle data for the current initial-state shower + */ + Ptr::const_pointer _beam; + + /** + * Storage of the intrinsic \f$p_t\f$ of the particles + */ + map > _intrinsic; + + /** + * Vetoes + */ + vector _vetoes; + + /** + * Full Shower Vetoes + */ + vector _fullShowerVetoes; + + /** + * Number of iterations for reweighting + */ + unsigned int _nReWeight; + + /** + * Whether or not we are reweighting + */ + bool _reWeight; + + /** + * number of IS emissions + */ + unsigned int _nis; + + /** + * Number of FS emissions + */ + unsigned int _nfs; + + /** + * The option for wqhich interactions to use + */ + ShowerInteraction::Type interaction_; + + /** + * Truncated shower switch + */ + bool _trunc_Mode; + + /** + * Count of the number of truncated emissions + */ + unsigned int _truncEmissions; + + /** + * Mode for the hard emissions + */ + int _hardEmission; + + /** + * Option to include spin correlations + */ + unsigned int _spinOpt; + + /** + * Option for the kernal for soft correlations + */ + unsigned int _softOpt; + + /** + * Option for hard radiation in POWHEG events + */ + bool _hardPOWHEG; + + /** + * True if no warnings about incorrect hard emission + * mode setting have been issued yet + */ + static bool _hardEmissionWarn; + + /** + * True if no warnings about missing truncated shower + * have been issued yet + */ + static bool _missingTruncWarn; + + /** + * The relevant hard scale to be used in the profile scales + */ + Energy muPt; + + /** + * Maximum number of emission attempts for FSR + */ + unsigned int _maxTryFSR; + + /** + * Maximum number of failures for FSR generation + */ + unsigned int _maxFailFSR; + + /** + * Failure fraction for FSR generation + */ + double _fracFSR; + + /** + * Counter for number of FSR emissions + */ + unsigned int _nFSR; + + /** + * Counter for the number of failed events due to FSR emissions + */ + unsigned int _nFailedFSR; + +}; + +} + +#endif /* Herwig_QTildeShowerHandler_H */ diff --git a/Shower/QTilde/ShowerConfig.cc b/Shower/QTilde/ShowerConfig.cc new file mode 100644 --- /dev/null +++ b/Shower/QTilde/ShowerConfig.cc @@ -0,0 +1,47 @@ +// -*- C++ -*- +// +// ShowerConfig.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 ShowerConfig class. +// +#include "ShowerConfig.h" +#include "QTilde/Base/SudakovFormFactor.h" + +using namespace Herwig; + +BranchingElement::~BranchingElement() {} + +BranchingElement::BranchingElement() {} + +BranchingElement::BranchingElement(SudakovPtr sud, IdList part) : sudakov(sud), particles(part) { + for(unsigned int ix=0;ixCC() ? tcPDPtr(part[ix]->CC()) : part[ix]); +} + +namespace ThePEG { + +/** + * Output operator to allow the structure + */ +PersistentOStream & operator << (PersistentOStream & os, + const Herwig::BranchingElement & x) { + os << x.sudakov << x.particles << x.conjugateParticles; + return os; +} + +/** + * Input operator to allow the structure + */ +PersistentIStream & operator >> (PersistentIStream & is, + Herwig::BranchingElement & x) { + is >> x.sudakov >> x.particles >> x.conjugateParticles; + return is; +} + +} diff --git a/Shower/ShowerConfig.h b/Shower/QTilde/ShowerConfig.h rename from Shower/ShowerConfig.h rename to Shower/QTilde/ShowerConfig.h --- a/Shower/ShowerConfig.h +++ b/Shower/QTilde/ShowerConfig.h @@ -1,156 +1,143 @@ // -*- C++ -*- // // ShowerConfig.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_ShowerConfig_H #define HERWIG_ShowerConfig_H // // This is the declaration of the ShowerConfig class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/PDT/ParticleData.h" -#include "Base/ShowerParticle.fh" -#include "Base/SudakovFormFactor.fh" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.fh" +#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.fh" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" +#include "ShowerInteraction.h" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * * Handy header file to be included in all Shower classes. * It contains only some useful typedefs. */ /** * Pointer to a ColourLine */ typedef Ptr::pointer ColinePtr; /** * Transient Pointer to a ColourLine */ typedef Ptr::transient_pointer tColinePtr; /** * A pair of ColourLine pointers */ typedef pair ColinePair; /** * A pair of transient ColourLine pointers */ typedef pair tColinePair; /** * A Vector of ShowerParticle pointers */ typedef vector ShowerParticleVector; /** * A Vector of transient ShowerParticle pointers */ typedef vector tShowerParticleVector; /** * Definition of the IdList for branchings */ typedef vector IdList; - - namespace ShowerInteraction { - /** - * Enum for the type of interaction - */ - enum Type { UNDEFINED=-1, QCD, QED, QEDQCD, EW, ALL }; - } - - namespace ShowerPartnerType { - /** - * Enum for the type of shower partner - */ - enum Type {Undefined,QCDColourLine,QCDAntiColourLine,QED,EW}; - } - + inline ShowerInteraction::Type convertInteraction(ShowerPartnerType::Type partner) { if(partner==ShowerPartnerType::QCDColourLine || partner==ShowerPartnerType::QCDAntiColourLine) return ShowerInteraction::QCD; else if(ShowerPartnerType::QED) return ShowerInteraction::QED; else if(ShowerPartnerType::EW) return ShowerInteraction::EW; else return ShowerInteraction::UNDEFINED; } /** * typedef to pair the SudakovFormFactor and the particles in a branching */ struct BranchingElement { /** * Constructor */ BranchingElement(); /** * Constructor */ BranchingElement(SudakovPtr sud, IdList part); /** * Destructor */ ~BranchingElement(); /** * Access to the Sudakov */ SudakovPtr sudakov; /** * Access to the particles */ IdList particles; /** * Access to the charge conjugate particles */ IdList conjugateParticles; }; /** * typedef to pair the PDG code of the particle and the BranchingElement */ typedef multimap BranchingList; /** * typedef to create a structure which can be inserted into a BranchingList */ typedef pair BranchingInsert; } namespace ThePEG { /** * Output operator to allow the structure */ PersistentOStream & operator << (PersistentOStream & os, const Herwig::BranchingElement & x); /** * Input operator to allow the structure */ PersistentIStream & operator >> (PersistentIStream & is, Herwig::BranchingElement & x); } #endif // HERWIG_ShowerConfig_H diff --git a/Shower/QTilde/ShowerInteraction.h b/Shower/QTilde/ShowerInteraction.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/ShowerInteraction.h @@ -0,0 +1,36 @@ +// -*- C++ -*- +// +// ShowerInteraction.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_ShowerInteraction_H +#define HERWIG_ShowerInteraction_H + +namespace Herwig { + +/** \ingroup Shower + * + * Handy header file to be included in all Shower classes. + * It contains only some useful enums. + */ + + namespace ShowerInteraction { + + /** + * Enum for the type of interaction + */ + enum Type { UNDEFINED=-1, QCD, QED, QEDQCD, EW, ALL }; + } + + namespace ShowerPartnerType { + /** + * Enum for the type of shower partner + */ + enum Type {Undefined,QCDColourLine,QCDAntiColourLine,QED,EW}; + } + +} +#endif // HERWIG_ShowerInteraction_H diff --git a/Shower/SplittingFunctions/HalfHalfOneEWSplitFn.cc b/Shower/QTilde/SplittingFunctions/HalfHalfOneEWSplitFn.cc rename from Shower/SplittingFunctions/HalfHalfOneEWSplitFn.cc rename to Shower/QTilde/SplittingFunctions/HalfHalfOneEWSplitFn.cc diff --git a/Shower/SplittingFunctions/HalfHalfOneEWSplitFn.h b/Shower/QTilde/SplittingFunctions/HalfHalfOneEWSplitFn.h rename from Shower/SplittingFunctions/HalfHalfOneEWSplitFn.h rename to Shower/QTilde/SplittingFunctions/HalfHalfOneEWSplitFn.h --- a/Shower/SplittingFunctions/HalfHalfOneEWSplitFn.h +++ b/Shower/QTilde/SplittingFunctions/HalfHalfOneEWSplitFn.h @@ -1,217 +1,217 @@ // -*- C++ -*- #ifndef Herwig_HalfHalfOneEWSplitFn_H #define Herwig_HalfHalfOneEWSplitFn_H // // This is the declaration of the HalfHalfOneEWSplitFn class. // -#include "Herwig/Shower/SplittingFunctions/SplittingFunction.h" +#include "SplittingFunction.h" namespace Herwig { using namespace ThePEG; /** * The HalfHalfOneEWSplitFn class implements the splitting function for * \f$\frac12\to q\frac12 1\f$ where the spin-1 particle is a massive electroweak gauge boson. * * @see \ref HalfHalfOneEWSplitFnInterfaces "The interfaces" * defined for HalfHalfOneEWSplitFn. */ class HalfHalfOneEWSplitFn: public SplittingFunction { public: /** * The default constructor. */ HalfHalfOneEWSplitFn() : SplittingFunction(1) {} /** * Concrete implementation of the method to determine whether this splitting * function can be used for a given set of particles. * @param ids The PDG codes for the particles in the splitting. */ virtual bool accept(const IdList & ids) const; /** * Methods to return the splitting function. */ //@{ /** * The concrete implementation of the splitting function, \f$P(z,t)\f$. * @param z The energy fraction. * @param t The scale. * @param ids The PDG codes for the particles in the splitting. * @param mass Whether or not to include the mass dependent terms * @param rho The spin density matrix */ virtual double P(const double z, const Energy2 t, const IdList & ids, const bool mass, const RhoDMatrix & rho) const; /** * The concrete implementation of the overestimate of the splitting function, * \f$P_{\rm over}\f$. * @param z The energy fraction. * @param ids The PDG codes for the particles in the splitting. */ virtual double overestimateP(const double z, const IdList & ids) const; /** * The concrete implementation of the * the ratio of the splitting function to the overestimate, i.e. * \f$P(z,t)/P_{\rm over}(z)\f$. * @param z The energy fraction. * @param t The scale. * @param ids The PDG codes for the particles in the splitting. * @param mass Whether or not to include the mass dependent terms * @param rho The spin density matrix */ virtual double ratioP(const double z, const Energy2 t, const IdList & ids, const bool mass, const RhoDMatrix & rho) const; /** * The concrete implementation of the indefinite integral of the * overestimated splitting function, \f$P_{\rm over}\f$. * @param z The energy fraction. * @param ids The PDG codes for the particles in the splitting. * @param PDFfactor Which additional factor to include for the PDF * 0 is no additional factor, * 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$ */ virtual double integOverP(const double z, const IdList & ids, unsigned int PDFfactor=0) const; /** * The concrete implementation of the inverse of the indefinite integral. * @param r Value of the splitting function to be inverted * @param ids The PDG codes for the particles in the splitting. * @param PDFfactor Which additional factor to include for the PDF * 0 is no additional factor, * 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$ */ virtual double invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor=0) const; //@} /** * Method to calculate the azimuthal angle * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param The azimuthal angle, \f$\phi\f$. * @return The weight */ virtual vector > generatePhiForward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix &); /** * Method to calculate the azimuthal angle for backward evolution * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param The azimuthal angle, \f$\phi\f$. * @return The weight */ virtual vector > generatePhiBackward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix &); /** * Calculate the matrix element for the splitting * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param The azimuthal angle, \f$\phi\f$. */ virtual DecayMEPtr matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool timeLike); protected: /** * Get the couplings */ void getCouplings(double & gL, double & gR, const IdList & ids) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HalfHalfOneEWSplitFn & operator=(const HalfHalfOneEWSplitFn &); private: /** * Z couplings */ map > gZ_; /** * W couplings */ double gWL_; }; } #endif /* Herwig_HalfHalfOneEWSplitFn_H */ diff --git a/Shower/SplittingFunctions/HalfHalfOneSplitFn.cc b/Shower/QTilde/SplittingFunctions/HalfHalfOneSplitFn.cc rename from Shower/SplittingFunctions/HalfHalfOneSplitFn.cc rename to Shower/QTilde/SplittingFunctions/HalfHalfOneSplitFn.cc diff --git a/Shower/SplittingFunctions/HalfHalfOneSplitFn.h b/Shower/QTilde/SplittingFunctions/HalfHalfOneSplitFn.h rename from Shower/SplittingFunctions/HalfHalfOneSplitFn.h rename to Shower/QTilde/SplittingFunctions/HalfHalfOneSplitFn.h diff --git a/Shower/SplittingFunctions/HalfOneHalfSplitFn.cc b/Shower/QTilde/SplittingFunctions/HalfOneHalfSplitFn.cc rename from Shower/SplittingFunctions/HalfOneHalfSplitFn.cc rename to Shower/QTilde/SplittingFunctions/HalfOneHalfSplitFn.cc diff --git a/Shower/SplittingFunctions/HalfOneHalfSplitFn.h b/Shower/QTilde/SplittingFunctions/HalfOneHalfSplitFn.h rename from Shower/SplittingFunctions/HalfOneHalfSplitFn.h rename to Shower/QTilde/SplittingFunctions/HalfOneHalfSplitFn.h diff --git a/Shower/SplittingFunctions/OneHalfHalfSplitFn.cc b/Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.cc rename from Shower/SplittingFunctions/OneHalfHalfSplitFn.cc rename to Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.cc --- a/Shower/SplittingFunctions/OneHalfHalfSplitFn.cc +++ b/Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.cc @@ -1,142 +1,142 @@ // -*- C++ -*- // // OneHalfHalfSplitFn.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 OneHalfHalfSplitFn class. // #include "OneHalfHalfSplitFn.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/Decay/TwoBodyDecayMatrixElement.h" using namespace Herwig; DescribeNoPIOClass describeOneHalfHalfSplitFn ("Herwig::OneHalfHalfSplitFn","HwShower.so"); void OneHalfHalfSplitFn::Init() { static ClassDocumentation documentation ("The OneHalfHalfSplitFn class implements the splitting function for g->q qbar"); } double OneHalfHalfSplitFn::P(const double z, const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix &) const { double zz = z*(1.-z); double val=1.-2.*zz; if(mass) { Energy m = ids[1]->mass(); val +=2.*sqr(m)/t; } return colourFactor(ids)*val; } double OneHalfHalfSplitFn::overestimateP(const double, const IdList &ids) const { return colourFactor(ids); } -double OneHalfHalfSplitFn::ratioP(const double z, const Energy2 t, +double OneHalfHalfSplitFn::ratioP(const double z, const Energy2 t, const IdList &ids, const bool mass, const RhoDMatrix &) const { double zz = z*(1.-z); double val = 1.-2.*zz; if(mass) { Energy m = ids[1]->mass(); val+= 2.*sqr(m)/t; } return val; } double OneHalfHalfSplitFn::integOverP(const double z, const IdList & ids, unsigned int PDFfactor) const { switch(PDFfactor) { case 0: return colourFactor(ids)*z; case 1: return colourFactor(ids)*log(z); case 2: return -colourFactor(ids)*log(1.-z); case 3: return colourFactor(ids)*log(z/(1.-z)); default: throw Exception() << "OneHalfHalfSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } double OneHalfHalfSplitFn::invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor) const { switch(PDFfactor) { case 0: return r/colourFactor(ids); case 1: return exp(r/colourFactor(ids)); case 2: return 1.-exp(-r/colourFactor(ids)); case 3: return 1./(1.+exp(-r/colourFactor(ids))); default: throw Exception() << "OneHalfHalfSplitFn::integOverP() invalid PDFfactor = " << PDFfactor << Exception::runerror; } } bool OneHalfHalfSplitFn::accept(const IdList &ids) const { if(ids.size()!=3) return false; if(ids[1]!=ids[2]->CC()) return false; if(ids[1]->iSpin()!=PDT::Spin1Half) return false; if(ids[0]->iSpin()!=PDT::Spin1) return false; return checkColours(ids); } vector > OneHalfHalfSplitFn::generatePhiForward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix & rho) { assert(rho.iSpin()==PDT::Spin1); double modRho = abs(rho(0,2)); Energy mq = ids[1]->mass(); Energy2 mq2 = sqr(mq); double fact = z*(1.-z)-mq2/t; double max = 1.+2.*fact*(-1.+2.*modRho); vector > output; output.push_back(make_pair( 0,(rho(0,0)+rho(2,2))*(1.-2.*fact)/max)); output.push_back(make_pair(-2,2.*fact*rho(0,2)/max)); output.push_back(make_pair( 2,2.*fact*rho(2,0)/max)); return output; } vector > OneHalfHalfSplitFn::generatePhiBackward(const double, const Energy2, const IdList &, const RhoDMatrix & ) { // no dependance return vector >(1,make_pair(0,1.)); } DecayMEPtr OneHalfHalfSplitFn::matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool timeLike) { static const Complex ii(0.,1.); // calculate the kernal DecayMEPtr kernal(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half))); double mt = !timeLike ? ZERO : ids[1]->mass()/sqrt(t); double root =sqrt(1.-sqr(mt)/z/(1.-z)); (*kernal)(0,0,0) = mt/sqrt(z*(1.-z)); (*kernal)(2,1,1) = (*kernal)(0,0,0); (*kernal)(0,0,1) = -z*root*exp(-ii*phi); (*kernal)(2,1,0) = -conj((*kernal)(0,0,1)); (*kernal)(0,1,0) = (1.-z)*exp(-ii*phi)*root; (*kernal)(2,0,1) = -conj((*kernal)(0,1,0)); (*kernal)(0,1,1) = 0.; (*kernal)(2,0,0) = 0.; return kernal; } diff --git a/Shower/SplittingFunctions/OneHalfHalfSplitFn.h b/Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.h rename from Shower/SplittingFunctions/OneHalfHalfSplitFn.h rename to Shower/QTilde/SplittingFunctions/OneHalfHalfSplitFn.h diff --git a/Shower/SplittingFunctions/OneOneOneSplitFn.cc b/Shower/QTilde/SplittingFunctions/OneOneOneSplitFn.cc rename from Shower/SplittingFunctions/OneOneOneSplitFn.cc rename to Shower/QTilde/SplittingFunctions/OneOneOneSplitFn.cc diff --git a/Shower/SplittingFunctions/OneOneOneSplitFn.h b/Shower/QTilde/SplittingFunctions/OneOneOneSplitFn.h rename from Shower/SplittingFunctions/OneOneOneSplitFn.h rename to Shower/QTilde/SplittingFunctions/OneOneOneSplitFn.h diff --git a/Shower/SplittingFunctions/SplittingFunction.cc b/Shower/QTilde/SplittingFunctions/SplittingFunction.cc rename from Shower/SplittingFunctions/SplittingFunction.cc rename to Shower/QTilde/SplittingFunctions/SplittingFunction.cc --- a/Shower/SplittingFunctions/SplittingFunction.cc +++ b/Shower/QTilde/SplittingFunctions/SplittingFunction.cc @@ -1,1025 +1,1025 @@ // -*- C++ -*- // // SplittingFunction.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 SplittingFunction class. // #include "SplittingFunction.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/EnumIO.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; DescribeAbstractClass describeSplittingFunction ("Herwig::SplittingFunction",""); void SplittingFunction::Init() { static ClassDocumentation documentation ("The SplittingFunction class is the based class for 1->2 splitting functions" " in Herwig"); static Switch interfaceColourStructure ("ColourStructure", "The colour structure for the splitting function", &SplittingFunction::_colourStructure, Undefined, false, false); static SwitchOption interfaceColourStructureTripletTripletOctet (interfaceColourStructure, "TripletTripletOctet", "3 -> 3 8", TripletTripletOctet); static SwitchOption interfaceColourStructureOctetOctetOctet (interfaceColourStructure, "OctetOctetOctet", "8 -> 8 8", OctetOctetOctet); static SwitchOption interfaceColourStructureOctetTripletTriplet (interfaceColourStructure, "OctetTripletTriplet", "8 -> 3 3bar", OctetTripletTriplet); static SwitchOption interfaceColourStructureTripletOctetTriplet (interfaceColourStructure, "TripletOctetTriplet", "3 -> 8 3", TripletOctetTriplet); static SwitchOption interfaceColourStructureSextetSextetOctet (interfaceColourStructure, "SextetSextetOctet", "6 -> 6 8", SextetSextetOctet); static SwitchOption interfaceColourStructureChargedChargedNeutral (interfaceColourStructure, "ChargedChargedNeutral", "q -> q 0", ChargedChargedNeutral); static SwitchOption interfaceColourStructureNeutralChargedCharged (interfaceColourStructure, "NeutralChargedCharged", "0 -> q qbar", NeutralChargedCharged); static SwitchOption interfaceColourStructureChargedNeutralCharged (interfaceColourStructure, "ChargedNeutralCharged", "q -> 0 q", ChargedNeutralCharged); static SwitchOption interfaceColourStructureEW (interfaceColourStructure, "EW", "q -> q W/Z", EW); static Switch interfaceInteractionType ("InteractionType", "Type of the interaction", &SplittingFunction::_interactionType, ShowerInteraction::UNDEFINED, false, false); static SwitchOption interfaceInteractionTypeQCD (interfaceInteractionType, "QCD","QCD",ShowerInteraction::QCD); static SwitchOption interfaceInteractionTypeQED (interfaceInteractionType, "QED","QED",ShowerInteraction::QED); static SwitchOption interfaceInteractionTypeEW (interfaceInteractionType, "EW","EW",ShowerInteraction::EW); static Switch interfaceAngularOrdered ("AngularOrdered", "Whether or not this interaction is angular ordered, " "normally only g->q qbar and gamma-> f fbar are the only ones which aren't.", &SplittingFunction::angularOrdered_, true, false, false); static SwitchOption interfaceAngularOrderedYes (interfaceAngularOrdered, "Yes", "Interaction is angular ordered", true); static SwitchOption interfaceAngularOrderedNo (interfaceAngularOrdered, "No", "Interaction isn't angular ordered", false); } void SplittingFunction::persistentOutput(PersistentOStream & os) const { using namespace ShowerInteraction; os << oenum(_interactionType) << _interactionOrder << oenum(_colourStructure) << _colourFactor << angularOrdered_; } void SplittingFunction::persistentInput(PersistentIStream & is, int) { using namespace ShowerInteraction; is >> ienum(_interactionType) >> _interactionOrder >> ienum(_colourStructure) >> _colourFactor >> angularOrdered_; } void SplittingFunction::colourConnection(tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second, ShowerPartnerType::Type partnerType, const bool back) const { if(_colourStructure==TripletTripletOctet) { if(!back) { ColinePair cparent = ColinePair(parent->colourLine(), parent->antiColourLine()); // ensure input consistency assert(( cparent.first && !cparent.second && partnerType==ShowerPartnerType::QCDColourLine) || ( !cparent.first && cparent.second && partnerType==ShowerPartnerType::QCDAntiColourLine)); // q -> q g if(cparent.first) { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addColoured(second); newline->addColoured ( first); newline->addAntiColoured (second); } // qbar -> qbar g else { ColinePtr newline=new_ptr(ColourLine()); cparent.second->addAntiColoured(second); newline->addColoured(second); newline->addAntiColoured(first); } // Set progenitor first->progenitor(parent->progenitor()); second->progenitor(parent->progenitor()); } else { ColinePair cfirst = ColinePair(first->colourLine(), first->antiColourLine()); // ensure input consistency assert(( cfirst.first && !cfirst.second && partnerType==ShowerPartnerType::QCDColourLine) || ( !cfirst.first && cfirst.second && partnerType==ShowerPartnerType::QCDAntiColourLine)); // q -> q g if(cfirst.first) { ColinePtr newline=new_ptr(ColourLine()); cfirst.first->addAntiColoured(second); newline->addColoured(second); newline->addColoured(parent); } // qbar -> qbar g else { ColinePtr newline=new_ptr(ColourLine()); cfirst.second->addColoured(second); newline->addAntiColoured(second); newline->addAntiColoured(parent); } // Set progenitor parent->progenitor(first->progenitor()); second->progenitor(first->progenitor()); } } else if(_colourStructure==OctetOctetOctet) { if(!back) { ColinePair cparent = ColinePair(parent->colourLine(), parent->antiColourLine()); // ensure input consistency assert(cparent.first&&cparent.second); // ensure first gluon is hardest if( first->id()==second->id() && parent->showerKinematics()->z()<0.5 ) swap(first,second); // colour line radiates if(partnerType==ShowerPartnerType::QCDColourLine) { // The colour line is radiating ColinePtr newline=new_ptr(ColourLine()); cparent.first->addColoured(second); cparent.second->addAntiColoured(first); newline->addColoured(first); newline->addAntiColoured(second); } // anti colour line radiates else if(partnerType==ShowerPartnerType::QCDAntiColourLine) { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addColoured(first); cparent.second->addAntiColoured(second); newline->addColoured(second); newline->addAntiColoured(first); } else assert(false); } else { ColinePair cfirst = ColinePair(first->colourLine(), first->antiColourLine()); // ensure input consistency assert(cfirst.first&&cfirst.second); // The colour line is radiating if(partnerType==ShowerPartnerType::QCDColourLine) { ColinePtr newline=new_ptr(ColourLine()); cfirst.first->addAntiColoured(second); cfirst.second->addAntiColoured(parent); newline->addColoured(parent); newline->addColoured(second); } // anti colour line radiates else if(partnerType==ShowerPartnerType::QCDAntiColourLine) { ColinePtr newline=new_ptr(ColourLine()); cfirst.first->addColoured(parent); cfirst.second->addColoured(second); newline->addAntiColoured(second); newline->addAntiColoured(parent); } else assert(false); } } else if(_colourStructure == OctetTripletTriplet) { if(!back) { ColinePair cparent = ColinePair(parent->colourLine(), parent->antiColourLine()); // ensure input consistency assert(cparent.first&&cparent.second); cparent.first ->addColoured ( first); cparent.second->addAntiColoured(second); // Set progenitor first->progenitor(parent->progenitor()); second->progenitor(parent->progenitor()); } else { ColinePair cfirst = ColinePair(first->colourLine(), first->antiColourLine()); // ensure input consistency assert(( cfirst.first && !cfirst.second) || (!cfirst.first && cfirst.second)); // g -> q qbar if(cfirst.first) { ColinePtr newline=new_ptr(ColourLine()); cfirst.first->addColoured(parent); newline->addAntiColoured(second); newline->addAntiColoured(parent); } // g -> qbar q else { ColinePtr newline=new_ptr(ColourLine()); cfirst.second->addAntiColoured(parent); newline->addColoured(second); newline->addColoured(parent); } // Set progenitor parent->progenitor(first->progenitor()); second->progenitor(first->progenitor()); } } else if(_colourStructure == TripletOctetTriplet) { if(!back) { ColinePair cparent = ColinePair(parent->colourLine(), parent->antiColourLine()); // ensure input consistency assert(( cparent.first && !cparent.second) || (!cparent.first && cparent.second)); // q -> g q if(cparent.first) { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addColoured(first); newline->addColoured (second); newline->addAntiColoured( first); } // qbar -> g qbar else { ColinePtr newline=new_ptr(ColourLine()); cparent.second->addAntiColoured(first); newline->addColoured ( first); newline->addAntiColoured(second); } // Set progenitor first->progenitor(parent->progenitor()); second->progenitor(parent->progenitor()); } else { ColinePair cfirst = ColinePair(first->colourLine(), first->antiColourLine()); // ensure input consistency assert(cfirst.first&&cfirst.second); // q -> g q if(parent->id()>0) { cfirst.first ->addColoured(parent); cfirst.second->addColoured(second); } else { cfirst.first ->addAntiColoured(second); cfirst.second->addAntiColoured(parent); } // Set progenitor parent->progenitor(first->progenitor()); second->progenitor(first->progenitor()); } } else if(_colourStructure==SextetSextetOctet) { //make sure we're not doing backward evolution assert(!back); //make sure something sensible assert(parent->colourLine() || parent->antiColourLine()); //get the colour lines or anti-colour lines bool isAntiColour=true; ColinePair cparent; if(parent->colourLine()) { cparent = ColinePair(const_ptr_cast(parent->colourInfo()->colourLines()[0]), const_ptr_cast(parent->colourInfo()->colourLines()[1])); isAntiColour=false; } else { cparent = ColinePair(const_ptr_cast(parent->colourInfo()->antiColourLines()[0]), const_ptr_cast(parent->colourInfo()->antiColourLines()[1])); } //check for sensible input // assert(cparent.first && cparent.second); // sextet has 2 colour lines if(!isAntiColour) { //pick at random which of the colour topolgies to take double topology = UseRandom::rnd(); if(topology < 0.25) { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addColoured(second); cparent.second->addColoured(first); newline->addColoured(first); newline->addAntiColoured(second); } else if(topology >=0.25 && topology < 0.5) { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addColoured(first); cparent.second->addColoured(second); newline->addColoured(first); newline->addAntiColoured(second); } else if(topology >= 0.5 && topology < 0.75) { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addColoured(second); cparent.second->addColoured(first); newline->addColoured(first); newline->addAntiColoured(second); } else { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addColoured(first); cparent.second->addColoured(second); newline->addColoured(first); newline->addAntiColoured(second); } } // sextet has 2 anti-colour lines else { double topology = UseRandom::rnd(); if(topology < 0.25){ ColinePtr newline=new_ptr(ColourLine()); cparent.first->addAntiColoured(second); cparent.second->addAntiColoured(first); newline->addAntiColoured(first); newline->addColoured(second); } else if(topology >=0.25 && topology < 0.5) { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addAntiColoured(first); cparent.second->addAntiColoured(second); newline->addAntiColoured(first); newline->addColoured(second); } else if(topology >= 0.5 && topology < 0.75) { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addAntiColoured(second); cparent.second->addAntiColoured(first); newline->addAntiColoured(first); newline->addColoured(second); } else { ColinePtr newline=new_ptr(ColourLine()); cparent.first->addAntiColoured(first); cparent.second->addAntiColoured(second); newline->addAntiColoured(first); newline->addColoured(second); } } } else if(_colourStructure == ChargedChargedNeutral) { if(!parent->data().coloured()) return; if(!back) { ColinePair cparent = ColinePair(parent->colourLine(), parent->antiColourLine()); // q -> q g if(cparent.first) { cparent.first->addColoured(first); } // qbar -> qbar g if(cparent.second) { cparent.second->addAntiColoured(first); } } else { ColinePair cfirst = ColinePair(first->colourLine(), first->antiColourLine()); // q -> q g if(cfirst.first) { cfirst.first->addColoured(parent); } // qbar -> qbar g if(cfirst.second) { cfirst.second->addAntiColoured(parent); } } } else if(_colourStructure == ChargedNeutralCharged) { if(!parent->data().coloured()) return; if(!back) { ColinePair cparent = ColinePair(parent->colourLine(), parent->antiColourLine()); // q -> q g if(cparent.first) { cparent.first->addColoured(second); } // qbar -> qbar g if(cparent.second) { cparent.second->addAntiColoured(second); } } else { if (second->dataPtr()->iColour()==PDT::Colour3 ) { ColinePtr newline=new_ptr(ColourLine()); newline->addColoured(second); newline->addColoured(parent); } else if (second->dataPtr()->iColour()==PDT::Colour3bar ) { ColinePtr newline=new_ptr(ColourLine()); newline->addAntiColoured(second); newline->addAntiColoured(parent); } } } else if(_colourStructure == NeutralChargedCharged ) { if(!back) { if(first->dataPtr()->coloured()) { ColinePtr newline=new_ptr(ColourLine()); if(first->dataPtr()->iColour()==PDT::Colour3) { newline->addColoured (first ); newline->addAntiColoured(second); } else if (first->dataPtr()->iColour()==PDT::Colour3bar) { newline->addColoured (second); newline->addAntiColoured(first ); } else assert(false); } } else { ColinePair cfirst = ColinePair(first->colourLine(), first->antiColourLine()); // gamma -> q qbar if(cfirst.first) { cfirst.first->addAntiColoured(second); } // gamma -> qbar q else if(cfirst.second) { cfirst.second->addColoured(second); } else assert(false); } } else if(_colourStructure == EW) { if(!parent->data().coloured()) return; if(!back) { ColinePair cparent = ColinePair(parent->colourLine(), parent->antiColourLine()); // q -> q g if(cparent.first) { cparent.first->addColoured(first); } // qbar -> qbar g if(cparent.second) { cparent.second->addAntiColoured(first); } } else { ColinePair cfirst = ColinePair(first->colourLine(), first->antiColourLine()); // q -> q g if(cfirst.first) { cfirst.first->addColoured(parent); } // qbar -> qbar g if(cfirst.second) { cfirst.second->addAntiColoured(parent); } } } else { assert(false); } } void SplittingFunction::doinit() { Interfaced::doinit(); assert(_interactionType!=ShowerInteraction::UNDEFINED); assert((_colourStructure>0&&_interactionType==ShowerInteraction::QCD) || (_colourStructure<0&&(_interactionType==ShowerInteraction::QED || _interactionType==ShowerInteraction::EW)) ); if(_colourFactor>0.) return; // compute the colour factors if need if(_colourStructure==TripletTripletOctet) { _colourFactor = 4./3.; } else if(_colourStructure==OctetOctetOctet) { _colourFactor = 3.; } else if(_colourStructure==OctetTripletTriplet) { _colourFactor = 0.5; } else if(_colourStructure==TripletOctetTriplet) { _colourFactor = 4./3.; } else if(_colourStructure==SextetSextetOctet) { _colourFactor = 10./3.; } else if(_colourStructure<0) { _colourFactor = 1.; } else { assert(false); } } bool SplittingFunction::checkColours(const IdList & ids) const { if(_colourStructure==TripletTripletOctet) { if(ids[0]!=ids[1]) return false; if((ids[0]->iColour()==PDT::Colour3||ids[0]->iColour()==PDT::Colour3bar) && ids[2]->iColour()==PDT::Colour8) return true; return false; } else if(_colourStructure==OctetOctetOctet) { for(unsigned int ix=0;ix<3;++ix) { if(ids[ix]->iColour()!=PDT::Colour8) return false; } return true; } else if(_colourStructure==OctetTripletTriplet) { if(ids[0]->iColour()!=PDT::Colour8) return false; if(ids[1]->iColour()==PDT::Colour3&&ids[2]->iColour()==PDT::Colour3bar) return true; if(ids[1]->iColour()==PDT::Colour3bar&&ids[2]->iColour()==PDT::Colour3) return true; return false; } else if(_colourStructure==TripletOctetTriplet) { if(ids[0]!=ids[2]) return false; if((ids[0]->iColour()==PDT::Colour3||ids[0]->iColour()==PDT::Colour3bar) && ids[1]->iColour()==PDT::Colour8) return true; return false; } else if(_colourStructure==SextetSextetOctet) { if(ids[0]!=ids[1]) return false; if((ids[0]->iColour()==PDT::Colour6 || ids[0]->iColour()==PDT::Colour6bar) && ids[2]->iColour()==PDT::Colour8) return true; return false; } else if(_colourStructure==ChargedChargedNeutral) { if(ids[0]!=ids[1]) return false; if(ids[2]->iCharge()!=0) return false; if(ids[0]->iCharge()==ids[1]->iCharge()) return true; return false; } else if(_colourStructure==ChargedNeutralCharged) { if(ids[0]!=ids[2]) return false; if(ids[1]->iCharge()!=0) return false; if(ids[0]->iCharge()==ids[2]->iCharge()) return true; return false; } else if(_colourStructure==NeutralChargedCharged) { if(ids[1]->id()!=-ids[2]->id()) return false; if(ids[0]->iCharge()!=0) return false; if(ids[1]->iCharge()==-ids[2]->iCharge()) return true; return false; } else { assert(false); } return false; } namespace { bool hasColour(tPPtr p) { PDT::Colour colour = p->dataPtr()->iColour(); return colour==PDT::Colour3 || colour==PDT::Colour8 || colour == PDT::Colour6; } bool hasAntiColour(tPPtr p) { PDT::Colour colour = p->dataPtr()->iColour(); return colour==PDT::Colour3bar || colour==PDT::Colour8 || colour == PDT::Colour6bar; } } void SplittingFunction::evaluateFinalStateScales(ShowerPartnerType::Type partnerType, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr emitter, tShowerParticlePtr emitted) { // identify emitter and emitted double zEmitter = z, zEmitted = 1.-z; bool bosonSplitting(false); // special for g -> gg, particle highest z is emitter if(emitter->id() == emitted->id() && emitter->id() == parent->id() && zEmitted > zEmitter) { swap(zEmitted,zEmitter); swap( emitted, emitter); } // otherwise if particle ID same else if(emitted->id()==parent->id()) { swap(zEmitted,zEmitter); swap( emitted, emitter); } // no real emitter/emitted else if(emitter->id()!=parent->id()) { bosonSplitting = true; } // may need to add angularOrder flag here // now the various scales // QED if(partnerType==ShowerPartnerType::QED) { assert(colourStructure()==ChargedChargedNeutral || colourStructure()==ChargedNeutralCharged || colourStructure()==NeutralChargedCharged ); // normal case if(!bosonSplitting) { assert(colourStructure()==ChargedChargedNeutral || colourStructure()==ChargedNeutralCharged ); // set the scales // emitter emitter->scales().QED = zEmitter*scale; emitter->scales().QED_noAO = scale; emitter->scales().QCD_c = min(scale,parent->scales().QCD_c ); emitter->scales().QCD_c_noAO = min(scale,parent->scales().QCD_c_noAO ); emitter->scales().QCD_ac = min(scale,parent->scales().QCD_ac ); emitter->scales().QCD_ac_noAO = min(scale,parent->scales().QCD_ac_noAO); emitter->scales().EW = min(scale,parent->scales().EW ); emitter->scales().EW_noAO = min(scale,parent->scales().EW_noAO ); // emitted emitted->scales().QED = zEmitted*scale; emitted->scales().QED_noAO = scale; emitted->scales().QCD_c = ZERO; emitted->scales().QCD_c_noAO = ZERO; emitted->scales().QCD_ac = ZERO; emitted->scales().QCD_ac_noAO = ZERO; emitted->scales().EW = min(scale,parent->scales().EW ); emitted->scales().EW_noAO = min(scale,parent->scales().EW_noAO ); } // gamma -> f fbar else { assert(colourStructure()==NeutralChargedCharged ); // emitter emitter->scales().QED = zEmitter*scale; emitter->scales().QED_noAO = scale; if(hasColour(emitter)) { emitter->scales().QCD_c = zEmitter*scale; emitter->scales().QCD_c_noAO = scale; } if(hasAntiColour(emitter)) { emitter->scales().QCD_ac = zEmitter*scale; emitter->scales().QCD_ac_noAO = scale; } emitter->scales().EW = zEmitter*scale; emitter->scales().EW_noAO = scale; // emitted emitted->scales().QED = zEmitted*scale; emitted->scales().QED_noAO = scale; if(hasColour(emitted)) { emitted->scales().QCD_c = zEmitted*scale; emitted->scales().QCD_c_noAO = scale; } if(hasAntiColour(emitted)) { emitted->scales().QCD_ac = zEmitted*scale; emitted->scales().QCD_ac_noAO = scale; } emitted->scales().EW = zEmitted*scale; emitted->scales().EW_noAO = scale; } } // QCD else if (partnerType==ShowerPartnerType::QCDColourLine || partnerType==ShowerPartnerType::QCDAntiColourLine) { // normal case eg q -> q g and g -> g g if(!bosonSplitting) { emitter->scales().QED = min(scale,parent->scales().QED ); emitter->scales().QED_noAO = min(scale,parent->scales().QED_noAO); emitter->scales().EW = min(scale,parent->scales().EW ); emitter->scales().EW_noAO = min(scale,parent->scales().EW_noAO); if(partnerType==ShowerPartnerType::QCDColourLine) { emitter->scales().QCD_c = zEmitter*scale; emitter->scales().QCD_c_noAO = scale; emitter->scales().QCD_ac = min(zEmitter*scale,parent->scales().QCD_ac ); emitter->scales().QCD_ac_noAO = min( scale,parent->scales().QCD_ac_noAO); } else { emitter->scales().QCD_c = min(zEmitter*scale,parent->scales().QCD_c ); emitter->scales().QCD_c_noAO = min( scale,parent->scales().QCD_c_noAO ); emitter->scales().QCD_ac = zEmitter*scale; emitter->scales().QCD_ac_noAO = scale; } // emitted emitted->scales().QED = ZERO; emitted->scales().QED_noAO = ZERO; emitted->scales().QCD_c = zEmitted*scale; emitted->scales().QCD_c_noAO = scale; emitted->scales().QCD_ac = zEmitted*scale; emitted->scales().QCD_ac_noAO = scale; emitted->scales().EW = min(scale,parent->scales().EW ); emitted->scales().EW_noAO = min(scale,parent->scales().EW_noAO); } // g -> q qbar else { // emitter if(emitter->dataPtr()->charged()) { emitter->scales().QED = zEmitter*scale; emitter->scales().QED_noAO = scale; } emitter->scales().EW = zEmitter*scale; emitter->scales().EW_noAO = scale; emitter->scales().QCD_c = zEmitter*scale; emitter->scales().QCD_c_noAO = scale; emitter->scales().QCD_ac = zEmitter*scale; emitter->scales().QCD_ac_noAO = scale; // emitted if(emitted->dataPtr()->charged()) { emitted->scales().QED = zEmitted*scale; emitted->scales().QED_noAO = scale; } emitted->scales().EW = zEmitted*scale; emitted->scales().EW_noAO = scale; emitted->scales().QCD_c = zEmitted*scale; emitted->scales().QCD_c_noAO = scale; emitted->scales().QCD_ac = zEmitted*scale; emitted->scales().QCD_ac_noAO = scale; } } else if(partnerType==ShowerPartnerType::EW) { // EW emitter->scales().EW = zEmitter*scale; emitter->scales().EW_noAO = scale; emitted->scales().EW = zEmitted*scale; emitted->scales().EW_noAO = scale; // QED // W radiation AO if(emitted->dataPtr()->charged()) { emitter->scales().QED = zEmitter*scale; emitter->scales().QED_noAO = scale; emitted->scales().QED = zEmitted*scale; emitted->scales().QED_noAO = scale; } // Z don't else { emitter->scales().QED = min(scale,parent->scales().QED ); emitter->scales().QED_noAO = min(scale,parent->scales().QED_noAO); emitted->scales().QED = ZERO; emitted->scales().QED_noAO = ZERO; } // QCD emitter->scales().QCD_c = min(scale,parent->scales().QCD_c ); emitter->scales().QCD_c_noAO = min(scale,parent->scales().QCD_c_noAO ); emitter->scales().QCD_ac = min(scale,parent->scales().QCD_ac ); emitter->scales().QCD_ac_noAO = min(scale,parent->scales().QCD_ac_noAO); emitted->scales().QCD_c = ZERO; emitted->scales().QCD_c_noAO = ZERO; emitted->scales().QCD_ac = ZERO; emitted->scales().QCD_ac_noAO = ZERO; } else assert(false); } void SplittingFunction::evaluateInitialStateScales(ShowerPartnerType::Type partnerType, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr spacelike, tShowerParticlePtr timelike) { // scale for time-like child Energy AOScale = (1.-z)*scale; // QED if(partnerType==ShowerPartnerType::QED) { if(parent->id()==spacelike->id()) { // parent parent ->scales().QED = scale; parent ->scales().QED_noAO = scale; parent ->scales().QCD_c = min(scale,spacelike->scales().QCD_c ); parent ->scales().QCD_c_noAO = min(scale,spacelike->scales().QCD_c_noAO ); parent ->scales().QCD_ac = min(scale,spacelike->scales().QCD_ac ); parent ->scales().QCD_ac_noAO = min(scale,spacelike->scales().QCD_ac_noAO); // timelike timelike->scales().QED = AOScale; timelike->scales().QED_noAO = scale; timelike->scales().QCD_c = ZERO; timelike->scales().QCD_c_noAO = ZERO; timelike->scales().QCD_ac = ZERO; timelike->scales().QCD_ac_noAO = ZERO; } else if(parent->id()==timelike->id()) { parent ->scales().QED = scale; parent ->scales().QED_noAO = scale; if(hasColour(parent)) { parent ->scales().QCD_c = scale; parent ->scales().QCD_c_noAO = scale; } if(hasAntiColour(parent)) { parent ->scales().QCD_ac = scale; parent ->scales().QCD_ac_noAO = scale; } // timelike timelike->scales().QED = AOScale; timelike->scales().QED_noAO = scale; if(hasColour(timelike)) { timelike->scales().QCD_c = AOScale; timelike->scales().QCD_c_noAO = scale; } if(hasAntiColour(timelike)) { timelike->scales().QCD_ac = AOScale; timelike->scales().QCD_ac_noAO = scale; } } else { parent ->scales().QED = scale; parent ->scales().QED_noAO = scale; parent ->scales().QCD_c = ZERO ; parent ->scales().QCD_c_noAO = ZERO ; parent ->scales().QCD_ac = ZERO ; parent ->scales().QCD_ac_noAO = ZERO ; // timelike timelike->scales().QED = AOScale; timelike->scales().QED_noAO = scale; if(hasColour(timelike)) { timelike->scales().QCD_c = min(AOScale,spacelike->scales().QCD_ac ); timelike->scales().QCD_c_noAO = min( scale,spacelike->scales().QCD_ac_noAO); } if(hasAntiColour(timelike)) { timelike->scales().QCD_ac = min(AOScale,spacelike->scales().QCD_c ); timelike->scales().QCD_ac_noAO = min( scale,spacelike->scales().QCD_c_noAO ); } } } // QCD else if (partnerType==ShowerPartnerType::QCDColourLine || partnerType==ShowerPartnerType::QCDAntiColourLine) { // timelike if(timelike->dataPtr()->charged()) { timelike->scales().QED = AOScale; timelike->scales().QED_noAO = scale; } if(hasColour(timelike)) { timelike->scales().QCD_c = AOScale; timelike->scales().QCD_c_noAO = scale; } if(hasAntiColour(timelike)) { timelike->scales().QCD_ac = AOScale; timelike->scales().QCD_ac_noAO = scale; } if(parent->id()==spacelike->id()) { parent ->scales().QED = min(scale,spacelike->scales().QED ); parent ->scales().QED_noAO = min(scale,spacelike->scales().QED_noAO ); parent ->scales().QCD_c = min(scale,spacelike->scales().QCD_c ); parent ->scales().QCD_c_noAO = min(scale,spacelike->scales().QCD_c_noAO ); parent ->scales().QCD_ac = min(scale,spacelike->scales().QCD_ac ); parent ->scales().QCD_ac_noAO = min(scale,spacelike->scales().QCD_ac_noAO); } else { if(parent->dataPtr()->charged()) { parent ->scales().QED = scale; parent ->scales().QED_noAO = scale; } if(hasColour(parent)) { parent ->scales().QCD_c = scale; parent ->scales().QCD_c_noAO = scale; } if(hasAntiColour(parent)) { parent ->scales().QCD_ac = scale; parent ->scales().QCD_ac_noAO = scale; } } } else if(partnerType==ShowerPartnerType::EW) { if(abs(spacelike->id())!=ParticleID::Wplus && spacelike->id() !=ParticleID::Z0 ) { // QCD scales parent ->scales().QCD_c = min(scale,spacelike->scales().QCD_c ); parent ->scales().QCD_c_noAO = min(scale,spacelike->scales().QCD_c_noAO ); parent ->scales().QCD_ac = min(scale,spacelike->scales().QCD_ac ); parent ->scales().QCD_ac_noAO = min(scale,spacelike->scales().QCD_ac_noAO); timelike->scales().QCD_c = ZERO; timelike->scales().QCD_c_noAO = ZERO; timelike->scales().QCD_ac = ZERO; timelike->scales().QCD_ac_noAO = ZERO; // QED scales if(timelike->id()==ParticleID::Z0) { parent ->scales().QED = min(scale,spacelike->scales().QED ); parent ->scales().QED_noAO = min(scale,spacelike->scales().QED_noAO ); timelike->scales().QED = ZERO; timelike->scales().QED_noAO = ZERO; } else { parent ->scales().QED = scale; parent ->scales().QED_noAO = scale; timelike->scales().QED = AOScale; timelike->scales().QED_noAO = scale; } // EW scales parent ->scales().EW = scale; parent ->scales().EW_noAO = scale; timelike->scales().EW = AOScale; timelike->scales().EW_noAO = scale; } else assert(false); } else assert(false); } void SplittingFunction::evaluateDecayScales(ShowerPartnerType::Type partnerType, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr spacelike, tShowerParticlePtr timelike) { assert(parent->id()==spacelike->id()); // angular-ordered scale for 2nd child Energy AOScale = (1.-z)*scale; // QED if(partnerType==ShowerPartnerType::QED) { // timelike timelike->scales().QED = AOScale; timelike->scales().QED_noAO = scale; timelike->scales().QCD_c = ZERO; timelike->scales().QCD_c_noAO = ZERO; timelike->scales().QCD_ac = ZERO; timelike->scales().QCD_ac_noAO = ZERO; timelike->scales().EW = ZERO; timelike->scales().EW_noAO = ZERO; // spacelike spacelike->scales().QED = scale; spacelike->scales().QED_noAO = scale; spacelike->scales().EW = max(scale,parent->scales().EW ); spacelike->scales().EW_noAO = max(scale,parent->scales().EW_noAO ); } // QCD else if(partnerType==ShowerPartnerType::QCDColourLine || partnerType==ShowerPartnerType::QCDAntiColourLine) { // timelike timelike->scales().QED = ZERO; timelike->scales().QED_noAO = ZERO; timelike->scales().QCD_c = AOScale; timelike->scales().QCD_c_noAO = scale; timelike->scales().QCD_ac = AOScale; timelike->scales().QCD_ac_noAO = scale; timelike->scales().EW = ZERO; timelike->scales().EW_noAO = ZERO; // spacelike spacelike->scales().QED = max(scale,parent->scales().QED ); spacelike->scales().QED_noAO = max(scale,parent->scales().QED_noAO ); spacelike->scales().EW = max(scale,parent->scales().EW ); spacelike->scales().EW_noAO = max(scale,parent->scales().EW_noAO ); } else if(partnerType==ShowerPartnerType::EW) { // EW timelike->scales().EW = AOScale; timelike->scales().EW_noAO = scale; spacelike->scales().EW = max(scale,parent->scales().EW ); spacelike->scales().EW_noAO = max(scale,parent->scales().EW_noAO ); // QCD timelike->scales().QCD_c = ZERO; timelike->scales().QCD_c_noAO = ZERO; timelike->scales().QCD_ac = ZERO; timelike->scales().QCD_ac_noAO = ZERO; timelike->scales().EW = ZERO; timelike->scales().EW_noAO = ZERO; // QED timelike->scales().QED = ZERO; timelike->scales().QED_noAO = ZERO; spacelike->scales().QED = max(scale,parent->scales().QED ); spacelike->scales().QED_noAO = max(scale,parent->scales().QED_noAO ); } else assert(false); spacelike->scales().QCD_c = max(scale,parent->scales().QCD_c ); spacelike->scales().QCD_c_noAO = max(scale,parent->scales().QCD_c_noAO ); spacelike->scales().QCD_ac = max(scale,parent->scales().QCD_ac ); spacelike->scales().QCD_ac_noAO = max(scale,parent->scales().QCD_ac_noAO); } diff --git a/Shower/SplittingFunctions/SplittingFunction.fh b/Shower/QTilde/SplittingFunctions/SplittingFunction.fh rename from Shower/SplittingFunctions/SplittingFunction.fh rename to Shower/QTilde/SplittingFunctions/SplittingFunction.fh diff --git a/Shower/SplittingFunctions/SplittingFunction.h b/Shower/QTilde/SplittingFunctions/SplittingFunction.h rename from Shower/SplittingFunctions/SplittingFunction.h rename to Shower/QTilde/SplittingFunctions/SplittingFunction.h --- a/Shower/SplittingFunctions/SplittingFunction.h +++ b/Shower/QTilde/SplittingFunctions/SplittingFunction.h @@ -1,377 +1,377 @@ // -*- C++ -*- // // SplittingFunction.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-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_SplittingFunction_H #define HERWIG_SplittingFunction_H // // This is the declaration of the SplittingFunction class. // #include "ThePEG/Interface/Interfaced.h" -#include "Herwig/Shower/ShowerConfig.h" +#include "Herwig/Shower/QTilde/ShowerConfig.h" #include "ThePEG/EventRecord/RhoDMatrix.h" #include "Herwig/Decay/DecayMatrixElement.h" -#include "Herwig/Shower/Base/ShowerKinematics.fh" +#include "Herwig/Shower/QTilde/Base/ShowerKinematics.fh" #include "ThePEG/EventRecord/ColourLine.h" #include "ThePEG/PDT/ParticleData.h" #include "SplittingFunction.fh" namespace Herwig { using namespace ThePEG; /** \ingroup Shower * Enum to define the possible types of colour structure which can occur in * the branching. */ enum ColourStructure {Undefined=0, TripletTripletOctet = 1,OctetOctetOctet =2, OctetTripletTriplet = 3,TripletOctetTriplet=4, SextetSextetOctet = 5, ChargedChargedNeutral=-1,ChargedNeutralCharged=-2, NeutralChargedCharged=-3,EW=-4}; /** \ingroup Shower * * This is an abstract class which defines the common interface * for all \f$1\to2\f$ splitting functions, for both initial-state * and final-state radiation. * * The SplittingFunction class contains a number of purely virtual members * which must be implemented in the inheriting classes. The class also stores * the interaction type of the spltting function. * * The inheriting classes need to specific the splitting function * \f$P(z,2p_j\cdot p_k)\f$, in terms of the energy fraction \f$z\f$ and * the evolution scale. In order to allow the splitting functions to be used * with different choices of evolution functions the scale is given by * \f[2p_j\cdot p_k=(p_j+p_k)^2-m_{jk}^2=Q^2-(p_j+p_k)^2=z(1-z)\tilde{q}^2= * \frac{p_T^2}{z(1-z)}-m_{jk}^2+\frac{m_j^2}{z}+\frac{m_k^2}{1-z},\f] * where \f$Q^2\f$ is the virtuality of the branching particle, * $p_T$ is the relative transverse momentum of the branching products and * \f$\tilde{q}^2\f$ is the angular variable described in hep-ph/0310083. * * In addition an overestimate of the * splitting function, \f$P_{\rm over}(z)\f$ which only depends upon \f$z\f$, * the integral, inverse of the integral for this overestimate and * ratio of the true splitting function to the overestimate must be provided * as they are necessary for the veto alogrithm used to implement the evolution. * * @see \ref SplittingFunctionInterfaces "The interfaces" * defined for SplittingFunction. */ class SplittingFunction: public Interfaced { public: /** * The default constructor. * @param b All splitting functions must have an interaction order */ SplittingFunction(unsigned int b) : Interfaced(), _interactionType(ShowerInteraction::UNDEFINED), _interactionOrder(b), _colourStructure(Undefined), _colourFactor(-1.), angularOrdered_(true) {} public: /** * Methods to return the interaction type and order for the splitting function */ //@{ /** * Return the type of the interaction */ ShowerInteraction::Type interactionType() const {return _interactionType;} /** * Return the order of the splitting function in the interaction */ unsigned int interactionOrder() const {return _interactionOrder;} /** * Return the colour structure */ ColourStructure colourStructure() const {return _colourStructure;} /** * Return the colour factor */ double colourFactor(const IdList &ids) const { if(_colourStructure>0) return _colourFactor; else if(_colourStructure<0) { if(_colourStructure==ChargedChargedNeutral || _colourStructure==ChargedNeutralCharged) { return sqr(double(ids[0]->iCharge())/3.); } else if(_colourStructure==NeutralChargedCharged) { return sqr(double(ids[1]->iCharge())/3.); } else if(_colourStructure==EW) { return 1.; } else assert(false); } else assert(false); } //@} /** * Purely virtual method which should determine whether this splitting * function can be used for a given set of particles. * @param ids The PDG codes for the particles in the splitting. */ virtual bool accept(const IdList & ids) const = 0; /** * Method to check the colours are correct */ virtual bool checkColours(const IdList & ids) const; /** * Methods to return the splitting function. */ //@{ /** * Purely virtual method which should return the exact value of the splitting function, * \f$P\f$ evaluated in terms of the energy fraction, \f$z\f$, and the evolution scale \f$\tilde{q}^2\f$. * @param z The energy fraction. * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param mass Whether or not to include the mass dependent terms * @param rho The spin density matrix */ virtual double P(const double z, const Energy2 t, const IdList & ids, const bool mass, const RhoDMatrix & rho) const = 0; /** * Purely virtual method which should return * an overestimate of the splitting function, * \f$P_{\rm over}\f$ such that the result \f$P_{\rm over}\geq P\f$. This function * should be simple enough that it does not depend on the evolution scale. * @param z The energy fraction. * @param ids The PDG codes for the particles in the splitting. */ virtual double overestimateP(const double z, const IdList & ids) const = 0; /** * Purely virtual method which should return * the ratio of the splitting function to the overestimate, i.e. * \f$P(z,\tilde{q}^2)/P_{\rm over}(z)\f$. * @param z The energy fraction. * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param mass Whether or not to include the mass dependent terms * @param rho The spin density matrix */ virtual double ratioP(const double z, const Energy2 t, const IdList & ids, const bool mass, const RhoDMatrix & rho) const = 0; /** * Purely virtual method which should return the indefinite integral of the * overestimated splitting function, \f$P_{\rm over}\f$. * @param z The energy fraction. * @param ids The PDG codes for the particles in the splitting. * @param PDFfactor Which additional factor to include for the PDF * 0 is no additional factor, * 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$ * */ virtual double integOverP(const double z, const IdList & ids, unsigned int PDFfactor=0) const = 0; /** * Purely virtual method which should return the inverse of the * indefinite integral of the * overestimated splitting function, \f$P_{\rm over}\f$ which is used to * generate the value of \f$z\f$. * @param r Value of the splitting function to be inverted * @param ids The PDG codes for the particles in the splitting. * @param PDFfactor Which additional factor to include for the PDF * 0 is no additional factor, * 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$ */ virtual double invIntegOverP(const double r, const IdList & ids, unsigned int PDFfactor=0) const = 0; //@} /** * Purely virtual method which should make the proper colour connection * between the emitting parent and the branching products. * @param parent The parent for the branching * @param first The first branching product * @param second The second branching product * @param partnerType The type of evolution partner * @param back Whether this is foward or backward evolution. */ virtual void colourConnection(tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second, ShowerPartnerType::Type partnerType, const bool back) const; /** * Method to calculate the azimuthal angle for forward evolution * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param The azimuthal angle, \f$\phi\f$. * @return The weight */ virtual vector > generatePhiForward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix &) = 0; /** * Method to calculate the azimuthal angle for backward evolution * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @return The weight */ virtual vector > generatePhiBackward(const double z, const Energy2 t, const IdList & ids, const RhoDMatrix &) = 0; /** * Calculate the matrix element for the splitting * @param z The energy fraction * @param t The scale \f$t=2p_j\cdot p_k\f$. * @param ids The PDG codes for the particles in the splitting. * @param phi The azimuthal angle, \f$\phi\f$. * @param timeLike Whether timelike or spacelike, affects inclusive of mass terms */ virtual DecayMEPtr matrixElement(const double z, const Energy2 t, const IdList & ids, const double phi, bool timeLike) = 0; /** * Whether or not the interaction is angular ordered */ bool angularOrdered() const {return angularOrdered_;} /** * Functions to state scales after branching happens */ //@{ /** * Sort out scales for final-state emission */ void evaluateFinalStateScales(ShowerPartnerType::Type type, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second); /** * Sort out scales for initial-state emission */ void evaluateInitialStateScales(ShowerPartnerType::Type type, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second); /** * Sort out scales for decay emission */ void evaluateDecayScales(ShowerPartnerType::Type type, Energy scale, double z, tShowerParticlePtr parent, tShowerParticlePtr first, tShowerParticlePtr second); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** * Set the colour factor */ void colourFactor(double in) {_colourFactor=in;} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SplittingFunction & operator=(const SplittingFunction &); private: /** * The interaction type for the splitting function. */ ShowerInteraction::Type _interactionType; /** * The order of the splitting function in the coupling */ unsigned int _interactionOrder; /** * The colour structure */ ColourStructure _colourStructure; /** * The colour factor */ double _colourFactor; /** * Whether or not this interaction is angular-ordered */ bool angularOrdered_; }; } #endif /* HERWIG_SplittingFunction_H */ diff --git a/Shower/SplittingFunctions/SplittingGenerator.cc b/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc rename from Shower/SplittingFunctions/SplittingGenerator.cc rename to Shower/QTilde/SplittingFunctions/SplittingGenerator.cc --- a/Shower/SplittingFunctions/SplittingGenerator.cc +++ b/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc @@ -1,651 +1,632 @@ // -*- C++ -*- // // SplittingGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2011 The Herwig Collaboration // // Herwig is licenced under version 2 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SplittingGenerator class. // #include "SplittingGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Repository/Repository.h" -#include "Herwig/Shower/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/ShowerHandler.h" #include "ThePEG/Utilities/Rebinder.h" #include #include "ThePEG/Utilities/DescribeClass.h" using namespace Herwig; namespace { bool checkInteraction(ShowerInteraction::Type allowed, ShowerInteraction::Type splitting) { if(allowed==ShowerInteraction::ALL) return true; else if(allowed==ShowerInteraction::QEDQCD && (splitting==ShowerInteraction::QED || splitting==ShowerInteraction::QCD )) return true; else if(allowed == splitting) return true; else return false; } } DescribeClass describeSplittingGenerator ("Herwig::SplittingGenerator",""); IBPtr SplittingGenerator::clone() const { return new_ptr(*this); } IBPtr SplittingGenerator::fullclone() const { return new_ptr(*this); } void SplittingGenerator::persistentOutput(PersistentOStream & os) const { - os << _isr_Mode << _fsr_Mode << _bbranchings << _fbranchings << _deTuning; + os << _bbranchings << _fbranchings << _deTuning; } void SplittingGenerator::persistentInput(PersistentIStream & is, int) { - is >> _isr_Mode >> _fsr_Mode >> _bbranchings >> _fbranchings >> _deTuning; + is >> _bbranchings >> _fbranchings >> _deTuning; } void SplittingGenerator::Init() { static ClassDocumentation documentation ("There class is responsible for initializing the Sudakov form factors ", "and generating splittings."); - static Switch interfaceISRMode - ("ISR", - "Include initial-state radiation?", - &SplittingGenerator::_isr_Mode, 1, false, false); - static SwitchOption interfaceISRMode0 - (interfaceISRMode,"No","ISR (Initial State Radiation) is OFF", 0); - static SwitchOption interfaceISRMode1 - (interfaceISRMode,"Yes","ISR (Initial State Radiation) is ON", 1); - - static Switch interfaceFSRMode - ("FSR", - "Include final-state radiation?", - &SplittingGenerator::_fsr_Mode, 1, false, false); - static SwitchOption interfaceFSRMode0 - (interfaceFSRMode,"No","FSR (Final State Radiation) is OFF", 0); - static SwitchOption interfaceFSRMode1 - (interfaceFSRMode,"Yes","FSR (Final State Radiation) is ON", 1); - static Command interfaceAddSplitting ("AddFinalSplitting", "Adds another splitting to the list of splittings considered " "in the shower. Command is a->b,c; Sudakov", &SplittingGenerator::addFinalSplitting); static Command interfaceAddInitialSplitting ("AddInitialSplitting", "Adds another splitting to the list of initial splittings to consider " "in the shower. Command is a->b,c; Sudakov. Here the particle a is the " "particle that is PRODUCED by the splitting. b is the initial state " "particle that is splitting in the shower.", &SplittingGenerator::addInitialSplitting); static Command interfaceDeleteSplitting ("DeleteFinalSplitting", "Deletes a splitting from the list of splittings considered " "in the shower. Command is a->b,c; Sudakov", &SplittingGenerator::deleteFinalSplitting); static Command interfaceDeleteInitialSplitting ("DeleteInitialSplitting", "Deletes a splitting from the list of initial splittings to consider " "in the shower. Command is a->b,c; Sudakov. Here the particle a is the " "particle that is PRODUCED by the splitting. b is the initial state " "particle that is splitting in the shower.", &SplittingGenerator::deleteInitialSplitting); static Parameter interfaceDetuning ("Detuning", "The Detuning parameter to make the veto algorithm less efficient to improve the weight variations", &SplittingGenerator::_deTuning, 1.0, 1.0, 10.0, false, false, Interface::limited); } string SplittingGenerator::addSplitting(string arg, bool final) { string partons = StringUtils::car(arg); string sudakov = StringUtils::cdr(arg); vector products; string::size_type next = partons.find("->"); if(next == string::npos) return "Error: Invalid string for splitting " + arg; if(partons.find(';') == string::npos) return "Error: Invalid string for splitting " + arg; tPDPtr parent = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+2); do { next = min(partons.find(','), partons.find(';')); tPDPtr pdp = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+1); if(pdp) products.push_back(pdp); else return "Error: Could not create splitting from " + arg; } while(partons[0] != ';' && partons.size()); SudakovPtr s; s = dynamic_ptr_cast(Repository::TraceObject(sudakov)); if(!s) return "Error: Could not load Sudakov " + sudakov + '\n'; IdList ids; ids.push_back(parent); for(vector::iterator it = products.begin(); it!=products.end(); ++it) ids.push_back(*it); // check splitting can handle this if(!s->splittingFn()->accept(ids)) return "Error: Sudakov " + sudakov + " SplittingFunction can't handle particles\n"; // add to map addToMap(ids,s,final); return ""; } string SplittingGenerator::deleteSplitting(string arg, bool final) { string partons = StringUtils::car(arg); string sudakov = StringUtils::cdr(arg); vector products; string::size_type next = partons.find("->"); if(next == string::npos) return "Error: Invalid string for splitting " + arg; if(partons.find(';') == string::npos) return "Error: Invalid string for splitting " + arg; tPDPtr parent = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+2); do { next = min(partons.find(','), partons.find(';')); tPDPtr pdp = Repository::findParticle(partons.substr(0,next)); partons = partons.substr(next+1); if(pdp) products.push_back(pdp); else return "Error: Could not create splitting from " + arg; } while(partons[0] != ';' && partons.size()); SudakovPtr s; s = dynamic_ptr_cast(Repository::TraceObject(sudakov)); if(!s) return "Error: Could not load Sudakov " + sudakov + '\n'; IdList ids; ids.push_back(parent); for(vector::iterator it = products.begin(); it!=products.end(); ++it) ids.push_back(*it); // check splitting can handle this if(!s->splittingFn()->accept(ids)) return "Error: Sudakov " + sudakov + " SplittingFunction can't handle particles\n"; // delete from map deleteFromMap(ids,s,final); return ""; } void SplittingGenerator::addToMap(const IdList &ids, const SudakovPtr &s, bool final) { - if(isISRadiationON() && !final) { + if(!final) { _bbranchings.insert(BranchingInsert(abs(ids[1]->id()),BranchingElement(s,ids))); s->addSplitting(ids); } - if(isFSRadiationON() && final) { + else { _fbranchings.insert(BranchingInsert(abs(ids[0]->id()),BranchingElement(s,ids))); s->addSplitting(ids); } } void SplittingGenerator::deleteFromMap(const IdList &ids, const SudakovPtr &s, bool final) { - if(isISRadiationON() && !final) { + if(!final) { pair range = _bbranchings.equal_range(abs(ids[1]->id())); for(BranchingList::iterator it=range.first; it!=range.second&&it!=_bbranchings.end();++it) { if(it->second.sudakov==s&&it->second.particles==ids) { BranchingList::iterator it2=it; --it; _bbranchings.erase(it2); } } s->removeSplitting(ids); } - if(isFSRadiationON() && final) { + else { pair range = _fbranchings.equal_range(abs(ids[0]->id())); for(BranchingList::iterator it=range.first; it!=range.second&&it!=_fbranchings.end();++it) { if(it->second.sudakov==s&&it->second.particles==ids) { BranchingList::iterator it2 = it; --it; _fbranchings.erase(it2); } } s->removeSplitting(ids); } } Branching SplittingGenerator::chooseForwardBranching(ShowerParticle &particle, double enhance, ShowerInteraction::Type type) const { RhoDMatrix rho; bool rhoCalc(false); Energy newQ = ZERO; ShoKinPtr kinematics = ShoKinPtr(); ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined); SudakovPtr sudakov = SudakovPtr(); IdList ids; // First, find the eventual branching, corresponding to the highest scale. long index = abs(particle.data().id()); // if no branchings return empty branching struct if( _fbranchings.find(index) == _fbranchings.end() ) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index); cit != _fbranchings.upper_bound(index); ++cit) { // check either right interaction or doing both if(!checkInteraction(type,cit->second.sudakov->interactionType())) continue; if(!rhoCalc) { rho = particle.extractRhoMatrix(true); rhoCalc = true; } // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered(); ShoKinPtr newKin; ShowerPartnerType::Type type; IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles; // work out which starting scale we need if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; newKin = cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,enhance,_deTuning, particle.scales().Max_Q2); } else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) { type = ShowerPartnerType::QCDColourLine; Energy startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; newKin= cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,0.5*enhance,_deTuning, particle.scales().Max_Q2); startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; ShoKinPtr newKin2 = cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,0.5*enhance,_deTuning, - particle.scales().Max_Q2); + particle.scales().Max_Q2); // pick the one with the highest scale if( ( newKin && newKin2 && newKin2->scale() > newKin->scale()) || (!newKin && newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } // other g -> q qbar else { Energy startingScale = angularOrdered ? max(particle.scales().QCD_c , particle.scales().QCD_ac ) : max(particle.scales().QCD_c_noAO, particle.scales().QCD_ac_noAO); newKin= cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,enhance,_deTuning, particle.scales().Max_Q2); type = UseRandom::rndbool() ? ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine; } } // everything else q-> qg etc else { Energy startingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } newKin= cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,enhance,_deTuning, particle.scales().Max_Q2); } } else if(cit->second.sudakov->interactionType()==ShowerInteraction::EW) { type = ShowerPartnerType::EW; Energy startingScale = particle.scales().EW; newKin = cit->second.sudakov-> generateNextTimeBranching(startingScale,particles,rho,enhance,_deTuning, particle.scales().Max_Q2); } // shouldn't be anything else else assert(false); // if no kinematics contine if(!newKin) continue; // select highest scale if( newKin->scale() > newQ ) { kinematics = newKin; newQ = newKin->scale(); ids = particles; sudakov = cit->second.sudakov; partnerType = type; } } // return empty branching if nothing happened if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), ShowerPartnerType::Undefined); - // and generate phi // if not hard generate phi kinematics->phi(sudakov->generatePhiForward(particle,ids,kinematics,rho)); // and return it return Branching(kinematics, ids,sudakov,partnerType); } Branching SplittingGenerator:: chooseDecayBranching(ShowerParticle &particle, const ShowerParticle::EvolutionScales & stoppingScales, Energy minmass, double enhance, ShowerInteraction::Type interaction) const { RhoDMatrix rho(particle.dataPtr()->iSpin()); Energy newQ = Constants::MaxEnergy; ShoKinPtr kinematics; SudakovPtr sudakov; ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined); IdList ids; // First, find the eventual branching, corresponding to the lowest scale. long index = abs(particle.data().id()); // if no branchings return empty branching struct if(_fbranchings.find(index) == _fbranchings.end()) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index); cit != _fbranchings.upper_bound(index); ++cit) { // check interaction doesn't change flavour if(cit->second.particles[1]->id()!=index&&cit->second.particles[2]->id()!=index) continue; // check either right interaction or doing both if(!checkInteraction(interaction,cit->second.sudakov->interactionType())) continue; // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered(); ShoKinPtr newKin; IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles; ShowerPartnerType::Type type; // work out which starting scale we need if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy stoppingScale = angularOrdered ? stoppingScales.QED : stoppingScales.QED_noAO; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; if(startingScale < stoppingScale ) { newKin = cit->second.sudakov-> generateNextDecayBranching(startingScale,stoppingScale,minmass,particles,rho, enhance,_deTuning); } } else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) { Energy stoppingColour = angularOrdered ? stoppingScales.QCD_c : stoppingScales.QCD_c_noAO; Energy stoppingAnti = angularOrdered ? stoppingScales.QCD_ac : stoppingScales.QCD_ac_noAO; Energy startingColour = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; Energy startingAnti = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; type = ShowerPartnerType::QCDColourLine; if(startingColoursecond.sudakov-> generateNextDecayBranching(startingColour,stoppingColour,minmass, particles,rho,0.5*enhance,_deTuning); } ShoKinPtr newKin2; if(startingAntisecond.sudakov-> generateNextDecayBranching(startingAnti,stoppingAnti,minmass, particles,rho,0.5*enhance,_deTuning); } // pick the one with the lowest scale if( (newKin&&newKin2&&newKin2->scale()scale()) || (!newKin&&newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } // other else { assert(false); } } // everything else else { Energy startingScale,stoppingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; stoppingScale = angularOrdered ? stoppingScales.QCD_c : stoppingScales.QCD_c_noAO; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; stoppingScale = angularOrdered ? stoppingScales.QCD_ac : stoppingScales.QCD_ac_noAO; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } if(startingScale < stoppingScale ) { newKin = cit->second.sudakov-> generateNextDecayBranching(startingScale,stoppingScale,minmass,particles,rho, enhance,_deTuning); } } } else if(cit->second.sudakov->interactionType()==ShowerInteraction::EW) { type = ShowerPartnerType::EW; Energy stoppingScale = stoppingScales.EW; Energy startingScale = particle.scales().EW; if(startingScale < stoppingScale ) { newKin = cit->second.sudakov-> generateNextDecayBranching(startingScale,stoppingScale,minmass,particles,rho,enhance,_deTuning); } } // shouldn't be anything else else assert(false); if(!newKin) continue; // select highest scale if(newKin->scale() < newQ ) { newQ = newKin->scale(); ids = particles; kinematics=newKin; sudakov=cit->second.sudakov; partnerType = type; } } // return empty branching if nothing happened if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), ShowerPartnerType::Undefined); // and generate phi kinematics->phi(sudakov->generatePhiDecay(particle,ids,kinematics,rho)); // and return it return Branching(kinematics, ids,sudakov,partnerType); } Branching SplittingGenerator:: chooseBackwardBranching(ShowerParticle &particle,PPtr, double enhance, Ptr::transient_const_pointer beam, ShowerInteraction::Type type, tcPDFPtr pdf, Energy freeze) const { RhoDMatrix rho; bool rhoCalc(false); Energy newQ=ZERO; ShoKinPtr kinematics=ShoKinPtr(); ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined); SudakovPtr sudakov; IdList ids; // First, find the eventual branching, corresponding to the highest scale. long index = abs(particle.id()); // if no possible branching return if(_bbranchings.find(index) == _bbranchings.end()) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined); // otherwise select branching for(BranchingList::const_iterator cit = _bbranchings.lower_bound(index); cit != _bbranchings.upper_bound(index); ++cit ) { // check either right interaction or doing both if(!checkInteraction(type,cit->second.sudakov->interactionType())) continue; // setup the PDF cit->second.sudakov->setPDF(pdf,freeze); //calc rho as needed if(!rhoCalc) { rho = particle.extractRhoMatrix(false); rhoCalc = true; } // whether or not this interaction should be angular ordered bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered(); ShoKinPtr newKin; IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles; ShowerPartnerType::Type type; if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) { type = ShowerPartnerType::QED; Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO; newKin=cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles, particle.x(),rho,enhance, beam,_deTuning); } else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) { // special for octets if(particle.dataPtr()->iColour()==PDT::Colour8) { // octet -> octet octet if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) { type = ShowerPartnerType::QCDColourLine; Energy startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; newKin = cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles, particle.x(),rho,0.5*enhance, beam,_deTuning); startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; ShoKinPtr newKin2 = cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles, particle.x(),rho, 0.5*enhance,beam,_deTuning); // pick the one with the highest scale if( (newKin&&newKin2&&newKin2->scale()>newKin->scale()) || (!newKin&&newKin2) ) { newKin = newKin2; type = ShowerPartnerType::QCDAntiColourLine; } } else { Energy startingScale = angularOrdered ? max(particle.scales().QCD_c , particle.scales().QCD_ac ) : max(particle.scales().QCD_c_noAO, particle.scales().QCD_ac_noAO); type = UseRandom::rndbool() ? ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine; newKin=cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles, particle.x(),rho,enhance,beam,_deTuning); } } // everything else else { Energy startingScale; if(particle.hasColour()) { type = ShowerPartnerType::QCDColourLine; startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO; } else { type = ShowerPartnerType::QCDAntiColourLine; startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO; } newKin=cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles,particle.x(),rho,enhance,beam,_deTuning); } } else if(cit->second.sudakov->interactionType()==ShowerInteraction::EW) { type = ShowerPartnerType::EW; Energy startingScale = particle.scales().EW; newKin=cit->second.sudakov-> generateNextSpaceBranching(startingScale,particles,particle.x(),rho,enhance,beam,_deTuning); } // shouldn't be anything else else assert(false); // if no kinematics contine if(!newKin) continue; // select highest scale if(newKin->scale() > newQ) { newQ = newKin->scale(); kinematics=newKin; ids = particles; sudakov=cit->second.sudakov; partnerType = type; } } // return empty branching if nothing happened if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(), ShowerPartnerType::Undefined); // initialize the ShowerKinematics - // and return it // and generate phi kinematics->phi(sudakov->generatePhiBackward(particle,ids,kinematics,rho)); // return the answer return Branching(kinematics, ids,sudakov,partnerType); } void SplittingGenerator::rebind(const TranslationMap & trans) { BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) { (cit->second).sudakov=trans.translate((cit->second).sudakov); for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) { (cit->second).particles[ix]=trans.translate((cit->second).particles[ix]); } for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) { (cit->second).conjugateParticles[ix]=trans.translate((cit->second).conjugateParticles[ix]); } } for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) { (cit->second).sudakov=trans.translate((cit->second).sudakov); for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) { (cit->second).particles[ix]=trans.translate((cit->second).particles[ix]); } for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) { (cit->second).conjugateParticles[ix]=trans.translate((cit->second).conjugateParticles[ix]); } } Interfaced::rebind(trans); } IVector SplittingGenerator::getReferences() { IVector ret = Interfaced::getReferences(); BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) { ret.push_back((cit->second).sudakov); for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) ret.push_back(const_ptr_cast((cit->second).particles[ix])); for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) ret.push_back(const_ptr_cast((cit->second).conjugateParticles[ix])); } for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) { ret.push_back((cit->second).sudakov); for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) ret.push_back(const_ptr_cast((cit->second).particles[ix])); for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) ret.push_back(const_ptr_cast((cit->second).conjugateParticles[ix])); } return ret; } void SplittingGenerator::factorizationScaleFactor(double f) { BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) {(cit->second).sudakov->factorizationScaleFactor(f);} for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) {(cit->second).sudakov->factorizationScaleFactor(f);} } void SplittingGenerator::renormalizationScaleFactor(double f) { BranchingList::iterator cit; for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) {(cit->second).sudakov->renormalizationScaleFactor(f);} for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) {(cit->second).sudakov->renormalizationScaleFactor(f);} } diff --git a/Shower/SplittingFunctions/SplittingGenerator.fh b/Shower/QTilde/SplittingFunctions/SplittingGenerator.fh rename from Shower/SplittingFunctions/SplittingGenerator.fh rename to Shower/QTilde/SplittingFunctions/SplittingGenerator.fh diff --git a/Shower/QTilde/SplittingFunctions/SplittingGenerator.h b/Shower/QTilde/SplittingFunctions/SplittingGenerator.h new file mode 100644 --- /dev/null +++ b/Shower/QTilde/SplittingFunctions/SplittingGenerator.h @@ -0,0 +1,330 @@ +// -*- C++ -*- +// +// SplittingGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator +// Copyright (C) 2002-2011 The Herwig Collaboration +// +// Herwig is licenced under version 2 of the GPL, see COPYING for details. +// Please respect the MCnet academic guidelines, see GUIDELINES for details. +// +#ifndef HERWIG_SplittingGenerator_H +#define HERWIG_SplittingGenerator_H +// +// This is the declaration of the SplittingGenerator class. +// + +#include "ThePEG/Interface/Interfaced.h" +#include "Herwig/Shower/QTilde/Base/Branching.h" +#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h" +#include "SplittingGenerator.fh" +#include "Herwig/Shower/QTilde/Base/ShowerParticle.h" +#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h" + +namespace Herwig { + +using namespace ThePEG; + +/** \ingroup Shower + * + * This class is responsible for creating, at the beginning of the Run, + * all the SplittingFunction objects and the corresponding + * SudakovFormFactor objects, and then of the generation of splittings + * (radiation emissions) during the event. + * Many switches are defined in this class which allowed the user to turn on/off: + * - each type of interaction (QCD, QED, EWK,...); + * - initial- and final-state radiation for all type of interactions; + * - initial- and final-state radiation for each type of interaction; + * - each type of splitting (\f$u\to ug\f$, \f$d\to dg\f$, \f$\ldots\f$, + * \f$g\to gg\f$, \f$g\to u\bar{u}\f$, \f$\ldots\f$). + * + * These switches are useful mainly for debugging, but eventually can + * also be used for a "quick and dirty" estimation of systematic errors. + * + * In the future it should be possible to implement in this class + * + * - the \f$1\to2\f$ azimuthal correlations for soft emission due to QCD coherence + * using the ShowerParticle object provided in the input. + * - Similarly having the \f$\rho-D\f$ matrix and the SplittingFunction pointer + * it should be possible to implement the spin correlations. + * + * @see SudakovFormFactor + * @see SplitFun + * + * @see \ref SplittingGeneratorInterfaces "The interfaces" + * defined for SplittingGenerator. + */ +class SplittingGenerator: public Interfaced { + +public: + + /** @name Standard constructors and destructors. */ + //@{ + /** + * The default constructor. + */ + SplittingGenerator() : _deTuning(1.) {} + //@} + +public: + + /** + * Methods to select the next branching and reconstruct the kinematics + */ + //@{ + /** + * Choose a new forward branching for a time-like particle + * The method returns: + * - a pointer to a ShowerKinematics object, which + * contains the information about the new scale and all other + * kinematics variables that need to be generated simultaneously; + * - a pointer to the SudakovFormFactor object associated + * with the chosen emission. + * - The PDG codes of the particles in the branching, + * as a Branching struct. + * + * In the case no branching has been generated, both the returned + * pointers are null ( ShoKinPtr() , tSudakovFFPtr() ). + * + * @param particle The particle to be evolved + * @param enhance The factor by which to ehnace the emission of radiation + * @param type The type of interaction to generate + * @return The Branching struct for the branching + */ + Branching chooseForwardBranching(ShowerParticle & particle, + double enhance, + ShowerInteraction::Type type) const; + + /** + * Select the next branching of a particles for the initial-state shower + * in the particle's decay. + * @param particle The particle being showerwed + * @param maxscale The maximum scale + * @param minmass Minimum mass of the particle after the branching + * @param enhance The factor by which to ehnace the emission of radiation + * @param type The type of interaction to generate + * @return The Branching struct for the branching + */ + Branching chooseDecayBranching(ShowerParticle & particle, + const ShowerParticle::EvolutionScales & maxScales, + Energy minmass,double enhance, + ShowerInteraction::Type type) const; + + /** + * Choose a new backward branching for a space-like particle. + * The method returns: + * - a pointer to a ShowerKinematics object, which + * contains the information about the new scale and all other + * kinematics variables that need to be generated simultaneously; + * - a pointer to the SudakovFormFactor object associated + * with the chosen emission. + * - The PDG codes of the particles in the branching, + * as a Branching struct. + * + * In the case no branching has been generated, both the returned + * pointers are null ( ShoKinPtr() , tSudakovFFPtr() ). + * + * @param particle The particle to be evolved + * @param enhance The factor by which to ehnace the emission of radiation + * @param beamparticle The beam particle + * @param beam The BeamParticleData object + * @param type The type of interaction to generate + * @return The Branching struct for the branching + */ + Branching + chooseBackwardBranching(ShowerParticle & particle, + PPtr beamparticle, + double enhance, + Ptr::transient_const_pointer beam, + ShowerInteraction::Type type, + tcPDFPtr , Energy ) const; + //@} + +public: + + /** + * Methods to parse the information from the input files to create the + * branchings + */ + //@{ + /** + * Add a final-state splitting + */ + string addFinalSplitting(string arg) { return addSplitting(arg,true); } + + /** + * Add an initial-state splitting + */ + string addInitialSplitting(string arg) { return addSplitting(arg,false); } + + /** + * Add a final-state splitting + */ + string deleteFinalSplitting(string arg) { return deleteSplitting(arg,true); } + + /** + * Add an initial-state splitting + */ + string deleteInitialSplitting(string arg) { return deleteSplitting(arg,false); } + //@} + + /** + * Access to the splittings + */ + //@{ + /** + * Access the final-state branchings + */ + const BranchingList & finalStateBranchings() const { return _fbranchings; } + + /** + * Access the initial-state branchings + */ + const BranchingList & initialStateBranchings() const { return _bbranchings; } + //@} + + /** + * Set the factorization scale factor + */ + void factorizationScaleFactor(double f); + + /** + * Set the renormalization scale factor + */ + void renormalizationScaleFactor(double f); + +public: + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +protected: + + /** @name Clone Methods. */ + //@{ + /** + * Make a simple clone of this object. + * @return a pointer to the new object. + */ + virtual IBPtr clone() const; + + /** Make a clone of this object, possibly modifying the cloned object + * to make it sane. + * @return a pointer to the new object. + */ + virtual IBPtr fullclone() const; + //@} + +protected: + + /** @name Standard Interfaced functions. */ + //@{ + /** + * Rebind pointer to other Interfaced objects. Called in the setup phase + * after all objects used in an EventGenerator has been cloned so that + * the pointers will refer to the cloned objects afterwards. + * @param trans a TranslationMap relating the original objects to + * their respective clones. + * @throws RebindException if no cloned object was found for a given + * pointer. + */ + virtual void rebind(const TranslationMap & trans) + ; + + /** + * Return a vector of all pointers to Interfaced objects used in this + * object. + * @return a vector of pointers. + */ + virtual IVector getReferences(); + //@} + +private: + + /** + * Add a branching to the map + * @param ids PDG coeds of the particles in the branching + * @param sudakov The SudakovFormFactor for the branching + * @param final Whether this is an initial- or final-state branching + */ + void addToMap(const IdList & ids, const SudakovPtr & sudakov, bool final); + + /** + * Remove a branching to the map + * @param ids PDG coeds of the particles in the branching + * @param sudakov The SudakovFormFactor for the branching + * @param final Whether this is an initial- or final-state branching + */ + void deleteFromMap(const IdList & ids, const SudakovPtr & sudakov, bool final); + + /** + * Obtain the reference vectors for a final-state particle + * @param particle The particle + * @param p The p reference vector + * @param n The n reference vector + */ + void finalStateBasisVectors(ShowerParticle particle, Lorentz5Momentum & p, + Lorentz5Momentum & n) const; + + /** + * Add a splitting + * @param in string to be parsed + * @param final Whether this is an initial- or final-state branching + */ + string addSplitting(string in ,bool final); + + /** + * Delete a splitting + * @param in string to be parsed + * @param final Whether this is an initial- or final-state branching + */ + string deleteSplitting(string in ,bool final); + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + SplittingGenerator & operator=(const SplittingGenerator &); + +private: + + /** + * List of the branchings and the appropriate Sudakovs for forward branchings + */ + BranchingList _fbranchings; + + /** + * Lists of the branchings and the appropriate Sudakovs for backward branchings. + */ + BranchingList _bbranchings; + + /** + * The detuning parameter + */ + double _deTuning; +}; + +} + +#endif /* HERWIG_SplittingGenerator_H */ diff --git a/Shower/SplittingFunctions/ZeroZeroOneSplitFn.cc b/Shower/QTilde/SplittingFunctions/ZeroZeroOneSplitFn.cc rename from Shower/SplittingFunctions/ZeroZeroOneSplitFn.cc rename to Shower/QTilde/SplittingFunctions/ZeroZeroOneSplitFn.cc diff --git a/Shower/SplittingFunctions/ZeroZeroOneSplitFn.h b/Shower/QTilde/SplittingFunctions/ZeroZeroOneSplitFn.h rename from Shower/SplittingFunctions/ZeroZeroOneSplitFn.h rename to Shower/QTilde/SplittingFunctions/ZeroZeroOneSplitFn.h diff --git a/Shower/RealEmissionProcess.fh b/Shower/RealEmissionProcess.fh new file mode 100644 --- /dev/null +++ b/Shower/RealEmissionProcess.fh @@ -0,0 +1,22 @@ +// -*- C++ -*- +// +// This is the forward declaration of the RealEmissionProcess class. +// +#ifndef HERWIG_RealEmissionProcess_FH +#define HERWIG_RealEmissionProcess_FH + +#include "ThePEG/Config/Pointers.h" + +namespace Herwig { + +class RealEmissionProcess; + +} + +namespace ThePEG { + +ThePEG_DECLARE_POINTERS(Herwig::RealEmissionProcess,RealEmissionProcessPtr); + +} + +#endif diff --git a/Shower/RealEmissionProcess.h b/Shower/RealEmissionProcess.h new file mode 100644 --- /dev/null +++ b/Shower/RealEmissionProcess.h @@ -0,0 +1,245 @@ +// -*- C++ -*- +// +// RealEmissionProcess.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_RealEmissionProcess_H +#define HERWIG_RealEmissionProcess_H + +#include "ThePEG/Config/ThePEG.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/EventRecord/SubProcess.h" +#include "ThePEG/Handlers/XComb.h" +#include "ThePEG/Config/Pointers.h" +#include "RealEmissionProcess.fh" +#include "Herwig/Shower/QTilde/ShowerInteraction.h" + +namespace Herwig { +using namespace ThePEG; + +/** + * Simple struct for hard processes and decays + */ +class RealEmissionProcess : public Base { + + friend ostream & operator<<(ostream & os, const RealEmissionProcess & proc); + +public: + + /** + * The incoming particles + */ + ParticleVector & incoming() { + return incoming_; + } + + /** + * The outgoing particles + */ + ParticleVector & outgoing() { + return outgoing_; + } + +public: + + /** + * The incoming particles + */ + ParticleVector & bornIncoming() { + return bornIncoming_; + } + + /** + * The outgoing particles + */ + ParticleVector & bornOutgoing() { + return bornOutgoing_; + } + + /** + * The hadrons + */ + ParticleVector & hadrons() { + return hadrons_; + } + +public: + + /** + * The emitter + */ + unsigned int emitter () const {return emitter_;} + + /** + * The spectator + */ + unsigned int spectator() const {return spectator_;} + + /** + * The emitted + */ + unsigned int emitted () const {return emitted_;} + + /** + * The emitter + */ + void emitter (unsigned int in) {emitter_=in;} + + /** + * The spectator + */ + void spectator(unsigned int in) {spectator_=in;} + + /** + * The emitted + */ + void emitted (unsigned int in) {emitted_=in;} + +public: + + /** + * Lorentz Rotation to final-state for II dipoles + */ + LorentzRotation transformation() const { return trans_;} + + /** + * Lorentz Rotation to final-state for II dipoles + */ + void transformation(LorentzRotation in) {trans_=in;} + +public: + + /** + * Get the x values + */ + pair x() const {return x_;} + + /** + * Set the x values + */ + void x(pair in) {x_=in;} + +public: + + /** + * Type of interaction + */ + ShowerInteraction::Type interaction() {return interaction_;} + + /** + * Type of interaction + */ + void interaction(ShowerInteraction::Type in) {interaction_ = in;} + + /** + * Emission scales + */ + map & pT() {return pT_;} + +private: + + /** + * The emitter + */ + unsigned int emitter_; + + /** + * The spectator + */ + unsigned int spectator_; + /** + * The emitter + */ + unsigned int emitted_; + +private: + + /** + * The incoming particles + */ + ParticleVector incoming_; + + /* + * The outgoing particles + */ + ParticleVector outgoing_; + +private: + + /** + * The hadrons + */ + ParticleVector hadrons_; + +private: + + /** + * Incoming for the Born process + */ + ParticleVector bornIncoming_; + + /** + * Outgoing for the Born process + */ + ParticleVector bornOutgoing_; + +private: + + /** + * Lorentz transformation for spectators in II + */ + LorentzRotation trans_; + + /** + * x values + */ + pair x_; + +private: + + /** + * Type of interaction + */ + ShowerInteraction::Type interaction_; + + /** + * Emission scales + */ + map pT_; +}; + +/** + * Output to a stream + */ +inline ostream & operator<<(ostream & os, const RealEmissionProcess & proc) { + os << "REAL EMISSION " + << proc.emitter_ << " " + << proc.spectator_ << " " + << proc.emitted_ << "\n"; + os << "BORN\n"; + for(unsigned int ix=0;ixcolourLine() << " " + << proc.bornIncoming_[ix]->antiColourLine() << " " + << *proc.bornIncoming_[ix] << "\n"; + for(unsigned int ix=0;ixcolourLine() << " " + << proc.bornOutgoing_[ix]->antiColourLine() << " " + << *proc.bornOutgoing_[ix] << "\n"; + os << "REAL\n"; + for(unsigned int ix=0;ixcolourLine() << " " + << proc.incoming_[ix]->antiColourLine() << " " + << *proc.incoming_[ix] << "\n"; + for(unsigned int ix=0;ixcolourLine() << " " + << proc.outgoing_[ix]->antiColourLine() << " " + << *proc.outgoing_[ix] << "\n"; + return os; +} + +} + +#endif diff --git a/Shower/ShowerEventRecord.cc b/Shower/ShowerEventRecord.cc new file mode 100644 --- /dev/null +++ b/Shower/ShowerEventRecord.cc @@ -0,0 +1,390 @@ +// -*- C++ -*- +// +// This is the implementation of the non-inlined, non-templated member +// functions of the ShowerEventRecord class. +// + +#include "ShowerEventRecord.h" +#include "ThePEG/Interface/ClassDocumentation.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/Repository/UseRandom.h" +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/Utilities/DescribeClass.h" +#include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h" +#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h" + +using namespace Herwig; + +ShowerEventRecord::ShowerEventRecord() + : isMCatNLOSEvent_(false),isMCatNLOHEvent_(false), + isPowhegSEvent_ (false),isPowhegHEvent_ (false) +{} + +ShowerEventRecord::~ShowerEventRecord() {} + + +void ShowerEventRecord::updateColour(PPtr particle, + bool recursive) { + // if attached to a colour line + if(particle->colourLine()) { + // one and only one + if(particle->colourInfo()->colourLines().size()==1) { + bool reset=false; + // if colour line from hard process reconnect + ColinePtr c1=particle->colourLine(); + if(colourLines().find(c1)!=colourLines().end()) { + c1->removeColoured(particle); + colourLines()[c1]->addColoured(particle); + reset=true; + } + // ensure properly connected to the line + if(!reset) { + ColinePtr c1=particle->colourLine(); + c1->removeColoured(particle); + c1->addColoured(particle); + } + } + else { + Ptr::pointer colour = + dynamic_ptr_cast::pointer>(particle->colourInfo()); + vector lines = colour->colourLines(); + for(unsigned int ix=0;ix(lines[ix]); + if(colourLines().find(c1)!=colourLines().end()) { + colour->colourLine(colourLines()[c1],int(ix)+1); + c1->removeColoured(particle); + } + } + } + } + // if attached to an anticolour line + if(particle->antiColourLine()) { + // one and only one + if(particle->colourInfo()->antiColourLines().size()==1) { + bool reset=false; + ColinePtr c1=particle->antiColourLine(); + // if anti colour line from hard process reconnect + if(colourLines().find(c1)!=colourLines().end()) { + c1->removeColoured(particle,true); + colourLines()[c1]->addColoured(particle,true); + reset=true; + } + if(!reset) { + ColinePtr c1=particle->antiColourLine(); + c1->removeColoured(particle,true); + c1->addColoured(particle,true); + } + } + else { + Ptr::pointer colour = + dynamic_ptr_cast::pointer>(particle->colourInfo()); + vector lines = colour->antiColourLines(); + for(unsigned int ix=0;ix(lines[ix]); + if(colourLines().find(c1)!=colourLines().end()) { + colour->antiColourLine(colourLines()[c1],int(ix)+1); + c1->removeColoured(particle,true); + } + } + } + } + if(!recursive) return; + for ( ParticleVector::const_iterator c = particle->children().begin(); + c != particle->children().end(); ++c ) { + updateColour(*c,true); + } +} + +void ShowerEventRecord::colourIsolate(const vector & original, + const vector & copy) { + // vectors must have same size + assert(original.size()==copy.size()); + // create a temporary map with all the particles to make looping easier + vector particles; + particles.reserve(original.size()); + for(unsigned int ix=0;ix::const_iterator cit; + // make the colour connections of the copies + for(cit=particles.begin();cit!=particles.end();++cit) { + if((*cit).first->colourInfo()) { + if((*cit).first->dataPtr()->iColour() != PDT::Colour6 && + (*cit).first->dataPtr()->iColour() != PDT::Colour6bar) + (*cit).first->colourInfo(new_ptr(ColourBase())); + else + (*cit).first->colourInfo(new_ptr(MultiColour())); + } + } + map cmap; + // make the colour connections of the copies + // loop over the particles + for(cit=particles.begin();cit!=particles.end();++cit) { + // if particle has at least one colour line + if((*cit).second->colourLine()) { + // one and only one line + if(int((*cit).second->colourInfo()->colourLines().size())==1) { + // if particle has a colour line + if(!(*cit).first->colourLine()) { + // make new line + tColinePtr oldline=(*cit).second->colourLine(); + ColinePtr newline=ColourLine::create((*cit).first); + cmap[oldline]=newline; + isolateLine(cit,particles,oldline,newline); + } + } + // more than one line + else { + Ptr::pointer colour1 = + dynamic_ptr_cast::pointer> + ((*cit).second->colourInfo()); + vector lines1 = colour1->colourLines(); + Ptr::pointer colour2 = + dynamic_ptr_cast::pointer> + ((*cit).first->colourInfo()); + vector lines2 = colour2->colourLines(); + // loop over lines + for(unsigned int ix=0;ixix && !lines2[ix]) || + lines2.size()<=ix) { + tColinePtr oldline = const_ptr_cast(lines1[ix]); + ColinePtr newline = new_ptr(ColourLine()); + cmap[oldline]=newline; + colour2->colourLine(newline, int(ix)+1); + isolateLine(cit,particles,oldline,newline); + } + } + } + } + // if anticolour line + if((*cit).second->antiColourLine()) { + // one and only one line + if(int((*cit).second->colourInfo()->antiColourLines().size())==1) { + // if not already change + if(!(*cit).first->antiColourLine()) { + // make new line + tColinePtr oldline=(*cit).second->antiColourLine(); + ColinePtr newline=ColourLine::create((*cit).first, true); + cmap[oldline]=newline; + isolateLine(cit,particles,oldline,newline); + } + } + // more than one line + else { + Ptr::pointer colour1 = + dynamic_ptr_cast::pointer> + ((*cit).second->colourInfo()); + vector lines1 = colour1->antiColourLines(); + Ptr::pointer colour2 = + dynamic_ptr_cast::pointer> + ((*cit).first->colourInfo()); + vector lines2 = colour2->antiColourLines(); + // loop over lines + for(unsigned int ix=0;ixix && !lines2[ix]) || + lines2.size()<=ix) { + tColinePtr oldline = const_ptr_cast(lines1[ix]); + ColinePtr newline = new_ptr(ColourLine()); + cmap[oldline]=newline; + colour2->antiColourLine(newline, int(ix)+1); + isolateLine(cit,particles,oldline,newline); + } + } + } + } + } + for ( map::const_iterator c = cmap.begin(); + c != cmap.end(); ++c ) { + colourLines()[c->second] = c->first; + } + // sort out sinks and sources + for(cit=particles.begin();cit!=particles.end();++cit) { + tColinePtr cline[2]; + tColinePair cpair; + for(unsigned int ix=0;ix<4;++ix) { + cline[0] = ix<2 ? cit->second->colourLine() : cit->second->antiColourLine(); + cline[1] = ix<2 ? cit->first ->colourLine() : cit->first ->antiColourLine(); + if(cline[0]) { + switch (ix) { + case 0: case 2: + cpair = cline[0]->sinkNeighbours(); + break; + case 1: case 3: + cpair = cline[0]->sourceNeighbours(); + break; + }; + } + else { + cpair = make_pair(tColinePtr(),tColinePtr()); + } + if(cline[0]&&cpair.first) { + map::const_iterator + mit[2] = {cmap.find(cpair.first),cmap.find(cpair.second)}; + if(mit[0]!=cmap.end()&&mit[1]!=cmap.end()) { + if(ix==0||ix==2) { + cline[1]->setSinkNeighbours(mit[0]->second,mit[1]->second); + } + else { + cline[1]->setSourceNeighbours(mit[0]->second,mit[1]->second); + } + } + } + } + } +} + +void ShowerEventRecord::isolateLine(vector::const_iterator cit, + vector & particles, + tcColinePtr oldline, + tColinePtr newline) { + // loop over particles + for(vector::const_iterator cjt=particles.begin(); + cjt!=particles.end();++cjt) { + if(cjt==cit) continue; + // if particle has colour line + if((*cjt).second->colourLine()) { + // if only one check if current line and reset + if(int((*cjt).second->colourInfo()->colourLines().size())==1) { + if((*cjt).second->colourLine()==oldline) + newline->addColoured((*cjt).first); + } + // if more than one check if each line current line and reset + else { + Ptr::pointer colour1 = + dynamic_ptr_cast::pointer> + ((*cjt).second->colourInfo()); + Ptr::pointer colour2 = + dynamic_ptr_cast::pointer> + ((*cjt).first ->colourInfo()); + for(unsigned int ix=0;ixcolourLines().size();++ix) { + if(colour1->colourLines()[ix]==oldline) + colour2->colourLine(newline,int(ix)+1); + } + } + } + // if particle has anticolour line + if((*cjt).second->antiColourLine()) { + // if only one check if current line and reset + if(int((*cjt).second->colourInfo()->antiColourLines().size())==1) { + if((*cjt).second->antiColourLine()==oldline) + newline->addColoured((*cjt).first,true); + } + // if more than one check if each line current line and reset + else { + Ptr::pointer colour1 = + dynamic_ptr_cast::pointer> + ((*cjt).second->colourInfo()); + Ptr::pointer colour2 = + dynamic_ptr_cast::pointer> + ((*cjt).first ->colourInfo()); + for(unsigned int ix=0;ixantiColourLines().size();++ix) { + if(colour1->antiColourLines()[ix]==oldline) + colour2->antiColourLine(newline, int(ix)+1); + } + } + } + } +} + +void ShowerEventRecord::mapColour(PPtr original, + PPtr copy) { + // has colour line + if(copy->colourLine()) { + // one and only one + if(copy->colourInfo()->colourLines().size()==1) { + colourLines_[copy->colourLine()] = original->colourLine(); + } + // more than one + else { + Ptr::pointer colour1 = + dynamic_ptr_cast::pointer>(copy->colourInfo()); + vector lines1 = colour1->colourLines(); + Ptr::pointer colour2 = + dynamic_ptr_cast::pointer>(original->colourInfo()); + vector lines2 = colour2->colourLines(); + for(unsigned int ix=0;ix(lines1[ix])] = + const_ptr_cast(lines2[ix]); + } + } + // has anticolour line + if(copy->antiColourLine()) { + // one and only one + if(copy->colourInfo()->antiColourLines().size()==1) { + colourLines_[copy->antiColourLine()] = original->antiColourLine(); + } + // more than one + else { + Ptr::pointer colour1 = + dynamic_ptr_cast::pointer>(copy->colourInfo()); + vector lines1 = colour1->antiColourLines(); + Ptr::pointer colour2 = + dynamic_ptr_cast::pointer>(original->colourInfo()); + vector lines2 = colour2->antiColourLines(); + for(unsigned int ix=0;ix(lines1[ix])] = + const_ptr_cast(lines2[ix]); + } + } +} + +void ShowerEventRecord::clear() { + subProcess_ = SubProPtr(); + XComb_ = StdXCombPtr(); + incoming_ = PPair(); + outgoing_.clear(); + intermediates_.clear(); + PDFs_ = pair(); + colourLines_.clear(); +} + +void ShowerEventRecord::identifyEventType() { + isMCatNLOSEvent_ = false; + isMCatNLOHEvent_ = false; + isPowhegSEvent_ = false; + isPowhegHEvent_ = false; + Ptr::tptr subme; + Ptr::tptr me; + + Ptr::ptr sxc = dynamic_ptr_cast::ptr>(xcombPtr()); + if ( sxc ) { + subme = dynamic_ptr_cast::tptr>(sxc->matrixElement()); + me = dynamic_ptr_cast::tptr>(sxc->matrixElement()); + } + if ( subme ) { + if ( subme->showerApproximation() ) { + showerApproximation_ = subme->showerApproximation(); + // separate MCatNLO and POWHEG-type corrections + if ( !subme->showerApproximation()->needsSplittingGenerator() ) { + if ( subme->realShowerSubtraction() ) + isMCatNLOHEvent_ = true; + else if ( subme->virtualShowerSubtraction() ) + isMCatNLOSEvent_ = true; + } + else { + if ( subme->realShowerSubtraction() ) + isPowhegHEvent_ = true; + else if ( subme->virtualShowerSubtraction() || subme->loopSimSubtraction() ) + isPowhegSEvent_ = true; + } + } + } else if ( me ) { + if ( me->factory()->showerApproximation() ) { + showerApproximation_ = me->factory()->showerApproximation(); + if ( !me->factory()->showerApproximation()->needsSplittingGenerator() ) + isMCatNLOSEvent_ = true; + else + isPowhegSEvent_ = true; + } + } + // check for truncated shower + truncatedShower_ = false; + if (me && me->factory()->showerApproximation()) { + if(me->factory()->showerApproximation()->needsTruncatedShower()) + truncatedShower_ = true; + } + else if (subme && subme->factory()->showerApproximation()) { + if(subme->factory()->showerApproximation()->needsTruncatedShower()) + truncatedShower_ = true; + } +} diff --git a/Shower/ShowerEventRecord.h b/Shower/ShowerEventRecord.h new file mode 100644 --- /dev/null +++ b/Shower/ShowerEventRecord.h @@ -0,0 +1,319 @@ +// -*- C++ -*- +#ifndef Herwig_ShowerEventRecord_H +#define Herwig_ShowerEventRecord_H +// +// This is the declaration of the ShowerEventRecord class. +// + +#include "ThePEG/Config/ThePEG.h" +#include "ThePEG/Handlers/StandardXComb.h" +#include "ThePEG/PDF/PDF.h" +#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * Here is the documentation of the ShowerEventRecord class. + */ +class ShowerEventRecord: public Base { + +public: + + /** @name Standard constructors and destructors. */ + //@{ + /** + * The default constructor. + */ + ShowerEventRecord(); + + /** + * The destructor. + */ + virtual ~ShowerEventRecord(); + //@} + +public: + + /** + * Return the subprocess currently showered + */ + tSubProPtr subProcess() const { return subProcess_; } + + /** + * Return the XComb describing the hard process. + */ + tStdXCombPtr xcombPtr() const { return XComb_; } + + /** + * Set the XComb describing the hard process. + */ + void xcombPtr(tStdXCombPtr in) { XComb_ = in; } + + /** + * Return the XComb describing the hard process. + */ + const StandardXComb& xcomb() const { return *XComb_; } + +public: + + /** + * Return the incoming partons at the current + * stage of the evolution. + */ + PPair& incoming() { return incoming_; } + + /** + * Return the incoming partons at the current + * stage of the evolution. + */ + const PPair& incoming() const { return incoming_; } + + /** + * Return the outgoing partons at the current + * stage of the evolution. + */ + PList& outgoing() { return outgoing_; } + + /** + * Return the outgoing partons at the current + * stage of the evolution. + */ + const PList& outgoing() const { return outgoing_; } + + /** + * Return the intermediate particles at the current + * stage of the evolution. + */ + PList& intermediates() { return intermediates_; } + + /** + * Return the intermediate particles at the current + * stage of the evolution. + */ + const PList& intermediates() const { return intermediates_; } + + /** + * Return the momentum fractions. + */ + const pair& fractions() const { return fractions_; } + + /** + * Return the momentum fractions. + */ + pair& fractions() { return fractions_; } + + /** + * Return the PDFs + */ + const pair& pdfs() const { return PDFs_; } + +public: + + /** @name MC@NLO diagnostics */ + //@{ + /** + * True, if Matchbox MC@NLO S-event + */ + bool isMCatNLOSEvent() const { return isMCatNLOSEvent_; } + + /** + * True, if matchbox MC@NLO H-event + */ + bool isMCatNLOHEvent() const { return isMCatNLOHEvent_; } + + /** + * True, if Matchbox MC@NLO S-event + */ + bool isPowhegSEvent() const { return isPowhegSEvent_; } + + /** + * True, if matchbox MC@NLO H-event + */ + bool isPowhegHEvent() const { return isPowhegHEvent_; } + + /** + * True, if Matchbox MC@NLO S-event + */ + void isMCatNLOSEvent(bool in) { isMCatNLOSEvent_ = in; } + + /** + * True, if matchbox MC@NLO H-event + */ + void isMCatNLOHEvent(bool in) { isMCatNLOHEvent_ = in; } + + /** + * Access to the shower approximation + */ + Ptr::tptr showerApproximation() { + return showerApproximation_; + } + + /** + * True if truncated shower required + */ + bool truncatedShower() const { return truncatedShower_; } + + /** + * True if truncated shower required + */ + void truncatedShower(bool in) { truncatedShower_=in; } + //@} + +public: + + /** + * Clear the event record: Give up ownership + * on any object involved in the evolution. + */ + virtual void clear(); + +protected: + + /** + * Set the subprocess + */ + void subProcess(tSubProPtr in) { subProcess_ = in; } + + /** + * Return the PDFs + */ + pair& pdfs() { return PDFs_; } + +public: + + /** + * Identify the type of event + */ + void identifyEventType(); + +protected: + + /** + * Map of colour lines used to reset colours when inserted into the event + */ + map & colourLines() {return colourLines_;} + + /** + * Isolate the colour of the process from the rest of the event. + * Called in the constructor + */ + void colourIsolate(const vector & original, const vector & copy); + + /** + * Update the colour information of a particle prior to insertion into the + * event record. + */ + void updateColour(PPtr particle, bool recursive); + + /** + * Map the colours for a given particle + */ + void mapColour(PPtr original, PPtr copy); + +private: + + /** + * Isolate a specific colour line + */ + void isolateLine(vector::const_iterator cit, + vector & particles, + tcColinePtr oldline, + tColinePtr newline); + +private: + + /** + * The assignment operator is private and must never be called. + * In fact, it should not even be implemented. + */ + ShowerEventRecord & operator=(const ShowerEventRecord &); + + +private: + + /** + * The subprocess currently showered. + */ + SubProPtr subProcess_; + + /** + * Pointer to the XComb which generated the hard process. + */ + StdXCombPtr XComb_; + + /** + * The incoming partons at the current + * stage of the evolution. + */ + PPair incoming_; + + /** + * The outgoing partons at the current stage of the evolution. + */ + PList outgoing_; + + /** + * The intermediate particles at the current + * stage of the evolution. + */ + PList intermediates_; + + /** + * The PDFs to be considered. + */ + pair PDFs_; + + /** + * Momentum fractions of the incoming partons. + */ + pair fractions_; + +private: + + /** + * Type of event + */ + //@{ + /** + * True, if Matchbox MC@NLO S-event + */ + bool isMCatNLOSEvent_; + + /** + * True, if matchbox MC@NLO H-event + */ + bool isMCatNLOHEvent_; + + /** + * True, if Matchbox Powheg S-event + */ + bool isPowhegSEvent_; + + /** + * True, if matchbox Powheg H-event + */ + bool isPowhegHEvent_; + + /** + * The shower approximation to provide the hard scale profile + */ + Ptr::tptr showerApproximation_; + + /** + * Map of colour lines used to reset colours when inserted into the event + */ + map colourLines_; + + /** + * Whether or ont needs truncated shower + */ + bool truncatedShower_; + //@} + +}; + +} + +#endif /* Herwig_ShowerEventRecord_H */ diff --git a/Shower/ShowerHandler.cc b/Shower/ShowerHandler.cc --- a/Shower/ShowerHandler.cc +++ b/Shower/ShowerHandler.cc @@ -1,935 +1,1042 @@ // -*- 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/Shower/QTilde/Base/ShowerTree.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; +tShowerHandlerPtr ShowerHandler::currentHandler_ = tShowerHandlerPtr(); 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_(), + maxtry_(10),maxtryMPI_(10),maxtryDP_(10),maxtryDecay_(100), factorizationScaleFactor_(1.0), renormalizationScaleFactor_(1.0), hardScaleFactor_(1.0), - restrictPhasespace_(true), maxPtIsMuF_(false), - splitHardProcess_(true) { + restrictPhasespace_(true), maxPtIsMuF_(false), + pdfFreezingScale_(2.5*GeV), + doFSR_(true), doISR_(true), + splitHardProcess_(true), + includeSpaceTime_(false), vMin_(0.1*GeV2), + reweight_(1.0) { 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_){ + 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_ + os << remDec_ << ounit(pdfFreezingScale_,GeV) << maxtry_ << maxtryMPI_ << maxtryDP_ << inputparticlesDecayInShower_ << particlesDecayInShower_ << MPIHandler_ << PDFA_ << PDFB_ << PDFARemnant_ << PDFBRemnant_ << includeSpaceTime_ << ounit(vMin_,GeV2) << factorizationScaleFactor_ << renormalizationScaleFactor_ << hardScaleFactor_ << restrictPhasespace_ << maxPtIsMuF_ << hardScaleProfile_ - << splitHardProcess_ << showerVariations_; + << showerVariations_ << doFSR_ << doISR_ << splitHardProcess_; } void ShowerHandler::persistentInput(PersistentIStream & is, int) { - is >> evolver_ >> remDec_ >> iunit(pdfFreezingScale_,GeV) >> maxtry_ + is >> remDec_ >> iunit(pdfFreezingScale_,GeV) >> maxtry_ >> maxtryMPI_ >> maxtryDP_ >> inputparticlesDecayInShower_ >> particlesDecayInShower_ >> MPIHandler_ >> PDFA_ >> PDFB_ >> PDFARemnant_ >> PDFBRemnant_ >> includeSpaceTime_ >> iunit(vMin_,GeV2) >> factorizationScaleFactor_ >> renormalizationScaleFactor_ >> hardScaleFactor_ >> restrictPhasespace_ >> maxPtIsMuF_ >> hardScaleProfile_ - >> splitHardProcess_ >> showerVariations_; + >> showerVariations_ >> doFSR_ >> doISR_ >> splitHardProcess_; } 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); + ("Main driver class for the showering."); 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 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 Command interfaceAddVariation + ("AddVariation", + "Add a shower variation.", + &ShowerHandler::doAddVariation, false); + + static Switch interfaceDoFSR + ("DoFSR", + "Switch on or off final state radiation.", + &ShowerHandler::doFSR_, true, false, false); + static SwitchOption interfaceDoFSROn + (interfaceDoFSR, + "Yes", + "Switch on final state radiation.", + true); + static SwitchOption interfaceDoFSROff + (interfaceDoFSR, + "No", + "Switch off final state radiation.", + false); + static Switch interfaceDoISR + ("DoISR", + "Switch on or off initial state radiation.", + &ShowerHandler::doISR_, true, false, false); + static SwitchOption interfaceDoISROn + (interfaceDoISR, + "Yes", + "Switch on initial state radiation.", + true); + static SwitchOption interfaceDoISROff + (interfaceDoISR, + "No", + "Switch off initial state radiation.", + 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(); + assert(false); } void ShowerHandler::cascade() { - + useMe(); // 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_; - + // get the PDF's from ThePEG (if locally overridden use the local versions) + tcPDFPtr first = PDFA_ ? tcPDFPtr(PDFA_) : firstPDF().pdf(); + tcPDFPtr second = PDFB_ ? tcPDFPtr(PDFB_) : secondPDF().pdf(); resetPDFs(make_pair(first,second)); - + // set the PDFs for the remnant 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; + setCurrentHandler(); // 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; + unSetCurrentHandler(); 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()); + remnantDecayer()->initialize(remnants, incoming_, *currentStep(), pdfFreezingScale()); // do the first forcedSplitting try { - remDec_->doSplit(incomingPartons, make_pair(rempdfs_.first,rempdfs_.second), true); + remnantDecayer()->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; + unSetCurrentHandler(); 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); + remnantDecayer()->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; + unSetCurrentHandler(); 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 = + 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)); +tPPair ShowerHandler::cascade(tSubProPtr, XCPtr) { + assert(false); } 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(); +namespace { + +bool decayProduct(tSubProPtr subProcess, + tPPtr particle) { + // must be time-like and not incoming + if(particle->momentum().m2()<=ZERO|| + particle == subProcess->incoming().first|| + particle == subProcess->incoming().second) return false; + // if only 1 outgoing and this is it + if(subProcess->outgoing().size()==1 && + subProcess->outgoing()[0]==particle) return true; + // must not be the s-channel intermediate otherwise + if(find(subProcess->incoming().first->children().begin(), + subProcess->incoming().first->children().end(),particle)!= + subProcess->incoming().first->children().end()&& + find(subProcess->incoming().second->children().begin(), + subProcess->incoming().second->children().end(),particle)!= + subProcess->incoming().second->children().end()&& + subProcess->incoming().first ->children().size()==1&& + subProcess->incoming().second->children().size()==1) + return false; + // if non-coloured this is enough + if(!particle->dataPtr()->coloured()) return true; + // if coloured must be unstable + if(particle->dataPtr()->stable()) return false; + // must not have same particle type as a child + int id = particle->id(); + for(unsigned int ix=0;ixchildren().size();++ix) + if(particle->children()[ix]->id()==id) return false; + // otherwise its a decaying particle + return true; } +PPtr findParent(PPtr original, bool & isHard, + set outgoingset, + tSubProPtr subProcess) { + PPtr parent=original; + isHard |=(outgoingset.find(original) != outgoingset.end()); + if(!original->parents().empty()) { + PPtr orig=original->parents()[0]; + if(CurrentGenerator::current().currentEventHandler()->currentStep()-> + find(orig)&&decayProduct(subProcess,orig)) { + parent=findParent(orig,isHard,outgoingset,subProcess); + } + } + return parent; +} +} + +void ShowerHandler::findDecayProducts(PPtr in,PerturbativeProcessPtr hard, + DecayProcessMap decay) const { + ParticleVector children=in->children(); + for(ParticleVector::const_iterator it=children.begin(); it!=children.end();++it) { + // if decayed or should be decayed in shower make the PerturbaitveProcess + bool radiates = false; + if(!(**it).children().empty()) { + // remove d,u,s,c,b quarks and leptons other than on-shell taus + if( StandardQCDPartonMatcher::Check((**it).id()) || + ( LeptonMatcher::Check((**it).id()) && !(abs((**it).id())==ParticleID::tauminus && + abs((**it).mass()-(**it).dataPtr()->mass())id()==(**it).id()) { + foundParticle = true; + } + else if((**it).children()[iy]->id()==ParticleID::g || + (**it).children()[iy]->id()==ParticleID::gamma) { + foundGauge = true; + } + } + radiates = foundParticle && foundGauge; + } + } + if(radiates) { + findDecayProducts(*it,hard,decay); + } + else if(!(**it).children().empty()|| + (decaysInShower((**it).id())&&!(**it).dataPtr()->stable())) { + createDecayProcess(in,hard,decay); + } + else { + hard->outgoing().push_back(make_pair(*it,PerturbativeProcessPtr())); + } + } +} + +void ShowerHandler::splitHardProcess(tPVector tagged, PerturbativeProcessPtr & hard, + DecayProcessMap & decay) const { + // temporary storage of the particles + set hardParticles; + // tagged particles in a set + set outgoingset(tagged.begin(),tagged.end()); + bool isHard=false; + // loop over the tagged particles + for (tParticleVector::const_iterator taggedP = tagged.begin(); + taggedP != tagged.end(); ++taggedP) { + // skip remnants + if(eventHandler()->currentCollision()->isRemnant(*taggedP)) continue; + // find the parent and whether its a decaying particle + bool isDecayProd=false; + // check if hard + isHard |=(outgoingset.find(*taggedP) != outgoingset.end()); + if(splitHardProcess_) { + tPPtr parent = *taggedP; + // check if from s channel decaying colourless particle + while(parent&&!parent->parents().empty()&&!isDecayProd) { + parent = parent->parents()[0]; + if(parent == subProcess_->incoming().first || + parent == subProcess_->incoming().second ) break; + isDecayProd = decayProduct(subProcess_,parent); + } + if (isDecayProd) + hardParticles.insert(findParent(parent,isHard,outgoingset,subProcess_)); + } + if (!isDecayProd) + hardParticles.insert(*taggedP); + } + // there must be something to shower + if(hardParticles.empty()) + throw Exception() << "No particles to shower in " + << "ShowerHandler::splitHardProcess()" + << Exception::eventerror; + // must be a hard process + if(!isHard) + throw Exception() << "Starting on decay not yet implemented in " + << "ShowerHandler::splitHardProcess()" + << Exception::runerror; + // create the hard process + hard = new_ptr(PerturbativeProcess()); + // incoming particles + hard->incoming().push_back(make_pair(subProcess_->incoming().first ,PerturbativeProcessPtr())); + hard->incoming().push_back(make_pair(subProcess_->incoming().second,PerturbativeProcessPtr())); + // outgoing particles + for(set::const_iterator it=hardParticles.begin();it!=hardParticles.end();++it) { + // if decayed or should be decayed in shower make the tree + PPtr orig = *it; + bool radiates = false; + if(!orig->children().empty()) { + // remove d,u,s,c,b quarks and leptons other than on-shell taus + if( StandardQCDPartonMatcher::Check(orig->id()) || + ( LeptonMatcher::Check(orig->id()) && + !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())children().size();++iy) { + if(orig->children()[iy]->id()==orig->id()) { + foundParticle = true; + } + else if(orig->children()[iy]->id()==ParticleID::g || + orig->children()[iy]->id()==ParticleID::gamma) { + foundGauge = true; + } + } + radiates = foundParticle && foundGauge; + } + } + if(radiates) { + findDecayProducts(orig,hard,decay); + } + else if(!(**it).children().empty()|| + (decaysInShower((**it).id())&&!(**it).dataPtr()->stable())) { + createDecayProcess(*it,hard,decay); + } + else { + hard->outgoing().push_back(make_pair(*it,PerturbativeProcessPtr())); + } + } +} + +void ShowerHandler::createDecayProcess(PPtr in,PerturbativeProcessPtr hard, DecayProcessMap & decay) const { + // there must be an incoming particle + assert(in); + // create the new process and connect with the parent + PerturbativeProcessPtr newDecay=new_ptr(PerturbativeProcess()); + newDecay->incoming().push_back(make_pair(in,hard)); + Energy width=in->dataPtr()->generateWidth(in->mass()); + decay.insert(make_pair(width,newDecay)); + hard->outgoing().push_back(make_pair(in,newDecay)); + // we need to deal with the decay products if decayed + ParticleVector children = in->children(); + if(!children.empty()) { + for(ParticleVector::const_iterator it = children.begin(); + it!= children.end(); ++it) { + // if decayed or should be decayed in shower make the tree + in->abandonChild(*it); + bool radiates = false; + if(!(**it).children().empty()) { + if(StandardQCDPartonMatcher::Check((**it).id())|| + (LeptonMatcher::Check((**it).id())&& !(abs((**it).id())==ParticleID::tauminus && + abs((**it).mass()-(**it).dataPtr()->mass())id()==(**it).id()) { + foundParticle = true; + } + else if((**it).children()[iy]->id()==ParticleID::g || + (**it).children()[iy]->id()==ParticleID::gamma) { + foundGauge = true; + } + } + radiates = foundParticle && foundGauge; + } + // finally assume all non-decaying particles are in this class + // pr 27/11/15 not sure about this bit + // if(!radiates) { + // radiates = !decaysInShower((**it).id()); + // } + } + if(radiates) { + findDecayProducts(*it,newDecay,decay); + } + else if(!(**it).children().empty()|| + (decaysInShower((**it).id())&&!(**it).dataPtr()->stable())) { + createDecayProcess(*it,newDecay,decay); + } + else { + newDecay->outgoing().push_back(make_pair(*it,PerturbativeProcessPtr())); + } + } + } +} + +void ShowerHandler::decay(PerturbativeProcessPtr process, + DecayProcessMap & decayMap) const { + PPtr parent = process->incoming()[0].first; + assert(parent); + if(parent->spinInfo()) parent->spinInfo()->decay(true); + unsigned int ntry = 0; + ParticleVector children; + while (true) { + // exit if fails + if (++ntry>=maxtryDecay_) + throw Exception() << "Failed to perform decay in ShowerHandler::decay()" + << " after " << maxtryDecay_ + << " attempts for " << parent->PDGName() + << Exception::eventerror; + // select decay mode + tDMPtr dm(parent->data().selectMode(*parent)); + if(!dm) + throw Exception() << "Failed to select decay mode in ShowerHandler::decay()" + << "for " << parent->PDGName() + << Exception::eventerror; + if(!dm->decayer()) + throw Exception() << "No Decayer for selected decay mode " + << " in ShowerHandler::decay()" + << Exception::runerror; + // start of try block + try { + children = dm->decayer()->decay(*dm, *parent); + // if no children have another go + if(children.empty()) continue; + // set up parent + parent->decayMode(dm); + // add children + for (unsigned int i = 0, N = children.size(); i < N; ++i ) { + children[i]->setLabVertex(parent->labDecayVertex()); + //parent->addChild(children[i]); + } + // if succeeded break out of loop + break; + } + catch(Veto) { + } + } + assert(!children.empty()); + for(ParticleVector::const_iterator it = children.begin(); + it!= children.end(); ++it) { + if(!(**it).children().empty()|| + (decaysInShower((**it).id())&&!(**it).dataPtr()->stable())) { + createDecayProcess(*it,process,decayMap); + } + else { + process->outgoing().push_back(make_pair(*it,PerturbativeProcessPtr())); + } + } +} diff --git a/Shower/ShowerHandler.h b/Shower/ShowerHandler.h --- a/Shower/ShowerHandler.h +++ b/Shower/ShowerHandler.h @@ -1,691 +1,766 @@ // -*- 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 "ShowerVariation.h" #include "Herwig/PDF/HwRemDecayer.fh" #include "ThePEG/EventRecord/RemnantParticle.fh" +#include "UEBase.h" +#include "PerturbativeProcess.h" +#include "Herwig/MatrixElement/Matchbox/Matching/HardScaleProfile.h" #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 for a pair of ThePEG::RemnantParticle pointers. + */ typedef pair RemPair; +public: + /** - * The default constructor. + * 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(); /** + * pointer to "this", the current ShowerHandler. + */ + static const tShowerHandlerPtr currentHandler() { + assert(currentHandler_); + return currentHandler_; + } + +public: + + /** * Hook to allow vetoing of event after showering hard sub-process * as in e.g. MLM merging. */ 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_; } - //@} - -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_; } + +public: + + /** + * @name Switches for initial- and final-state radiation + */ + //@{ + /** + * Switch for any radiation + */ + bool doRadiation() const {return doFSR_ || doISR_;} + + /** + * Switch on or off final state radiation. + */ + bool doFSR() const { return doFSR_;} + + /** + * Switch on or off initial state radiation. + */ + bool doISR() const { return doISR_;} //@} - /** - * Access to the Evolver - */ - tEvolverPtr evolver() const {return evolver_;} +public: /** - * Generate hard emissions for CKKW etc + * @name Switches for scales */ - virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const; - + //@{ /** - * Return true, if the shower handler can generate a truncated - * shower for POWHEG style events generated using Matchbox + * Return true if maximum pt should be deduced from the factorization scale */ - virtual bool canHandleMatchboxTrunc() const { return false; } + bool hardScaleIsMuF() const { return maxPtIsMuF_; } /** * The factorization scale factor. */ double factorizationScaleFactor() const { - return factorizationScaleFactor_; + return factorizationScaleFactor_; } /** * The renormalization scale factor. */ double renormalizationScaleFactor() const { - return renormalizationScaleFactor_ ; + return renormalizationScaleFactor_; } /** * The scale factor for the hard scale */ double hardScaleFactor() const { return hardScaleFactor_; } - /** * 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); - - }; +public: /** * 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_; } +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) {} + }; + +public: + + /** @name Functions used by the persistent I/O system. */ + //@{ + /** + * Function used to write out object persistently. + * @param os the persistent output stream written to. + */ + void persistentOutput(PersistentOStream & os) const; + + /** + * Function used to read in object persistently. + * @param is the persistent input stream read from. + * @param version the version number of the object when written. + */ + void persistentInput(PersistentIStream & is, int version); + //@} + + /** + * The standard Init function used to initialize the interfaces. + * Called exactly once for each class by the class description system + * before the main function starts or + * when this class is dynamically loaded. + */ + static void Init(); + +protected: + + /** @name Functions to perform the cascade + */ + //@{ + /** + * The main method which manages the showering of a subprocess. + */ + virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb); + + /** + * Set up for the cascade + */ + void prepareCascade(tSubProPtr sub) { + current_ = currentStep(); + subProcess_ = sub; + } + + /** + * 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); + //@} + protected: /** - * A reweighting factor applied by the showering + * Set/unset the current shower handler */ - double reweight_; + //@{ + /** + * Set the current handler + */ + void setCurrentHandler() { + currentHandler_ = tShowerHandlerPtr(this); + } /** - * The shower variation weights + * Unset the current handler */ - map currentWeights_; + void unSetCurrentHandler() { + currentHandler_ = tShowerHandlerPtr(); + } + //@} +protected: + + /** + * @name Members relating to the underlying event and MPI + */ + //@{ + + /** + * Return true if multiple parton interactions are switched on + * and can be used for this beam setup. + */ + bool isMPIOn() const { + return MPIHandler_ && MPIHandler_->beamOK(); + } + + /** + * Access function for the MPIHandler, it should only be called after + * checking with isMPIOn. + */ + tUEBasePtr getMPIHandler() const { + assert(MPIHandler_); + return MPIHandler_; + } + + /** + * Is a beam particle where hadronic structure is resolved + */ + bool isResolvedHadron(tPPtr); + + /** + * Get the remnants from the ThePEG::PartonBinInstance es and + * do some checks. + */ + RemPair getRemnants(PBIPair incbins); + + /** + * Reset the PDF's after the hard collision has been showered + */ + void setMPIPDFs(); + //@} + +public: + + /** + * Check if a particle decays in the shower + * @param id The PDG code for the particle + */ + bool decaysInShower(long id) const { + return ( particlesDecayInShower_.find( abs(id) ) != + particlesDecayInShower_.end() ); + } + +protected: + + /** + * Members to handle splitting up of hard process and decays + */ + //@{ + + /** + * Split the hard process into production and decays + * @param tagged The tagged particles from the StepHandler + * @param hard The hard perturbative process + * @param decay The decay particles + */ + void splitHardProcess(tPVector tagged, PerturbativeProcessPtr & hard, + DecayProcessMap & decay) const; + + /** + * Decay a particle + */ + void decay(PerturbativeProcessPtr, + DecayProcessMap & decay) const; + + /** + * Find decay products from the hard process and create decay processes + * @param parent The parent particle + * @param hard The hard process + * @param decay The decay processes + */ + void findDecayProducts(PPtr parent, PerturbativeProcessPtr hard, DecayProcessMap decay) const; + + /** + * Find decay products from the hard process and create decay processes + * @param parent The parent particle + * @param hard The parent hard process + * @param decay The decay processes + */ + void createDecayProcess(PPtr parent,PerturbativeProcessPtr hard, DecayProcessMap & decay) const; + //@} + + /** + * @name Functions to return information relevant to the process being showered + */ + //@{ + /** + * Return the currently used SubProcess. + */ + tSubProPtr currentSubProcess() const { + assert(subProcess_); + return subProcess_; + } + + /** + * Access to the incoming beam particles + */ + tPPair incomingBeams() const { + return incoming_; + } + //@} + +protected: + + /** + * Weight handling for shower variations + */ + //@ /** * Combine the variation weights which have been encountered */ void combineWeights(); /** * Initialise the weights in currentEvent() */ void initializeWeights(); /** * Reset the current weights */ void resetWeights(); + //@} + + + + /** + * Return true, if the shower handler can generate a truncated + * shower for POWHEG style events generated using Matchbox + */ + virtual bool canHandleMatchboxTrunc() const { return false; } + + + + + + +protected: + + /** + * Return the maximum number of attempts for showering + * a given subprocess. + */ + unsigned int maxtry() const { return maxtry_; } 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. + * pointer to "this", the current ShowerHandler. */ - tUEBasePtr getMPIHandler() const { - assert(MPIHandler_); - return MPIHandler_; - } - -private: + static tShowerHandlerPtr currentHandler_; /** * 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_; +private: /** - * The PDF for beam particle B. Overrides the particle's own PDF setting. + * Maximum tries for various stages of the showering process */ - 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 + * Maximum number of attempts to generate a decay */ - set particlesDecayInShower_; + unsigned int maxtryDecay_; + //@} + +private: /** - * PDG codes of the particles which decay during showering - * this is a vector that is interfaced so they can be changed + * Factors for the various scales */ - 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_; /** * 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_; + //@} +private: + + /** + * Storage of information about the current event + */ + //@{ + /** + * The incoming beam particles for the current collision + */ + tPPair incoming_; + + /** + * Boost to get back to the lab + */ + LorentzRotation boost_; + + /** + * Const pointer to the currently handeled ThePEG::SubProcess + */ + tSubProPtr subProcess_; + + /** + * Const pointer to the current step + */ + tcStepPtr current_; + //@} + +private: + + /** + * PDFs to be used for the various stages and related parameters + */ + //@{ + /** + * The PDF freezing scale + */ + Energy pdfFreezingScale_; + + /** + * 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 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_; + //@} + +private: + + /** + * @name Parameters for initial- and final-state radiation + */ + //@{ + /** + * Switch on or off final state radiation. + */ + bool doFSR_; + + /** + * Switch on or off initial state radiation. + */ + bool doISR_; + //@} + +private: + + /** + * @name Parameters for particle decays + */ + //@{ /** * Whether or not to split into hard and decay trees */ bool splitHardProcess_; /** + * 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_; + //@} + +private: + + /** + * Parameters for the space-time model + */ + //@{ + /** + * Whether or not to include spa-cetime distances in the shower + */ + bool includeSpaceTime_; + + /** + * The minimum virtuality for the space-time model + */ + Energy2 vMin_; + //@} + +private: + + /** + * Parameters relevant for reweight and variations + */ + //@{ + /** * 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 + /** + * A reweighting factor applied by the showering */ - 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) {} - }; + double reweight_; /** - * pointer to "this", the current ShowerHandler. + * The shower variation weights */ - static ShowerHandler * currentHandler() { - assert(currentHandler_); - return currentHandler_; - } - -protected: - - /** - * Set the current handler - */ - void setCurrentHandler() { - currentHandler_ = this; - } - + map currentWeights_; + //@} }; -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/Shower/ShowerVariation.cc b/Shower/ShowerVariation.cc new file mode 100644 --- /dev/null +++ b/Shower/ShowerVariation.cc @@ -0,0 +1,47 @@ +// -*- C++ -*- +// +// ShowerVariation.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 ShowerVariation class. +// + +#include "ShowerVariation.h" + +using namespace Herwig; + +string 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 ShowerVariation::put(PersistentOStream& os) const { + os << renormalizationScaleFactor << factorizationScaleFactor + << firstInteraction << secondaryInteractions; +} + +void ShowerVariation::get(PersistentIStream& is) { + is >> renormalizationScaleFactor >> factorizationScaleFactor + >> firstInteraction >> secondaryInteractions; +} diff --git a/Shower/ShowerVariation.h b/Shower/ShowerVariation.h new file mode 100644 --- /dev/null +++ b/Shower/ShowerVariation.h @@ -0,0 +1,78 @@ +// -*- C++ -*- +// +// ShowerVariation.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_ShowerVariation_H +#define HERWIG_ShowerVariation_H + +#include "ThePEG/Persistency/PersistentOStream.h" +#include "ThePEG/Persistency/PersistentIStream.h" + +namespace Herwig { + +using namespace ThePEG; + +/** + * A struct identifying a shower variation + */ +struct ShowerVariation { + + /** + * Default constructor + */ + ShowerVariation() : renormalizationScaleFactor(1.0), + factorizationScaleFactor(1.0), + firstInteraction(true), + secondaryInteractions(false) {} + + /** + * 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; + + /** + * 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); + +}; + +inline PersistentOStream& operator<<(PersistentOStream& os, const ShowerVariation& var) { + var.put(os); return os; +} + +inline PersistentIStream& operator>>(PersistentIStream& is, ShowerVariation& var) { + var.get(is); return is; +} + +} +#endif /* HERWIG_ShowerVariation_H */ diff --git a/Shower/SplittingFunctions/SplittingGenerator.h b/Shower/SplittingFunctions/SplittingGenerator.h deleted file mode 100644 --- a/Shower/SplittingFunctions/SplittingGenerator.h +++ /dev/null @@ -1,360 +0,0 @@ -// -*- C++ -*- -// -// SplittingGenerator.h is a part of Herwig - A multi-purpose Monte Carlo event generator -// Copyright (C) 2002-2011 The Herwig Collaboration -// -// Herwig is licenced under version 2 of the GPL, see COPYING for details. -// Please respect the MCnet academic guidelines, see GUIDELINES for details. -// -#ifndef HERWIG_SplittingGenerator_H -#define HERWIG_SplittingGenerator_H -// -// This is the declaration of the SplittingGenerator class. -// - -#include "ThePEG/Interface/Interfaced.h" -#include "Herwig/Shower/Base/Branching.h" -#include "Herwig/Shower/Base/SudakovFormFactor.h" -#include "SplittingGenerator.fh" -#include "Herwig/Shower/Base/ShowerParticle.h" -#include "Herwig/Shower/Base/ShowerKinematics.h" - -namespace Herwig { - -using namespace ThePEG; - -/** \ingroup Shower - * - * This class is responsible for creating, at the beginning of the Run, - * all the SplittingFunction objects and the corresponding - * SudakovFormFactor objects, and then of the generation of splittings - * (radiation emissions) during the event. - * Many switches are defined in this class which allowed the user to turn on/off: - * - each type of interaction (QCD, QED, EWK,...); - * - initial- and final-state radiation for all type of interactions; - * - initial- and final-state radiation for each type of interaction; - * - each type of splitting (\f$u\to ug\f$, \f$d\to dg\f$, \f$\ldots\f$, - * \f$g\to gg\f$, \f$g\to u\bar{u}\f$, \f$\ldots\f$). - * - * These switches are useful mainly for debugging, but eventually can - * also be used for a "quick and dirty" estimation of systematic errors. - * - * In the future it should be possible to implement in this class - * - * - the \f$1\to2\f$ azimuthal correlations for soft emission due to QCD coherence - * using the ShowerParticle object provided in the input. - * - Similarly having the \f$\rho-D\f$ matrix and the SplittingFunction pointer - * it should be possible to implement the spin correlations. - * - * @see SudakovFormFactor - * @see SplitFun - * - * @see \ref SplittingGeneratorInterfaces "The interfaces" - * defined for SplittingGenerator. - */ -class SplittingGenerator: public Interfaced { - -public: - - /** @name Standard constructors and destructors. */ - //@{ - /** - * The default constructor. - */ - SplittingGenerator() : _isr_Mode(1), _fsr_Mode(1), _deTuning(1.) {} - //@} - -public: - - /** - * Methods to select the next branching and reconstruct the kinematics - */ - //@{ - /** - * Choose a new forward branching for a time-like particle - * The method returns: - * - a pointer to a ShowerKinematics object, which - * contains the information about the new scale and all other - * kinematics variables that need to be generated simultaneously; - * - a pointer to the SudakovFormFactor object associated - * with the chosen emission. - * - The PDG codes of the particles in the branching, - * as a Branching struct. - * - * In the case no branching has been generated, both the returned - * pointers are null ( ShoKinPtr() , tSudakovFFPtr() ). - * - * @param particle The particle to be evolved - * @param enhance The factor by which to ehnace the emission of radiation - * @param type The type of interaction to generate - * @return The Branching struct for the branching - */ - Branching chooseForwardBranching(ShowerParticle & particle, - double enhance, - ShowerInteraction::Type type) const; - - /** - * Select the next branching of a particles for the initial-state shower - * in the particle's decay. - * @param particle The particle being showerwed - * @param maxscale The maximum scale - * @param minmass Minimum mass of the particle after the branching - * @param enhance The factor by which to ehnace the emission of radiation - * @param type The type of interaction to generate - * @return The Branching struct for the branching - */ - Branching chooseDecayBranching(ShowerParticle & particle, - const ShowerParticle::EvolutionScales & maxScales, - Energy minmass,double enhance, - ShowerInteraction::Type type) const; - - /** - * Choose a new backward branching for a space-like particle. - * The method returns: - * - a pointer to a ShowerKinematics object, which - * contains the information about the new scale and all other - * kinematics variables that need to be generated simultaneously; - * - a pointer to the SudakovFormFactor object associated - * with the chosen emission. - * - The PDG codes of the particles in the branching, - * as a Branching struct. - * - * In the case no branching has been generated, both the returned - * pointers are null ( ShoKinPtr() , tSudakovFFPtr() ). - * - * @param particle The particle to be evolved - * @param enhance The factor by which to ehnace the emission of radiation - * @param beamparticle The beam particle - * @param beam The BeamParticleData object - * @param type The type of interaction to generate - * @return The Branching struct for the branching - */ - Branching - chooseBackwardBranching(ShowerParticle & particle, - PPtr beamparticle, - double enhance, - Ptr::transient_const_pointer beam, - ShowerInteraction::Type type, - tcPDFPtr , Energy ) const; - //@} - -public: - - /** - * Access to the switches - */ - //@{ - /** - * It returns true/false if the initial-state radiation is on/off. - */ - bool isISRadiationON() const { return _isr_Mode; } - - /** - * It returns true/false if the final-state radiation is on/off. - */ - bool isFSRadiationON() const { return _fsr_Mode; } - //@} - - /** - * Methods to parse the information from the input files to create the - * branchings - */ - //@{ - /** - * Add a final-state splitting - */ - string addFinalSplitting(string arg) { return addSplitting(arg,true); } - - /** - * Add an initial-state splitting - */ - string addInitialSplitting(string arg) { return addSplitting(arg,false); } - - /** - * Add a final-state splitting - */ - string deleteFinalSplitting(string arg) { return deleteSplitting(arg,true); } - - /** - * Add an initial-state splitting - */ - string deleteInitialSplitting(string arg) { return deleteSplitting(arg,false); } - //@} - - /** - * Access to the splittings - */ - //@{ - /** - * Access the final-state branchings - */ - const BranchingList & finalStateBranchings() const { return _fbranchings; } - - /** - * Access the initial-state branchings - */ - const BranchingList & initialStateBranchings() const { return _bbranchings; } - //@} - - /** - * Set the factorization scale factor - */ - void factorizationScaleFactor(double f); - - /** - * Set the renormalization scale factor - */ - void renormalizationScaleFactor(double f); - -public: - - /** @name Functions used by the persistent I/O system. */ - //@{ - /** - * Function used to write out object persistently. - * @param os the persistent output stream written to. - */ - void persistentOutput(PersistentOStream & os) const; - - /** - * Function used to read in object persistently. - * @param is the persistent input stream read from. - * @param version the version number of the object when written. - */ - void persistentInput(PersistentIStream & is, int version); - //@} - - /** - * The standard Init function used to initialize the interfaces. - * Called exactly once for each class by the class description system - * before the main function starts or - * when this class is dynamically loaded. - */ - static void Init(); - -protected: - - /** @name Clone Methods. */ - //@{ - /** - * Make a simple clone of this object. - * @return a pointer to the new object. - */ - virtual IBPtr clone() const; - - /** Make a clone of this object, possibly modifying the cloned object - * to make it sane. - * @return a pointer to the new object. - */ - virtual IBPtr fullclone() const; - //@} - -protected: - - /** @name Standard Interfaced functions. */ - //@{ - /** - * Rebind pointer to other Interfaced objects. Called in the setup phase - * after all objects used in an EventGenerator has been cloned so that - * the pointers will refer to the cloned objects afterwards. - * @param trans a TranslationMap relating the original objects to - * their respective clones. - * @throws RebindException if no cloned object was found for a given - * pointer. - */ - virtual void rebind(const TranslationMap & trans) - ; - - /** - * Return a vector of all pointers to Interfaced objects used in this - * object. - * @return a vector of pointers. - */ - virtual IVector getReferences(); - //@} - -private: - - /** - * Add a branching to the map - * @param ids PDG coeds of the particles in the branching - * @param sudakov The SudakovFormFactor for the branching - * @param final Whether this is an initial- or final-state branching - */ - void addToMap(const IdList & ids, const SudakovPtr & sudakov, bool final); - - /** - * Remove a branching to the map - * @param ids PDG coeds of the particles in the branching - * @param sudakov The SudakovFormFactor for the branching - * @param final Whether this is an initial- or final-state branching - */ - void deleteFromMap(const IdList & ids, const SudakovPtr & sudakov, bool final); - - /** - * Obtain the reference vectors for a final-state particle - * @param particle The particle - * @param p The p reference vector - * @param n The n reference vector - */ - void finalStateBasisVectors(ShowerParticle particle, Lorentz5Momentum & p, - Lorentz5Momentum & n) const; - - /** - * Add a splitting - * @param in string to be parsed - * @param final Whether this is an initial- or final-state branching - */ - string addSplitting(string in ,bool final); - - /** - * Delete a splitting - * @param in string to be parsed - * @param final Whether this is an initial- or final-state branching - */ - string deleteSplitting(string in ,bool final); - -private: - - /** - * The assignment operator is private and must never be called. - * In fact, it should not even be implemented. - */ - SplittingGenerator & operator=(const SplittingGenerator &); - -private: - - /** - * Switches to control the radiation - */ - //@{ - /** - * Is inqitial-state radiation on/off - */ - bool _isr_Mode; - - /** - * Is final-state radiation on/off - */ - bool _fsr_Mode; - //@} - - /** - * List of the branchings and the appropriate Sudakovs for forward branchings - */ - BranchingList _fbranchings; - - /** - * Lists of the branchings and the appropriate Sudakovs for backward branchings. - */ - BranchingList _bbranchings; - - /** - * The detuning parameter - */ - double _deTuning; -}; - -} - -#endif /* HERWIG_SplittingGenerator_H */ diff --git a/Tests/Rivet/Templates/DIS-Powheg.in b/Tests/Rivet/Templates/DIS-Powheg.in --- a/Tests/Rivet/Templates/DIS-Powheg.in +++ b/Tests/Rivet/Templates/DIS-Powheg.in @@ -1,56 +1,56 @@ ################################################## # Example generator based on DIS parameters # usage: Herwig read DIS.in ################################################## read Matchbox/Powheg-Default-ShowerAlphaSTune.in set /Herwig/Particles/e-:PDF /Herwig/Partons/NoPDF set /Herwig/Particles/e+:PDF /Herwig/Partons/NoPDF # switch off final-state electron/muon FSR do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting e-->e-,gamma; /Herwig/Shower/LtoLGammaSudakov do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting mu-->mu-,gamma; /Herwig/Shower/LtoLGammaSudakov do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting tau-->tau-,gamma; /Herwig/Shower/LtoLGammaSudakov set /Herwig/Shower/KinematicsReconstructor:ReconstructionOption Colour ################################################## # Need to use an NLO PDF ################################################## set /Herwig/Particles/p+:PDF /Herwig/Partons/HardNLOPDF set /Herwig/Particles/pbar-:PDF /Herwig/Partons/HardNLOPDF set /Herwig/Shower/ShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF set /Herwig/Partons/MPIExtractor:FirstPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/HardNLOPDF ################################################## # Setup the POWHEG shower ################################################## cd /Herwig/Shower -set Evolver:IntrinsicPtGaussian 1.9*GeV -set Evolver:HardEmissionMode POWHEG +set ShowerHandler:IntrinsicPtGaussian 1.9*GeV +set ShowerHandler:HardEmission POWHEG cd /Herwig/MatrixElements/ # Neutral current DIS insert SimpleDIS:MatrixElements[0] /Herwig/MatrixElements/PowhegMEDISNC ${process} cd /Herwig/Generators set DISGenerator:NumberOfEvents 10000000 set DISGenerator:RandomNumberGenerator:Seed 31122001 set DISGenerator:DebugLevel 0 set DISGenerator:PrintEvent 10 set DISGenerator:MaxErrors 1000000 set /Herwig/Shower/ShowerHandler:MPIHandler NULL cd /Herwig/Generators create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so insert DISGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis mv /Herwig/Generators/DISGenerator /Herwig/Generators/EventGenerator read ${parameterFile} ################################################## # Save run for later usage with 'Herwig run' ################################################## cd /Herwig/Generators saverun ${runname} EventGenerator diff --git a/Tests/Rivet/Templates/Hadron-Gamma.in b/Tests/Rivet/Templates/Hadron-Gamma.in --- a/Tests/Rivet/Templates/Hadron-Gamma.in +++ b/Tests/Rivet/Templates/Hadron-Gamma.in @@ -1,54 +1,57 @@ +# -*- ThePEG-repository -*- ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 1000000 set LHCGenerator:EventHandler:StatLevel Full set LHCGenerator:EventHandler:Sampler:Ntry 10000 set /Herwig/Partons/QCDExtractor:FlatSHatY 0 ################################################## # Change the proton PDFs to those for photon radiation ################################################## set /Herwig/Particles/p+:PDF /Herwig/Partons/BudnevPDF set /Herwig/Particles/pbar-:PDF /Herwig/Partons/BudnevPDF set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/BudnevPDF set /Herwig/Partons/QCDExtractor:SecondPDF /Herwig/Partons/BudnevPDF +set /Herwig/Shower/ShowerHandler:PDFA NULL +set /Herwig/Shower/ShowerHandler:PDFB NULL # No MPI set LHCGenerator:EventHandler:CascadeHandler:MPIHandler NULL ################################################## # Create the Herwig analysis ################################################## create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis set /Herwig/Analysis/RivetAnalysis:Debug No ################################################## # Cuts ################################################## cd /Herwig/Cuts set QCDCuts:ScaleMin 0.0*GeV set QCDCuts:X1Min 0 set QCDCuts:X2Min 0 set QCDCuts:X1Max 1. set QCDCuts:X2Max 1. set QCDCuts:MHatMin 1.*GeV erase QCDCuts:MultiCuts 0 set LeptonKtCut:MinKT 3*GeV mv /Herwig/Generators/LHCGenerator /Herwig/Generators/EventGenerator cd /Herwig/MatrixElements ${process} cd /Herwig/Generators read ${parameterFile} ################################################## # Save run for later usage with 'Herwig run' ################################################## cd /Herwig/Generators saverun ${runname} EventGenerator diff --git a/Tests/Rivet/Templates/Hadron-Powheg.in b/Tests/Rivet/Templates/Hadron-Powheg.in --- a/Tests/Rivet/Templates/Hadron-Powheg.in +++ b/Tests/Rivet/Templates/Hadron-Powheg.in @@ -1,49 +1,49 @@ ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 1000000 ################################################## # Need to use an NLO PDF ################################################## set /Herwig/Particles/p+:PDF /Herwig/Partons/HardNLOPDF set /Herwig/Particles/pbar-:PDF /Herwig/Partons/HardNLOPDF set /Herwig/Shower/ShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF set /Herwig/Shower/ShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF set /Herwig/Partons/MPIExtractor:FirstPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/MPIExtractor:SecondPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/HardNLOPDF set /Herwig/Partons/QCDExtractor:SecondPDF /Herwig/Partons/HardNLOPDF ################################################## # Setup the POWHEG shower ################################################## cd /Herwig/Shower -set Evolver:IntrinsicPtGaussian 1.9*GeV -set Evolver:HardEmissionMode POWHEG +set ShowerHandler:IntrinsicPtGaussian 1.9*GeV +set ShowerHandler:HardEmission POWHEG read Matchbox/Powheg-Default-ShowerAlphaSTune.in ################################################## # Create the Herwig analysis ################################################## cd /Herwig/Generators create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis mv /Herwig/Generators/LHCGenerator /Herwig/Generators/EventGenerator cd /Herwig/MatrixElements ${process} cd /Herwig/Generators read ${parameterFile} ################################################## # Save run for later usage with 'Herwig run' ################################################## cd /Herwig/Generators saverun ${runname} EventGenerator diff --git a/Tests/Rivet/Templates/LEP-Powheg.in b/Tests/Rivet/Templates/LEP-Powheg.in --- a/Tests/Rivet/Templates/LEP-Powheg.in +++ b/Tests/Rivet/Templates/LEP-Powheg.in @@ -1,45 +1,45 @@ ################################################## # base parameters for LEP analyses ################################################## ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators read Matchbox/Powheg-Default-ShowerAlphaSTune.in set LEPGenerator:NumberOfEvents 100000000 set LEPGenerator:RandomNumberGenerator:Seed 31122001 set LEPGenerator:DebugLevel 0 set LEPGenerator:PrintEvent 10 set LEPGenerator:MaxErrors 1000000 # no MPI set LEPGenerator:EventHandler:CascadeHandler:MPIHandler NULL ################################################## # Switch off ISR ################################################## set /Herwig/Particles/e-:PDF /Herwig/Partons/NoPDF set /Herwig/Particles/e+:PDF /Herwig/Partons/NoPDF ################################################## # Create the Herwig analysis ################################################## create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis ################################################## # Use the NLO q qbar matrix element ################################################## -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG insert /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/PowhegMEee2gZ2qq ${process} set /Herwig/Shower/PartnerFinder:QEDPartner IIandFF mv /Herwig/Generators/LEPGenerator /Herwig/Generators/EventGenerator read ${parameterFile} ################################################## # Save run for later usage with 'Herwig run' ################################################## cd /Herwig/Generators saverun ${runname} EventGenerator diff --git a/Tests/python/make_input_files.py b/Tests/python/make_input_files.py --- a/Tests/python/make_input_files.py +++ b/Tests/python/make_input_files.py @@ -1,1483 +1,1508 @@ #! /usr/bin/env python import logging,sys,os from string import strip, Template import sys if sys.version_info[:3] < (2,4,0): print "rivet scripts require Python version >= 2.4.0... exiting" sys.exit(1) if __name__ == "__main__": import logging from optparse import OptionParser, OptionGroup parser = OptionParser(usage="%prog name [...]") (opts, args) = parser.parse_args() ## Check args if len(args) != 1: logging.error("Must specify at least input file") sys.exit(1) name=args[0] collider="" # select the template to load # collider parameters = {} if(name.find("BFactory")==0) : collider="BFactory" elif(name.find("LEP")==0) : collider="LEP" elif(name.find("DIS")==0) : collider="DIS" elif(name.find("TVT")==0) : collider="TVT" elif(name.find("LHC-GammaGamma")==0) : collider="LHC-GammaGamma" elif(name.find("LHC")==0) : collider="LHC" elif(name.find("ISR")==0) : collider="ISR" elif(name.find("SppS")==0) : collider="SppS" elif(name.find("Star")==0) : collider="Star" simulation="" istart = 1 print name if(name.find("Matchbox-Powheg")>0) : istart = 3 simulation="Matchbox" parameters["shower"] = "read Matchbox/Powheg-DefaultShower.in\n" elif(name.find("Matchbox")>0) : istart = 2 simulation="Matchbox" parameters["shower"] = "read Matchbox/MCatNLO-DefaultShower.in\n" elif(name.find("Dipole")>0) : istart = 2 simulation="Matchbox" parameters["shower"] = "read Matchbox/MCatNLO-DipoleShower.in\n" elif(name.find("Powheg")>0) : istart = 2 simulation="Powheg" if(simulation=="Matchbox") : parameters["bscheme"] = "read Matchbox/FiveFlavourScheme.in\n" if(parameters["shower"].find("Dipole")>=0) : parameters["bscheme"] += "read Matchbox/FiveFlavourNoBMassScheme.in\n" if(collider.find("DIS")<0) : parameters["nlo"] = "read Matchbox/MadGraph-OpenLoops.in\n" if(collider=="") : logging.error("Can\'t find collider") sys.exit(1) # find the template if(simulation=="") : if(collider.find("LHC-GammaGamma") >=0) : istart += 1 templateName="Hadron-Gamma.in" elif(collider.find("TVT")>=0 or collider.find("LHC") >=0 or collider.find("ISR")>=0 or collider.find("SppS")>=0 or collider.find("Star")>=0) : templateName="Hadron.in" elif(collider.find("BFactory")<0) : templateName= "%s.in" % (collider) else : templateName= "LEP.in" else : if(collider.find("TVT")>=0 or collider.find("LHC") >=0 or collider.find("ISR")>=0 or collider.find("SppS")>=0 or collider.find("Star")>=0) : templateName= "Hadron-%s.in" % (simulation) elif(collider.find("BFactory")<0) : templateName= "%s-%s.in" % (collider,simulation) else : templateName= "LEP-%s.in" % (simulation) with open(os.path.join("Rivet/Templates",templateName), 'r') as f: templateText = f.read() template = Template( templateText ) # work out the name of the parameter file nameSplit=name.split("-") parameterName=nameSplit[istart] for i in range(istart+1,len(nameSplit)) : parameterName += "-%s" % nameSplit[i] # work out the process and parameters process="" # Bfactory if(collider=="BFactory") : if(simulation=="") : if(parameterName=="10.58-res") : process += "\ncreate Herwig::MEee2VectorMeson /Herwig/MatrixElements/MEUpsilon HwMELepton.so\nset /Herwig/MatrixElements/MEUpsilon:VectorMeson /Herwig/Particles/Upsilon(4S)\nset /Herwig/MatrixElements/MEUpsilon:Coupling 0.0004151809\nset /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEUpsilon" elif(parameterName=="10.58") : process += "\ncreate Herwig::MEee2VectorMeson /Herwig/MatrixElements/MEUpsilon HwMELepton.so\nset /Herwig/MatrixElements/MEUpsilon:VectorMeson /Herwig/Particles/Upsilon(4S)\nset /Herwig/MatrixElements/MEUpsilon:Coupling 0.0004151809\ninsert /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEUpsilon\n" process += "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4\n" else : process += "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4\n" elif(simulation=="Powheg") : process = "set /Herwig/MatrixElements/PowhegMEee2gZ2qq:MaximumFlavour 4\n" elif(simulation=="Matchbox" ) : process = "do Factory:Process e- e+ -> u ubar\ndo Factory:Process e- e+ -> d dbar\ndo Factory:Process e- e+ -> c cbar\ndo Factory:Process e- e+ -> s sbar\n" # DIS elif(collider=="DIS") : if(simulation=="") : if(parameterName.find("NoME")>=0) : - process = "set /Herwig/Shower/Evolver:MECorrMode 0" + process = "set /Herwig/Shower/ShowerHandler:HardEmission None" parameterName=parameterName.replace("NoME-","") else : process = "" elif(simulation=="Powheg") : process = "" elif(simulation=="Matchbox" ) : if(parameterName.find("e-")>=0) : process="do Factory:Process e- p -> e- j" else : process="do Factory:Process e+ p -> e+ j" # LEP elif(collider=="LEP") : if(simulation=="") : process="" if(parameterName=="10") : process="set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4" elif(simulation=="Powheg") : process="" if(parameterName=="10") : process="set /Herwig/MatrixElements/PowhegMEee2gZ2qq:MaximumFlavour 4" elif(simulation=="Matchbox" ) : if(parameterName=="10") : process="do Factory:Process e- e+ -> u ubar\ndo Factory:Process e- e+ -> d dbar\ndo Factory:Process e- e+ -> c cbar\ndo Factory:Process e- e+ -> s sbar" else : process="do Factory:Process e- e+ -> j j" # TVT elif(collider=="TVT") : process="set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/pbar-\n" if(parameterName.find("Run-II")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 1960.0\n" elif(parameterName.find("Run-I")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 1800.0\n" elif(parameterName.find("900")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 900.0\n" elif(parameterName.find("630")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 630.0\n" elif(parameterName.find("300")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 300.0\n" if(simulation=="") : if(parameterName.find("PromptPhoton")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaJet\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 15.\n" elif(parameterName.find("DiPhoton-GammaGamma")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaGamma\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaGamma","") elif(parameterName.find("DiPhoton-GammaJet")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaJet\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaJet","") elif(parameterName.find("UE")>=0) : process += "insert SimpleQCD:MatrixElements[0] MEMinBias\n" process += "set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" process += "set /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts\n" process += "create Herwig::MPIXSecReweighter /Herwig/Generators/MPIXSecReweighter\n" process += "insert /Herwig/Generators/EventGenerator:EventHandler:PostSubProcessHandlers 0 /Herwig/Generators/MPIXSecReweighter\n" process += "set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n" process += "set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n" elif(parameterName.find("Jets")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEQCD2to2\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if(parameterName.find("Run-II-Jets-10")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 500.*GeV\n" elif(parameterName.find("Run-II-Jets-11")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 900.*GeV\n" elif(parameterName.find("Run-I-Jets-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" elif(parameterName.find("Run-I-Jets-2")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 40.\n" elif(parameterName.find("Run-I-Jets-3")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 65.\n" elif(parameterName.find("Run-I-Jets-4")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 90.\n" elif(parameterName.find("Run-I-Jets-5")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 160.\n" elif(parameterName.find("Run-I-Jets-6")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 100.*GeV\n" elif(parameterName.find("Run-I-Jets-7")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 400.*GeV\n" elif(parameterName.find("Run-I-Jets-8")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 700.*GeV\n" elif(parameterName.find("Run-II-Jets-0")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 15.\n" elif(parameterName.find("Run-II-Jets-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 25.\n" elif(parameterName.find("Run-II-Jets-2")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 40.\n" elif(parameterName.find("Run-II-Jets-3")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 60.\n" elif(parameterName.find("Run-II-Jets-4")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 85.\n" elif(parameterName.find("Run-II-Jets-5")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 110.\n" elif(parameterName.find("Run-II-Jets-6")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 160.\n" elif(parameterName.find("Run-II-Jets-7")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 250.\n" elif(parameterName.find("Run-II-Jets-8")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 100.*GeV\n" elif(parameterName.find("Run-II-Jets-9")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 300.*GeV\n" elif(parameterName.find("900-Jets-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 10.\n" elif(parameterName.find("300-Jets-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 6.\n" elif(parameterName.find("630-Jets-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" elif(parameterName.find("630-Jets-2")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 40.\n" elif(parameterName.find("630-Jets-3")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 75.\n" elif(parameterName.find("900-Jets-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 10.\n" elif(parameterName.find("Run-I-WZ")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Electron\ninsert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" elif(parameterName.find("Run-I-W")>=0 or parameterName.find("Run-II-W")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Electron\n" elif(parameterName.find("Run-I-Z")>=0 or parameterName.find("Run-II-Z-e")>=0) : process +="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" elif(parameterName.find("Run-II-Z-LowMass-mu")>=0) : process +="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 25*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n" elif(parameterName.find("Run-II-Z-HighMass-mu")>=0) : process +="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 150*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 600*GeV\n" elif(parameterName.find("Run-II-Z-mu")>=0) : process +="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" elif(simulation=="Powheg") : if(parameterName.find("Run-I-WZ")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Electron\ninsert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" elif(parameterName.find("Run-I-W")>=0 or parameterName.find("Run-II-W")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Electron\n" elif(parameterName.find("Run-I-Z")>=0 or parameterName.find("Run-II-Z-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" elif(parameterName.find("Run-II-Z-LowMass-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 25*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n" elif(parameterName.find("Run-II-Z-HighMass-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 150*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 600*GeV\n" elif(parameterName.find("Run-II-Z-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" elif(parameterName.find("DiPhoton-GammaGamma")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaGammaPowheg\n" process+="set MEGammaGammaPowheg:Process GammaGamma\n" process+="insert SimpleQCD:MatrixElements[0] MEGammaGamma\n" process+="set MEGammaGamma:Process gg\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaGamma","") elif(parameterName.find("DiPhoton-GammaJet")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaGammaPowheg\n" process+="set MEGammaGammaPowheg:Process VJet\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaJet","") elif(simulation=="Matchbox" ) : if(parameterName.find("Jets")>=0) : process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n" process+="do Factory:Process p p j j\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if(parameterName.find("Run-II-Jets-10")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 500.*GeV\n" elif(parameterName.find("Run-II-Jets-11")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 900.*GeV\n" elif(parameterName.find("Run-II-Jets-12")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 300.*GeV\n" elif(parameterName.find("Run-I-Jets-1")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n" elif(parameterName.find("Run-I-Jets-2")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 40.\n" elif(parameterName.find("Run-I-Jets-3")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 65.\n" elif(parameterName.find("Run-I-Jets-4")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 90.\n" elif(parameterName.find("Run-I-Jets-5")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 160.\n" elif(parameterName.find("Run-I-Jets-6")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 100.*GeV\n" elif(parameterName.find("Run-I-Jets-7")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 400.*GeV\n" elif(parameterName.find("Run-I-Jets-8")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 700.*GeV\n" elif(parameterName.find("Run-II-Jets-0")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 15.\n" elif(parameterName.find("Run-II-Jets-1")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 25.\n" elif(parameterName.find("Run-II-Jets-2")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 40.\n" elif(parameterName.find("Run-II-Jets-3")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 60.\n" elif(parameterName.find("Run-II-Jets-4")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 85.\n" elif(parameterName.find("Run-II-Jets-5")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 110.\n" elif(parameterName.find("Run-II-Jets-6")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 160.\n" elif(parameterName.find("Run-II-Jets-7")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 250.\n" elif(parameterName.find("Run-II-Jets-8")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 100.*GeV\n" elif(parameterName.find("Run-II-Jets-9")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 300.*GeV\n" elif(parameterName.find("900-Jets-1")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 10.\n" elif(parameterName.find("300-Jets-1")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 6.\n" elif(parameterName.find("630-Jets-1")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n" elif(parameterName.find("630-Jets-2")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 40.\n" elif(parameterName.find("630-Jets-3")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 75.\n" elif(parameterName.find("900-Jets-1")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 10.\n" elif(parameterName.find("Run-I-WZ")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar e+ e-\ndo Factory:Process p pbar e+ nu\ndo Factory:Process p pbar e- nu\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("Run-I-W")>=0 or parameterName.find("Run-II-W")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar e+ nu\ndo Factory:Process p pbar e- nu\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("Run-I-Z")>=0 or parameterName.find("Run-II-Z-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar e+ e-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("Run-II-Z-LowMass-mu")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar mu+ mu-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 25*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n" elif(parameterName.find("Run-II-Z-HighMass-mu")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar mu+ mu-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 150.*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 600*GeV\n" elif(parameterName.find("Run-II-Z-mu")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar mu+ mu-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" # Star elif(collider=="Star" ) : process = "set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n" process+= "set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n" process+= "set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/p+\n" process+= "set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 200.0\n" process+= "set /Herwig/Cuts/QCDCuts:X2Min 0.01\n" if(simulation=="") : if(parameterName.find("UE")>=0) : process += "insert SimpleQCD:MatrixElements[0] MEMinBias\n" process += "set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" process += "set /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts\n" process += "create Herwig::MPIXSecReweighter /Herwig/Generators/MPIXSecReweighter\n" process += "insert /Herwig/Generators/EventGenerator:EventHandler:PostSubProcessHandlers 0 /Herwig/Generators/MPIXSecReweighter\n" else : process+="insert SimpleQCD:MatrixElements[0] MEQCD2to2\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if(parameterName.find("Jets-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 2.\n" elif(parameterName.find("Jets-2")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n" elif(parameterName.find("Jets-3")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" elif(parameterName.find("Jets-4")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 25.\n" else : logging.error("Star not supported for %s " % simulation) sys.exit(1) # ISR and SppS elif(collider=="ISR" or collider =="SppS" ) : process="set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n" process+="set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n" if(collider=="SppS") : process ="set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/pbar-\n" if(parameterName.find("30")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 30.4\n" elif(parameterName.find("44")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 44.4\n" elif(parameterName.find("53")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 53.0\n" elif(parameterName.find("62")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 62.2\n" elif(parameterName.find("63")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 63.0\n" elif(parameterName.find("200")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 200.0\n" elif(parameterName.find("500")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 500.0\n" elif(parameterName.find("546")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 546.0\n" elif(parameterName.find("900")>=0) : process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 900.0\n" if(simulation=="") : process += "insert SimpleQCD:MatrixElements[0] MEMinBias\n" process += "set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" process += "set /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts\n" process += "create Herwig::MPIXSecReweighter /Herwig/Generators/MPIXSecReweighter\n" process += "insert /Herwig/Generators/EventGenerator:EventHandler:PostSubProcessHandlers 0 /Herwig/Generators/MPIXSecReweighter\n" else : logging.error(" SppS and ISR not supported for %s " % simulation) sys.exit(1) # LHC elif(collider=="LHC") : if(parameterName.find("7-")==0) : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0\n" elif(parameterName.find("8-")==0) : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 8000.0\n" elif(parameterName.find("13-")==0) : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 13000.0\n" elif(parameterName.find("900")==0) : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 900.0\n" elif(parameterName.find("2360")==0) : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 2360.0\n" elif(parameterName.find("2760")==0) : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 2760.0\n" else : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0\n" if(simulation=="") : if(parameterName.find("8-VBF")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2HiggsVBF\n" elif(parameterName.find("VBF")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n" process+="set /Herwig/Particles/tau-:Stable Stable\n" process+="insert SimpleQCD:MatrixElements[0] MEPP2HiggsVBF\n" elif(parameterName.find("ggHJet")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n" process+="set /Herwig/Particles/tau-:Stable Stable\n" process+="insert SimpleQCD:MatrixElements[0] MEHiggsJet\n" elif(parameterName.find("8-ggH")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEHiggs\n" process+="insert SimpleQCD:MatrixElements[0] MEHiggsJet\n" process+="set MEHiggsJet:Process qqbar\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("ggH")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n" process+="set /Herwig/Particles/tau-:Stable Stable\n" process+="insert SimpleQCD:MatrixElements[0] MEHiggs\n" process+="insert SimpleQCD:MatrixElements[0] MEHiggsJet\n" process+="set MEHiggsJet:Process qqbar\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("PromptPhoton")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaJet\n" if(parameterName.find("PromptPhoton-1")>=0) : process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" elif(parameterName.find("PromptPhoton-2")>=0) : process+="set /Herwig/Cuts/PhotonKtCut:MinKT 25.\n" elif(parameterName.find("PromptPhoton-3")>=0) : process+="set /Herwig/Cuts/PhotonKtCut:MinKT 80.\n" elif(parameterName.find("PromptPhoton-4")>=0) : process+="set /Herwig/Cuts/PhotonKtCut:MinKT 150.\n" elif(parameterName.find("DiPhoton-GammaGamma")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaGamma\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaGamma","") elif(parameterName.find("DiPhoton-GammaJet")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaJet\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaJet","") elif(parameterName.find("8-WH")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2WH\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("8-ZH")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2ZH\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("WH")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n" process+="do /Herwig/Particles/W+:SelectDecayModes W+->nu_e,e+; W+->nu_mu,mu+;\n" process+="insert SimpleQCD:MatrixElements[0] MEPP2WH\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("ZH")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n" process+="do /Herwig/Particles/Z0:SelectDecayModes Z0->e-,e+; Z0->mu-,mu+;\n" process+="insert SimpleQCD:MatrixElements[0] MEPP2ZH\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("UE")>=0) : process += "insert SimpleQCD:MatrixElements[0] MEMinBias\n" process += "set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" process += "set /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts\n" process += "create Herwig::MPIXSecReweighter /Herwig/Generators/MPIXSecReweighter\n" process += "insert /Herwig/Generators/EventGenerator:EventHandler:PostSubProcessHandlers 0 /Herwig/Generators/MPIXSecReweighter\n" if(parameterName.find("Long")>=0) : process += "set /Herwig/Decays/DecayHandler:MaxLifeTime 100*mm\n" elif(parameterName.find("7-Jets")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEQCD2to2\n" process+="set MEQCD2to2:MaximumFlavour 5\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if(parameterName.find("7-Jets-0")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n" elif(parameterName.find("7-Jets-10")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 200.*GeV\n" elif(parameterName.find("7-Jets-11")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 600.*GeV\n" elif(parameterName.find("7-Jets-12")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 1000.*GeV\n" elif(parameterName.find("7-Jets-13")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 1600.*GeV\n" elif(parameterName.find("7-Jets-14")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 2200.*GeV\n" elif(parameterName.find("7-Jets-15")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 2800.*GeV\n" elif(parameterName.find("7-Jets-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 10.\n" elif(parameterName.find("7-Jets-2")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" elif(parameterName.find("7-Jets-3")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 40.\n" elif(parameterName.find("7-Jets-4")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 70.\n" elif(parameterName.find("7-Jets-5")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 150.\n" elif(parameterName.find("7-Jets-6")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 200.\n" elif(parameterName.find("7-Jets-7")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 300.\n" elif(parameterName.find("7-Jets-8")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 500.\n" elif(parameterName.find("7-Jets-9")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 90.*GeV\n" elif(parameterName.find("7-Charm")>=0 or \ parameterName.find("7-Bottom")>=0) : if(parameterName.find("7-Bottom")>=0) : process+="cp MEHeavyQuark MEBottom\n" process+="set MEBottom:QuarkType Bottom\n" process+="insert SimpleQCD:MatrixElements[0] MEBottom\n" else : process+="cp MEHeavyQuark MECharm\n" process+="set MECharm:QuarkType Charm\n" process+="insert SimpleQCD:MatrixElements[0] MECharm\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if(parameterName.find("-0")>=0) : if(parameterName.find("7-Bottom")>=0) : process+="set MEBottom:Process Pair\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.\n" elif(parameterName.find("-1")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n" elif(parameterName.find("-2")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n" elif(parameterName.find("-3")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 50.\n" elif(parameterName.find("-4")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 80.\n" elif(parameterName.find("-5")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 110.\n" elif(parameterName.find("-6")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 90.*GeV\n" elif(parameterName.find("-7")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 340.*GeV\n" elif(parameterName.find("-8")>=0) : process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 500.*GeV\n" elif(parameterName.find("Top-L")>=0) : process+="set MEHeavyQuark:QuarkType Top\n" process+="insert SimpleQCD:MatrixElements[0] MEHeavyQuark\n" process+="do /Herwig/Particles/t:SelectDecayModes t->nu_e,e+,b; t->nu_mu,mu+,b;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("Top-SL")>=0) : process+="set MEHeavyQuark:QuarkType Top\n" process+="insert SimpleQCD:MatrixElements[0] MEHeavyQuark\n" process+="set /Herwig/Particles/t:Synchronized Not_synchronized\n" process+="set /Herwig/Particles/tbar:Synchronized Not_synchronized\n" process+="do /Herwig/Particles/t:SelectDecayModes t->nu_e,e+,b; t->nu_mu,mu+,b;\n" process+="do /Herwig/Particles/tbar:SelectDecayModes tbar->b,bbar,cbar; tbar->bbar,cbar,d; tbar->bbar,cbar,s; tbar->bbar,s,ubar; tbar->bbar,ubar,d;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("Top-All")>=0) : process+="set MEHeavyQuark:QuarkType Top\n" process+="insert SimpleQCD:MatrixElements[0] MEHeavyQuark\n" elif(parameterName.find("WZ")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process WZ\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+;\n" process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_ebar,e-; /Herwig/Particles/W-/W-->nu_mubar,mu-;\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("WW-emu")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process WW\n" process+="set /Herwig/Particles/W+:Synchronized 0\n" process+="set /Herwig/Particles/W-:Synchronized 0\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+;\n" process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_mubar,mu-;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("WW-ll")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process WW\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+; /Herwig/Particles/W+/W+->nu_tau,tau+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("ZZ-ll")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process ZZ\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("ZZ-lv")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process ZZ\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+; /Herwig/Particles/Z0/Z0->nu_e,nu_ebar; /Herwig/Particles/Z0/Z0->nu_mu,nu_mubar; /Herwig/Particles/Z0/Z0->nu_tau,nu_taubar;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("W-Z-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Electron\n" elif(parameterName.find("W-Z-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Muon\n" elif(parameterName.find("W-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Electron\n" elif(parameterName.find("W-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Muon\n" elif(parameterName.find("Z-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" elif(parameterName.find("Z-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" elif(parameterName.find("Z-LowMass-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 20.*GeV\nset /Herwig/Cuts/MassCut:MinM 20.*GeV\nset /Herwig/Cuts/MassCut:MaxM 70.*GeV\n" elif(parameterName.find("Z-MedMass-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 40.*GeV\nset /Herwig/Cuts/MassCut:MinM 40.*GeV\nset /Herwig/Cuts/MassCut:MaxM 130.*GeV\n" elif(parameterName.find("Z-LowMass-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 10.*GeV\nset /Herwig/Cuts/MassCut:MinM 10.*GeV\nset /Herwig/Cuts/MassCut:MaxM 70.*GeV\n" elif(parameterName.find("Z-Mass1")>=0) : process+="set /Herwig/Cuts/QCDCuts:MHatMin 10.*GeV\n" process+="set /Herwig/Cuts/MassCut:MinM 10.*GeV\n" process+="set /Herwig/Cuts/MassCut:MaxM 35.*GeV\n" if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" else : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" elif(parameterName.find("Z-Mass2")>=0) : process+="set /Herwig/Cuts/QCDCuts:MHatMin 25.*GeV\n" process+="set /Herwig/Cuts/MassCut:MinM 25.*GeV\n" process+="set /Herwig/Cuts/MassCut:MaxM 70.*GeV\n" if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" else : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" elif(parameterName.find("Z-Mass3")>=0) : process+="set /Herwig/Cuts/QCDCuts:MHatMin 60.*GeV\n" process+="set /Herwig/Cuts/MassCut:MinM 60.*GeV\n" process+="set /Herwig/Cuts/MassCut:MaxM 120.*GeV\n" if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" else : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" elif(parameterName.find("Z-Mass4")>=0) : process+="set /Herwig/Cuts/QCDCuts:MHatMin 110.*GeV\n" process+="set /Herwig/Cuts/MassCut:MinM 110.*GeV\n" process+="set /Herwig/Cuts/MassCut:MaxM 8000.*GeV\n" if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n" else : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" elif(parameterName.find("W-Jet")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEWJet\nset MEWJet:WDecay Electron\n" if(parameterName.find("W-Jet-1-e")>=0) : process+="set /Herwig/Cuts/WBosonKtCut:MinKT 100.0*GeV\n" parameterName=parameterName.replace("W-Jet-1-e","W-Jet-e") elif(parameterName.find("W-Jet-2-e")>=0) : process+="set /Herwig/Cuts/WBosonKtCut:MinKT 190.0*GeV\n" parameterName=parameterName.replace("W-Jet-2-e","W-Jet-e") elif(parameterName.find("W-Jet-3-e")>=0) : process+="set /Herwig/Cuts/WBosonKtCut:MinKT 270.0*GeV\n" parameterName=parameterName.replace("W-Jet-3-e","W-Jet-e") elif(parameterName.find("Z-Jet")>=0) : if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEZJet\nset MEZJet:ZDecay Electron\n" if(parameterName.find("Z-Jet-0-e")>=0) : process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 35.0*GeV\n" parameterName=parameterName.replace("Z-Jet-0-e","Z-Jet-e") elif(parameterName.find("Z-Jet-1-e")>=0) : process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 100.0*GeV\n" parameterName=parameterName.replace("Z-Jet-1-e","Z-Jet-e") elif(parameterName.find("Z-Jet-2-e")>=0) : process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 190.0*GeV\n" parameterName=parameterName.replace("Z-Jet-2-e","Z-Jet-e") elif(parameterName.find("Z-Jet-3-e")>=0) : process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 270.0*GeV\n" parameterName=parameterName.replace("Z-Jet-3-e","Z-Jet-e") else : process+="insert SimpleQCD:MatrixElements[0] MEZJet\nset MEZJet:ZDecay Muon\n" process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 35.0*GeV\n" parameterName=parameterName.replace("Z-Jet-0-mu","Z-Jet-mu") elif(parameterName.find("WGamma")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2VGamma\nset MEPP2VGamma:Process 1\nset MEPP2VGamma:MassOption 1\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 10.\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" if(parameterName.find("-e")>=0) : process+="do /Herwig/Particles/W+:SelectDecayModes W+->nu_e,e+;\n" else : process+="do /Herwig/Particles/W+:SelectDecayModes W+->nu_mu,mu+;\n" elif(parameterName.find("ZGamma")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEPP2VGamma\nset MEPP2VGamma:Process 2\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 10.\n" if(parameterName.find("-e")>=0) : process+="do /Herwig/Particles/Z0:SelectDecayModes Z0->e-,e+;\n" else : process+="do /Herwig/Particles/Z0:SelectDecayModes Z0->mu-,mu+;\n" else : logging.error(" Process %s not supported for internal matrix elements" % name) sys.exit(1) elif(simulation=="Powheg") : if(parameterName.find("8-VBF")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2HiggsVBF\n" elif(parameterName.find("VBF")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n" process+="set /Herwig/Particles/tau-:Stable Stable\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2HiggsVBF\n" elif(parameterName.find("ggHJet")>=0) : logging.error(" Process %s not supported for POWHEG matrix elements" % name) sys.exit(1) elif(parameterName.find("8-ggH")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEHiggs\n" elif(parameterName.find("ggH")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n" process+="set /Herwig/Particles/tau-:Stable Stable\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEHiggs\n" elif(parameterName.find("8-WH")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2WH\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("8-ZH")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2ZH\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("WH")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n" process+="do /Herwig/Particles/W+:SelectDecayModes W+->nu_e,e+; W+->nu_mu,mu+;\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2WH\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("ZH")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n" process+="do /Herwig/Particles/Z0:SelectDecayModes Z0->e-,e+; Z0->mu-,mu+;\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2ZH\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n" elif(parameterName.find("UE")>=0) : logging.error(" Process %s not supported for powheg matrix elements" % name) sys.exit(1) elif(parameterName.find("WZ")>=0) : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" + process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; + process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process WZ\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+;\n" process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_ebar,e-; /Herwig/Particles/W-/W-->nu_mubar,mu-;\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("WW-emu")>=0) : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" + process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; + process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process WW\n" process+="set /Herwig/Particles/W+:Synchronized 0\n" process+="set /Herwig/Particles/W-:Synchronized 0\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+;\n" process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_mubar,mu-;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("WW-ll")>=0) : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" + process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; + process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process WW\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+; /Herwig/Particles/W+/W+->nu_tau,tau+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("ZZ-ll")>=0) : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" + process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; + process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process ZZ\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("ZZ-lv")>=0) : process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n" process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n" + process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n"; + process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n"; + process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n"; process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n" process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process ZZ\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+; /Herwig/Particles/Z0/Z0->nu_e,nu_ebar; /Herwig/Particles/Z0/Z0->nu_mu,nu_mubar; /Herwig/Particles/Z0/Z0->nu_tau,nu_taubar;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("W-Z-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Electron\n" elif(parameterName.find("W-Z-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n" process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Muon\n" elif(parameterName.find("W-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Electron\n" elif(parameterName.find("W-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Muon\n" elif(parameterName.find("Z-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" elif(parameterName.find("Z-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" elif(parameterName.find("Z-LowMass-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 20.*GeV\nset /Herwig/Cuts/MassCut:MinM 20.*GeV\nset /Herwig/Cuts/MassCut:MaxM 70.*GeV\n" elif(parameterName.find("Z-MedMass-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 40.*GeV\nset /Herwig/Cuts/MassCut:MinM 40.*GeV\nset /Herwig/Cuts/MassCut:MaxM 130.*GeV\n" elif(parameterName.find("Z-LowMass-mu")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" process+="set /Herwig/Cuts/QCDCuts:MHatMin 10.*GeV\nset /Herwig/Cuts/MassCut:MinM 10.*GeV\nset /Herwig/Cuts/MassCut:MaxM 70.*GeV\n" elif(parameterName.find("Z-Mass1")>=0) : process+="set /Herwig/Cuts/QCDCuts:MHatMin 10.*GeV\n" process+="set /Herwig/Cuts/MassCut:MinM 10.*GeV\n" process+="set /Herwig/Cuts/MassCut:MaxM 35.*GeV\n" if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" else : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" elif(parameterName.find("Z-Mass2")>=0) : process+="set /Herwig/Cuts/QCDCuts:MHatMin 25.*GeV\n" process+="set /Herwig/Cuts/MassCut:MinM 25.*GeV\n" process+="set /Herwig/Cuts/MassCut:MaxM 70.*GeV\n" if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" else : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" elif(parameterName.find("Z-Mass3")>=0) : process+="set /Herwig/Cuts/QCDCuts:MHatMin 60.*GeV\n" process+="set /Herwig/Cuts/MassCut:MinM 60.*GeV\n" process+="set /Herwig/Cuts/MassCut:MaxM 120.*GeV\n" if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" else : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" elif(parameterName.find("Z-Mass4")>=0) : process+="set /Herwig/Cuts/QCDCuts:MHatMin 110.*GeV\n" process+="set /Herwig/Cuts/MassCut:MinM 110.*GeV\n" process+="set /Herwig/Cuts/MassCut:MaxM 8000.*GeV\n" if(parameterName.find("-e")>=0) : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n" else : process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n" elif(parameterName.find("DiPhoton-GammaGamma")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaGammaPowheg\n" process+="set MEGammaGammaPowheg:Process GammaGamma\n" process+="insert SimpleQCD:MatrixElements[0] MEGammaGamma\n" process+="set MEGammaGamma:Process gg\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaGamma","") elif(parameterName.find("DiPhoton-GammaJet")>=0) : process+="insert SimpleQCD:MatrixElements[0] MEGammaGammaPowheg\n" process+="set MEGammaGammaPowheg:Process VJet\n" process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n" process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n" parameterName=parameterName.replace("-GammaJet","") else : logging.error(" Process %s not supported for internal POWHEG matrix elements" % name) sys.exit(1) elif(simulation=="Matchbox" ) : if(parameterName.find("8-VBF")>=0) : parameters["nlo"] = "read Matchbox/VBFNLO.in\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 3\n" process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/Z0\n" process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/W+\n" process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/W-\n" process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/gamma\n" process+="do Factory:DiagramGenerator:TimeLikeRange 0 0\n" process+="do Factory:Process p p h0 j j\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" if(parameterName.find("GammaGamma")>=0) : process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("VBF")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n" process+="set /Herwig/Particles/tau-:Stable Stable\n" parameters["nlo"] = "read Matchbox/VBFNLO.in\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 3\n" process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/Z0\n" process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/W+\n" process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/W-\n" process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/gamma\n" process+="do Factory:DiagramGenerator:TimeLikeRange 0 0\n" process+="do Factory:Process p p h0 j j\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" elif(parameterName.find("ggHJet")>=0) : parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n" process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n" process+="set /Herwig/Particles/tau-:Stable Stable\n" process+="set Factory:OrderInAlphaS 3\nset Factory:OrderInAlphaEW 1\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="do Factory:Process p p h0 j\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" elif(parameterName.find("8-ggH")>=0) : parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n" process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 1\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="do Factory:Process p p h0\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" if(parameterName.find("GammaGamma")>=0) : process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("ggH")>=0) : parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n" process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n" process+="set /Herwig/Particles/tau-:Stable Stable\n" process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 1\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="do Factory:Process p p h0\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" elif(parameterName.find("8-WH")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="do Factory:Process p p W+ h0\n" process+="do Factory:Process p p W- h0\n" process+="set /Herwig/Particles/W+:HardProcessWidth 0.\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" if(parameterName.find("GammaGamma")>=0) : process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("8-ZH")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="set /Herwig/Particles/Z0:HardProcessWidth 0.\n" process+="do Factory:Process p p Z0 h0\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n" if(parameterName.find("GammaGamma")>=0) : process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("WH")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 3\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="do Factory:Process p p e+ nu h0\n" process+="do Factory:Process p p e- nu h0\n" process+="do Factory:Process p p mu+ nu h0\n" process+="do Factory:Process p p mu- nu h0\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("ZH")>=0) : process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 3\n" process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n" process+="do Factory:Process p p e+ e- h0\n" process+="do Factory:Process p p mu+ mu- h0\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("UE")>=0) : logging.error(" Process %s not supported for Matchbox matrix elements" % name) sys.exit(1) elif(parameterName.find("7-Jets")>=0) : process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n" process+="do Factory:Process p p j j\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if(parameterName.find("7-Jets-0")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 5.\n" elif(parameterName.find("7-Jets-10")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 200.*GeV\n" elif(parameterName.find("7-Jets-11")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 600.*GeV\n" elif(parameterName.find("7-Jets-12")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 1000.*GeV\n" elif(parameterName.find("7-Jets-13")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 1600.*GeV\n" elif(parameterName.find("7-Jets-14")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 2200.*GeV\n" elif(parameterName.find("7-Jets-15")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 2800.*GeV\n" elif(parameterName.find("7-Jets-1")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 10.\n" elif(parameterName.find("7-Jets-2")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n" elif(parameterName.find("7-Jets-3")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 40.\n" elif(parameterName.find("7-Jets-4")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 70.\n" elif(parameterName.find("7-Jets-5")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 150.\n" elif(parameterName.find("7-Jets-6")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 200.\n" elif(parameterName.find("7-Jets-7")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 300.\n" elif(parameterName.find("7-Jets-8")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 500.\n" elif(parameterName.find("7-Jets-9")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 90.*GeV\n" elif(parameterName.find("7-Charm")>=0 or \ parameterName.find("7-Bottom")>=0) : parameters["bscheme"]="read Matchbox/FourFlavourScheme.in" process+="set /Herwig/Particles/b:HardProcessMass 4.2*GeV\n" process+="set /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n" process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n" if(parameterName.find("7-Bottom")>=0) : process+="do Factory:Process p p b bbar\n" else: process+="do Factory:Process p p c cbar\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n" if(parameterName.find("-0")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 0.\n" elif(parameterName.find("-1")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 5.\n" elif(parameterName.find("-2")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n" elif(parameterName.find("-3")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 50.\n" elif(parameterName.find("-4")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 80.\n" elif(parameterName.find("-5")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 110.\n" elif(parameterName.find("-6")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 90.*GeV\n" elif(parameterName.find("-7")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 340.*GeV\n" elif(parameterName.find("-8")>=0) : process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.\n" process+="set /Herwig/Cuts/SecondJet:PtMin 25.\n" process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n" process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n" process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n" process+="set /Herwig/Cuts/JetPairMass:MassMin 500.*GeV\n" elif(parameterName.find("Top-L")>=0) : process+="set /Herwig/Particles/t:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/tbar:HardProcessWidth 0.*GeV\n" process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n" process+="do Factory:Process p p t tbar\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/TopPairMTScale\n" process+="do /Herwig/Particles/t:SelectDecayModes t->nu_e,e+,b; t->nu_mu,mu+,b;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("Top-SL")>=0) : process+="set /Herwig/Particles/t:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/tbar:HardProcessWidth 0.*GeV\n" process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n" process+="do Factory:Process p p t tbar\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/TopPairMTScale\n" process+="set /Herwig/Particles/t:Synchronized Not_synchronized\n" process+="set /Herwig/Particles/tbar:Synchronized Not_synchronized\n" process+="do /Herwig/Particles/t:SelectDecayModes t->nu_e,e+,b; t->nu_mu,mu+,b;\n" process+="do /Herwig/Particles/tbar:SelectDecayModes tbar->b,bbar,cbar; tbar->bbar,cbar,d; tbar->bbar,cbar,s; tbar->bbar,s,ubar; tbar->bbar,ubar,d;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" elif(parameterName.find("Top-All")>=0) : process+="set /Herwig/Particles/t:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/tbar:HardProcessWidth 0.*GeV\n" process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n" process+="do Factory:Process p p t tbar\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/TopPairMTScale\n" elif(parameterName.find("WZ")>=0) : process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p W+ Z0\ndo Factory:Process p p W- Z0\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 171.6*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+;\n" process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_ebar,e-; /Herwig/Particles/W-/W-->nu_mubar,mu-;\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("WW-emu")>=0) : process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p W+ W-\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 160.8*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/Particles/W+:Synchronized 0\n" process+="set /Herwig/Particles/W-:Synchronized 0\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+;\n" process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_mubar,mu-;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("WW-ll")>=0) : process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p W+ W-\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 160.8*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+; /Herwig/Particles/W+/W+->nu_tau,tau+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("ZZ-ll")>=0) : process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p Z0 Z0\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 182.2*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("ZZ-lv")>=0) : process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n" process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n" process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p Z0 Z0\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 182.2*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+; /Herwig/Particles/Z0/Z0->nu_e,nu_ebar; /Herwig/Particles/Z0/Z0->nu_mu,nu_mubar; /Herwig/Particles/Z0/Z0->nu_tau,nu_taubar;\n" process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n" process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("W-Z-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\n" process+="do Factory:Process p p e+ e-\ndo Factory:Process p p e+ nu\ndo Factory:Process p p e- nu\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("W-Z-mu")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\n" process+="do Factory:Process p p mu+ mu-\ndo Factory:Process p p mu+ nu\ndo Factory:Process p p mu- nu\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("W-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ nu\ndo Factory:Process p p e- nu\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("W-mu")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ nu\ndo Factory:Process p p mu- nu\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("Z-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("Z-mu")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("Z-jj")>=0) : process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 2\n" process+="do Factory:Process p p e+ e- j j\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 40.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("Z-LowMass-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 20*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n" elif(parameterName.find("Z-MedMass-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 40*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 130*GeV\n" elif(parameterName.find("Z-LowMass-mu")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 10*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n" elif(parameterName.find("Z-Mass1")>=0) : process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 10*GeV\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MaxMass 35*GeV\n" if(parameterName.find("-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n" else : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n" elif(parameterName.find("Z-Mass2")>=0) : process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 25*GeV\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n" if(parameterName.find("-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n" else : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n" elif(parameterName.find("Z-Mass3")>=0) : process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" if(parameterName.find("-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n" else : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n" elif(parameterName.find("Z-Mass4")>=0) : process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 115*GeV\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MaxMass 8000*GeV\n" if(parameterName.find("-e")>=0) : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n" else : process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n" elif(parameterName.find("W-Jet")>=0) : process+="set Factory:OrderInAlphaS 1\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ nu j\ndo Factory:Process p p e- nu j\n\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/HTScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" if(parameterName.find("W-Jet-1-e")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 100.*GeV\n" parameterName=parameterName.replace("W-Jet-1-e","W-Jet-e") elif(parameterName.find("W-Jet-2-e")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 190.0*GeV\n" parameterName=parameterName.replace("W-Jet-2-e","W-Jet-e") elif(parameterName.find("W-Jet-3-e")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 270.0*GeV\n" parameterName=parameterName.replace("W-Jet-3-e","W-Jet-e") elif(parameterName.find("Z-Jet")>=0) : process+="set Factory:OrderInAlphaS 1\nset Factory:OrderInAlphaEW 2\n" if(parameterName.find("-e")>=0) : process+="do Factory:Process p p e+ e- j\n" if(parameterName.find("Z-Jet-0-e")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 35.*GeV\n" parameterName=parameterName.replace("Z-Jet-0-e","Z-Jet-e") elif(parameterName.find("Z-Jet-1-e")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 100.*GeV\n" parameterName=parameterName.replace("Z-Jet-1-e","Z-Jet-e") elif(parameterName.find("Z-Jet-2-e")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 190.0*GeV\n" parameterName=parameterName.replace("Z-Jet-2-e","Z-Jet-e") elif(parameterName.find("Z-Jet-3-e")>=0) : process+="set /Herwig/Cuts/FirstJet:PtMin 270.0*GeV\n" parameterName=parameterName.replace("Z-Jet-3-e","Z-Jet-e") else : process+="do Factory:Process p p mu+ mu- j\n" process+="set /Herwig/Cuts/FirstJet:PtMin 35.*GeV\n" parameterName=parameterName.replace("Z-Jet-0-mu","Z-Jet-mu") process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/HTScale\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" elif(parameterName.find("Z-bb")>=0) : parameters["bscheme"]="read Matchbox/FourFlavourScheme.in" process+="set /Herwig/Particles/b:HardProcessMass 4.2*GeV\nset /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n" process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e- b bbar\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 66*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 116*GeV\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 18.*GeV\n" process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" elif(parameterName.find("Z-b")>=0) : process+="do Factory:StartParticleGroup bjet\n" process+="insert Factory:ParticleGroup 0 /Herwig/Particles/b\n" process+="insert Factory:ParticleGroup 0 /Herwig/Particles/bbar\n" process+="do Factory:EndParticleGroup\n" process+="set Factory:OrderInAlphaS 1\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e- bjet\n" process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 15.*GeV\n" elif(parameterName.find("W-b")>=0) : parameters["bscheme"]="read Matchbox/FourFlavourScheme.in" process += "set /Herwig/Particles/b:HardProcessMass 4.2*GeV\nset /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n" process += "set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 2\n" process += "do Factory:Process p p e+ nu b bbar\ndo Factory:Process p p e- nu b bbar\n" process += "do Factory:Process p p mu+ nu b bbar\ndo Factory:Process p p mu- nu b bbar\n" process += "set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 80.4*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n" process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n" process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n" process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n" process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n" process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n" else : logging.error(" Process %s not supported for Matchbox matrix elements" % name) sys.exit(1) # LHC-GammaGamma elif(collider=="LHC-GammaGamma" ) : if(parameterName.find("-7-")>=0) : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0\n" elif(parameterName.find("-8-")>=0) : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 8000.0\n" else : process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0\n" if(simulation=="") : if(parameterName.find("7")>=0) : process += "insert SimpleQCD:MatrixElements 0 /Herwig/MatrixElements/MEgg2ff\n" process += "set /Herwig/MatrixElements/MEgg2ff:Process Muon\n" else : logging.error(" Process %s not supported for default matrix elements" % name) sys.exit(1) else : logging.error("LHC-GammaGamma not supported for %s " % simulation) sys.exit(1) parameters['parameterFile'] = os.path.join(collider,collider+"-"+parameterName+".in") parameters['runname'] = name parameters['process'] = process # write the file if(simulation=="Matchbox" ) : with open(os.path.join("Rivet",name+".in") ,'w') as f: f.write( template.substitute(parameters)) else : with open(os.path.join("Rivet",name+".in") ,'w') as f: f.write( template.substitute(parameters)) diff --git a/Utilities/Statistics/EventContribution.h b/Utilities/Statistics/EventContribution.h --- a/Utilities/Statistics/EventContribution.h +++ b/Utilities/Statistics/EventContribution.h @@ -1,175 +1,175 @@ // -*- C++ -*- // // EventContribution.hpp is a part of myStatistics // Copyright (C) 2012-2013 Simon Platzer // // myStatistics is licenced under version 2 of the GPL, see COPYING for details. // #ifndef MYSTATISTICS_EventContribution_hpp_included #define MYSTATISTICS_EventContribution_hpp_included #include namespace Statistics { /** * \brief A pointlike or boxlike eventContribution; serves to define the EventContribution concept * \author Simon Platzer */ class EventContribution { public: /** * Construct an eventContribution with given width */ - EventContribution(const double& newCentralValue, - const double& newWeight, - const double& newWidth = 0.0) + EventContribution(double newCentralValue, + double newWeight, + double newWidth = 0.0) : theCentralValue(newCentralValue), theSupport(newCentralValue - newWidth/2., newCentralValue + newWidth/2.), theWeight(newWeight) {} public: /** * Return the central value */ - const double& centralValue() const { return theCentralValue; } + double centralValue() const { return theCentralValue; } /** * Return the support */ const std::pair& support() const { return theSupport; } /** * Return the normalized overlap with an interval */ double overlap(const std::pair& interval) const { return calculateOverlap(interval,support(),support().second-support().first); } /** * Return the eventContribution weight */ double weight() const { return theWeight; } public: /** * Remap the central value and support given a periodicity * interval; if the support exceeds the periodicity it is ajusted * to the peridocity interval. */ void periodic(const std::pair& periodicity) { double delta = periodicity.second - periodicity.first; if ( support().second - support().first > delta ) { theSupport.first = centralValue() - delta/2.; theSupport.second = centralValue() + delta/2.; } double shift = 0.; if ( centralValue() >= periodicity.second ) { while ( centralValue() >= periodicity.second ) { shift -= delta; theCentralValue -= delta; } } else if ( centralValue() < periodicity.first ) { while ( centralValue() <= periodicity.first ) { shift += delta; theCentralValue += delta; } } theSupport.first += shift; theSupport.second += shift; if ( theSupport.first < periodicity.first ) theSupport.first += delta; if ( theSupport.second > periodicity.second ) theSupport.second -= delta; } /** * Adjust to lower boundary */ void noUnderflow(double lower) { if ( support().first < lower ) { double shift = lower - support().first; theSupport.first += shift; theSupport.second += shift; theCentralValue += shift; } } /** * Adjust to upper boundary */ void noOverflow(double upper) { if ( support().second > upper ) { double shift = upper - support().second - DBL_EPSILON; theSupport.first += shift; theSupport.second += shift; theCentralValue += shift; } } /** * Return the normalized overlap with an interval, assuming a * periodic quantity */ double overlap(const std::pair& interval, const std::pair& periodicity) const { if ( support().first < support().second ) return calculateOverlap(interval,support(),support().second-support().first); double norm = support().second - periodicity.first + periodicity.second - support().first; return calculateOverlap(interval,std::make_pair(periodicity.first,support().second),norm) + calculateOverlap(interval,std::make_pair(support().first,periodicity.second),norm); } private: /** * Calculate the normalized overlap with an interval */ double calculateOverlap(const std::pair& interval, const std::pair& newSupport, double norm) const { if ( newSupport.first == newSupport.second ) { if ( newSupport.first >= interval.first && newSupport.second < interval.second ) return 1.0; return 0.0; } if ( newSupport.first <= interval.first && newSupport.second <= interval.first ) return 0.0; if ( newSupport.first >= interval.second && newSupport.second >= interval.second ) return 0.0; double lower = std::max(newSupport.first,interval.first); double upper = std::min(newSupport.second,interval.second); return std::max(0.0,(upper-lower)/norm); } /** * The central value */ double theCentralValue; /** * The support */ std::pair theSupport; /** * The eventContribution weight */ double theWeight; }; } #endif // MYSTATISTICS_EventContribution_hpp_included diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -1,245 +1,246 @@ 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 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/EW/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 + Shower/QTilde/Makefile + Shower/QTilde/Matching/Makefile + Shower/Dipole/Makefile + Shower/Dipole/Base/Makefile + Shower/Dipole/Kernels/Makefile + Shower/Dipole/Kinematics/Makefile + Shower/Dipole/Utility/Makefile + Shower/Dipole/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/include/Makefile.am b/include/Makefile.am --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,37 +1,36 @@ BUILT_SOURCES = done-all-links AUTOMAKE_OPTIONS = -Wno-portability DIRLINKS = $(top_srcdir)/Analysis \ $(top_srcdir)/Decay \ $(top_srcdir)/Hadronization \ $(top_srcdir)/MatrixElement \ $(top_srcdir)/Models \ $(top_srcdir)/PDF \ $(top_srcdir)/PDT \ $(top_srcdir)/Shower \ - $(top_srcdir)/DipoleShower \ $(top_srcdir)/Sampling \ $(top_srcdir)/UnderlyingEvent \ $(top_srcdir)/Utilities LOOPTOOLHEADERS = $(top_srcdir)/Looptools/include/clooptools.h CLEANFILES = done-all-links done-all-links: $(DIRLINKS) $(LOOPTOOLHEADERS) mkdir -p Herwig/Config Herwig/Looptools $(LN_S) -f $(addprefix ../, $(DIRLINKS)) Herwig $(LN_S) -f $(addprefix ../../, $(LOOPTOOLHEADERS)) Herwig/Looptools touch done-all-links install-data-local: find Herwig -follow \( -name '*.h' -or -name '*.icc' \ -or -name '*.tcc' -or -name '*.fh' -or -name '*.xh' \) \ -exec $(install_sh_DATA) \{\} $(DESTDIR)$(includedir)/\{\} \; uninstall-local: rm -rf $(DESTDIR)$(includedir)/Herwig clean-local: rm -rf Herwig 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 18:0:0 +Herwig_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 19: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_compiler_vendor.m4 b/m4/ax_compiler_vendor.m4 --- a/m4/ax_compiler_vendor.m4 +++ b/m4/ax_compiler_vendor.m4 @@ -1,63 +1,87 @@ # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html # =========================================================================== # # SYNOPSIS # # AX_COMPILER_VENDOR # # DESCRIPTION # # Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun, # hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft, # watcom, etc. The vendor is returned in the cache variable # $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # # 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. # # 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 . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 9 +#serial 15 AC_DEFUN([AX_COMPILER_VENDOR], -[ -AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, - [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown - # note: don't check for gcc first since some other compilers define __GNUC__ - for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale:__PATHCC__,__PATHSCALE__ clang:__clang__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do - vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" +[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, + dnl Please add if possible support to ax_compiler_version.m4 + [# note: don't check for gcc first since some other compilers define __GNUC__ + vendors="intel: __ICC,__ECC,__INTEL_COMPILER + ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ + pathscale: __PATHCC__,__PATHSCALE__ + clang: __clang__ + cray: _CRAYC + fujitsu: __FUJITSU + gnu: __GNUC__ + sun: __SUNPRO_C,__SUNPRO_CC + hp: __HP_cc,__HP_aCC + dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER + borland: __BORLANDC__,__CODEGEARC__,__TURBOC__ + comeau: __COMO__ + kai: __KCC + lcc: __LCC__ + sgi: __sgi,sgi + microsoft: _MSC_VER + metrowerks: __MWERKS__ + watcom: __WATCOMC__ + portland: __PGI + tcc: __TINYC__ + unknown: UNKNOWN" + for ventest in $vendors; do + case $ventest in + *:) vendor=$ventest; continue ;; + *) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;; + esac AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ -#if !($vencpp) - thisisanerror; -#endif -])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break]) + #if !($vencpp) + thisisanerror; + #endif + ])], [break]) done + ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` ]) ]) diff --git a/m4/boost.m4 b/m4/boost.m4 --- a/m4/boost.m4 +++ b/m4/boost.m4 @@ -1,1562 +1,1572 @@ # 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 +# serial 26 ], [# ], [])]) # 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. +dnl So get rid of the # and empty lines, and glue the remaining ones together. (eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | grep -v '#' | + grep -v '^[[[:space:]]]*$' | 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 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_ASSIGN() +# ------------- +# Look for Boost.Assign +BOOST_DEFUN([Assign], +[BOOST_FIND_HEADER([boost/assign.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 # * 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_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]); #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; #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" # 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_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_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_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], [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, 4) \ + _BOOST_gcc_test(5, 4) \ _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/src/DIS.in b/src/DIS.in --- a/src/DIS.in +++ b/src/DIS.in @@ -1,106 +1,106 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on DIS parameters # usage: Herwig read DIS.in ################################################## ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set DISGenerator:NumberOfEvents 10000000 set DISGenerator:RandomNumberGenerator:Seed 31122001 set DISGenerator:PrintEvent 10 set DISGenerator:MaxErrors 10000 set /Herwig/Shower/ShowerHandler:MPIHandler NULL # switch off final-state electron/muon FSR do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting e-->e-,gamma; /Herwig/Shower/LtoLGammaSudakov do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting mu-->mu-,gamma; /Herwig/Shower/LtoLGammaSudakov do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting tau-->tau-,gamma; /Herwig/Shower/LtoLGammaSudakov set /Herwig/Shower/KinematicsReconstructor:ReconstructionOption Colour # no pdfs for leptons set /Herwig/Shower/ShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF set /Herwig/Partons/MPIExtractor:SecondPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/QCDExtractor:SecondPDF /Herwig/Partons/HardNLOPDF ################################################## # DIS physics parameters (override defaults here) ################################################## ################################################## # Matrix Elements for lepton-hadron collisions # (by default only neutral-current switched on) ################################################## cd /Herwig/MatrixElements/ # Neutral current DIS insert SimpleDIS:MatrixElements[0] MEDISNC # Charged current matrix element insert SimpleDIS:MatrixElements[0] MEDISCC ################################################## # NLO IN POWHEG SCHEME ################################################## ################################################### ## Need to use an NLO PDF ################################################### # set /Herwig/Particles/p+:PDF /Herwig/Partons/HardNLOPDF # set /Herwig/Particles/pbar-:PDF /Herwig/Partons/HardNLOPDF # set /Herwig/Shower/ShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF # set /Herwig/Partons/MPIExtractor:FirstPDF /Herwig/Partons/MPIPDF # set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/HardNLOPDF # ################################################### ## Setup the POWHEG shower ################################################### #cd /Herwig/Shower -#set Evolver:HardEmissionMode POWHEG +#set ShowerHandler:HardEmission POWHEG #read Matchbox/Powheg-Default-ShowerAlphaSTune.in ################################################### ## NLO Matrix Elements for lepton-hadron collisions ## in the POWHEG approach ################################################### # #cd /Herwig/MatrixElements/ # ## Neutral current DIS #insert SimpleDIS:MatrixElements[0] PowhegMEDISNC ## Charged current matrix element #insert SimpleDIS:MatrixElements[0] PowhegMEDISCC cd /Herwig/Generators ################################################## # Useful analysis handlers for lepton-hadron physics ################################################## ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert DISGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert DISGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun DIS DISGenerator ################################################## # uncomment this section for an example batch run # of two repeats with different parameters # # Note that a separate call of 'Herwig run' # is not required in this case ################################################## # set DISGenerator:NumberOfEvents 10 # run DIS-full DISGenerator # # run DIS-initial DISGenerator diff --git a/src/GammaGamma.in b/src/GammaGamma.in --- a/src/GammaGamma.in +++ b/src/GammaGamma.in @@ -1,69 +1,71 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on LEP parameters # usage: Herwig read LEP.in ################################################## ################################################## # Change the electron/position PDFs ################################################## set /Herwig/Particles/e+:PDF /Herwig/Partons/WWPDF set /Herwig/Particles/e-:PDF /Herwig/Partons/WWPDF +set /Herwig/Shower/ShowerHandler:PDFA NULL +set /Herwig/Shower/ShowerHandler:PDFB NULL ################################################## # Selected the hard process ################################################## cd /Herwig/MatrixElements # fermion-antifermion insert SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEgg2ff # W+W- #insert SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEgg2WW ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LEPGenerator:NumberOfEvents 100000000 set LEPGenerator:RandomNumberGenerator:Seed 31122001 set LEPGenerator:PrintEvent 10 set LEPGenerator:MaxErrors 10000 ################################################## # LEP physics parameters (override defaults) ################################################## set LEPGenerator:EventHandler:LuminosityFunction:Energy 500. set LEPGenerator:EventHandler:CascadeHandler:MPIHandler NULL set /Herwig/Shower/PartnerFinder:QEDPartner IIandFF cd /Herwig/Generators ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################### # Save run for later usage with 'Herwig run' ################################################## saverun GammaGamma LEPGenerator ################################################## # uncomment this section for an example batch run # of two repeats with different parameters # # Note that a separate call of 'Herwig run' # is not required ################################################## # set LEPGenerator:NumberOfEvents 100 # run LEP-Zpole LEPGenerator # set LEPGenerator:EventHandler:LuminosityFunction:Energy 208.0 # run LEP-maxE LEPGenerator diff --git a/src/ILC-MSSM.in b/src/ILC-MSSM.in --- a/src/ILC-MSSM.in +++ b/src/ILC-MSSM.in @@ -1,61 +1,61 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the MSSM in lepton collisions # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG read MSSM.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # --- Hard Process ---- # The particle name can be found in the relevant model file # by searching for its PDG code and noting the text # '/Herwig/Particles/###' where the hashes denote the name # Switch to decide whether to include EW diagrams in the # hard process (On by default) set HPConstructor:IncludeEW Yes # Example hard process: incoming leptons outgoing gaugions insert HPConstructor:Incoming 0 /Herwig/Particles/e+ insert HPConstructor:Incoming 1 /Herwig/Particles/e- insert HPConstructor:Outgoing 0 /Herwig/Particles/~chi_20 insert HPConstructor:Outgoing 1 /Herwig/Particles/~chi_1+ insert HPConstructor:Outgoing 2 /Herwig/Particles/~chi_2+ insert HPConstructor:Outgoing 3 /Herwig/Particles/~chi_30 # --- Perturbative Decays --- # Read in the spectrum file and optional decay table. # If a decay table is in a separate file # then add another 'setup' line with that # file as the argument. The provided # spectrum file is an example using SPheno 2.2.3 setup MSSM/Model CMSSM40.1.1.slha # Other parameters for run cd /Herwig/Generators set LEPGenerator:NumberOfEvents 10000000 set LEPGenerator:RandomNumberGenerator:Seed 31122001 set LEPGenerator:PrintEvent 10 set LEPGenerator:MaxErrors 10000 set LEPGenerator:EventHandler:LuminosityFunction:Energy 800.0 set LEPGenerator:EventHandler:CascadeHandler:MPIHandler NULL set /Herwig/Shower/PartnerFinder:QEDPartner IIandFF saverun ILC-MSSM LEPGenerator diff --git a/src/ILC-MUED.in b/src/ILC-MUED.in --- a/src/ILC-MUED.in +++ b/src/ILC-MUED.in @@ -1,62 +1,62 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based for MUED in lepton collisions # # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG read MUED.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # The UED parameters (these are the default) set MUED/Model:InverseRadius 300.*GeV set MUED/Model:LambdaR 20 # --- Hard Process ---- # The particle name can be found in the relevant model file # by searching for its PDG code and noting the text # '/Herwig/Particles/###' where the hashes denote the name # Switch to decide whether to include EW diagrams in the # hard process (On by default) set HPConstructor:IncludeEW Yes # Example hard process: Incoming leptons, outgoing kk bosons and leptons insert HPConstructor:Incoming 0 /Herwig/Particles/e+ insert HPConstructor:Incoming 1 /Herwig/Particles/e- insert HPConstructor:Outgoing 0 /Herwig/Particles/KK1_Z0 insert HPConstructor:Outgoing 1 /Herwig/Particles/KK1_W+ insert HPConstructor:Outgoing 2 /Herwig/Particles/KK1_e_L- insert HPConstructor:Outgoing 3 /Herwig/Particles/KK1_e_R- # Other parameters for run cd /Herwig/Generators set LEPGenerator:NumberOfEvents 100000000 set LEPGenerator:RandomNumberGenerator:Seed 31122001 set LEPGenerator:PrintEvent 10 set LEPGenerator:MaxErrors 10000 set LEPGenerator:EventHandler:LuminosityFunction:Energy 800.0 set LEPGenerator:EventHandler:CascadeHandler:MPIHandler NULL set /Herwig/Shower/PartnerFinder:QEDPartner IIandFF ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun ILC-MUED LEPGenerator diff --git a/src/ILC-RS.in b/src/ILC-RS.in --- a/src/ILC-RS.in +++ b/src/ILC-RS.in @@ -1,56 +1,56 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Randell-Sundrum model # in lepton collisions # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read RS.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # Example hard process: Incoming leptons,resonant gravition insert ResConstructor:Incoming 0 /Herwig/Particles/e- insert ResConstructor:Incoming 1 /Herwig/Particles/e+ insert ResConstructor:Intermediates 0 /Herwig/Particles/Graviton insert ResConstructor:Outgoing 0 /Herwig/Particles/e+ insert ResConstructor:Outgoing 0 /Herwig/Particles/W+ insert ResConstructor:Outgoing 0 /Herwig/Particles/Z0 insert ResConstructor:Outgoing 0 /Herwig/Particles/u insert ResConstructor:Outgoing 0 /Herwig/Particles/t # coupling # set RS/Model:Lambda_pi 10000*GeV # Other parameters for run cd /Herwig/Generators set LEPGenerator:NumberOfEvents 100000000 set LEPGenerator:RandomNumberGenerator:Seed 31122001 set LEPGenerator:PrintEvent 10 set LEPGenerator:MaxErrors 10000 set LEPGenerator:EventHandler:LuminosityFunction:Energy 800.0 set LEPGenerator:EventHandler:CascadeHandler:MPIHandler NULL set /Herwig/Shower/PartnerFinder:QEDPartner IIandFF ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun ILC-RS LEPGenerator diff --git a/src/LEP.in b/src/LEP.in --- a/src/LEP.in +++ b/src/LEP.in @@ -1,113 +1,113 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on LEP parameters # usage: Herwig read LEP.in ################################################## ################################################## # Change settings for the ee->Z->qq matrix element # to avoid producing top quarks # # 'set' lines like this can be omitted if the # default value is already okay. # # Any repository setting can be modified here ################################################## ################################################## # Selected the hard process ################################################## # leading-order processes ################################################## cd /Herwig/MatrixElements # default e+e- > q qbar (5 flavours d,u,s,c,b) insert SimpleEE:MatrixElements 0 MEee2gZ2qq # e+e- > l+l- # insert SimpleEE:MatrixElements[0] MEee2gZ2ll # e+e- > W+W- ZZ # insert SimpleEE:MatrixElements[0] MEee2VV # higgs+Z # insert SimpleEE:MatrixElements[0] MEee2ZH # higgs+e+e-/nu_enu_ebar via VBF # insert SimpleEE:MatrixElements[0] MEee2HiggsVBF ################################################## # NLO powheg processes ################################################## -#set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +#set /Herwig/Shower/ShowerHandler:HardEmission POWHEG #read Matchbox/Powheg-Default-ShowerAlphaSTune.in #insert SimpleEE:MatrixElements 0 PowhegMEee2gZ2qq #insert SimpleEE:MatrixElements 0 PowhegMEee2gZ2ll ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LEPGenerator:NumberOfEvents 100000000 set LEPGenerator:RandomNumberGenerator:Seed 31122001 set LEPGenerator:PrintEvent 10 set LEPGenerator:MaxErrors 10000 ################################################## # LEP physics parameters (override defaults) ################################################## set LEPGenerator:EventHandler:LuminosityFunction:Energy 91.2 set LEPGenerator:EventHandler:CascadeHandler:MPIHandler NULL set /Herwig/Shower/PartnerFinder:QEDPartner IIandFF cd /Herwig/Generators ################################################## # Useful analysis handlers for LEP physics ################################################## # particle multiplicities # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/LEPMultiplicity # b multiplicities # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/BMultiplicity # b fragmentation functions # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/BFrag # event shapes and single particle spectra # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/Shapes # identified particle spectra # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/LEPIdent # four jet analysis (needs Fastjet installed) # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/LEPFourJet # general jet analysis (needs Fastjet installed) # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/LEPJet ################################################## # Useful analysis handlers for B-factory physics ################################################## # BELLE data on charm hadron spetra # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/BELLECharm # CLEO data on charm meson spectra # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/CLEOCharm ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################### # Save run for later usage with 'Herwig run' ################################################## saverun LEP LEPGenerator ################################################## # uncomment this section for an example batch run # of two repeats with different parameters # # Note that a separate call of 'Herwig run' # is not required ################################################## # set LEPGenerator:NumberOfEvents 100 # run LEP-Zpole LEPGenerator # set LEPGenerator:EventHandler:LuminosityFunction:Energy 208.0 # run LEP-maxE LEPGenerator diff --git a/src/LHC-ADD.in b/src/LHC-ADD.in --- a/src/LHC-ADD.in +++ b/src/LHC-ADD.in @@ -1,55 +1,55 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Randall-Sundrum model # in hadron collisions # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read ADD.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # Example hard process: Incoming proton, gravition + jet insert HPConstructor:Incoming 0 /Herwig/Particles/g insert HPConstructor:Incoming 0 /Herwig/Particles/u insert HPConstructor:Incoming 0 /Herwig/Particles/ubar insert HPConstructor:Incoming 0 /Herwig/Particles/d insert HPConstructor:Incoming 0 /Herwig/Particles/dbar insert HPConstructor:Incoming 0 /Herwig/Particles/s insert HPConstructor:Incoming 0 /Herwig/Particles/sbar insert HPConstructor:Incoming 0 /Herwig/Particles/c insert HPConstructor:Incoming 0 /Herwig/Particles/cbar insert HPConstructor:Outgoing 0 /Herwig/Particles/Graviton # coupling set ADD/Model:Delta 2 set ADD/Model:DdPlanckMass 1000.*GeV # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 saverun LHC-ADD LHCGenerator diff --git a/src/LHC-GammaGamma.in b/src/LHC-GammaGamma.in --- a/src/LHC-GammaGamma.in +++ b/src/LHC-GammaGamma.in @@ -1,79 +1,80 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on LEP parameters # usage: Herwig read LEP.in ################################################## ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LHCGenerator:NumberOfEvents 100000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:EventHandler:Sampler:Ntry 10000 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 ################################################## # Choice of phase-space generation for PDFs ################################################## set /Herwig/Partons/QCDExtractor:FlatSHatY 0 ################################################## # Change the proton PDFs to those for photon radiation ################################################## set /Herwig/Particles/p+:PDF /Herwig/Partons/BudnevPDF set /Herwig/Particles/pbar-:PDF /Herwig/Partons/BudnevPDF set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/BudnevPDF set /Herwig/Partons/QCDExtractor:SecondPDF /Herwig/Partons/BudnevPDF - +set /Herwig/Shower/ShowerHandler:PDFA NULL +set /Herwig/Shower/ShowerHandler:PDFB NULL ################################################## # Cuts ################################################## cd /Herwig/Cuts set QCDCuts:ScaleMin 0.0*GeV set QCDCuts:X1Min 0 set QCDCuts:X2Min 0 set QCDCuts:X1Max 1. set QCDCuts:X2Max 1. set QCDCuts:MHatMin 1.*GeV erase QCDCuts:MultiCuts 0 set LeptonKtCut:MinKT 3*GeV ################################################## # Selected the hard process ################################################## cd /Herwig/MatrixElements # fermion-antifermion insert SimpleQCD:MatrixElements 0 /Herwig/MatrixElements/MEgg2ff set /Herwig/MatrixElements/MEgg2ff:Process Muon # W+W- #insert SimpleQCD:MatrixElements 0 /Herwig/MatrixElements/MEgg2WW ################################################## # LHC physics parameters (override defaults) ################################################## cd /Herwig/Generators set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000. set LHCGenerator:EventHandler:CascadeHandler:MPIHandler NULL ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################### # Save run for later usage with 'Herwig run' ################################################## saverun LHC-GammaGamma LHCGenerator diff --git a/src/LHC-LH.in b/src/LHC-LH.in --- a/src/LHC-LH.in +++ b/src/LHC-LH.in @@ -1,65 +1,65 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Little Higgs model # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read LH.model cd /Herwig/NewPhysics set LH/Model:f 1*TeV set LH/Model:VEVRatio 0.01 ################################################## # # This section contains the user defined settings # ################################################## # --- Hard Process ---- # The particle name can be found in the relevant model file # by searching for its PDG code and noting the text # '/Herwig/Particles/###' where the hashes denote the name # Example hard process: Incoming proton, outgoing T quark set HPConstructor:IncludeEW No insert HPConstructor:Incoming 0 /Herwig/Particles/g insert HPConstructor:Incoming 0 /Herwig/Particles/u insert HPConstructor:Incoming 0 /Herwig/Particles/ubar insert HPConstructor:Incoming 0 /Herwig/Particles/d insert HPConstructor:Incoming 0 /Herwig/Particles/dbar insert HPConstructor:Outgoing 0 /Herwig/Particles/T # Example hard process: Incoming proton, outgoing leptons via Z_H insert ResConstructor:Incoming 0 /Herwig/Particles/g insert ResConstructor:Incoming 0 /Herwig/Particles/u insert ResConstructor:Incoming 0 /Herwig/Particles/ubar insert ResConstructor:Incoming 0 /Herwig/Particles/d insert ResConstructor:Incoming 0 /Herwig/Particles/dbar insert ResConstructor:Intermediates 0 /Herwig/Particles/Z_H insert ResConstructor:Outgoing 0 /Herwig/Particles/e- insert ResConstructor:Outgoing 0 /Herwig/Particles/mu- # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:DebugLevel 0 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 saverun LHC-LH LHCGenerator diff --git a/src/LHC-LHTP.in b/src/LHC-LHTP.in --- a/src/LHC-LHTP.in +++ b/src/LHC-LHTP.in @@ -1,62 +1,62 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Little Higgs model with # T-parity # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read LHTP.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # --- Hard Process ---- # The particle name can be found in the relevant model file # by searching for its PDG code and noting the text # '/Herwig/Particles/###' where the hashes denote the name # Switch to decide whether to include EW diagrams in the # hard process (On by default) set HPConstructor:IncludeEW No # Example hard process: Incoming proton, outgoing squarks insert HPConstructor:Incoming 0 /Herwig/Particles/g insert HPConstructor:Incoming 0 /Herwig/Particles/u insert HPConstructor:Incoming 0 /Herwig/Particles/ubar insert HPConstructor:Incoming 0 /Herwig/Particles/d insert HPConstructor:Incoming 0 /Herwig/Particles/dbar insert HPConstructor:Incoming 0 /Herwig/Particles/c insert HPConstructor:Incoming 0 /Herwig/Particles/cbar insert HPConstructor:Incoming 0 /Herwig/Particles/s insert HPConstructor:Incoming 0 /Herwig/Particles/sbar insert HPConstructor:Incoming 0 /Herwig/Particles/b insert HPConstructor:Incoming 0 /Herwig/Particles/bbar insert HPConstructor:Outgoing 0 /Herwig/Particles/TpT # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:DebugLevel 0 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 saverun LHC-LHTP LHCGenerator diff --git a/src/LHC-LQ.in b/src/LHC-LQ.in --- a/src/LHC-LQ.in +++ b/src/LHC-LQ.in @@ -1,73 +1,68 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Leptoquark model # in hadron collisions # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read Leptoquark.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # Example hard process: Incoming proton, outgoing leptoquarks insert HPConstructor:Incoming 0 /Herwig/Particles/u insert HPConstructor:Incoming 1 /Herwig/Particles/ubar insert HPConstructor:Incoming 2 /Herwig/Particles/d insert HPConstructor:Incoming 3 /Herwig/Particles/dbar insert HPConstructor:Incoming 4 /Herwig/Particles/s insert HPConstructor:Incoming 5 /Herwig/Particles/sbar insert HPConstructor:Incoming 6 /Herwig/Particles/c insert HPConstructor:Incoming 7 /Herwig/Particles/cbar insert HPConstructor:Incoming 8 /Herwig/Particles/g insert HPConstructor:Outgoing 0 /Herwig/Particles/S0 insert HPConstructor:Outgoing 1 /Herwig/Particles/S0bar # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV - - -cd /Herwig/Shower -set SplittingGenerator:ISR Yes -set SplittingGenerator:FSR Yes +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Cuts cd /Herwig/Cuts set JetKtCut:MinKT 0.0*GeV set QCDCuts:MHatMax 13000.0*GeV set EECuts:MHatMin 0.0*GeV set PhotonKtCut:MinKT 0.0*GeV set PhotonKtCut:MinEta -10. set PhotonKtCut:MaxEta 10. set MassCut:MinM 0.*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 1000 set LHCGenerator:MaxErrors 10000 saverun LHC-LQ LHCGenerator diff --git a/src/LHC-MB.in b/src/LHC-MB.in --- a/src/LHC-MB.in +++ b/src/LHC-MB.in @@ -1,56 +1,56 @@ # -*- ThePEG-repository -*- ################################################################################ # This file contains our best tune to UE data from ATLAS at 7 TeV. More recent # tunes and tunes for other centre-of-mass energies as well as more usage # instructions can be obtained from this Herwig wiki page: # http://projects.hepforge.org/herwig/trac/wiki/MB_UE_tunes ################################################################################ ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 1000000 set LHCGenerator:DebugLevel 0 set LHCGenerator:DumpPeriod -1 set LHCGenerator:DebugEvent 0 ################################################## # LHC physics parameters (override defaults here) ################################################## set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV ################################################## # Matrix Elements for hadron-hadron collisions ################################################## cd /Herwig/MatrixElements/ insert SimpleQCD:MatrixElements[0] MEMinBias # MPI model settings set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0 cd /Herwig/Generators # Change to have no pT cuts for MinBias set LHCGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts #insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile #set /Herwig/Analysis/HepMCFile:PrintEvent 1000000 #set /Herwig/Analysis/HepMCFile:Format GenEvent #set /Herwig/Analysis/HepMCFile:Units GeV_mm #set /Herwig/Analysis/HepMCFile:Filename events.fifo ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun LHC-MB LHCGenerator diff --git a/src/LHC-MSSM.in b/src/LHC-MSSM.in --- a/src/LHC-MSSM.in +++ b/src/LHC-MSSM.in @@ -1,75 +1,75 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the MSSM # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG read MSSM.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # --- Hard Process ---- # The particle name can be found in the relevant model file # by searching for its PDG code and noting the text # '/Herwig/Particles/###' where the hashes denote the name # Switch to decide whether to include EW diagrams in the # hard process (On by default) set HPConstructor:IncludeEW No # Example hard process: Incoming proton, outgoing squarks insert HPConstructor:Incoming 0 /Herwig/Particles/g insert HPConstructor:Incoming 1 /Herwig/Particles/u insert HPConstructor:Incoming 2 /Herwig/Particles/ubar insert HPConstructor:Incoming 3 /Herwig/Particles/d insert HPConstructor:Incoming 4 /Herwig/Particles/dbar insert HPConstructor:Outgoing 0 /Herwig/Particles/~u_L insert HPConstructor:Outgoing 1 /Herwig/Particles/~u_Lbar insert HPConstructor:Outgoing 2 /Herwig/Particles/~d_L insert HPConstructor:Outgoing 3 /Herwig/Particles/~d_Lbar # --- Perturbative Decays --- # Read in the spectrum file and optional decay table. # If a decay table is in a separate file # then add another 'setup' line with that # file as the argument. The provided # spectrum file is an example using SPheno 2.2.3 setup MSSM/Model CMSSM40.1.1.slha # To disable a particular decay mode, add it's tag to the DisableModes # interface of the DecayConstructor object, i.e. #insert DecayConstructor:DisableModes 0 ~u_L->~chi_20,u; #insert DecayConstructor:DisableModes 1 ~chi_20->~e_R-,e+; # etc ... # To set a minimum allowed branching fraction (the default is shown) #set NewModel:MinimumBR 1e-6 # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 saverun LHC-MSSM LHCGenerator diff --git a/src/LHC-MUED.in b/src/LHC-MUED.in --- a/src/LHC-MUED.in +++ b/src/LHC-MUED.in @@ -1,79 +1,79 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the MUED # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read MUED.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # The UED parameters (these are the default) set MUED/Model:InverseRadius 500.*GeV set MUED/Model:LambdaR 20 # --- Hard Process ---- # The particle name can be found in the relevant model file # by searching for its PDG code and noting the text # '/Herwig/Particles/###' where the hashes denote the name # Switch to decide whether to include EW diagrams in the # hard process (On by default) set HPConstructor:IncludeEW No # Example hard process: Incoming proton, outgoing kk quarks insert HPConstructor:Incoming 0 /Herwig/Particles/g insert HPConstructor:Incoming 1 /Herwig/Particles/u insert HPConstructor:Incoming 2 /Herwig/Particles/ubar insert HPConstructor:Incoming 3 /Herwig/Particles/d insert HPConstructor:Incoming 4 /Herwig/Particles/dbar insert HPConstructor:Outgoing 0 /Herwig/Particles/KK1_u_L insert HPConstructor:Outgoing 1 /Herwig/Particles/KK1_u_Lbar insert HPConstructor:Outgoing 2 /Herwig/Particles/KK1_d_L insert HPConstructor:Outgoing 3 /Herwig/Particles/KK1_d_Lbar # --- Perturbative Decays --- # All of the two- and three-body decay modes are calculated automatically. # Set the next line to 'Yes' to enable the creation of the three-body modes. # Initialisation of all three-body decayers will take several minutes. # For production runs, they should be enabled! set ThreeBodyDC:CreateDecayModes Yes # To disable a particular decay mode, add it's tag to the DisableModes # interface of the DecayConstructor object, i.e. #insert DecayConstructor:DisableModes 0 KK1_u_L->KK1_Z0,u; #insert DecayConstructor:DisableModes 1 KK1_Z0->KK1_e_R-,e+; # etc ... # To set a minimum allowed branching fraction (the default is shown) #set NewModel:MinimumBR 1e-6 # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 saverun LHC-MUED LHCGenerator diff --git a/src/LHC-NMSSM.in b/src/LHC-NMSSM.in --- a/src/LHC-NMSSM.in +++ b/src/LHC-NMSSM.in @@ -1,65 +1,65 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the NMSSM # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read NMSSM.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # --- Hard Process ---- # The particle name can be found in the relevant model file # by searching for its PDG code and noting the text # '/Herwig/Particles/###' where the hashes denote the name # Switch to decide whether to include EW diagrams in the # hard process (On by default) set HPConstructor:IncludeEW No # Example hard process: Incoming proton, outgoing squarks insert HPConstructor:Incoming 0 /Herwig/Particles/g insert HPConstructor:Incoming 1 /Herwig/Particles/u insert HPConstructor:Incoming 2 /Herwig/Particles/ubar insert HPConstructor:Incoming 3 /Herwig/Particles/d insert HPConstructor:Incoming 4 /Herwig/Particles/dbar insert HPConstructor:Outgoing 0 /Herwig/Particles/~u_L insert HPConstructor:Outgoing 1 /Herwig/Particles/~u_Lbar insert HPConstructor:Outgoing 2 /Herwig/Particles/~d_L insert HPConstructor:Outgoing 3 /Herwig/Particles/~d_Lbar # --- Perturbative Decays --- # Read in the spectrum file and optional decay table. # If a decay table is in a separate file # then add another 'setup' line with that # file as the argument. The provided # spectrum file is an example using NMHDecay-1.2.1 setup NMSSM/Model NMSSM.spc # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 saverun LHC-NMSSM LHCGenerator diff --git a/src/LHC-Powheg.in b/src/LHC-Powheg.in --- a/src/LHC-Powheg.in +++ b/src/LHC-Powheg.in @@ -1,119 +1,119 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on LHC parameters # using NLO matrix elements and matching in # the Powheg formalism # usage: Herwig read LHC.in ################################################## ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 ################################################## # Need to use an NLO PDF ################################################## set /Herwig/Particles/p+:PDF /Herwig/Partons/HardNLOPDF set /Herwig/Particles/pbar-:PDF /Herwig/Partons/HardNLOPDF set /Herwig/Shower/ShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF set /Herwig/Shower/ShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF set /Herwig/Partons/MPIExtractor:FirstPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/MPIExtractor:SecondPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/HardNLOPDF set /Herwig/Partons/QCDExtractor:SecondPDF /Herwig/Partons/HardNLOPDF ################################################## # Setup the POWHEG shower ################################################## cd /Herwig/Shower -set Evolver:HardEmissionMode POWHEG +set ShowerHandler:HardEmission POWHEG read Matchbox/Powheg-Default-ShowerAlphaSTune.in ################################################## # LHC physics parameters (override defaults here) ################################################## cd /Herwig/Generators set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV ################################################## # Matrix Elements for hadron-hadron collisions # (by default only gamma/Z switched on) ################################################## cd /Herwig/MatrixElements/ # Drell-Yan Z/gamma insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff # # Drell-Yan W # insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff # higgs + W (N.B. if considering all W decay modes useful to set ) # (jet pT cut to zero so no cut on W decay products ) # insert SimpleQCD:MatrixElements[0] PowhegMEPP2WH # set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV # # higgs + Z (N.B. if considering all Z decay modes useful to set ) # (jet pT cut to zero so no cut on Z decay products ) # insert SimpleQCD:MatrixElements[0] PowhegMEPP2ZH # set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV # # gg/qqbar -> Higgs # insert SimpleQCD:MatrixElements[0] PowhegMEHiggs # # Weak boson pair production: WW / ZZ / WZ / W+Z [WpZ] / W-Z [WmZ] # needs the gauge bosons decayed before the shower # create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler # set /Herwig/NewPhysics/DecayHandler:NewStep No # insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau- # insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+ # insert /Herwig/EventHandlers/LHCHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler # insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV # set PowhegMEPP2VV:Process WpZ # # Higgs production via VBF # insert SimpleQCD:MatrixElements[0] PowhegMEPP2HiggsVBF cd /Herwig/Generators ################################################## # Useful analysis handlers for hadron-hadron physics ################################################## # analysis of W/Z events # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/DrellYan ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun LHC-Powheg LHCGenerator ################################################## # uncomment this section for an example batch run # of two repeats with different parameters # # Note that a separate call of 'Herwig run' # is not required in this case ################################################## # set LHCGenerator:NumberOfEvents 10 # run LHC-full LHCGenerator # # set LHCGenerator:EventHandler:LuminosityFunction:Energy 900.0 # run LHC-initial LHCGenerator diff --git a/src/LHC-RPV.in b/src/LHC-RPV.in --- a/src/LHC-RPV.in +++ b/src/LHC-RPV.in @@ -1,85 +1,85 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the MSSM # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model # trilinear RPV read RPV-Tri.model cd /Herwig/NewPhysics # example with LLE and LQD from SOFTSUSY #set TwoBodyDC:CreateDecayModes Yes #set ThreeBodyDC:CreateDecayModes Yes #set WeakDecayConstructor:CreateDecayModes Yes #setup RPV/Model RPV-TRI.slha # example with 4-body UDD decays using input from ISASUSY set FourBodyDC:CreateDecayModes Yes insert FourBodyDC:Particles 0 /Herwig/Particles/~tau_1- setup RPV/Model RPV-UDD.slha # Bilinear RPV #read RPV-Bi.model #cd /Herwig/NewPhysics #setup RPV/Model RPV-BI.slha ################################################## # # This section contains the user defined settings # ################################################## # --- Hard Process ---- # The particle name can be found in the relevant model file # by searching for its PDG code and noting the text # '/Herwig/Particles/###' where the hashes denote the name # Switch to decide whether to include EW diagrams in the # hard process (On by default) set HPConstructor:IncludeEW No # Example hard process: Incoming proton, outgoing squarks insert HPConstructor:Incoming 0 /Herwig/Particles/g insert HPConstructor:Incoming 1 /Herwig/Particles/u insert HPConstructor:Incoming 2 /Herwig/Particles/ubar insert HPConstructor:Incoming 3 /Herwig/Particles/d insert HPConstructor:Incoming 4 /Herwig/Particles/dbar insert HPConstructor:Outgoing 0 /Herwig/Particles/~u_L insert HPConstructor:Outgoing 1 /Herwig/Particles/~u_Lbar insert HPConstructor:Outgoing 2 /Herwig/Particles/~d_L insert HPConstructor:Outgoing 3 /Herwig/Particles/~d_Lbar erase DecayConstructor:NBodyDecayConstructors 0 erase DecayConstructor:NBodyDecayConstructors 1 # To disable a particular decay mode, add it's tag to the DisableModes # interface of the DecayConstructor object, i.e. #insert DecayConstructor:DisableModes 0 ~u_L->~chi_20,u; #insert DecayConstructor:DisableModes 1 ~chi_20->~e_R-,e+; # etc ... # To set a minimum allowed branching fraction (the default is shown) #set NewModel:MinimumBR 1e-6 # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 saverun LHC-RPV LHCGenerator diff --git a/src/LHC-RS.in b/src/LHC-RS.in --- a/src/LHC-RS.in +++ b/src/LHC-RS.in @@ -1,55 +1,55 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Randall-Sundrum model # in hadron collisions # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG read RS.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # Example hard process: Incoming proton,resonant graviton insert ResConstructor:Incoming 0 /Herwig/Particles/g insert ResConstructor:Incoming 0 /Herwig/Particles/u insert ResConstructor:Incoming 0 /Herwig/Particles/ubar insert ResConstructor:Incoming 0 /Herwig/Particles/d insert ResConstructor:Incoming 0 /Herwig/Particles/dbar insert ResConstructor:Intermediates 0 /Herwig/Particles/Graviton insert ResConstructor:Outgoing 0 /Herwig/Particles/e+ insert ResConstructor:Outgoing 1 /Herwig/Particles/W+ insert ResConstructor:Outgoing 2 /Herwig/Particles/Z0 insert ResConstructor:Outgoing 3 /Herwig/Particles/gamma # coupling set RS/Model:Lambda_pi 10000*GeV # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 saverun LHC-RS LHCGenerator diff --git a/src/LHC-Sextet.in b/src/LHC-Sextet.in --- a/src/LHC-Sextet.in +++ b/src/LHC-Sextet.in @@ -1,114 +1,114 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Sextet model # in hadron collisions. # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read Sextet.model cd /Herwig/NewPhysics ################################################## # # This section contains the user defined settings # ################################################## # Example hard process: Incoming proton, gravition + jet #insert HPConstructor:Incoming 0 /Herwig/Particles/g #insert HPConstructor:Incoming 0 /Herwig/Particles/u #insert HPConstructor:Incoming 0 /Herwig/Particles/ubar #insert HPConstructor:Incoming 0 /Herwig/Particles/d #insert HPConstructor:Incoming 0 /Herwig/Particles/dbar #insert HPConstructor:Incoming 0 /Herwig/Particles/s #insert HPConstructor:Incoming 0 /Herwig/Particles/sbar #insert HPConstructor:Incoming 0 /Herwig/Particles/c #insert HPConstructor:Incoming 0 /Herwig/Particles/cbar #### Scalar DQ Singlet Y=4/3 insert HPConstructor:Outgoing 0 /Herwig/Particles/DQPhi_1'' do /Herwig/NewPhysics/Sextet/Model:EnableParticles Scalar Singlet Y=4/3 #### Scalar DQ Singlet Y=1/3 insert HPConstructor:Outgoing 0 /Herwig/Particles/DQPhi_1 do /Herwig/NewPhysics/Sextet/Model:EnableParticles Scalar Singlet Y=1/3 #### Scalar DQ Singlet Y=-2/3 insert HPConstructor:Outgoing 0 /Herwig/Particles/DQPhi_1' do /Herwig/NewPhysics/Sextet/Model:EnableParticles Scalar Singlet Y=-2/3 #### Scalar DQ Triplet Y=1/3 insert HPConstructor:Outgoing 0 /Herwig/Particles/DQPhi_3+ insert HPConstructor:Outgoing 0 /Herwig/Particles/DQPhi_30 insert HPConstructor:Outgoing 0 /Herwig/Particles/DQPhi_3- do /Herwig/NewPhysics/Sextet/Model:EnableParticles Scalar Triplet Y=1/3 #### Vector DQ Doublet Y=-1/6 insert HPConstructor:Outgoing 0 /Herwig/Particles/DQV_1+ insert HPConstructor:Outgoing 0 /Herwig/Particles/DQV_1- do /Herwig/NewPhysics/Sextet/Model:EnableParticles Vector Doublet Y=-1/6 #### Vector DQ Doublet Y=-5/6 insert HPConstructor:Outgoing 0 /Herwig/Particles/DQV_2+ insert HPConstructor:Outgoing 0 /Herwig/Particles/DQV_2- do /Herwig/NewPhysics/Sextet/Model:EnableParticles Vector Doublet Y=5/6 #set HPConstructor:DebugME Yes # Example hard process: Incoming proton,resonant sextet insert ResConstructor:Incoming 0 /Herwig/Particles/u insert ResConstructor:Outgoing 0 /Herwig/Particles/d insert ResConstructor:Intermediates 0 /Herwig/Particles/DQPhi_1'' #insert ResConstructor:Intermediates 0 /Herwig/Particles/DQV_2+ insert ResConstructor:Outgoing 0 /Herwig/Particles/u insert ResConstructor:Outgoing 0 /Herwig/Particles/d #couplings #1st generation set Sextet/Model:g1L 0 1.0 set Sextet/Model:g1R 0 1.0 set Sextet/Model:g1RDoublePrime 0 1.0 set Sextet/Model:g1RPrime 0 1.0 set Sextet/Model:g2 0 1.0 set Sextet/Model:g2Prime 0 1.0 set Sextet/Model:g3L 0 1.0 #2nd generation set Sextet/Model:g1L 1 1.0 set Sextet/Model:g1R 1 1.0 set Sextet/Model:g1RDoublePrime 1 1.0 set Sextet/Model:g1RPrime 1 1.0 set Sextet/Model:g2 1 1.0 set Sextet/Model:g2Prime 1 1.0 set Sextet/Model:g3L 1 1.0 #3rd generation set Sextet/Model:g1L 2 1.0 set Sextet/Model:g1R 2 1.0 set Sextet/Model:g1RDoublePrime 2 1.0 set Sextet/Model:g1RPrime 2 1.0 set Sextet/Model:g2 2 1.0 set Sextet/Model:g2Prime 2 1.0 set Sextet/Model:g3L 2 1.0 # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV # Other parameters for run cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 1000 set LHCGenerator:MaxErrors 10000 set LHCGenerator:EventHandler:CascadeHandler NULL #set LHCGenerator:EventHandler:CascadeHandler:MPIHandler NULL set LHCGenerator:EventHandler:DecayHandler NULL set LHCGenerator:EventHandler:HadronizationHandler NULL set /Herwig/Analysis/Basics:CheckQuark 0 #set /Herwig/Particles/DQPhi_1'':NominalMass 1000.*GeV saverun LHC-Sextet LHCGenerator \ No newline at end of file diff --git a/src/LHC-TRP.in b/src/LHC-TRP.in --- a/src/LHC-TRP.in +++ b/src/LHC-TRP.in @@ -1,71 +1,71 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on LHC parameters # usage: Herwig read LHC.in ################################################## cd /Herwig/Particles create ThePEG::ParticleData graviton setup graviton 39 graviton 0.0 0.0 0.0 0.0 0 0 0 1 cd /Herwig/EventHandlers #set LHCHandler:CascadeHandler NULL #set LHCHandler:HadronizationHandler NULL #set LHCHandler:DecayHandler NULL ################################################## # Technical parameters for this run ################################################## cd /Herwig cd /Herwig/Generators set LHCGenerator:NumberOfEvents 1000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 ################################################## # LHC physics parameters (override defaults here) ################################################## set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV cd /Herwig/Cuts #set JetKtCut:MinKT 100.0*GeV set QCDCuts:MHatMin 4500*GeV ################################################## # Matrix Elements for hadron-hadron collisions ################################################## cd /Herwig/MatrixElements/ create Herwig::METRP2to2 METransplanck HwTransplanck.so insert SimpleQCD:MatrixElements[0] METransplanck #set METransplanck:Process 6 set METransplanck:NumberExtraDimensions 6 set METransplanck:PlanckMass 1500 cd /Herwig/Generators ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun LHC-TRP LHCGenerator diff --git a/src/LHC-TTBA.in b/src/LHC-TTBA.in --- a/src/LHC-TTBA.in +++ b/src/LHC-TTBA.in @@ -1,110 +1,106 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Leptoquark model # in hadron collisions # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read TTBA.model #Set up semi-leptonic (e or mu) top/hadronic topbar set /Herwig/Particles/t:Synchronized Not_synchronized set /Herwig/Particles/tbar:Synchronized Not_synchronized set /Herwig/Particles/t/t->b,bbar,c;:OnOff Off set /Herwig/Particles/t/t->b,c,dbar;:OnOff Off set /Herwig/Particles/t/t->b,c,sbar;:OnOff Off set /Herwig/Particles/t/t->b,sbar,u;:OnOff Off set /Herwig/Particles/t/t->b,u,dbar;:OnOff Off set /Herwig/Particles/t/t->nu_e,e+,b;:OnOff On set /Herwig/Particles/t/t->nu_mu,mu+,b;:OnOff On set /Herwig/Particles/t/t->nu_tau,tau+,b;:OnOff Off set /Herwig/Particles/tbar/tbar->b,bbar,cbar;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,cbar,d;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,cbar,s;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,s,ubar;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,ubar,d;:OnOff On set /Herwig/Particles/tbar/tbar->nu_ebar,e-,bbar;:OnOff Off set /Herwig/Particles/tbar/tbar->nu_mubar,mu-,bbar;:OnOff Off set /Herwig/Particles/tbar/tbar->nu_taubar,tau-,bbar;:OnOff Off cd /Herwig/Generators ################################################## # LHC physics parameters (override defaults here) ################################################## # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV ################################################## # # This section contains the user defined settings # ################################################## # Example hard process: Incoming proton, outgoing leptoquarks cd /Herwig/NewPhysics set HPConstructor:Processes Exclusive insert HPConstructor:Incoming 0 /Herwig/Particles/u insert HPConstructor:Incoming 1 /Herwig/Particles/ubar insert HPConstructor:Incoming 2 /Herwig/Particles/d insert HPConstructor:Incoming 3 /Herwig/Particles/dbar insert HPConstructor:Incoming 4 /Herwig/Particles/s insert HPConstructor:Incoming 5 /Herwig/Particles/sbar insert HPConstructor:Incoming 6 /Herwig/Particles/c insert HPConstructor:Incoming 7 /Herwig/Particles/cbar insert HPConstructor:Incoming 8 /Herwig/Particles/b insert HPConstructor:Incoming 9 /Herwig/Particles/bbar insert HPConstructor:Incoming 10 /Herwig/Particles/g # Comment out the following line if Axigluon model is selected insert /Herwig/NewPhysics/HPConstructor:Excluded 0 /Herwig/Particles/Ag insert HPConstructor:Outgoing 0 /Herwig/Particles/t insert HPConstructor:Outgoing 1 /Herwig/Particles/tbar #This is available for comparison to the LO Hw++ result #cd /Herwig/MatrixElements #insert SimpleQCD:MatrixElements[0] MEHeavyQuark -cd /Herwig/Shower -set SplittingGenerator:ISR Yes -set SplittingGenerator:FSR Yes - cd /Herwig/EventHandlers #set LHCHandler:CascadeHandler NULL #set LHCHandler:HadronizationHandler NULL #set LHCHandler:DecayHandler NULL # Other parameters for run cd /Herwig/Generators # Uncomment to turn off MPI #set LHCGenerator:EventHandler:CascadeHandler:MPIHandler NULL set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 100 set LHCGenerator:MaxErrors 10000 #HepMC analysis #insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile #set /Herwig/Analysis/HepMCFile:PrintEvent 10000 #set /Herwig/Analysis/HepMCFile:Format GenEvent #set /Herwig/Analysis/HepMCFile:Units GeV_mm saverun LHC-TTBA LHCGenerator diff --git a/src/LHC-ZP.in b/src/LHC-ZP.in --- a/src/LHC-ZP.in +++ b/src/LHC-ZP.in @@ -1,138 +1,134 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Leptoquark model # in hadron collisions # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read Zprime.model set /Herwig/Particles/t:Synchronized Not_synchronized set /Herwig/Particles/tbar:Synchronized Not_synchronized #set /Herwig/Particles/t/t->b,bbar,c;:OnOff On #set /Herwig/Particles/t/t->b,c,dbar;:OnOff On #set /Herwig/Particles/t/t->b,c,sbar;:OnOff On #set /Herwig/Particles/t/t->b,sbar,u;:OnOff On #set /Herwig/Particles/t/t->b,u,dbar;:OnOff On #set /Herwig/Particles/t/t->nu_e,e+,b;:OnOff Off #set /Herwig/Particles/t/t->nu_mu,mu+,b;:OnOff Off #set /Herwig/Particles/t/t->nu_tau,tau+,b;:OnOff Off #set /Herwig/Particles/tbar/tbar->b,bbar,cbar;:OnOff Off #set /Herwig/Particles/tbar/tbar->bbar,cbar,d;:OnOff Off #set /Herwig/Particles/tbar/tbar->bbar,cbar,s;:OnOff Off #set /Herwig/Particles/tbar/tbar->bbar,s,ubar;:OnOff Off #set /Herwig/Particles/tbar/tbar->bbar,ubar,d;:OnOff Off #set /Herwig/Particles/tbar/tbar->nu_ebar,e-,bbar;:OnOff On #set /Herwig/Particles/tbar/tbar->nu_mubar,mu-,bbar;:OnOff On #set /Herwig/Particles/tbar/tbar->nu_taubar,tau-,bbar;:OnOff Off set /Herwig/Particles/t/t->b,bbar,c;:OnOff Off set /Herwig/Particles/t/t->b,c,dbar;:OnOff Off set /Herwig/Particles/t/t->b,c,sbar;:OnOff Off set /Herwig/Particles/t/t->b,sbar,u;:OnOff Off set /Herwig/Particles/t/t->b,u,dbar;:OnOff Off set /Herwig/Particles/t/t->nu_e,e+,b;:OnOff On set /Herwig/Particles/t/t->nu_mu,mu+,b;:OnOff On set /Herwig/Particles/t/t->nu_tau,tau+,b;:OnOff Off set /Herwig/Particles/tbar/tbar->b,bbar,cbar;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,cbar,d;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,cbar,s;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,s,ubar;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,ubar,d;:OnOff On set /Herwig/Particles/tbar/tbar->nu_ebar,e-,bbar;:OnOff Off set /Herwig/Particles/tbar/tbar->nu_mubar,mu-,bbar;:OnOff Off set /Herwig/Particles/tbar/tbar->nu_taubar,tau-,bbar;:OnOff Off cd /Herwig/Generators set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 #set LHCGenerator:EventHandler:BeamB /Herwig/Particles/pbar- ################################################## # # This section contains the user defined settings # ################################################## # Example hard process: Incoming proton, outgoing leptoquarks cd /Herwig/NewPhysics set HPConstructor:Processes Exclusive insert HPConstructor:Incoming 0 /Herwig/Particles/u insert HPConstructor:Incoming 1 /Herwig/Particles/ubar insert HPConstructor:Incoming 2 /Herwig/Particles/d insert HPConstructor:Incoming 3 /Herwig/Particles/dbar insert HPConstructor:Incoming 4 /Herwig/Particles/s insert HPConstructor:Incoming 5 /Herwig/Particles/sbar insert HPConstructor:Incoming 6 /Herwig/Particles/c insert HPConstructor:Incoming 7 /Herwig/Particles/cbar insert HPConstructor:Incoming 8 /Herwig/Particles/g # Comment out the following line if Axigluon model is selected insert /Herwig/NewPhysics/HPConstructor:Excluded 0 /Herwig/Particles/g insert /Herwig/NewPhysics/HPConstructor:Excluded 1 /Herwig/Particles/t insert /Herwig/NewPhysics/HPConstructor:Excluded 2 /Herwig/Particles/tbar insert HPConstructor:Outgoing 0 /Herwig/Particles/t insert HPConstructor:Outgoing 1 /Herwig/Particles/tbar # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV cd /Herwig/Analysis set Basics:CheckQuark false # Cuts cd /Herwig/Cuts set JetKtCut:MinKT 0.0*GeV set QCDCuts:MHatMax 13000.0*GeV set EECuts:MHatMin 0.0*GeV set PhotonKtCut:MinKT 0.0*GeV set PhotonKtCut:MinEta -10. set PhotonKtCut:MaxEta 10. set MassCut:MinM 0.*GeV -cd /Herwig/Shower -set SplittingGenerator:ISR Yes -set SplittingGenerator:FSR Yes - cd /Herwig/EventHandlers #set LHCHandler:CascadeHandler NULL #set LHCHandler:HadronizationHandler NULL #set LHCHandler:DecayHandler NULL # Other parameters for run cd /Herwig/Generators # Turn off MPI set LHCGenerator:EventHandler:CascadeHandler:MPIHandler NULL set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 1000 set LHCGenerator:MaxErrors 10000 # HEPMC output if required #insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile #set /Herwig/Analysis/HepMCFile:PrintEvent 10000 #set /Herwig/Analysis/HepMCFile:Format GenEvent #set /Herwig/Analysis/HepMCFile:Units GeV_mm saverun LHC-ZP LHCGenerator diff --git a/src/LHC-diffractive.in b/src/LHC-diffractive.in --- a/src/LHC-diffractive.in +++ b/src/LHC-diffractive.in @@ -1,103 +1,103 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on LHC parameters # usage: Herwig read LHC-diffractive.in ################################################## ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 set LHCGenerator:EventHandler:StatLevel Full ################################################## # LHC physics parameters (override defaults here) ################################################## set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV cd /Herwig/Partons # Set the PDFs for the beams # This is for double diffractive, comment out either the first or second # for single diffractive set QCDExtractor:FirstPDF PomeronFlux set QCDExtractor:SecondPDF PomeronFlux ## Reggeon Structure Function ################################# # MUST HAVE LHAPDF linked with ThePEG #create ThePEG::LHAPDF PionPDF ThePEGLHAPDF.so #set PionPDF:PDFNumber 212 #set PionPDF:PType PionOrVMD #set PionPDF:RangeException Freeze # #create ThePEG::SoftRemnantHandler PionRemnants #set PionRemnants:RemnantDecayer RemnantDecayer #set PionPDF:RemnantHandler /Herwig/Partons/PionRemnants # #create Herwig::ReggeonPDF ReggeonPDF HwReggeonPDF.so #set ReggeonPDF:PDF PionPDF #set ReggeonPDF:RemnantHandler PionRemnants #set /Herwig/Particles/reggeon:PDF ReggeonPDF # uncomment to switch pomeron off if only reggeon required #set /Herwig/Particles/pomeron:PDF NULL ################################################################# ################################################## # Choice of phase-space generation for PDFs ################################################## set QCDExtractor:FlatSHatY 0 ################################################## # Cuts ################################################## cd /Herwig/Cuts set QCDCuts:MHatMin 1. set QCDCuts:MHatMax 20000 set QCDCuts:X2Min 1.0e-7 set QCDCuts:X2Max 1. set QCDCuts:X1Min 1.0e-7 set QCDCuts:X1Max 1. set JetKtCut:MinKT 10. set LeptonKtCut:MinKT 1. ################################################## # Matrix Elements for diffractive collisions # (by default on QCD 2->2 switched on) ################################################## cd /Herwig/MatrixElements/ insert SimpleQCD:MatrixElements[0] /Herwig/UnderlyingEvent/MEQCD2to2Fast cd /Herwig/Generators # MPI doesn't work set LHCGenerator:EventHandler:CascadeHandler:MPIHandler NULL ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun LHC-diffractive LHCGenerator diff --git a/src/LHC.in b/src/LHC.in --- a/src/LHC.in +++ b/src/LHC.in @@ -1,162 +1,162 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on LHC parameters # usage: Herwig read LHC.in ################################################## ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 ################################################## # LHC physics parameters (override defaults here) ################################################## # Intrinsic pT tune extrapolated to LHC energy -set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV +set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV ######################## ## sqrt(s) = 13000 GeV ## ######################## set LHCGenerator:EventHandler:LuminosityFunction:Energy 13000.0 ################################################## # Matrix Elements for hadron-hadron collisions # (by default only gamma/Z switched on) ################################################## cd /Herwig/MatrixElements/ # # Electroweak boson W/Z processes # # Drell-Yan Z/gamma insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff # # Drell-Yan W # insert SimpleQCD:MatrixElements[0] MEqq2W2ff # # W+jet # insert SimpleQCD:MatrixElements[0] MEWJet # # Z+jet # insert SimpleQCD:MatrixElements[0] MEZJet # # WW/WZ/ZZ # insert SimpleQCD:MatrixElements[0] MEPP2VV # # Wgamma/Zgamma # insert SimpleQCD:MatrixElements[0] MEPP2VGamma # # add QED radiation off W/Z decay products using YFS formalism # cd /Herwig/EventHandlers # insert LHCHandler:PostSubProcessHandlers[0] /Herwig/QEDRadiation/QEDRadiationHandler # # QCD and gamma processes # # QCD 2-2 scattering # insert SimpleQCD:MatrixElements[0] MEQCD2to2 # # gamma+jet # insert SimpleQCD:MatrixElements[0] MEGammaJet # # gamma-gamma # insert SimpleQCD:MatrixElements[0] MEGammaGamma # # Heavy quark processes # # # top-antitop production # insert SimpleQCD:MatrixElements[0] MEHeavyQuark # # single-top # t-channel # insert SimpleQCD:MatrixElements[0] MESingleTopTChannel # s-channel # insert SimpleQCD:MatrixElements[0] MESingleTopSChannel # tW # insert SimpleQCD:MatrixElements[0] MESingleTopTW # # Higgs Processes # # # gg/qqbar -> Higgs (recommend including q qbar->Hg as not in ME correction) # insert SimpleQCD:MatrixElements[0] MEHiggs # insert SimpleQCD:MatrixElements[0] MEHiggsJet # set MEHiggsJet:Process qqbar # set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV # # higgs+jet # insert SimpleQCD:MatrixElements[0] MEHiggsJet # # higgs + W (N.B. if considering all W decay modes useful to set ) # (jet pT cut to zero so no cut on W decay products ) # insert SimpleQCD:MatrixElements[0] MEPP2WH # set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV # # higgs + Z (N.B. if considering all Z decay modes useful to set ) # (jet pT cut to zero so no cut on Z decay products ) # insert SimpleQCD:MatrixElements[0] MEPP2ZH # set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV # # VBF Higgs # insert SimpleQCD:MatrixElements[0] MEPP2HiggsVBF # # t tbar Higgs # insert SimpleQCD:MatrixElements[0] MEPP2ttbarH # # b bbar Higgs # insert SimpleQCD:MatrixElements[0] MEPP2bbbarH cd /Herwig/Generators ################################################## # Useful analysis handlers for hadron-hadron physics ################################################## # analysis of W/Z events # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/DrellYan # analysis of top-antitop events # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/TTbar # analysis of gamma+jet events # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/GammaJet # analysis of gamma-gamma events # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/GammaGamma # analysis of higgs-jet events # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HiggsJet ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun LHC LHCGenerator ################################################## # uncomment this section for an example batch run # of two repeats with different parameters # # Note that a separate call of 'Herwig run' # is not required in this case ################################################## # set LHCGenerator:NumberOfEvents 10 # run LHC-full LHCGenerator # # set LHCGenerator:EventHandler:LuminosityFunction:Energy 900.0 # run LHC-initial LHCGenerator diff --git a/src/Matchbox/MCatLO-DefaultShower.in.in b/src/Matchbox/MCatLO-DefaultShower.in.in --- a/src/Matchbox/MCatLO-DefaultShower.in.in +++ b/src/Matchbox/MCatLO-DefaultShower.in.in @@ -1,23 +1,23 @@ # -*- ThePEG-repository -*- read Matchbox/LO.in -set /Herwig/Shower/Evolver:HardVetoReadOption PrimaryCollision -set /Herwig/Shower/Evolver:SpinCorrelations No -set /Herwig/Shower/Evolver:HardEmissionMode DecayMECorrection +set /Herwig/Shower/ShowerHandler:HardVetoReadOption PrimaryCollision +set /Herwig/Shower/ShowerHandler:SpinCorrelations No +set /Herwig/Shower/ShowerHandler:HardEmission MECorrection set /Herwig/Shower/KinematicsReconstructor:InitialStateReconOption SofterFraction set /Herwig/Shower/PartnerFinder:PartnerMethod 0 set /Herwig/Shower/PartnerFinder:ScaleChoice 0 set /Herwig/Shower/ShowerHandler:RestrictPhasespace On set /Herwig/Shower/ShowerHandler:MaxPtIsMuF Yes set /Herwig/Shower/ShowerHandler:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/Shower/ShowerHandler cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so diff --git a/src/Matchbox/MCatNLO-DefaultShower.in.in b/src/Matchbox/MCatNLO-DefaultShower.in.in --- a/src/Matchbox/MCatNLO-DefaultShower.in.in +++ b/src/Matchbox/MCatNLO-DefaultShower.in.in @@ -1,29 +1,29 @@ # -*- ThePEG-repository -*- -set /Herwig/Shower/Evolver:HardVetoReadOption PrimaryCollision -set /Herwig/Shower/Evolver:SpinCorrelations No -set /Herwig/Shower/Evolver:HardEmissionMode DecayMECorrection +set /Herwig/Shower/ShowerHandler:HardVetoReadOption PrimaryCollision +set /Herwig/Shower/ShowerHandler:SpinCorrelations No +set /Herwig/Shower/ShowerHandler:HardEmission MECorrection set /Herwig/Shower/KinematicsReconstructor:InitialStateReconOption SofterFraction set /Herwig/Shower/PartnerFinder:PartnerMethod 0 set /Herwig/Shower/PartnerFinder:ScaleChoice 0 set /Herwig/Shower/ShowerHandler:RestrictPhasespace On set /Herwig/Shower/ShowerHandler:MaxPtIsMuF Yes set /Herwig/Shower/ShowerHandler:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/Shower/ShowerHandler cd /Herwig/MatrixElements/Matchbox set Factory:ShowerApproximation QTildeMatching # tunes read Matchbox/MCatNLO-Default-HardAlphaSTune.in cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so diff --git a/src/Matchbox/PQCDLevel.in b/src/Matchbox/PQCDLevel.in --- a/src/Matchbox/PQCDLevel.in +++ b/src/Matchbox/PQCDLevel.in @@ -1,13 +1,13 @@ # -*- ThePEG-repository -*- set /Herwig/DipoleShower/DipoleShowerHandler:MPIHandler NULL set /Herwig/Shower/ShowerHandler:MPIHandler NULL set /Herwig/Shower/PowhegShowerHandler:MPIHandler NULL -set /Herwig/Shower/Evolver:Interactions QCDOnly +set /Herwig/Shower/ShowerHandler:Interaction QCD cd /Herwig/EventHandlers set EventHandler:HadronizationHandler NULL set EventHandler:DecayHandler NULL set /Herwig/Analysis/Basics:CheckQuark No diff --git a/src/Matchbox/Powheg-DefaultShower.in.in b/src/Matchbox/Powheg-DefaultShower.in.in --- a/src/Matchbox/Powheg-DefaultShower.in.in +++ b/src/Matchbox/Powheg-DefaultShower.in.in @@ -1,32 +1,31 @@ # -*- ThePEG-repository -*- read Matchbox/Powheg.in -set /Herwig/Shower/Evolver:HardVetoReadOption PrimaryCollision -set /Herwig/Shower/Evolver:MECorrMode No -set /Herwig/Shower/Evolver:SpinCorrelations No +set /Herwig/Shower/PowhegShowerHandler:HardVetoReadOption PrimaryCollision +set /Herwig/Shower/PowhegShowerHandler:SpinCorrelations No set /Herwig/Shower/KinematicsReconstructor:InitialStateReconOption SofterFraction set /Herwig/Shower/PartnerFinder:PartnerMethod 0 set /Herwig/Shower/PartnerFinder:ScaleChoice 0 set /Herwig/Shower/PowhegShowerHandler:RestrictPhasespace On set /Herwig/Shower/PowhegShowerHandler:MaxPtIsMuF Yes set /Herwig/Shower/PowhegShowerHandler:HardScaleProfile NULL cd /Herwig/EventHandlers set EventHandler:CascadeHandler /Herwig/Shower/PowhegShowerHandler cd /Herwig/Shower set PowhegShowerHandler:Factory /Herwig/MatrixElements/Matchbox/Factory -set Evolver:HardEmissionMode FullPOWHEG +set PowhegShowerHandler:HardEmission POWHEG # tunes read Matchbox/Powheg-Default-HardAlphaSTune.in cd /Herwig/Analysis @CREATE_RIVET@ ThePEG::RivetAnalysis Rivet RivetAnalysis.so @CREATE_HEPMC@ ThePEG::HepMCFile HepMC HepMCAnalysis.so diff --git a/src/TVT-Powheg.in b/src/TVT-Powheg.in --- a/src/TVT-Powheg.in +++ b/src/TVT-Powheg.in @@ -1,105 +1,105 @@ # -*- ThePEG-repository -*- ################################################## # Example generator based on Tevatron parameters # using NLO matrix elements and matching in # the Powheg formalism # usage: Herwig read TVT.in # # Since most parameters are identical to LHC, # we use the default LHCGenerator and adapt only # for the differences ################################################## ################################################## # Technical parameters for this run ################################################## cd /Herwig/Generators set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 10 set LHCGenerator:MaxErrors 10000 ################################################## # Need to use an NLO PDF ################################################## set /Herwig/Particles/p+:PDF /Herwig/Partons/HardNLOPDF set /Herwig/Particles/pbar-:PDF /Herwig/Partons/HardNLOPDF set /Herwig/Shower/ShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF set /Herwig/Shower/ShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF set /Herwig/Partons/MPIExtractor:FirstPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/MPIExtractor:SecondPDF /Herwig/Partons/MPIPDF set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/HardNLOPDF set /Herwig/Partons/QCDExtractor:SecondPDF /Herwig/Partons/HardNLOPDF ################################################## # Setup the POWHEG shower ################################################## cd /Herwig/Shower -set Evolver:HardEmissionMode POWHEG +set ShowerHandler:HardEmission POWHEG read Matchbox/Powheg-Default-ShowerAlphaSTune.in ################################################## # Tevatron physics parameters (override defaults) ################################################## cd /Herwig/Generators set LHCGenerator:EventHandler:LuminosityFunction:Energy 2000.0 set LHCGenerator:EventHandler:BeamB /Herwig/Particles/pbar- ################################################## # Matrix Elements for hadron-hadron collisions # (by default only gamma/Z switched on) ################################################## cd /Herwig/MatrixElements # Drell-Yan Z/gamma insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff # Drell-Yan W # insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff # higgs + W (N.B. if considering all W decay modes useful to set ) # (jet pT cut to zero so no cut on W decay products ) # insert SimpleQCD:MatrixElements[0] PowhegMEPP2WH # set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV # higgs + Z (N.B. if considering all Z decay modes useful to set ) # (jet pT cut to zero so no cut on Z decay products ) # insert SimpleQCD:MatrixElements[0] PowhegMEPP2ZH # set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV # gg/qqbar -> Higgs # insert SimpleQCD:MatrixElements[0] PowhegMEHiggs cd /Herwig/Generators ################################################## # Useful analysis handlers for hadron-hadron physics ################################################## # analysis of W/Z events # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/DrellYan ################################################## # Useful analysis handlers for HepMC related output ################################################## # Schematic overview of an event (requires --with-hepmc to be set at configure time # and the graphviz program 'dot' to produce a plot) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/Plot # A HepMC dump file (requires --with-hepmc to be set at configure time) # insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile # set /Herwig/Analysis/HepMCFile:PrintEvent 100 # set /Herwig/Analysis/HepMCFile:Format GenEvent # set /Herwig/Analysis/HepMCFile:Units GeV_mm ################################################## # Save run for later usage with 'Herwig run' ################################################## saverun TVT-Powheg LHCGenerator ################################################## # uncomment this section for an example batch run # of two repeats with different parameters # # Note that a separate call of 'Herwig run' # is not required ################################################## # set LHCGenerator:NumberOfEvents 10 # run TVT-2000 LHCGenerator # # set LHCGenerator:EventHandler:LuminosityFunction:Energy 1800.0 # run TVT-1800 LHCGenerator diff --git a/src/TVT-TTBA.in b/src/TVT-TTBA.in --- a/src/TVT-TTBA.in +++ b/src/TVT-TTBA.in @@ -1,104 +1,100 @@ # -*- ThePEG-repository -*- ################################################## # Example generator for the Leptoquark model # in hadron collisions # The best way to use this is to make your own # copy of this file and edit that as you require. # # The first section loads the model file which # does not contain anything that users need to touch. # # The second section contains the user settings. ################################################### # Set emission to POWHEG for radiation in decays -set /Herwig/Shower/Evolver:HardEmissionMode POWHEG +set /Herwig/Shower/ShowerHandler:HardEmission POWHEG # read model read TTBA.model #Set up semi-leptonic (e or mu) top/hadronic topbar set /Herwig/Particles/t:Synchronized Not_synchronized set /Herwig/Particles/tbar:Synchronized Not_synchronized set /Herwig/Particles/t/t->b,bbar,c;:OnOff Off set /Herwig/Particles/t/t->b,c,dbar;:OnOff Off set /Herwig/Particles/t/t->b,c,sbar;:OnOff Off set /Herwig/Particles/t/t->b,sbar,u;:OnOff Off set /Herwig/Particles/t/t->b,u,dbar;:OnOff Off set /Herwig/Particles/t/t->nu_e,e+,b;:OnOff On set /Herwig/Particles/t/t->nu_mu,mu+,b;:OnOff On set /Herwig/Particles/t/t->nu_tau,tau+,b;:OnOff Off set /Herwig/Particles/tbar/tbar->b,bbar,cbar;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,cbar,d;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,cbar,s;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,s,ubar;:OnOff On set /Herwig/Particles/tbar/tbar->bbar,ubar,d;:OnOff On set /Herwig/Particles/tbar/tbar->nu_ebar,e-,bbar;:OnOff Off set /Herwig/Particles/tbar/tbar->nu_mubar,mu-,bbar;:OnOff Off set /Herwig/Particles/tbar/tbar->nu_taubar,tau-,bbar;:OnOff Off cd /Herwig/Generators set LHCGenerator:EventHandler:LuminosityFunction:Energy 1960.0 set LHCGenerator:EventHandler:BeamB /Herwig/Particles/pbar- ################################################## # # This section contains the user defined settings # ################################################## # Example hard process: Incoming proton, outgoing leptoquarks cd /Herwig/NewPhysics set HPConstructor:Processes Exclusive insert HPConstructor:Incoming 0 /Herwig/Particles/u insert HPConstructor:Incoming 1 /Herwig/Particles/ubar insert HPConstructor:Incoming 2 /Herwig/Particles/d insert HPConstructor:Incoming 3 /Herwig/Particles/dbar insert HPConstructor:Incoming 4 /Herwig/Particles/s insert HPConstructor:Incoming 5 /Herwig/Particles/sbar insert HPConstructor:Incoming 6 /Herwig/Particles/c insert HPConstructor:Incoming 7 /Herwig/Particles/cbar insert HPConstructor:Incoming 8 /Herwig/Particles/b insert HPConstructor:Incoming 9 /Herwig/Particles/bbar insert HPConstructor:Incoming 10 /Herwig/Particles/g # Comment out the following line if Axigluon model is selected insert /Herwig/NewPhysics/HPConstructor:Excluded 0 /Herwig/Particles/Ag insert HPConstructor:Outgoing 0 /Herwig/Particles/t insert HPConstructor:Outgoing 1 /Herwig/Particles/tbar #This is available for comparison to the LO Hw++ result #cd /Herwig/MatrixElements #insert SimpleQCD:MatrixElements[0] MEHeavyQuark -cd /Herwig/Shower -set SplittingGenerator:ISR Yes -set SplittingGenerator:FSR Yes - cd /Herwig/EventHandlers #set LHCHandler:CascadeHandler NULL #set LHCHandler:HadronizationHandler NULL #set LHCHandler:DecayHandler NULL # Other parameters for run cd /Herwig/Generators # Uncomment to turn off MPI #set LHCGenerator:EventHandler:CascadeHandler:MPIHandler NULL set LHCGenerator:NumberOfEvents 10000000 set LHCGenerator:RandomNumberGenerator:Seed 31122001 set LHCGenerator:PrintEvent 100 set LHCGenerator:MaxErrors 10000 #insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/HepMCFile #set /Herwig/Analysis/HepMCFile:PrintEvent 10000 #set /Herwig/Analysis/HepMCFile:Format GenEvent #set /Herwig/Analysis/HepMCFile:Units GeV_mm saverun TVT-TTBA LHCGenerator diff --git a/src/defaults/DipoleShowerDefaults.in b/src/defaults/DipoleShowerDefaults.in --- a/src/defaults/DipoleShowerDefaults.in +++ b/src/defaults/DipoleShowerDefaults.in @@ -1,500 +1,499 @@ # -*- ThePEG-repository -*- ################################################################################ # # Default setup for the dipole shower. # ################################################################################ ################################################################################ # Load libraries ################################################################################ library HwDipoleShower.so mkdir /Herwig/DipoleShower cd /Herwig/DipoleShower create Herwig::DipoleShowerHandler DipoleShowerHandler set DipoleShowerHandler:FreezeGrid 100000 newdef DipoleShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF newdef DipoleShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF newdef DipoleShowerHandler:PDFARemnant /Herwig/Partons/RemnantPDF newdef DipoleShowerHandler:PDFBRemnant /Herwig/Partons/RemnantPDF ################################################################################ # Setup the underlying event and fix missing reference. ################################################################################ set DipoleShowerHandler:MPIHandler /Herwig/UnderlyingEvent/MPIHandler set DipoleShowerHandler:RemDecayer /Herwig/Partons/RemnantDecayer -set DipoleShowerHandler:Evolver /Herwig/Shower/Evolver ################################################################################ # Setup the ordering. ################################################################################ create Herwig::DipoleChainOrdering ChainPtOrdering ################################################################################ # Setup the reshuffler. ################################################################################ create Herwig::ConstituentReshuffler ConstituentReshuffler set DipoleShowerHandler:ConstituentReshuffler ConstituentReshuffler ################################################################################ # Setup intrinsic pt. ################################################################################ create Herwig::IntrinsicPtGenerator IntrinsicPtGenerator set DipoleShowerHandler:IntrinsicPtGenerator IntrinsicPtGenerator cd /Herwig/DipoleShower ################################################################################ # Setup the alphas ################################################################################ cp /Herwig/Couplings/NLOAlphaS NLOAlphaS ################################################################################ # Setup the splitting kinematics. ################################################################################ mkdir /Herwig/DipoleShower/Kinematics cd /Herwig/DipoleShower/Kinematics create Herwig::FFLightKinematics FFLightKinematics create Herwig::FILightKinematics FILightKinematics create Herwig::IFLightKinematics IFLightKinematics create Herwig::IILightKinematics IILightKinematics create Herwig::FFMassiveKinematics FFMassiveKinematics create Herwig::FIMassiveKinematics FIMassiveKinematics create Herwig::IFMassiveKinematics IFMassiveKinematics ################################################################################ # Setup the kernels. ################################################################################ mkdir /Herwig/DipoleShower/Kernels cd /Herwig/DipoleShower/Kernels ################################################################################ # FF ################################################################################ create Herwig::FFgx2ggxDipoleKernel FFgx2ggxDipoleKernel set FFgx2ggxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FFLightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFgx2ggxDipoleKernel create Herwig::FFqx2qgxDipoleKernel FFqx2qgxDipoleKernel set FFqx2qgxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FFLightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFqx2qgxDipoleKernel create Herwig::FFgx2qqxDipoleKernel FFgx2qqxDipoleKernel set FFgx2qqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FFLightKinematics cp FFgx2qqxDipoleKernel FFgx2ddxDipoleKernel set FFgx2ddxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFgx2ddxDipoleKernel cp FFgx2qqxDipoleKernel FFgx2uuxDipoleKernel set FFgx2uuxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFgx2uuxDipoleKernel cp FFgx2qqxDipoleKernel FFgx2ccxDipoleKernel set FFgx2ccxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFgx2ccxDipoleKernel cp FFgx2qqxDipoleKernel FFgx2ssxDipoleKernel set FFgx2ssxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFgx2ssxDipoleKernel cp FFgx2qqxDipoleKernel FFgx2bbxDipoleKernel set FFgx2bbxDipoleKernel:Flavour /Herwig/Particles/b insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFgx2bbxDipoleKernel ### massive dipoles create Herwig::FFMgx2ggxDipoleKernel FFMgx2ggxDipoleKernel set FFMgx2ggxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FFMassiveKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMgx2ggxDipoleKernel create Herwig::FFMqx2qgxDipoleKernel FFMqx2qgxDipoleKernel set FFMqx2qgxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FFMassiveKinematics cp FFMqx2qgxDipoleKernel FFMdx2dgxDipoleKernel set FFMdx2dgxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMdx2dgxDipoleKernel cp FFMqx2qgxDipoleKernel FFMux2ugxDipoleKernel set FFMux2ugxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMux2ugxDipoleKernel cp FFMqx2qgxDipoleKernel FFMcx2cgxDipoleKernel set FFMcx2cgxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMcx2cgxDipoleKernel cp FFMqx2qgxDipoleKernel FFMsx2sgxDipoleKernel set FFMsx2sgxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMsx2sgxDipoleKernel cp FFMqx2qgxDipoleKernel FFMbx2bgxDipoleKernel set FFMbx2bgxDipoleKernel:Flavour /Herwig/Particles/b insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMbx2bgxDipoleKernel cp FFMqx2qgxDipoleKernel FFMtx2tgxDipoleKernel set FFMtx2tgxDipoleKernel:Flavour /Herwig/Particles/t insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMtx2tgxDipoleKernel create Herwig::FFMgx2qqxDipoleKernel FFMgx2qqxDipoleKernel set FFMgx2qqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FFMassiveKinematics cp FFMgx2qqxDipoleKernel FFMgx2ddxDipoleKernel set FFMgx2ddxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMgx2ddxDipoleKernel cp FFMgx2qqxDipoleKernel FFMgx2uuxDipoleKernel set FFMgx2uuxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMgx2uuxDipoleKernel cp FFMgx2qqxDipoleKernel FFMgx2ccxDipoleKernel set FFMgx2ccxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMgx2ccxDipoleKernel cp FFMgx2qqxDipoleKernel FFMgx2ssxDipoleKernel set FFMgx2ssxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMgx2ssxDipoleKernel cp FFMgx2qqxDipoleKernel FFMgx2bbxDipoleKernel set FFMgx2bbxDipoleKernel:Flavour /Herwig/Particles/b insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FFMgx2bbxDipoleKernel ################################################################################ # create the pdf ratio object ################################################################################ create Herwig::PDFRatio PDFRatio ################################################################################ # FI ################################################################################ create Herwig::FIgx2ggxDipoleKernel FIgx2ggxDipoleKernel set FIgx2ggxDipoleKernel:PDFRatio PDFRatio set FIgx2ggxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FILightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIgx2ggxDipoleKernel create Herwig::FIqx2qgxDipoleKernel FIqx2qgxDipoleKernel set FIqx2qgxDipoleKernel:PDFRatio PDFRatio set FIqx2qgxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FILightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIqx2qgxDipoleKernel create Herwig::FIgx2qqxDipoleKernel FIgx2qqxDipoleKernel set FIgx2qqxDipoleKernel:PDFRatio PDFRatio set FIgx2qqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FILightKinematics cp FIgx2qqxDipoleKernel FIgx2ddxDipoleKernel set FIgx2ddxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIgx2ddxDipoleKernel cp FIgx2qqxDipoleKernel FIgx2uuxDipoleKernel set FIgx2uuxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIgx2uuxDipoleKernel cp FIgx2qqxDipoleKernel FIgx2ccxDipoleKernel set FIgx2ccxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIgx2ccxDipoleKernel cp FIgx2qqxDipoleKernel FIgx2ssxDipoleKernel set FIgx2ssxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIgx2ssxDipoleKernel cp FIgx2qqxDipoleKernel FIgx2bbxDipoleKernel set FIgx2bbxDipoleKernel:Flavour /Herwig/Particles/b insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIgx2bbxDipoleKernel ### massive dipoles create Herwig::FIMqx2qgxDipoleKernel FIMqx2qgxDipoleKernel set FIMqx2qgxDipoleKernel:PDFRatio PDFRatio set FIMqx2qgxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FIMassiveKinematics cp FIMqx2qgxDipoleKernel FIMdx2dgxDipoleKernel set FIMdx2dgxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMdx2dgxDipoleKernel cp FIMqx2qgxDipoleKernel FIMux2ugxDipoleKernel set FIMux2ugxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMux2ugxDipoleKernel cp FIMqx2qgxDipoleKernel FIMcx2cgxDipoleKernel set FIMcx2cgxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMcx2cgxDipoleKernel cp FIMqx2qgxDipoleKernel FIMsx2sgxDipoleKernel set FIMsx2sgxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMsx2sgxDipoleKernel cp FIMqx2qgxDipoleKernel FIMbx2bgxDipoleKernel set FIMbx2bgxDipoleKernel:Flavour /Herwig/Particles/b insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMbx2bgxDipoleKernel cp FIMqx2qgxDipoleKernel FIMtx2tgxDipoleKernel set FIMtx2tgxDipoleKernel:Flavour /Herwig/Particles/t insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMtx2tgxDipoleKernel create Herwig::FIMgx2qqxDipoleKernel FIMgx2qqxDipoleKernel set FIMgx2qqxDipoleKernel:PDFRatio PDFRatio set FIMgx2qqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/FIMassiveKinematics cp FIMgx2qqxDipoleKernel FIMgx2ddxDipoleKernel set FIMgx2ddxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMgx2ddxDipoleKernel cp FIMgx2qqxDipoleKernel FIMgx2uuxDipoleKernel set FIMgx2uuxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMgx2uuxDipoleKernel cp FIMgx2qqxDipoleKernel FIMgx2ccxDipoleKernel set FIMgx2ccxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMgx2ccxDipoleKernel cp FIMgx2qqxDipoleKernel FIMgx2ssxDipoleKernel set FIMgx2ssxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMgx2ssxDipoleKernel cp FIMgx2qqxDipoleKernel FIMgx2bbxDipoleKernel set FIMgx2bbxDipoleKernel:Flavour /Herwig/Particles/b insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMgx2bbxDipoleKernel #cp FIMgx2qqxDipoleKernel FIMgx2ttxDipoleKernel #set FIMgx2ttxDipoleKernel:Flavour /Herwig/Particles/t #insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 FIMgx2ttxDipoleKernel ################################################################################ # IF ################################################################################ create Herwig::IFgx2ggxDipoleKernel IFgx2ggxDipoleKernel set IFgx2ggxDipoleKernel:PDFRatio PDFRatio set IFgx2ggxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IFLightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2ggxDipoleKernel create Herwig::IFqx2qgxDipoleKernel IFqx2qgxDipoleKernel set IFqx2qgxDipoleKernel:PDFRatio PDFRatio set IFqx2qgxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IFLightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFqx2qgxDipoleKernel create Herwig::IFqx2gqxDipoleKernel IFqx2gqxDipoleKernel set IFqx2gqxDipoleKernel:PDFRatio PDFRatio set IFqx2gqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IFLightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFqx2gqxDipoleKernel create Herwig::IFgx2qqxDipoleKernel IFgx2qqxDipoleKernel set IFgx2qqxDipoleKernel:PDFRatio PDFRatio set IFgx2qqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IFLightKinematics cp IFgx2qqxDipoleKernel IFgx2ddbarxDipoleKernel set IFgx2ddbarxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2ddbarxDipoleKernel cp IFgx2qqxDipoleKernel IFgx2dbardxDipoleKernel set IFgx2dbardxDipoleKernel:Flavour /Herwig/Particles/dbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2dbardxDipoleKernel cp IFgx2qqxDipoleKernel IFgx2uubarxDipoleKernel set IFgx2uubarxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2uubarxDipoleKernel cp IFgx2qqxDipoleKernel IFgx2ubaruxDipoleKernel set IFgx2ubaruxDipoleKernel:Flavour /Herwig/Particles/ubar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2ubaruxDipoleKernel cp IFgx2qqxDipoleKernel IFgx2ccbarxDipoleKernel set IFgx2ccbarxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2ccbarxDipoleKernel cp IFgx2qqxDipoleKernel IFgx2cbarcxDipoleKernel set IFgx2cbarcxDipoleKernel:Flavour /Herwig/Particles/cbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2cbarcxDipoleKernel cp IFgx2qqxDipoleKernel IFgx2ssbarxDipoleKernel set IFgx2ssbarxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2ssbarxDipoleKernel cp IFgx2qqxDipoleKernel IFgx2sbarsxDipoleKernel set IFgx2sbarsxDipoleKernel:Flavour /Herwig/Particles/sbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFgx2sbarsxDipoleKernel ### massive dipoles create Herwig::IFMgx2ggxDipoleKernel IFMgx2ggxDipoleKernel set IFMgx2ggxDipoleKernel:PDFRatio PDFRatio set IFMgx2ggxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IFMassiveKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2ggxDipoleKernel create Herwig::IFMqx2qgxDipoleKernel IFMqx2qgxDipoleKernel set IFMqx2qgxDipoleKernel:PDFRatio PDFRatio set IFMqx2qgxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IFMassiveKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMqx2qgxDipoleKernel create Herwig::IFMqx2gqxDipoleKernel IFMqx2gqxDipoleKernel set IFMqx2gqxDipoleKernel:PDFRatio PDFRatio set IFMqx2gqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IFMassiveKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMqx2gqxDipoleKernel create Herwig::IFMgx2qqxDipoleKernel IFMgx2qqxDipoleKernel set IFMgx2qqxDipoleKernel:PDFRatio PDFRatio set IFMgx2qqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IFMassiveKinematics cp IFMgx2qqxDipoleKernel IFMgx2ddbarxDipoleKernel set IFMgx2ddbarxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2ddbarxDipoleKernel cp IFMgx2qqxDipoleKernel IFMgx2dbardxDipoleKernel set IFMgx2dbardxDipoleKernel:Flavour /Herwig/Particles/dbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2dbardxDipoleKernel cp IFMgx2qqxDipoleKernel IFMgx2uubarxDipoleKernel set IFMgx2uubarxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2uubarxDipoleKernel cp IFMgx2qqxDipoleKernel IFMgx2ubaruxDipoleKernel set IFMgx2ubaruxDipoleKernel:Flavour /Herwig/Particles/ubar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2ubaruxDipoleKernel cp IFMgx2qqxDipoleKernel IFMgx2ccbarxDipoleKernel set IFMgx2ccbarxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2ccbarxDipoleKernel cp IFMgx2qqxDipoleKernel IFMgx2cbarcxDipoleKernel set IFMgx2cbarcxDipoleKernel:Flavour /Herwig/Particles/cbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2cbarcxDipoleKernel cp IFMgx2qqxDipoleKernel IFMgx2ssbarxDipoleKernel set IFMgx2ssbarxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2ssbarxDipoleKernel cp IFMgx2qqxDipoleKernel IFMgx2sbarsxDipoleKernel set IFMgx2sbarsxDipoleKernel:Flavour /Herwig/Particles/sbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IFMgx2sbarsxDipoleKernel ################################################################################ # II ################################################################################ create Herwig::IIgx2ggxDipoleKernel IIgx2ggxDipoleKernel set IIgx2ggxDipoleKernel:PDFRatio PDFRatio set IIgx2ggxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IILightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2ggxDipoleKernel create Herwig::IIqx2qgxDipoleKernel IIqx2qgxDipoleKernel set IIqx2qgxDipoleKernel:PDFRatio PDFRatio set IIqx2qgxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IILightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIqx2qgxDipoleKernel create Herwig::IIqx2gqxDipoleKernel IIqx2gqxDipoleKernel set IIqx2gqxDipoleKernel:PDFRatio PDFRatio set IIqx2gqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IILightKinematics insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIqx2gqxDipoleKernel create Herwig::IIgx2qqxDipoleKernel IIgx2qqxDipoleKernel set IIgx2qqxDipoleKernel:PDFRatio PDFRatio set IIgx2qqxDipoleKernel:SplittingKinematics /Herwig/DipoleShower/Kinematics/IILightKinematics cp IIgx2qqxDipoleKernel IIgx2ddbarxDipoleKernel set IIgx2ddbarxDipoleKernel:Flavour /Herwig/Particles/d insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2ddbarxDipoleKernel cp IIgx2qqxDipoleKernel IIgx2dbardxDipoleKernel set IIgx2dbardxDipoleKernel:Flavour /Herwig/Particles/dbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2dbardxDipoleKernel cp IIgx2qqxDipoleKernel IIgx2uubarxDipoleKernel set IIgx2uubarxDipoleKernel:Flavour /Herwig/Particles/u insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2uubarxDipoleKernel cp IIgx2qqxDipoleKernel IIgx2ubaruxDipoleKernel set IIgx2ubaruxDipoleKernel:Flavour /Herwig/Particles/ubar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2ubaruxDipoleKernel cp IIgx2qqxDipoleKernel IIgx2ccbarxDipoleKernel set IIgx2ccbarxDipoleKernel:Flavour /Herwig/Particles/c insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2ccbarxDipoleKernel cp IIgx2qqxDipoleKernel IIgx2cbarcxDipoleKernel set IIgx2cbarcxDipoleKernel:Flavour /Herwig/Particles/cbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2cbarcxDipoleKernel cp IIgx2qqxDipoleKernel IIgx2ssbarxDipoleKernel set IIgx2ssbarxDipoleKernel:Flavour /Herwig/Particles/s insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2ssbarxDipoleKernel cp IIgx2qqxDipoleKernel IIgx2sbarsxDipoleKernel set IIgx2sbarsxDipoleKernel:Flavour /Herwig/Particles/sbar insert /Herwig/DipoleShower/DipoleShowerHandler:Kernels 0 IIgx2sbarsxDipoleKernel cd / ################################################################################ # Setup the dipole shower parameters ################################################################################ cd /Herwig/DipoleShower ################################################################################ # matching parameters ################################################################################ set /Herwig/MatrixElements/Matchbox/MEMatching:FFPtCut 1.0*GeV set /Herwig/MatrixElements/Matchbox/MEMatching:FFScreeningScale 0.0*GeV set /Herwig/MatrixElements/Matchbox/MEMatching:FIPtCut 1.0*GeV set /Herwig/MatrixElements/Matchbox/MEMatching:FIScreeningScale 0.0*GeV set /Herwig/MatrixElements/Matchbox/MEMatching:IIPtCut 1.0*GeV set /Herwig/MatrixElements/Matchbox/MEMatching:IIScreeningScale 0.0*GeV set /Herwig/MatrixElements/Matchbox/DipoleMatching:ShowerHandler /Herwig/DipoleShower/DipoleShowerHandler set /Herwig/MatrixElements/Matchbox/DipoleMatching:FFPtCut 1.0*GeV set /Herwig/MatrixElements/Matchbox/DipoleMatching:FFScreeningScale 0.0*GeV set /Herwig/MatrixElements/Matchbox/DipoleMatching:FIPtCut 1.0*GeV set /Herwig/MatrixElements/Matchbox/DipoleMatching:FIScreeningScale 0.0*GeV set /Herwig/MatrixElements/Matchbox/DipoleMatching:IIPtCut 1.0*GeV set /Herwig/MatrixElements/Matchbox/DipoleMatching:IIScreeningScale 0.0*GeV ################################################################################ # shower parameters ################################################################################ set DipoleShowerHandler:GlobalAlphaS NLOAlphaS set DipoleShowerHandler:EvolutionOrdering ChainPtOrdering set IntrinsicPtGenerator:ValenceIntrinsicPtScale 1.26905*GeV set IntrinsicPtGenerator:SeaIntrinsicPtScale 1.1613*GeV cd /Herwig/DipoleShower/Kinematics set FFLightKinematics:IRCutoff 1.014259*GeV set FILightKinematics:IRCutoff 1.0*GeV set IFLightKinematics:IRCutoff 1.0*GeV set IILightKinematics:IRCutoff 1.0*GeV set FFMassiveKinematics:IRCutoff 1.014259*GeV set FIMassiveKinematics:IRCutoff 1.0*GeV set IFMassiveKinematics:IRCutoff 1.0*GeV cd / diff --git a/src/defaults/Shower.in b/src/defaults/Shower.in --- a/src/defaults/Shower.in +++ b/src/defaults/Shower.in @@ -1,333 +1,338 @@ # -*- ThePEG-repository -*- ############################################################ # Setup of default parton shower # # Useful switches for users are marked near the top of # this file. # # Don't edit this file directly, but reset the switches # in your own input files! ############################################################ library HwMPI.so library HwShower.so library HwMatching.so mkdir /Herwig/Shower cd /Herwig/Shower -create Herwig::ShowerHandler ShowerHandler +create Herwig::QTildeShowerHandler ShowerHandler newdef ShowerHandler:MPIHandler /Herwig/UnderlyingEvent/MPIHandler newdef ShowerHandler:RemDecayer /Herwig/Partons/RemnantDecayer # use LO PDFs for Shower, can be changed later newdef ShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF newdef ShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF newdef ShowerHandler:PDFARemnant /Herwig/Partons/RemnantPDF newdef ShowerHandler:PDFBRemnant /Herwig/Partons/RemnantPDF ##################################### # initial setup, don't change these! ##################################### create Herwig::SplittingGenerator SplittingGenerator create Herwig::ShowerAlphaQCD AlphaQCD create Herwig::ShowerAlphaQED AlphaQED set AlphaQED:CouplingSource Thompson create Herwig::ShowerAlphaQED AlphaEW set AlphaEW:CouplingSource MZ -create Herwig::Evolver Evolver create Herwig::QTildeModel ShowerModel create Herwig::QTildeFinder PartnerFinder newdef PartnerFinder:PartnerMethod 1 newdef PartnerFinder:ScaleChoice 1 create Herwig::QTildeReconstructor KinematicsReconstructor newdef KinematicsReconstructor:ReconstructionOption Colour3 newdef KinematicsReconstructor:InitialStateReconOption SofterFraction newdef KinematicsReconstructor:InitialInitialBoostOption LongTransBoost newdef /Herwig/Partons/RemnantDecayer:AlphaS AlphaQCD newdef /Herwig/Partons/RemnantDecayer:AlphaEM AlphaQED -newdef ShowerHandler:Evolver Evolver newdef ShowerModel:PartnerFinder PartnerFinder newdef ShowerModel:KinematicsReconstructor KinematicsReconstructor -newdef Evolver:ShowerModel ShowerModel -newdef Evolver:SplittingGenerator SplittingGenerator -newdef Evolver:Interaction QEDQCD -newdef Evolver:SpinCorrelations Yes -newdef Evolver:SoftCorrelations Singular +newdef ShowerHandler:ShowerModel ShowerModel +newdef ShowerHandler:SplittingGenerator SplittingGenerator +newdef ShowerHandler:Interaction QEDQCD +newdef ShowerHandler:SpinCorrelations Yes +newdef ShowerHandler:SoftCorrelations Singular ################################################################## # Intrinsic pT # # Recommended: # 1.9 GeV for Tevatron W/Z production. # 2.1 GeV for LHC W/Z production at 10 TeV # 2.2 GeV for LHC W/Z production at 14 TeV # # Set all parameters to 0 to disable ################################################################## -newdef Evolver:IntrinsicPtGaussian 1.3*GeV -newdef Evolver:IntrinsicPtBeta 0 -newdef Evolver:IntrinsicPtGamma 0*GeV -newdef Evolver:IntrinsicPtIptmax 0*GeV -############################################################# -# Main control switches for the parton shower. -############################################################# -newdef SplittingGenerator:ISR Yes -newdef SplittingGenerator:FSR Yes +newdef ShowerHandler:IntrinsicPtGaussian 1.3*GeV +newdef ShowerHandler:IntrinsicPtBeta 0 +newdef ShowerHandler:IntrinsicPtGamma 0*GeV +newdef ShowerHandler:IntrinsicPtIptmax 0*GeV ############################################################# # Set up truncated shower handler. ############################################################# create Herwig::PowhegShowerHandler PowhegShowerHandler set PowhegShowerHandler:MPIHandler /Herwig/UnderlyingEvent/MPIHandler set PowhegShowerHandler:RemDecayer /Herwig/Partons/RemnantDecayer -set PowhegShowerHandler:Evolver /Herwig/Shower/Evolver newdef PowhegShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF newdef PowhegShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF newdef PowhegShowerHandler:PDFARemnant /Herwig/Partons/RemnantPDF newdef PowhegShowerHandler:PDFBRemnant /Herwig/Partons/RemnantPDF - -############################################################# - +newdef PowhegShowerHandler:MPIHandler /Herwig/UnderlyingEvent/MPIHandler +newdef PowhegShowerHandler:RemDecayer /Herwig/Partons/RemnantDecayer +newdef PowhegShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF +newdef PowhegShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF +newdef PowhegShowerHandler:PDFARemnant /Herwig/Partons/RemnantPDF +newdef PowhegShowerHandler:PDFBRemnant /Herwig/Partons/RemnantPDF +newdef PowhegShowerHandler:ShowerModel ShowerModel +newdef PowhegShowerHandler:SplittingGenerator SplittingGenerator +newdef PowhegShowerHandler:Interaction QEDQCD +newdef PowhegShowerHandler:SpinCorrelations Yes +newdef PowhegShowerHandler:SoftCorrelations Singular +newdef PowhegShowerHandler:IntrinsicPtGaussian 1.3*GeV +newdef PowhegShowerHandler:IntrinsicPtBeta 0 +newdef PowhegShowerHandler:IntrinsicPtGamma 0*GeV +newdef PowhegShowerHandler:IntrinsicPtIptmax 0*GeV +newdef PowhegShowerHandler:ReconstructionOption OffShell3 ############################################################# # End of interesting user servicable section. # # Anything that follows below should only be touched if you # know what you're doing. # # Really. ############################################################# # # a few default values -newdef Evolver:MECorrMode 1 -newdef Evolver:ReconstructionOption OffShell3 +newdef ShowerHandler:MECorrMode 1 +newdef ShowerHandler:ReconstructionOption OffShell3 newdef AlphaQCD:ScaleFactor 1.0 newdef AlphaQCD:NPAlphaS 2 newdef AlphaQCD:Qmin 0.935 newdef AlphaQCD:NumberOfLoops 2 newdef AlphaQCD:InputOption 1 newdef AlphaQCD:AlphaMZ 0.134 # # # Lets set up all the splittings create Herwig::HalfHalfOneSplitFn QtoQGammaSplitFn set QtoQGammaSplitFn:InteractionType QED set QtoQGammaSplitFn:ColourStructure ChargedChargedNeutral set QtoQGammaSplitFn:AngularOrdered Yes create Herwig::HalfHalfOneSplitFn QtoQGSplitFn newdef QtoQGSplitFn:InteractionType QCD newdef QtoQGSplitFn:ColourStructure TripletTripletOctet set QtoQGSplitFn:AngularOrdered Yes create Herwig::OneOneOneSplitFn GtoGGSplitFn newdef GtoGGSplitFn:InteractionType QCD newdef GtoGGSplitFn:ColourStructure OctetOctetOctet set GtoGGSplitFn:AngularOrdered Yes create Herwig::OneHalfHalfSplitFn GtoQQbarSplitFn newdef GtoQQbarSplitFn:InteractionType QCD newdef GtoQQbarSplitFn:ColourStructure OctetTripletTriplet set GtoQQbarSplitFn:AngularOrdered No create Herwig::OneHalfHalfSplitFn GammatoQQbarSplitFn newdef GammatoQQbarSplitFn:InteractionType QED newdef GammatoQQbarSplitFn:ColourStructure NeutralChargedCharged set GammatoQQbarSplitFn:AngularOrdered No create Herwig::HalfOneHalfSplitFn QtoGQSplitFn newdef QtoGQSplitFn:InteractionType QCD newdef QtoGQSplitFn:ColourStructure TripletOctetTriplet set QtoGQSplitFn:AngularOrdered Yes create Herwig::HalfOneHalfSplitFn QtoGammaQSplitFn newdef QtoGammaQSplitFn:InteractionType QED newdef QtoGammaQSplitFn:ColourStructure ChargedNeutralCharged set QtoGammaQSplitFn:AngularOrdered Yes create Herwig::HalfHalfOneEWSplitFn QtoQWZSplitFn newdef QtoQWZSplitFn:InteractionType EW newdef QtoQWZSplitFn:ColourStructure EW # # Now the Sudakovs create Herwig::QTildeSudakov SudakovCommon newdef SudakovCommon:Alpha AlphaQCD newdef SudakovCommon:cutoffKinScale 0.0*GeV newdef SudakovCommon:PDFmax 1.0 newdef SudakovCommon:CutOffOption pT newdef SudakovCommon:pTmin 1.67*GeV cp SudakovCommon QtoQGSudakov newdef QtoQGSudakov:SplittingFunction QtoQGSplitFn newdef QtoQGSudakov:PDFmax 1.9 cp SudakovCommon QtoQGammaSudakov set QtoQGammaSudakov:SplittingFunction QtoQGammaSplitFn set QtoQGammaSudakov:Alpha AlphaQED set QtoQGammaSudakov:PDFmax 1.9 cp QtoQGammaSudakov LtoLGammaSudakov cp SudakovCommon QtoQWZSudakov set QtoQWZSudakov:SplittingFunction QtoQWZSplitFn set QtoQWZSudakov:Alpha AlphaEW set QtoQWZSudakov:PDFmax 1.9 cp QtoQWZSudakov LtoLWZSudakov cp SudakovCommon GtoGGSudakov newdef GtoGGSudakov:SplittingFunction GtoGGSplitFn newdef GtoGGSudakov:PDFmax 2.0 cp SudakovCommon GtoQQbarSudakov newdef GtoQQbarSudakov:SplittingFunction GtoQQbarSplitFn newdef GtoQQbarSudakov:PDFmax 120.0 cp SudakovCommon GammatoQQbarSudakov newdef GammatoQQbarSudakov:SplittingFunction GammatoQQbarSplitFn newdef GammatoQQbarSudakov:PDFmax 120.0 cp SudakovCommon GtobbbarSudakov newdef GtobbbarSudakov:SplittingFunction GtoQQbarSplitFn newdef GtobbbarSudakov:PDFmax 40000.0 cp SudakovCommon GtoccbarSudakov newdef GtoccbarSudakov:SplittingFunction GtoQQbarSplitFn newdef GtoccbarSudakov:PDFmax 2000.0 cp SudakovCommon QtoGQSudakov newdef QtoGQSudakov:SplittingFunction QtoGQSplitFn cp SudakovCommon QtoGammaQSudakov newdef QtoGammaQSudakov:SplittingFunction QtoGammaQSplitFn cp SudakovCommon utoGuSudakov newdef utoGuSudakov:SplittingFunction QtoGQSplitFn newdef utoGuSudakov:PDFFactor OverOneMinusZ newdef utoGuSudakov:PDFmax 5.0 cp SudakovCommon dtoGdSudakov newdef dtoGdSudakov:SplittingFunction QtoGQSplitFn newdef dtoGdSudakov:PDFFactor OverOneMinusZ # # Now add the final splittings # do SplittingGenerator:AddFinalSplitting u->u,g; QtoQGSudakov do SplittingGenerator:AddFinalSplitting d->d,g; QtoQGSudakov do SplittingGenerator:AddFinalSplitting s->s,g; QtoQGSudakov do SplittingGenerator:AddFinalSplitting c->c,g; QtoQGSudakov do SplittingGenerator:AddFinalSplitting b->b,g; QtoQGSudakov do SplittingGenerator:AddFinalSplitting t->t,g; QtoQGSudakov # do SplittingGenerator:AddFinalSplitting g->g,g; GtoGGSudakov # do SplittingGenerator:AddFinalSplitting g->u,ubar; GtoQQbarSudakov do SplittingGenerator:AddFinalSplitting g->d,dbar; GtoQQbarSudakov do SplittingGenerator:AddFinalSplitting g->s,sbar; GtoQQbarSudakov do SplittingGenerator:AddFinalSplitting g->c,cbar; GtoccbarSudakov do SplittingGenerator:AddFinalSplitting g->b,bbar; GtobbbarSudakov do SplittingGenerator:AddFinalSplitting g->t,tbar; GtoQQbarSudakov # do SplittingGenerator:AddFinalSplitting gamma->u,ubar; GammatoQQbarSudakov do SplittingGenerator:AddFinalSplitting gamma->d,dbar; GammatoQQbarSudakov do SplittingGenerator:AddFinalSplitting gamma->s,sbar; GammatoQQbarSudakov do SplittingGenerator:AddFinalSplitting gamma->c,cbar; GammatoQQbarSudakov do SplittingGenerator:AddFinalSplitting gamma->b,bbar; GammatoQQbarSudakov do SplittingGenerator:AddFinalSplitting gamma->t,tbar; GammatoQQbarSudakov do SplittingGenerator:AddFinalSplitting gamma->e-,e+; GammatoQQbarSudakov do SplittingGenerator:AddFinalSplitting gamma->mu-,mu+; GammatoQQbarSudakov do SplittingGenerator:AddFinalSplitting gamma->tau-,tau+; GammatoQQbarSudakov # do SplittingGenerator:AddFinalSplitting u->u,gamma; QtoQGammaSudakov do SplittingGenerator:AddFinalSplitting d->d,gamma; QtoQGammaSudakov do SplittingGenerator:AddFinalSplitting s->s,gamma; QtoQGammaSudakov do SplittingGenerator:AddFinalSplitting c->c,gamma; QtoQGammaSudakov do SplittingGenerator:AddFinalSplitting b->b,gamma; QtoQGammaSudakov do SplittingGenerator:AddFinalSplitting t->t,gamma; QtoQGammaSudakov do SplittingGenerator:AddFinalSplitting e-->e-,gamma; LtoLGammaSudakov do SplittingGenerator:AddFinalSplitting mu-->mu-,gamma; LtoLGammaSudakov do SplittingGenerator:AddFinalSplitting tau-->tau-,gamma; LtoLGammaSudakov # # Now lets add the initial splittings. Remember the form a->b,c; means # that particle a is the particle given and we backward branch to # particle b which is initial state and particle c which is final state # do SplittingGenerator:AddInitialSplitting u->u,g; QtoQGSudakov do SplittingGenerator:AddInitialSplitting d->d,g; QtoQGSudakov do SplittingGenerator:AddInitialSplitting s->s,g; QtoQGSudakov do SplittingGenerator:AddInitialSplitting c->c,g; QtoQGSudakov do SplittingGenerator:AddInitialSplitting b->b,g; QtoQGSudakov do SplittingGenerator:AddInitialSplitting u->u,gamma; QtoQGammaSudakov do SplittingGenerator:AddInitialSplitting d->d,gamma; QtoQGammaSudakov do SplittingGenerator:AddInitialSplitting s->s,gamma; QtoQGammaSudakov do SplittingGenerator:AddInitialSplitting c->c,gamma; QtoQGammaSudakov do SplittingGenerator:AddInitialSplitting b->b,gamma; QtoQGammaSudakov do SplittingGenerator:AddInitialSplitting t->t,gamma; QtoQGammaSudakov do SplittingGenerator:AddInitialSplitting g->g,g; GtoGGSudakov # do SplittingGenerator:AddInitialSplitting g->d,dbar; GtoQQbarSudakov do SplittingGenerator:AddInitialSplitting g->u,ubar; GtoQQbarSudakov do SplittingGenerator:AddInitialSplitting g->s,sbar; GtoQQbarSudakov do SplittingGenerator:AddInitialSplitting g->c,cbar; GtoccbarSudakov do SplittingGenerator:AddInitialSplitting g->b,bbar; GtobbbarSudakov # do SplittingGenerator:AddInitialSplitting gamma->d,dbar; GammatoQQbarSudakov do SplittingGenerator:AddInitialSplitting gamma->u,ubar; GammatoQQbarSudakov do SplittingGenerator:AddInitialSplitting gamma->s,sbar; GammatoQQbarSudakov do SplittingGenerator:AddInitialSplitting gamma->c,cbar; GammatoQQbarSudakov do SplittingGenerator:AddInitialSplitting gamma->b,bbar; GammatoQQbarSudakov # do SplittingGenerator:AddInitialSplitting d->g,d; dtoGdSudakov do SplittingGenerator:AddInitialSplitting u->g,u; utoGuSudakov do SplittingGenerator:AddInitialSplitting s->g,s; QtoGQSudakov do SplittingGenerator:AddInitialSplitting c->g,c; QtoGQSudakov do SplittingGenerator:AddInitialSplitting b->g,b; QtoGQSudakov do SplittingGenerator:AddInitialSplitting dbar->g,dbar; dtoGdSudakov do SplittingGenerator:AddInitialSplitting ubar->g,ubar; utoGuSudakov do SplittingGenerator:AddInitialSplitting sbar->g,sbar; QtoGQSudakov do SplittingGenerator:AddInitialSplitting cbar->g,cbar; QtoGQSudakov do SplittingGenerator:AddInitialSplitting bbar->g,bbar; QtoGQSudakov # do SplittingGenerator:AddInitialSplitting d->gamma,d; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting u->gamma,u; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting s->gamma,s; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting c->gamma,c; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting b->gamma,b; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting dbar->gamma,dbar; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting ubar->gamma,ubar; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting sbar->gamma,sbar; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting cbar->gamma,cbar; QtoGammaQSudakov do SplittingGenerator:AddInitialSplitting bbar->gamma,bbar; QtoGammaQSudakov # # Electroweak # do SplittingGenerator:AddFinalSplitting u->u,Z0; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting d->d,Z0; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting s->s,Z0; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting c->c,Z0; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting b->b,Z0; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting t->t,Z0; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting u->u,Z0; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting d->d,Z0; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting s->s,Z0; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting c->c,Z0; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting b->b,Z0; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting t->t,Z0; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting u->d,W+; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting c->s,W+; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting d->u,W-; QtoQWZSudakov do SplittingGenerator:AddFinalSplitting s->c,W-; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting u->d,W+; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting c->s,W+; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting d->u,W-; QtoQWZSudakov do SplittingGenerator:AddInitialSplitting s->c,W-; QtoQWZSudakov