Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Hadronization/HadronSelector.h b/Hadronization/HadronSelector.h
--- a/Hadronization/HadronSelector.h
+++ b/Hadronization/HadronSelector.h
@@ -1,838 +1,846 @@
// -*- C++ -*-
//
// HadronSelector.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_HadronSelector_H
#define HERWIG_HadronSelector_H
//
// This is the declaration of the HadronSelector class.
//
#include "ThePEG/Interface/Interfaced.h"
#include <ThePEG/Persistency/PersistentOStream.h>
#include <ThePEG/Persistency/PersistentIStream.h>
#include <ThePEG/PDT/ParticleData.h>
#include <ThePEG/PDT/StandardMatchers.h>
#include <ThePEG/Repository/EventGenerator.h>
#include "HadronSelector.fh"
namespace Herwig {
using namespace ThePEG;
/**\ingroup Hadronization
* \class HadronSelector
* \brief This class selects the hadron flavours of a cluster decay.
* \author Philip Stephens
* \author Alberto Ribon
* \author Peter Richardson
*
* This is the base class for the selection of either a pair of hadrons, or
* in some cases a single hadron. The different approaches which were
* previously implemented in this class are now implemented in the
* HwppSelector and Hw64Selector which inherit from this class.
*
* This class implements a number of methods which are needed by all models
* and in addition contains the weights for the different meson multiplets and
* mixing of the light \f$I=0\f$ mesons.
*
* @see \ref HadronSelectorInterfaces "The interfaces"
* defined for HadronSelector.
* @see HwppSelector
* @see Hw64Selector
*/
class HadronSelector: public Interfaced {
public:
/** \ingroup Hadronization
* \class HadronInfo
* \brief Class used to store all the hadron information for easy access.
* \author Philip Stephens
*
* Note that:
* - the hadrons in _table can be filled in any ordered
* w.r.t. the mass value, and flavours for different
* groups (for instance, (u,s) hadrons don't need to
* be placed after (d,s) or any other flavour), but
* all hadrons with the same flavours must be consecutive
* ( for instance you cannot alternate hadrons of type
* (d,s) with those of flavour (u,s) ).
* Furthermore, it is assumed that particle and antiparticle
* have the same weights, and therefore only one of them
* must be entered in the table: we have chosen to refer
* to the particle, defined as PDG id > 0, although if
* an anti-particle is provided in input it is automatically
* transform to its particle, simply by taking the modulus
* of its id.
*/
class HadronInfo {
public:
/**
* Constructor
* @param idin The PDG code of the hadron
* @param datain The pointer to the ParticleData object
* @param swtin The singlet/decuplet/orbital factor
* @param massin The mass of the hadron
*/
HadronInfo(long idin=0, tPDPtr datain=tPDPtr(),
double swtin=1., Energy massin=ZERO)
: id(idin), ptrData(datain), swtef(swtin), wt(1.0), overallWeight(0.0),
mass(massin)
{}
/**
* Comparision operator on mass
*/
inline bool operator<(const HadronInfo &x) const {
if(mass!=x.mass) return mass < x.mass;
else return id < x.id;
}
/**
* The hadrons id.
*/
long id;
/**
* pointer to ParticleData, to get the spin, etc...
*/
tPDPtr ptrData;
/**
* singlet/decuplet/orbital factor
*/
double swtef;
/**
* mixing factor
*/
double wt;
/**
* (2*J+1)*wt*swtef
*/
double overallWeight;
/**
* The hadrons mass
*/
Energy mass;
/**
* Rescale the weight for a given hadron
*/
void rescale(double x) const {
const_cast<HadronInfo*>(this)->overallWeight *= x;
}
/**
* Friend method used to print the value of a table element.
*/
friend PersistentOStream & operator<< (PersistentOStream & os,
const HadronInfo & hi ) {
os << hi.id << hi.ptrData << hi.swtef << hi.wt
<< hi.overallWeight << ounit(hi.mass,GeV);
return os;
}
/**
* debug output
*/
friend ostream & operator<< (ostream & os, const HadronInfo & hi );
/**
* Friend method used to read in the value of a table element.
*/
friend PersistentIStream & operator>> (PersistentIStream & is,
HadronInfo & hi ) {
is >> hi.id >> hi.ptrData >> hi.swtef >> hi.wt
>> hi.overallWeight >> iunit(hi.mass,GeV);
return is;
}
};
/** \ingroup Hadronization
* \class Kupco
* \brief Class designed to make STL routines easy to use.
* \author Philip Stephens
*
* This class is used to generate a list of the hadron pairs which can
* be produced that allows easy traversal and quick access.
*/
class Kupco {
public:
/**
* Constructor
* @param inidQ PDG code of the quark drawn from the vacuum.
* @param inhad1 ParticleData for the first hadron produced.
* @param inhad2 ParticleData for the second hadron produced.
* @param inwgt The weight for the hadron pair
*/
inline Kupco(tcPDPtr inidQ,tcPDPtr inhad1,tcPDPtr inhad2, Energy inwgt)
: idQ(inidQ),hadron1(inhad1),hadron2(inhad2),weight(inwgt)
{}
/**
* id of the quark drawn from the vacuum.
*/
tcPDPtr idQ;
/**
* The ParticleData object for the first hadron produced.
*/
tcPDPtr hadron1;
/**
* The ParticleData object for the second hadron produced.
*/
tcPDPtr hadron2;
/**
* Weight factor of this componation.
*/
Energy weight;
};
public:
/**
* The helper classes
*/
//@{
/**
* The type is used to contain all the hadrons info of a given flavour.
*/
typedef set<HadronInfo> KupcoData;
//@}
/**
* The hadron table type.
*/
typedef map<pair<long,long>,KupcoData> HadronTable;
public:
/**
* The default constructor.
*/
HadronSelector(unsigned int);
/**
* Method to return a pair of hadrons given the PDG codes of
* two or three constituents
* @param cluMass The mass of the cluster
* @param par1 The first constituent
* @param par2 The second constituent
* @param par3 The third constituent
*/
virtual pair<tcPDPtr,tcPDPtr> chooseHadronPair(const Energy cluMass, tcPDPtr par1,
tcPDPtr par2,tcPDPtr par3 = PDPtr())
= 0;
/**
* This returns the lightest pair of hadrons given by the flavours.
*
* Given the two (or three) constituents of a cluster, it returns
* the two lightest hadrons with proper flavour numbers.
* Furthermore, the first of the two hadrons must have the constituent with
* par1, and the second must have the constituent with par2.
* \todo At the moment it does *nothing* in the case that also par3 is present.
*
* The method is implemented by calling twice lightestHadron,
* once with (par1,quarktopick->CC()) ,and once with (par2,quarktopick)
* where quarktopick is either the pointer to
* d or u quarks . In fact, the idea is that whatever the flavour of par1
* and par2, no matter if (anti-)quark or (anti-)diquark, the lightest
* pair of hadrons containing flavour par1 and par2 will have either
* flavour d or u, being the lightest quarks.
* The method returns the pair (PDPtr(),PDPtr()) if anything goes wrong.
*
* \todo The method assumes par3 == PDPtr() (otherwise we don't know how to proceed: a
* possible, trivial way would be to randomly select two of the three
* (anti-)quarks and treat them as a (anti-)diquark, reducing the problem
* to two components as treated below.
* In the normal (two components) situation, the strategy is the following:
* treat in the same way the two possibilities: (d dbar) (i=0) and
* (u ubar) (i=1) as the pair quark-antiquark necessary to form a
* pair of hadrons containing the input flavour par1 and par2; finally,
* select the one that produces the lightest pair of hadrons, compatible
* with the charge conservation constraint.
*/
pair<tcPDPtr,tcPDPtr> lightestHadronPair(tcPDPtr ptr1, tcPDPtr ptr2,
tcPDPtr ptr3 = PDPtr ()) const;
/**
* Returns the mass of the lightest pair of hadrons with the given particles
* @param ptr1 is the first constituent
* @param ptr2 is the second constituent
* @param ptr3 is the third constituent
*/
inline Energy massLightestHadronPair(tcPDPtr ptr1, tcPDPtr ptr2,
tcPDPtr ptr3 = PDPtr ()) const {
pair<tcPDPtr,tcPDPtr> pairData = lightestHadronPair(ptr1, ptr2, ptr3);
if ( ! pairData.first || ! pairData.second ) return ZERO;
return ( pairData.first->mass() + pairData.second->mass() );
}
/**
* Returns the lightest hadron formed by the given particles.
*
* Given the id of two (or three) constituents of a cluster, it returns
* the lightest hadron with proper flavour numbers.
* At the moment it does *nothing* in the case that also 'ptr3' present.
* @param ptr1 is the first constituent
* @param ptr2 is the second constituent
* @param ptr3 is the third constituent
*/
inline tcPDPtr lightestHadron(tcPDPtr ptr1, tcPDPtr ptr2,
+#ifndef NDEBUG
tcPDPtr ptr3 = PDPtr ()) const {
+#else
+ tcPDPtr = PDPtr ()) const {
+#endif
// The method assumes ptr3 == 0
// rest not implemented
assert(ptr1 && ptr2 && !ptr3);
// find entry in the table
pair<long,long> ids = make_pair(abs(ptr1->id()),abs(ptr2->id()));
HadronTable::const_iterator tit=_table.find(ids);
// throw exception if flavours wrong
if (tit==_table.end())
throw Exception() << "Could not find "
<< ids.first << ' ' << ids.second
<< " in _table. "
<< "In HadronSelector::lightestHadron()"
<< Exception::eventerror;
if(tit->second.empty())
throw Exception() << "HadronSelector::lightestHadron "
<< "could not find any hadrons containing "
<< ptr1->id() << ' ' << ptr2->id() << '\n'
<< tit->first.first << ' '
<< tit->first.second << Exception::eventerror;
// find the lightest hadron
int sign = signHadron(ptr1,ptr2,tit->second.begin()->ptrData);
tcPDPtr candidate = sign > 0 ?
tit->second.begin()->ptrData : tit->second.begin()->ptrData->CC();
// \todo 20 GeV limit is temporary fudge to let SM particles go through.
// \todo Use isExotic instead?
if (candidate->mass() > 20*GeV
&& candidate->mass() < ptr1->constituentMass() + ptr2->constituentMass()) {
generator()->log() << "HadronSelector::lightestHadron: "
<< "chosen candidate " << candidate->PDGName()
<< " is lighter than its constituents "
<< ptr1->PDGName() << ", " << ptr2->PDGName() << '\n'
<< candidate->mass()/GeV << " < " << ptr1->constituentMass()/GeV
<< " + " << ptr2->constituentMass()/GeV << '\n'
<< "Check your particle data tables.\n";
assert(false);
}
return candidate;
}
/**
* Return the nominal mass of the hadron returned by lightestHadron()
* @param ptr1 is the first constituent
* @param ptr2 is the second constituent
* @param ptr3 is the third constituent
*/
inline Energy massLightestHadron(tcPDPtr ptr1, tcPDPtr ptr2,
- tcPDPtr ptr3 = PDPtr ()) const {
+#ifndef NDEBUG
+ tcPDPtr ptr3 = PDPtr ()) const {
+#else
+ tcPDPtr = PDPtr ()) const {
+#endif
// The method assumes ptr3 == empty
assert(!(ptr3));
// find entry in the table
pair<long,long> ids(abs(ptr1->id()),abs(ptr2->id()));
HadronTable::const_iterator tit=_table.find(ids);
// throw exception if flavours wrong
if(tit==_table.end()||tit->second.empty())
throw Exception() << "HadronSelector::massLightestHadron "
<< "failed for particle" << ptr1->id() << " "
<< ptr2->id()
<< Exception::eventerror;
// return the mass
return tit->second.begin()->mass;
}
/**
* Returns the mass of the lightest pair of baryons.
* @param ptr1 is the first constituent
* @param ptr2 is the second constituent
*/
Energy massLightestBaryonPair(tcPDPtr ptr1, tcPDPtr ptr2) const;
/**
* Return the weights for the different quarks and diquarks
*/
//@{
/**
* The down quark weight.
*/
inline double pwtDquark() const {
return _pwtDquark;
}
/**
* The up quark weight.
*/
inline double pwtUquark() const {
return _pwtUquark;
}
/**
* The strange quark weight.
*/
inline double pwtSquark() const {
return _pwtSquark;
}
/**
* The charm quark weight.
*/
inline double pwtCquark() const {
return _pwtCquark;
}
/**
* The bottom quark weight.
*/
inline double pwtBquark() const {
return _pwtBquark;
}
/**
* The diquark weight.
*/
inline double pwtDIquark() const {
return _pwtDIquark;
}
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for 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.
*
* The array _repwt is initialized using the interfaces to set different
* weights for different meson multiplets and the constructHadronTable()
* method called to complete the construction of the hadron tables.
*
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
protected:
/**
* Construct the table of hadron data
* This is the main method to initialize the hadron data (mainly the
* weights associated to each hadron, taking into account its spin,
* eventual isoscalar-octect mixing, singlet-decuplet factor). This is
* the method that one should update when new or updated hadron data is
* available.
*
* This class implements the construction of the basic table but can be
* overridden if needed in inheriting classes.
*
* The rationale for factors used for diquarks involving different quarks can
* be can be explained by taking a prototype example that in the exact SU(2) limit,
* in which:
* \f[m_u=m_d\f]
* \f[M_p=M_n=M_\Delta\f]
* and we will have equal numbers of u and d quarks produced.
* Suppose that we weight 1 the diquarks made of the same
* quark and 1/2 those made of different quarks, the fractions
* of u and d baryons (p, n, Delta) we get are the following:
* - \f$\Delta^{++}\f$: 1 possibility only u uu with weight 1
* - \f$\Delta^- \f$: 1 possibility only d dd with weight 1
* - \f$p,\Delta^+ \f$: 2 possibilities u ud with weight 1/2
* d uu with weight 1
* - \f$n,\Delta^0 \f$: 2 possibilities d ud with weight 1/2
* u dd with weight 1
* In the latter two cases, we have to take into account the
* fact that p and n have spin 1/2 whereas Delta+ and Delta0
* have spin 3/2 therefore from phase space we get a double weight
* for Delta+ and Delta0 relative to p and n respectively.
* Therefore the relative amount of these baryons that is
* produced is the following:
* # p = # n = ( 1/2 + 1 ) * 1/3 = 1/2
* # Delta++ = # Delta- = 1 = ( 1/2 + 1) * 2/3 # Delta+ = # Delta0
* which is correct, and therefore the weight 1/2 for the
* diquarks of different types of quarks is justified (at least
* in this limit of exact SU(2) ).
*/
virtual void constructHadronTable();
/**
* Access to the table of hadrons
*/
inline HadronTable & table() {
return _table;
}
/**
* Access to the list of partons
*/
inline vector<PDPtr> & partons() {
return _partons;
}
/**
* Access the parton weights
*/
inline double pwt(tcPDPtr p) {
assert(p);
if ( p->id() < 0 ) p = p->CC();
map<tcPDPtr,double>::iterator it = _pwt.find(p);
assert( it != _pwt.end() );
return it->second;
}
/**
* Methods for the mixing of \f$I=0\f$ mesons
*/
//@{
/**
* Return the probability of mixing for Octet-Singlet isoscalar mixing,
* the probability of the
* \f$\frac1{\sqrt{2}}(|u\bar{u}\rangle + |d\bar{d}\rangle)\f$ component
* is returned.
* @param angleMix The mixing angle in degrees (not radians)
* @param order is 0 for no mixing, 1 for the first resonance of a pair,
* 2 for the second one.
* The mixing is defined so that for example with \f$\eta-\eta'\f$ mixing where
* the mixing angle is \f$\theta=-23^0$ with $\eta\f$ as the first particle
* and \f$\eta'\f$ the second one.
* The convention used is
* \f[\eta = \cos\theta|\eta_{\rm octet }\rangle
* -\sin\theta|\eta_{\rm singlet}\rangle\f]
* \f[\eta' = \sin\theta|\eta_{\rm octet }\rangle
* -\cos\theta|\eta_{\rm singlet}\rangle\f]
* with
* \f[|\eta_{\rm singlet}\rangle = \frac1{\sqrt{3}}
* \left[|u\bar{u}\rangle + |d\bar{d}\rangle + |s\bar{s}\rangle\right]\f]
* \f[|\eta_{\rm octet }\rangle = \frac1{\sqrt{6}}
* \left[|u\bar{u}\rangle + |d\bar{d}\rangle - 2|s\bar{s}\rangle\right]\f]
*/
inline double probabilityMixing(const double angleMix,
const int order) {
static double convert=Constants::pi/180.0;
if (order == 1)
return sqr( cos( angleMix*convert + atan( sqrt(2.0) ) ) );
else if (order == 2)
return sqr( sin( angleMix*convert + atan( sqrt(2.0) ) ) );
else
return 1.;
}
/**
* Returns the weight of given mixing state.
* @param id The PDG code of the meson
*/
virtual double mixingStateWeight(long id);
//@}
/**
* Calculates a special weight specific to a given hadron.
* @param id The PDG code of the hadron
*/
double specialWeight(long id);
/**
* This method returns the proper sign ( > 0 hadron; < 0 anti-hadron )
* for the input PDG id idHad > 0, suppose to be made by the
* two constituent particle pointers: par1 and par2 (both with proper sign).
*/
int signHadron(tcPDPtr ptr1, tcPDPtr ptr2, tcPDPtr hadron) const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<HadronSelector> initHadronSelector;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
HadronSelector & operator=(const HadronSelector &);
private:
/**
* The PDG codes of the constituent particles allowed
*/
vector<PDPtr> _partons;
/**
* The PDG codes of the hadrons which cannot be produced in the hadronization
*/
vector<PDPtr> _forbidden;
/**
* The weights for the different quarks and diquarks
*/
//@{
/**
* The probability of producting a down quark.
*/
double _pwtDquark;
/**
* The probability of producting an up quark.
*/
double _pwtUquark;
/**
* The probability of producting a strange quark.
*/
double _pwtSquark;
/**
* The probability of producting a charm quark.
*/
double _pwtCquark;
/**
* The probability of producting a bottom quark.
*/
double _pwtBquark;
/**
* The probability of producting a diquark.
*/
double _pwtDIquark;
/**
* Weights for quarks and diquarks.
*/
map<tcPDPtr,double> _pwt;
//@}
/**
* The mixing angles for the \f$I=0\f$ mesons containing light quarks
*/
//@{
/**
* The \f$\eta-\eta'\f$ mixing angle
*/
double _etamix;
/**
* The \f$\phi-\omega\f$ mixing angle
*/
double _phimix;
/**
* The \f$h_1'-h_1\f$ mixing angle
*/
double _h1mix;
/**
* The \f$f_0(1710)-f_0(1370)\f$ mixing angle
*/
double _f0mix;
/**
* The \f$f_1(1420)-f_1(1285)\f$ mixing angle
*/
double _f1mix;
/**
* The \f$f'_2-f_2\f$ mixing angle
*/
double _f2mix;
/**
* The \f$\eta_2(1870)-\eta_2(1645)\f$ mixing angle
*/
double _eta2mix;
/**
* The \f$\phi(???)-\omega(1650)\f$ mixing angle
*/
double _omhmix;
/**
* The \f$\phi_3-\omega_3\f$ mixing angle
*/
double _ph3mix;
/**
* The \f$\eta(1475)-\eta(1295)\f$ mixing angle
*/
double _eta2Smix;
/**
* The \f$\phi(1680)-\omega(1420)\f$ mixing angle
*/
double _phi2Smix;
//@}
/**
* The weights for the various meson multiplets to be used to supress the
* production of particular states
*/
//@{
/**
* The weights for the \f$\phantom{1}^1S_0\f$ multiplets
*/
vector<double> _weight1S0;
/**
* The weights for the \f$\phantom{1}^3S_1\f$ multiplets
*/
vector<double> _weight3S1;
/**
* The weights for the \f$\phantom{1}^1P_1\f$ multiplets
*/
vector<double> _weight1P1;
/**
* The weights for the \f$\phantom{1}^3P_0\f$ multiplets
*/
vector<double> _weight3P0;
/**
* The weights for the \f$\phantom{1}^3P_1\f$ multiplets
*/
vector<double> _weight3P1;
/**
* The weights for the \f$\phantom{1}^3P_2\f$ multiplets
*/
vector<double> _weight3P2;
/**
* The weights for the \f$\phantom{1}^1D_2\f$ multiplets
*/
vector<double> _weight1D2;
/**
* The weights for the \f$\phantom{1}^3D_1\f$ multiplets
*/
vector<double> _weight3D1;
/**
* The weights for the \f$\phantom{1}^3D_2\f$ multiplets
*/
vector<double> _weight3D2;
/**
* The weights for the \f$\phantom{1}^3D_3\f$ multiplets
*/
vector<double> _weight3D3;
//@}
/**
* The weights for the excited meson multiplets
*/
vector<vector<vector<double> > > _repwt;
/**
* Singlet and Decuplet weights
*/
//@{
/**
* The singlet weight
*/
double _sngWt;
/**
* The decuplet weight
*/
double _decWt;
//@}
/**
* The table of hadron data
*/
HadronTable _table;
/**
* Enums so arrays can be statically allocated
*/
//@{
/**
* Defines values for array sizes. L,J,N max values for excited mesons.
*/
enum MesonMultiplets { Lmax = 3, Jmax = 4, Nmax = 4};
//@}
/**
* Option for the construction of the tables
*/
unsigned int _topt;
/**
* Which particles to produce for debugging purposes
*/
unsigned int _trial;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of HadronSelector. */
template <>
struct BaseClassTrait<Herwig::HadronSelector,1> {
/** Typedef of the first base class of HadronSelector. */
typedef Interfaced NthBase;
};
/** This template specialization informs ThePEG about the name of
* the HadronSelector class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::HadronSelector>
: public ClassTraitsBase<Herwig::HadronSelector> {
/** Return a platform-independent class name */
static string className() { return "Herwig::HadronSelector"; }
};
/** @endcond */
}
#endif /* HERWIG_HadronSelector_H */
diff --git a/MatrixElement/Powheg/MEPP2VVPowheg.cc b/MatrixElement/Powheg/MEPP2VVPowheg.cc
--- a/MatrixElement/Powheg/MEPP2VVPowheg.cc
+++ b/MatrixElement/Powheg/MEPP2VVPowheg.cc
@@ -1,5378 +1,5360 @@
// -*- C++ -*-
//
// MEPP2VVPowheg.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 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/DecayMatrixElement.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<Complex>(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<unsigned int>(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> MEPP2VVPowheg::initMEPP2VVPowheg;
// Definition of the static class description member.
void MEPP2VVPowheg::Init() {
static Switch<MEPP2VVPowheg,unsigned int> 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<MEPP2VVPowheg,unsigned int> 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<MEPP2VVPowheg,unsigned int> 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<MEPP2VVPowheg,double> 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<MEPP2VVPowheg,unsigned int> 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<MEPP2VVPowheg,unsigned int> 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 (mT(V1)+mT(V2))/2. "
"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<MEPP2VVPowheg,Energy> 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<MEPP2VVPowheg,Energy> 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<MEPP2VVPowheg,bool> 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<MEPP2VVPowheg,ShowerAlpha> interfaceCoupling
("Coupling",
"The object calculating the strong coupling constant",
&MEPP2VVPowheg::showerAlphaS_, false, false, true, false, false);
static Parameter<MEPP2VVPowheg,double> 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<MEPP2VVPowheg,double> 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<MEPP2VVPowheg,double> 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<MEPP2VVPowheg,double> 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<MEPP2VVPowheg, Energy> 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<tcHwSMPtr>(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<StandardCKM>::pointer
theCKM=dynamic_ptr_cast<Ptr<StandardCKM>::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<Complex > > 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<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().first->dataPtr());
// The -z hadron in the lab:
hadron_B_=dynamic_ptr_cast<Ptr<BeamParticleData>::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 s2(H_.s2r());
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 s2(H_.s2r());
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 s2(H_.s2r());
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);
- Energy2 del(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());
- 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;
}
}
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);
- Energy2 sig(mZ2+mW2);
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 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 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 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 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 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 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
- Energy2 mZ2(B.k22b()); // the 2->2 from the 2->3 kinematics.
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
- 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.
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());
- 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());
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<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> 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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<VectorWaveFunction> 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<tcPDPtr> 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<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_t;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_t = (!(k1data->id()==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;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
// if(getMatrix) {
// if(khel==0)
// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,0) = hel_amp;
// else
// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,2) = hel_amp;
// }
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
// if(getMatrix) {
// 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) {
// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,1) = Complex(0.,0.);
// }
// }
// }
// }
// }
// Spin and colour averaging factors = 1/4 * CF * 1/3 = 1/9
sum_hel_amps_sqr /= 9.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==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<SpinorWaveFunction> qin;
vector<SpinorBarWaveFunction> 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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<VectorWaveFunction> 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<tcPDPtr> 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<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_q;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_q = (!(k1data->id()==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;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
// if(getMatrix) {
// if(p2hel==0)
// qg_hel_amps_(p1hel,0,k1hel,k2hel,khel) = hel_amp;
// else
// qg_hel_amps_(p1hel,2,k1hel,k2hel,khel) = hel_amp;
// }
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
// if(getMatrix) {
// for(unsigned int p1hel=0;p1hel<2;++p1hel) {
// for(unsigned int k1hel=0;k1hel<3;++k1hel) {
// for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// for(unsigned int khel=0;khel<2;++khel) {
// qg_hel_amps_(p1hel,1,k1hel,k2hel,khel) = Complex(0.,0.);
// }
// }
// }
// }
// }
// Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
sum_hel_amps_sqr /= 24.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==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<SpinorBarWaveFunction> qbin;
vector<SpinorWaveFunction> 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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<VectorWaveFunction> 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<tcPDPtr> 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<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_q;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_q = (!(k1data->id()==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;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
// if(getMatrix) {
// if(p1hel==0)
// gqb_hel_amps_(0,p2hel,k1hel,k2hel,khel) = hel_amp;
// else
// gqb_hel_amps_(2,p2hel,k1hel,k2hel,khel) = hel_amp;
// }
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
// if(getMatrix) {
// for(unsigned int p2hel=0;p2hel<2;++p2hel) {
// for(unsigned int k1hel=0;k1hel<3;++k1hel) {
// for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// for(unsigned int khel=0;khel<2;++khel) {
// gqb_hel_amps_(1,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
// }
// }
// }
// }
// }
// Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
sum_hel_amps_sqr /= 24.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==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<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> 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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<tcPDPtr> 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<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_t;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_t = (!(k1data->id()==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;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
// if(getMatrix) lo_hel_amps_(p1hel,p2hel,k1hel,k2hel) = hel_amp;
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
// Spin and colour averaging factors = 1/4 * 1/3 = 1/12
sum_hel_amps_sqr /= 12.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr;
}
HardTreePtr MEPP2VVPowheg::generateHardest(ShowerTreePtr tree) {
// Now we want to set these data vectors according to the particles we've
// received from the current 2->2 hard collision:
vector<ShowerProgenitorPtr> particlesToShower;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit )
particlesToShower.push_back(cit->first);
qProgenitor_ = particlesToShower[0];
qbProgenitor_ = particlesToShower[1];
showerQuark_ = particlesToShower[0]->progenitor();
showerAntiquark_ = particlesToShower[1]->progenitor();
qHadron_ = particlesToShower[0]->beam();
qbHadron_ = particlesToShower[1]->beam();
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()<ZERO ? true : false;
assert(tree->outgoingLines().size()==2);
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit )
particlesToShower.push_back(cit->first);
V1_ = particlesToShower[2]->progenitor();
V2_ = particlesToShower[3]->progenitor();
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_);
// *** 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;ix<outgoing.size();ix++)
if(outgoing[ix]->parents()[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<Lorentz5Momentum> 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<Lorentz5Momentum> theRealMomenta;
channel_ = 999;
if(!getEvent(theRealMomenta,channel_)) return HardTreePtr();
// Set the maximum pT for subsequent emissions:
pT_ < min_pT_ ? qProgenitor_ ->maximumpT(min_pT_) : qProgenitor_ ->maximumpT(pT_);
pT_ < min_pT_ ? qbProgenitor_->maximumpT(min_pT_) : qbProgenitor_->maximumpT(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()<ZERO)||
channel_==1) fermionNumberOfMother_ = -1;
assert(fermionNumberOfMother_!=0);
// If the quark in the original tree was travelling in the -z direction
// then we need to unflip the event (flips are automatically carried out
// when the original quark travels in the in -z direction when the
// bornVVKinematics object is created):
if(flipped_)
for(unsigned int ix=0;ix<theRealMomenta.size();ix++)
theRealMomenta[ix].rotateY(-Constants::pi);
// Randomly rotate the event about the beam axis:
double randomPhi(UseRandom::rnd()*2.*Constants::pi);
for(unsigned int ix=0;ix<theRealMomenta.size();ix++)
theRealMomenta[ix].rotateZ(randomPhi);
// Warn if momentum conservation is not obeyed:
Lorentz5Momentum inMinusOut(theRealMomenta[0]+theRealMomenta[1]
-theRealMomenta[2]-theRealMomenta[3]
-theRealMomenta[4]);
if(inMinusOut.t()>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 ;
// 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 ));
}
// 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 ));
}
// 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 ));
}
// 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 nasonTree, using this information:
ShowerParticlePtr mother;
ShowerParticlePtr spacelikeSon;
ShowerParticlePtr timelikeSon;
ShowerParticlePtr spectator;
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;
}
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);
motherBranching->colourPartner(spectatorBranching);
spectatorBranching->colourPartner(motherBranching);
vector<HardBranchingPtr> 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);
// 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 nasonTree=new_ptr(HardTree(hardBranchings,spacelikeBranchings,
ShowerInteraction::QCD));
if(nasonTree->branchings().size()!=4) throw Exception()
<< "MEPP2VVPowheg::generateHardest()\n"
<< "The nasonTree has " << nasonTree->branchings().size() << "branchings\n"
<< nasonTree << "\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) {
nasonTree->connect(showerQuark_ ,motherBranching );
nasonTree->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) {
nasonTree->connect(showerAntiquark_,motherBranching );
nasonTree->connect(showerQuark_ ,spectatorBranching);
spacelikeSonBranching->beam(qbProgenitor_->original()->parents()[0]);
motherBranching ->beam(qbProgenitor_->original()->parents()[0]);
spectatorBranching ->beam(qProgenitor_ ->original()->parents()[0]);
}
// nasonTree->connect(V1_ ,V1_Branching );
// nasonTree->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);
} else if(fermionNumberOfMother_==-1) {
bornColourLine->addAntiColoured(mother);
bornColourLine->addColoured(spectator);
}
// this is a pain but we need the boost, which we don't have yet here!!
vector<Lorentz5Momentum> pin(2);
vector<Lorentz5Momentum> pq (2);
vector<HardBranchingPtr>::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()<ZERO) swap(x[0],x[1]);
Lorentz5Momentum pnew = x[0]*pq[0]+x[1]*pq[1];
LorentzRotation toRest = LorentzRotation(-pcm .boostVector());
LorentzRotation fromRest = LorentzRotation( pnew.boostVector());
Lorentz5Momentum pv[2]=
{fromRest*toRest*V1_Branching->branchingParticle()->momentum(),
fromRest*toRest*V2_Branching->branchingParticle()->momentum()};
LorentzRotation R(-(mother->momentum()+spectator ->momentum()).boostVector());
R.boost((showerQuark_->momentum()+showerAntiquark_->momentum()).boostVector());
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit = tree->treelinks().begin();
tit != tree->treelinks().end();++tit) {
ShowerTreePtr decayTree = tit->first;
map<ShowerProgenitorPtr,ShowerParticlePtr>::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<ShowerProgenitorPtr,tShowerParticlePtr>::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) {
Lorentz5Momentum ptemp = boost*cjt->first->progenitor()->momentum();
cjt->first->original() ->set5Momentum(cjt->first->progenitor()->momentum());
cjt->first->progenitor()->deepTransform(boost);
cjt->first->original() ->deepTransform(boost);
cjt->first->copy() ->deepTransform(boost);
}
}
return nasonTree;
}
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*x2<p2/sqr(generator()->maximumCMEnergy())) 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<Lorentz5Momentum> & 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(pT<min_pT_) {
pT=ZERO;
rejectEmission = false;
}
if(rejectionWeight>1.) {
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_<min_pT_) {
pT_ = ZERO;
channel = 3;
}
if(channel==3) return false;
if(channel>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<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> 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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<VectorWaveFunction> 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<tcPDPtr> 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<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_t;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_t = (!(k1data->id()==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;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
if(getMatrix) {
if(khel==0)
qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,0) = hel_amp;
else
qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,2) = hel_amp;
}
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
if(getMatrix) {
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) {
qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,1) = Complex(0.,0.);
}
}
}
}
}
// Calculate the production density matrix:
if(getMatrix) {
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) {
Complex theElement(0.,0.);
// For each k1hel, k1helpr, k2hel, k2helpr sum over fermion and gluon spins...
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<3;khel+=2) {
theElement += qqb_hel_amps(p1hel,p2hel,k1hel ,k2hel ,khel)
*conj(qqb_hel_amps(p1hel,p2hel,k1helpr,k2helpr,khel));
}
}
}
// ...and then set the production matrix element to the sum:
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] = theElement;
}
}
}
}
}
// Spin and colour averaging factors = 1/4 * CF * 1/3 = 1/9
sum_hel_amps_sqr /= 9.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==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<SpinorWaveFunction> qin;
vector<SpinorBarWaveFunction> 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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<VectorWaveFunction> 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<tcPDPtr> 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<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_q;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_q = (!(k1data->id()==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;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
if(getMatrix) {
if(p2hel==0)
qg_hel_amps(p1hel,0,k1hel,k2hel,khel) = hel_amp;
else
qg_hel_amps(p1hel,2,k1hel,k2hel,khel) = hel_amp;
}
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
if(getMatrix) {
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int khel=0;khel<2;++khel) {
qg_hel_amps(p1hel,1,k1hel,k2hel,khel) = Complex(0.,0.);
}
}
}
}
}
// Calculate the production density matrix:
if(getMatrix) {
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) {
Complex theElement(0.,0.);
// For each k1hel, k1helpr, k2hel, k2helpr sum over fermion and gluon spins...
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<3;p2hel+=2) {
for(unsigned int khel=0;khel<2;++khel) {
theElement += qg_hel_amps(p1hel,p2hel,k1hel ,k2hel ,khel)
*conj(qg_hel_amps(p1hel,p2hel,k1helpr,k2helpr,khel));
}
}
}
// ...and then set the production matrix element to the sum:
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] = theElement;
}
}
}
}
}
// Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
sum_hel_amps_sqr /= 24.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==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<SpinorBarWaveFunction> qbin;
vector<SpinorWaveFunction> 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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<VectorWaveFunction> 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<tcPDPtr> 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<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_q;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_q = (!(k1data->id()==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;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
if(getMatrix) {
if(p1hel==0)
gqb_hel_amps(0,p2hel,k1hel,k2hel,khel) = hel_amp;
else
gqb_hel_amps(2,p2hel,k1hel,k2hel,khel) = hel_amp;
}
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
if(getMatrix) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int khel=0;khel<2;++khel) {
gqb_hel_amps(1,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
}
}
}
}
}
// Calculate the production density matrix:
if(getMatrix) {
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) {
Complex theElement(0.,0.);
// For each k1hel, k1helpr, k2hel, k2helpr sum over fermion and gluon spins...
for(unsigned int p1hel=0;p1hel<3;p1hel+=2) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<2;++khel) {
theElement += gqb_hel_amps(p1hel,p2hel,k1hel ,k2hel ,khel)
*conj(gqb_hel_amps(p1hel,p2hel,k1helpr,k2helpr,khel));
}
}
}
// ...and then set the production matrix element to the sum:
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] = theElement;
}
}
}
}
}
// Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
sum_hel_amps_sqr /= 24.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==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<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> 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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<tcPDPtr> 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<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_t;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_t = (!(k1data->id()==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;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
if(getMatrix) lo_hel_amps(p1hel,p2hel,k1hel,k2hel) = hel_amp;
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
// Calculate the production density matrix:
if(getMatrix) {
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) {
Complex theElement(0.,0.);
// For each k1hel, k1helpr, k2hel, k2helpr sum over the fermion spins...
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
if((p1hel==p2hel)&&helicityConservation_) continue;
theElement += lo_hel_amps(p1hel,p2hel,k1hel ,k2hel )
*conj(lo_hel_amps(p1hel,p2hel,k1helpr,k2helpr));
}
}
// ...and then set the production matrix element to the sum:
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] = theElement;
}
}
}
}
}
// Spin and colour averaging factors = 1/4 * 1/3 = 1/12
sum_hel_amps_sqr /= 12.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==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<VectorWaveFunction> v1;
vector<VectorWaveFunction> 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<SpinorWaveFunction> k3,k5;
vector<SpinorBarWaveFunction> 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);
}
DecayMatrixElement decayAmps(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()<decayWeight) vetoed = false;
else vetoed = true;
}
return;
}
Energy2 MEPP2VVPowheg::triangleFn(Energy2 m12,Energy2 m22, Energy2 m32) {
Energy4 lambda2(m12*m12+m22*m22+m32*m32-2.*m12*m22-2.*m12*m32-2.*m22*m32);
if(lambda2>=ZERO) {
return sqrt(lambda2);
} else {
generator()->log()
<< "MEPP2VVPowheg::triangleFn "
<< "kinematic instability, imaginary triangle function\n";
return -999999.*GeV2;
}
}
diff --git a/Models/ADD/ADDModelFFGGRVertex.cc b/Models/ADD/ADDModelFFGGRVertex.cc
--- a/Models/ADD/ADDModelFFGGRVertex.cc
+++ b/Models/ADD/ADDModelFFGGRVertex.cc
@@ -1,83 +1,88 @@
// -*- C++ -*-
//
// ADDModelFFGGRVertex.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 ADDModelFFGGRVertex class.
//
#include "ADDModelFFGGRVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG;
ADDModelFFGGRVertex::ADDModelFFGGRVertex()
: couplast_(0.), q2last_(ZERO), kappa_(ZERO), r_(ZERO) {
for(int ix=1;ix<7;++ix) {
addToList(-ix,ix,21,39);
}
}
void ADDModelFFGGRVertex::doinit() {
orderInGem(1);
orderInGs (1);
FFVTVertex::doinit();
tcHwADDPtr hwADD=dynamic_ptr_cast<tcHwADDPtr>(generator()->standardModel());
if(!hwADD) throw Exception()
<< "Must have ADDModel in ADDModelFFGGRVertex::doinit()"
<< Exception::runerror;
kappa_ = 2./hwADD->MPlanckBar();
r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar();
}
void ADDModelFFGGRVertex::persistentOutput(PersistentOStream & os) const {
os << ounit(kappa_,InvGeV) << ounit(r_,GeV);
}
void ADDModelFFGGRVertex::persistentInput(PersistentIStream & is, int) {
is >> iunit(kappa_,InvGeV) >> iunit(r_,GeV);
}
ClassDescription<ADDModelFFGGRVertex> ADDModelFFGGRVertex::initADDModelFFGGRVertex;
// Definition of the static class description member.
void ADDModelFFGGRVertex::Init() {
static ClassDocumentation<ADDModelFFGGRVertex> documentation
("The ADDModelFFGGRVertexxs class is the implementation"
" of the two fermion vector coupling for the ADD model.");
}
+#ifndef NDEBUG
void ADDModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr,
tcPDPtr cc, tcPDPtr) {
+#else
+void ADDModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr,
+ tcPDPtr, tcPDPtr) {
+#endif
// work out the particles
assert(cc->id()==ParticleID::g && abs(aa->id()) <= 6);
Complex coup;
// overall factor
if(q2last_!=q2||couplast_==0.) {
couplast_ = strongCoupling(q2);
q2last_=q2;
}
left (1.);
right(1.);
// set the coupling
norm(UnitRemoval::E * kappa_ * couplast_);
}
Complex ADDModelFFGGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part,
Energy mass, Energy width) {
if(part->id()!=ParticleID::Graviton)
return VertexBase::propagator(iopt,q2,part,mass,width);
else
return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_));
}
diff --git a/Models/ADD/ADDModelGGGGRVertex.cc b/Models/ADD/ADDModelGGGGRVertex.cc
--- a/Models/ADD/ADDModelGGGGRVertex.cc
+++ b/Models/ADD/ADDModelGGGGRVertex.cc
@@ -1,76 +1,81 @@
// -*- C++ -*-
//
// ADDModelGGGGRVertex.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 ADDModelGGGGRVertex class.
//
#include "ADDModelGGGGRVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG;
ADDModelGGGGRVertex::ADDModelGGGGRVertex()
: kappa_(ZERO), r_(ZERO), couplast_(0.), q2last_(ZERO) {
addToList(21, 21, 21, 39);
}
void ADDModelGGGGRVertex::doinit() {
VVVTVertex::doinit();
orderInGem(1);
orderInGs (1);
// set the graviton coupling
tcHwADDPtr hwADD=dynamic_ptr_cast<tcHwADDPtr>(generator()->standardModel());
if(!hwADD)
throw Exception()
<< "Must have ADDModel in ADDModelGGGGRVertex::doinit()"
<< Exception::runerror;
kappa_=2./hwADD->MPlanckBar();
r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar();
}
void ADDModelGGGGRVertex::persistentOutput(PersistentOStream & os) const {
os << ounit(kappa_,InvGeV) << ounit(r_,GeV);
}
void ADDModelGGGGRVertex::persistentInput(PersistentIStream & is, int) {
is >> iunit(kappa_,InvGeV) >> iunit(r_,GeV);
}
ClassDescription<ADDModelGGGGRVertex> ADDModelGGGGRVertex::initADDModelGGGGRVertex;
// Definition of the static class description member.
void ADDModelGGGGRVertex::Init() {
static ClassDocumentation<ADDModelGGGGRVertex> documentation
("The ADDModelGGGGRVertex class is the four point coupling"
" of three vector bosons and a graviton in the Randell-Sundrum model.");
}
+#ifndef NDEBUG
void ADDModelGGGGRVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b,
tcPDPtr c, tcPDPtr) {
+#else
+void ADDModelGGGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr,
+ tcPDPtr, tcPDPtr) {
+#endif
assert(a->id() == ParticleID::g && b->id() == ParticleID::g &&
c->id() == ParticleID::g);
if(q2!=q2last_||couplast_==0.) {
couplast_ = strongCoupling(q2);
q2last_=q2;
}
norm(Complex(couplast_*kappa_*UnitRemoval::E));
}
Complex ADDModelGGGGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part,
Energy mass, Energy width) {
if(part->id()!=ParticleID::Graviton)
return VertexBase::propagator(iopt,q2,part,mass,width);
else
return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_));
}
diff --git a/Models/RSModel/RSModelFFGGRVertex.cc b/Models/RSModel/RSModelFFGGRVertex.cc
--- a/Models/RSModel/RSModelFFGGRVertex.cc
+++ b/Models/RSModel/RSModelFFGGRVertex.cc
@@ -1,72 +1,77 @@
// -*- C++ -*-
//
// RSModelFFGGRVertex.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 RSModelFFGGRVertex class.
//
#include "RSModelFFGGRVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG;
RSModelFFGGRVertex::RSModelFFGGRVertex()
: couplast_(0.), q2last_(ZERO), kappa_(ZERO) {
for(int ix=1;ix<7;++ix) {
addToList(-ix,ix,21,39);
}
}
void RSModelFFGGRVertex::doinit() {
orderInGem(1);
orderInGs (1);
FFVTVertex::doinit();
tcHwRSPtr hwRS=dynamic_ptr_cast<tcHwRSPtr>(generator()->standardModel());
if(!hwRS) throw Exception()
<< "Must have RSModel in RSModelFFGGRVertex::doinit()"
<< Exception::runerror;
kappa_ = 2./hwRS->lambda_pi();
}
void RSModelFFGGRVertex::persistentOutput(PersistentOStream & os) const {
os << ounit(kappa_,InvGeV);
}
void RSModelFFGGRVertex::persistentInput(PersistentIStream & is, int) {
is >> iunit(kappa_,InvGeV);
}
ClassDescription<RSModelFFGGRVertex> RSModelFFGGRVertex::initRSModelFFGGRVertex;
// Definition of the static class description member.
void RSModelFFGGRVertex::Init() {
static ClassDocumentation<RSModelFFGGRVertex> documentation
("The RSModelFFGGRVertexxs class is the implementation"
" of the two fermion vector coupling for the RS model.");
}
// FFGGR coupling
+#ifndef NDEBUG
void RSModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr,
tcPDPtr cc, tcPDPtr) {
+#else
+void RSModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr,
+ tcPDPtr, tcPDPtr) {
+#endif
// work out the particles
assert(cc->id()==ParticleID::g && abs(aa->id()) <=6 );
// overall factor
if(q2last_ != q2 || couplast_ == 0. ) {
couplast_ = strongCoupling(q2);
q2last_ = q2;
}
left (1.);
right(1.);
// set the coupling
norm( UnitRemoval::E * kappa_ * couplast_);
}
diff --git a/Models/RSModel/RSModelGGGGRVertex.cc b/Models/RSModel/RSModelGGGGRVertex.cc
--- a/Models/RSModel/RSModelGGGGRVertex.cc
+++ b/Models/RSModel/RSModelGGGGRVertex.cc
@@ -1,68 +1,73 @@
// -*- C++ -*-
//
// RSModelGGGGRVertex.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 RSModelGGGGRVertex class.
//
#include "RSModelGGGGRVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG;
RSModelGGGGRVertex::RSModelGGGGRVertex()
: kappa_(ZERO), _couplast(0.), _q2last(ZERO) {
addToList(21, 21, 21, 39);
}
void RSModelGGGGRVertex::doinit() {
VVVTVertex::doinit();
orderInGem(1);
orderInGs (1);
// set the graviton coupling
tcHwRSPtr hwRS=dynamic_ptr_cast<tcHwRSPtr>(generator()->standardModel());
if(!hwRS)
throw Exception()
<< "Must have RSModel in RSModelGGGGRVertex::doinit()"
<< Exception::runerror;
kappa_=2./hwRS->lambda_pi();
}
void RSModelGGGGRVertex::persistentOutput(PersistentOStream & os) const {
os << ounit(kappa_,InvGeV);
}
void RSModelGGGGRVertex::persistentInput(PersistentIStream & is, int) {
is >> iunit(kappa_,InvGeV);
}
ClassDescription<RSModelGGGGRVertex> RSModelGGGGRVertex::initRSModelGGGGRVertex;
// Definition of the static class description member.
void RSModelGGGGRVertex::Init() {
static ClassDocumentation<RSModelGGGGRVertex> documentation
("The RSModelGGGGRVertex class is the four point coupling"
" of three vector bosons and a graviton in the Randell-Sundrum model.");
}
// couplings for the GGGGR vertex
+#ifndef NDEBUG
void RSModelGGGGRVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b,
tcPDPtr c, tcPDPtr) {
+#else
+void RSModelGGGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr,
+ tcPDPtr, tcPDPtr) {
+#endif
assert(a->id() == ParticleID::g && b->id() == ParticleID::g &&
c->id() == ParticleID::g);
if(q2!=_q2last||_couplast==0.) {
_couplast = strongCoupling(q2);
_q2last=q2;
}
norm(Complex(_couplast*kappa_*UnitRemoval::E));
}
diff --git a/Models/StandardModel/SMFFGVertex.cc b/Models/StandardModel/SMFFGVertex.cc
--- a/Models/StandardModel/SMFFGVertex.cc
+++ b/Models/StandardModel/SMFFGVertex.cc
@@ -1,62 +1,65 @@
// -*- C++ -*-
//
// SMFFGVertex.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 StandardModelFFGVertex class.
//
#include "SMFFGVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
using namespace Herwig;
using namespace ThePEG;
NoPIOClassDescription<SMFFGVertex>
SMFFGVertex::initSMFFGVertex;
// Definition of the static class description member.
void SMFFGVertex::Init() {
static ClassDocumentation<SMFFGVertex> documentation
("The SMFFGVertex class is the implementation of"
"the coupling of the gluon to the Standard Model fermions");
}
// coupling for FFG vertex
+#ifndef NDEBUG
void SMFFGVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr,tcPDPtr) {
+#else
+void SMFFGVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr,tcPDPtr) {
+#endif
// first the overall normalisation
if(q2!=_q2last||_couplast==0.) {
_couplast = -strongCoupling(q2);
_q2last=q2;
}
norm(_couplast);
// the left and right couplings
- int iferm=abs(aa->id());
- assert(iferm>=1 && iferm<=6);
+ assert( abs(aa->id()) >= 1 && abs(aa->id()) <= 6 );
left(1.);
right(1.);
}
SMFFGVertex::SMFFGVertex() : _couplast(0.), _q2last(ZERO) {
// PDG codes for the particles
for(int ix=1;ix<7;++ix) {
addToList(-ix,ix,21);
}
}
void SMFFGVertex::doinit() {
orderInGs(1);
orderInGem(0);
FFVVertex::doinit();
}
diff --git a/Models/StandardModel/SMHHHVertex.cc b/Models/StandardModel/SMHHHVertex.cc
--- a/Models/StandardModel/SMHHHVertex.cc
+++ b/Models/StandardModel/SMHHHVertex.cc
@@ -1,64 +1,68 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SMHHHVertex class.
//
#include "SMHHHVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
SMHHHVertex::SMHHHVertex() : couplast_(0.), q2last_(ZERO) {
addToList(25,25,25);
}
IBPtr SMHHHVertex::clone() const {
return new_ptr(*this);
}
IBPtr SMHHHVertex::fullclone() const {
return new_ptr(*this);
}
void SMHHHVertex::persistentOutput(PersistentOStream & os) const {
os << ounit(ratio_,GeV);
}
void SMHHHVertex::persistentInput(PersistentIStream & is, int) {
is >> iunit(ratio_,GeV);
}
ClassDescription<SMHHHVertex> SMHHHVertex::initSMHHHVertex;
// Definition of the static class description member.
void SMHHHVertex::Init() {
static ClassDocumentation<SMHHHVertex> documentation
("The SMHHHVertex class implements the triple Higgs"
" coupling in the Standard Model.");
}
void SMHHHVertex::doinit() {
SSSVertex::doinit();
ratio_ = -1.5*sqr(getParticleData(ParticleID::h0)->mass())/
getParticleData(ParticleID::Wplus)->mass();
orderInGem(1);
orderInGs (0);
}
+#ifndef NDEBUG
void SMHHHVertex::setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2,tcPDPtr part3) {
+#else
+void SMHHHVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr,tcPDPtr) {
+#endif
assert(part1->id()==ParticleID::h0 &&
part2->id()==ParticleID::h0 &&
part3->id()==ParticleID::h0 );
if(q2!=q2last_||couplast_==0.) {
couplast_ = weakCoupling(q2)*ratio_*UnitRemoval::InvE;
q2last_=q2;
}
norm(couplast_);
}
diff --git a/Models/StandardModel/SMWWHHVertex.cc b/Models/StandardModel/SMWWHHVertex.cc
--- a/Models/StandardModel/SMWWHHVertex.cc
+++ b/Models/StandardModel/SMWWHHVertex.cc
@@ -1,67 +1,71 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SMWWHHVertex class.
//
#include "SMWWHHVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
SMWWHHVertex::SMWWHHVertex() : couplast_(0.), q2last_(ZERO) {
addToList( 23, 23, 25, 25);
addToList( 24,-24, 25, 25);
}
IBPtr SMWWHHVertex::clone() const {
return new_ptr(*this);
}
IBPtr SMWWHHVertex::fullclone() const {
return new_ptr(*this);
}
void SMWWHHVertex::persistentOutput(PersistentOStream & os) const {
os << ratio_;
}
void SMWWHHVertex::persistentInput(PersistentIStream & is, int) {
is >> ratio_;
}
ClassDescription<SMWWHHVertex> SMWWHHVertex::initSMWWHHVertex;
// Definition of the static class description member.
void SMWWHHVertex::Init() {
static ClassDocumentation<SMWWHHVertex> documentation
("The SMWWHHVertex class implements the coupling of two electroweeak"
" gauge bosons and the Higgs boson in the Standard Model.");
}
void SMWWHHVertex::doinit() {
VVSSVertex::doinit();
ratio_ = 1./(1.-sin2ThetaW());
orderInGem(2);
orderInGs (0);
}
void SMWWHHVertex::setCoupling(Energy2 q2,
tcPDPtr part1,tcPDPtr,
+#ifndef NDEBUG
tcPDPtr part3,tcPDPtr part4) {
+#else
+ tcPDPtr,tcPDPtr) {
+#endif
assert(part3->id()==ParticleID::h0 && part4->id()==ParticleID::h0 );
if(q2!=q2last_||couplast_==0.) {
couplast_ = sqr(weakCoupling(q2));
q2last_=q2;
}
if(part1->id()==ParticleID::Z0) {
norm(0.5*couplast_*ratio_);
}
else {
norm(0.5*couplast_);
}
}
diff --git a/Models/Susy/SSCNWVertex.cc b/Models/Susy/SSCNWVertex.cc
--- a/Models/Susy/SSCNWVertex.cc
+++ b/Models/Susy/SSCNWVertex.cc
@@ -1,125 +1,129 @@
// -*- C++ -*-
//
// SSCNWVertex.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 SSCNWVertex class.
//
#include "SSCNWVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
using namespace ThePEG::Helicity;
using namespace Herwig;
SSCNWVertex::SSCNWVertex() : _sw(0.), _couplast(0.), _q2last(ZERO),
_id1last(0), _id2last(0), _leftlast(0.),
_rightlast(0.) {
long neu[] = { 1000022, 1000023, 1000025, 1000035, 1000045 };
long cha[] = { 1000024, 1000037 };
// sign == -1 outgoing W-, sign == +1 outgoing W+
for(int sign = -1; sign < 2; sign += 2)
for(unsigned int ine = 0; ine < 5; ++ine)
for(unsigned int ic = 0; ic < 2; ++ic)
addToList(-sign*cha[ic], neu[ine], sign*24);
}
void SSCNWVertex::doinit() {
FFVVertex::doinit();
tSusyBasePtr theSS = dynamic_ptr_cast<SusyBasePtr>(generator()->standardModel());
if(!theSS)
throw InitException() << "SSCNWVertex::doinit() - The model pointer is null!"
<< Exception::abortnow;
_sw = sqrt(sin2ThetaW());
_theN = theSS->neutralinoMix();
_theU = theSS->charginoUMix();
_theV = theSS->charginoVMix();
if(!_theN || !_theU || ! _theV)
throw InitException() << "SSCNWVertex::doinit() - "
<< "A mixing matrix pointer is null."
<< " N: " << _theN << " U: " << _theU << " V: "
<< _theV << Exception::abortnow;
orderInGs(0);
orderInGem(1);
}
void SSCNWVertex::persistentOutput(PersistentOStream & os) const {
os << _sw << _theN << _theU << _theV;
}
void SSCNWVertex::persistentInput(PersistentIStream & is, int) {
is >> _sw >> _theN >> _theU >> _theV;
}
ClassDescription<SSCNWVertex> SSCNWVertex::initSSCNWVertex;
// Definition of the static class description member.
void SSCNWVertex::Init() {
static ClassDocumentation<SSCNWVertex> documentation
("This class implements the coupling of a W boson to a "
"neutralino and a chargino");
}
void SSCNWVertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2,
+#ifndef NDEBUG
tcPDPtr part3) {
+#else
+ tcPDPtr) {
+#endif
assert(abs(part3->id()) == ParticleID::Wplus);
long neu, cha;
if(part1->charged()) {
cha = part1->id();
neu = part2->id();
}
else {
cha = part2->id();
neu = part1->id();
}
assert((abs(cha) == 1000024 || abs(cha) == 1000037) &&
(neu == 1000022 || neu == 1000023 ||
neu == 1000025 || neu == 1000035 ||
neu == 1000045) );
if(q2 != _q2last||_couplast==0.) {
_q2last = q2;
_couplast = weakCoupling(q2);;
}
norm(_couplast);
if(cha != _id1last || neu != _id2last) {
_id1last = cha;
_id2last = neu;
unsigned int eigc = abs(cha) == 1000037 ? 1 : 0;
unsigned int eign(0);
if (neu == 1000023) eign = 1;
else if(neu == 1000025) eign = 2;
else if(neu == 1000035) eign = 3;
else if(neu == 1000045) eign = 4;
_leftlast = (*_theN)(eign, 1)*conj((*_theV)(eigc, 0)) -
( (*_theN)(eign, 3)*conj((*_theV)(eigc, 1))/sqrt(2));
_rightlast = conj((*_theN)(eign, 1))*(*_theU)(eigc, 0) +
( conj((*_theN)(eign, 2))*(*_theU)(eigc, 1)/sqrt(2));
}
Complex ltemp = _leftlast;
Complex rtemp = _rightlast;
// conjugate if +ve chargino
if(cha>0) {
ltemp = conj(ltemp);
rtemp = conj(rtemp);
}
if((part1->id()==cha&&cha>0)||(part2->id()==cha&&cha<0)) {
Complex temp = ltemp;
ltemp = -rtemp;
rtemp = -temp;
}
left (ltemp);
right(rtemp);
}
diff --git a/Models/Susy/SSGNGVertex.cc b/Models/Susy/SSGNGVertex.cc
--- a/Models/Susy/SSGNGVertex.cc
+++ b/Models/Susy/SSGNGVertex.cc
@@ -1,232 +1,236 @@
// -*- C++ -*-
//
// SSGNGVertex.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 SSGNGVertex class.
//
#include "SSGNGVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Models/Susy/MixingMatrix.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig++/Utilities/Maths.h"
using namespace ThePEG::Helicity;
using namespace Herwig;
SSGNGVertex::SSGNGVertex() : _sw(0.), _cw(0.), _idlast(0),
_q2last(ZERO), _couplast(0.),
_leftlast(ZERO), _rightlast(ZERO) {
int ineu[5] = {1000022,1000023,1000025,1000035,1000045};
for(unsigned int i = 0; i < 5; ++i) {
addToList(1000021, ineu[i], 21);
}
}
void SSGNGVertex::doinit() {
GeneralFFVVertex::doinit();
tMSSMPtr theSS = dynamic_ptr_cast<tMSSMPtr>(generator()->standardModel());
if(!theSS)
throw InitException() << "SSGNGVertex::doinit() - "
<< "The model pointer is null."
<< Exception::abortnow;
_theN = theSS->neutralinoMix();
if(!_theN )
throw InitException() << "SSGNGVertex::doinit - The neutralino "
<< "mixing matrix pointer is null."
<< Exception::abortnow;
_sw = sqrt(sin2ThetaW());
_cw = sqrt(1 - _sw*_sw);
_mw = getParticleData(ParticleID::Wplus)->mass();
double tb = theSS->tanBeta();
_sb = tb/sqrt(1 + sqr(tb));
_cb = sqrt(1 - sqr(_sb));
_stop = theSS->stopMix();
_sbot = theSS->sbottomMix();
orderInGem(1);
orderInGs(2);
}
void SSGNGVertex::persistentOutput(PersistentOStream & os) const {
os << _sw << _cw << _theN << ounit(_mw,GeV) << _sb << _cb
<< _stop << _sbot;
}
void SSGNGVertex::persistentInput(PersistentIStream & is, int) {
is >> _sw >> _cw >> _theN >> iunit(_mw,GeV) >> _sb >> _cb
>> _stop >> _sbot;
}
ClassDescription<SSGNGVertex> SSGNGVertex::initSSGNGVertex;
// Definition of the static class description member.
void SSGNGVertex::Init() {
static ClassDocumentation<SSGNGVertex> documentation
("The coupling of a Z-boson to a pair of neutralinos");
}
void SSGNGVertex::setCoupling(Energy2 q2, tcPDPtr part1,
+#ifndef NDEBUG
tcPDPtr part2,tcPDPtr part3) {
+#else
+ tcPDPtr part2,tcPDPtr) {
+#endif
int o[2]={1,0};
long in1 = part1->id();
long in2 = part2->id();
Energy Mj = part1->mass();
Energy Mi = part2->mass();
if(in1!=ParticleID::SUSY_g) {
swap(in1,in2);
swap(Mj,Mi);
}
// checks of the particle ids
assert(part3->id()==ParticleID::g);
assert(in1 == ParticleID::SUSY_g);
assert(in2 == ParticleID::SUSY_chi_10 || in2 == ParticleID::SUSY_chi_20 ||
in2 == ParticleID::SUSY_chi_30 || in2 == ParticleID::SUSY_chi_40 ||
in2 == 1000045 );
// normal couplings are zero
setLeft (0.);
setRight(0.);
if(q2 != _q2last || _couplast==0.) {
_q2last = q2;
_couplast = weakCoupling(q2)*sqr(strongCoupling(q2))/
32./sqr(Constants::pi);
}
if(in2 != _idlast) {
_leftlast = ZERO;
_rightlast = ZERO;
_idlast = in2;
unsigned int neu(in2 - 1000022);
if(neu > 1) neu = (in2-1000005)/10;
Complex n1prime = (*_theN)(neu,0)*_cw + (*_theN)(neu,1)*_sw;
Complex n2prime = (*_theN)(neu,1)*_cw - (*_theN)(neu,0)*_sw;
// squark/quark loops
for(long iferm=1;iferm<7;++iferm) {
tcPDPtr smf = getParticleData(iferm);
Energy mf = smf->mass();
double qf = smf->charge()/eplus;
double y = 0.5*mf/_mw;
Complex bracketl = qf*_sw*( conj(n1prime) - _sw*conj(n2prime)/_cw );
double lambda(0.);
// neutralino mixing element
Complex nlf(0.);
if( iferm % 2 == 0 ) {
y /= _sb;
lambda = -0.5 + qf*sqr(_sw);
nlf = (*_theN)(neu,3);
}
else {
y /= _cb;
lambda = 0.5 + qf*sqr(_sw);
nlf = (*_theN)(neu,2);
}
Complex bracketr = _sw*qf*n1prime - n2prime*lambda/_cw;
for(long iy=0;iy<2;++iy) {
long isf = 1000000*(1+iy)+iferm;
Energy msf = getParticleData(isf)->mass();
if(mf+msf<Mj||mf+msf<Mi) continue;
Complex g[2][2];
Complex ma1(0.), ma2(0.);
// heavy fermions
if( iferm == 5 || iferm == 6 ) {
if( iferm == 5 ) {
ma1 = (*_sbot)(iy,0);
ma2 = (*_sbot)(iy,1);
}
else if( iferm == 6 ) {
ma1 = (*_stop)(iy,0);
ma2 = (*_stop)(iy,1);
}
}
else if(iy==0) {
ma1 = 1.;
}
else {
ma2 = 1.;
}
g[0][0] = y*conj(nlf)*ma1 - ma2*bracketl;
g[0][1] = y*nlf *ma2 + ma1*bracketr;
g[1][0] = - ma2;
g[1][1] = + ma1;
swap(g[0][0],g[0][1]);
complex<InvEnergy2> I,J,K,I2;
loopIntegrals(Mi,Mj,msf,mf,I,J,K,I2);
complex<InvEnergy> coup[2];
for(unsigned int ix=0;ix<2;++ix) {
coup[ix] = Mj*(I2-K)*(g[0][ix]*g[1][o[ix]]-conj(g[0][o[ix]]*g[1][ix]))
+Mi*K*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]]))
+mf*I*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]]));
}
_leftlast += 2.*coup[0];
_rightlast += 2.*coup[1];
}
}
}
norm(_couplast);
setLeftSigma ( _leftlast);
setRightSigma(_rightlast);
}
void SSGNGVertex::loopIntegrals(Energy Mi, Energy Mj, Energy M, Energy m,
complex<InvEnergy2> & I, complex<InvEnergy2> & J,
complex<InvEnergy2> & K, complex<InvEnergy2> & I2) {
static const Complex ii(0.,1.);
static const Energy eps(100.*MeV);
Energy2 m2(sqr(m)),M2(sqr(M)),Mi2(sqr(Mi)),Mj2(sqr(Mj));
using Math::Li2;
// general form
if(m>eps) {
Energy4 li = sqr(m2+M2-Mi2)-4.*sqr(m*M);
complex<Energy2> rli = li<ZERO ? ii*sqrt(-li) : sqrt(li);
Energy4 lj = sqr(m2+M2-Mj2)-4.*sqr(m*M);
complex<Energy2> rlj = lj<ZERO ? ii*sqrt(-lj) : sqrt(lj);
Complex arg[6]={0.5/m2*(Mj2+m2-M2+rlj) ,0.5/m2*(Mj2+m2-M2-rlj),
0.5/m2*(Mi2+m2-M2+rli) ,0.5/m2*(Mi2+m2-M2-rli),
0.5/m/M*(m2+M2-Mj2+rlj),0.5/m/M*(m2+M2-Mi2+rli)};
I = 1./(Mi2-Mj2)*(Li2(arg[0])+Li2(arg[1])-
Li2(arg[2])-Li2(arg[3]));
J = 1./(Mj2-Mi2)*(sqr(log(arg[4]))-sqr(log(arg[5])))-I;
Complex Itest[2];
for(unsigned int ix=0;ix<2;++ix) {
Complex a,b;
if(ix==0) {
a = 0.5*(M2+Mj2-m2)/Mj2;
b = 0.5*rlj/Mj2;
}
else {
a = 0.5*(M2+Mi2-m2)/Mi2;
b = 0.5*rli/Mi2;
}
Itest[ix] = -b*log(b-a)+a*log(b-a)+log(-a-b)*a
+log(-a-b)*b+log(1.+b-a)+log(1.+b-a)*b-log(1.+b-a)*a+log(1.-a-b)
-log(1.-a-b)*a-log(1.-a-b)*b-2.;
}
I2 = (Itest[0]-Itest[1]+log(Mj2/Mi2))/(Mj2-Mi2);
// I2 = (M2-m2)/Mi2/Mj2*log(m/M)
// +1./(Mj2-Mi2)*(0.5*rlj/Mj2*log((m2+M2-Mj2-rlj)/
// (m2+M2-Mj2+rlj))-
// 0.5*rli/Mi2*log((m2+M2-Mi2-rli)/
// (m2+M2-Mi2+rli)));
K = 1./(Mi2-Mj2)*(1.+Complex(m2*I+M2*J-Mj2*I2));
}
// leading term for small m
else {
I = 1./(Mj2-Mi2)*(-Li2(double(Mj2/(Mj2-M2)))+Li2(double(Mi2/(Mi2-M2)))
-2.*log(m/M)*log((M2-Mj2)/(M2-Mi2))
+0.5*sqr(log((M2-Mj2)/M2))-0.5*sqr(log((M2-Mi2)/M2)));
J = 1./(Mj2-Mi2)*(Li2(double(Mj2/(Mj2-M2)))-Li2(double(Mi2/(Mi2-M2)))
-0.5*sqr(log((M2-Mi2)/M2))+0.5*sqr(log((M2-Mj2)/M2)));
I2 = 1./(Mj2-Mi2)*log((M2-Mj2)/(M2-Mi2))
+M2/(Mj2-Mi2)/sqr(Mi*Mj)*(Mj2*log((M2-Mi2)/M2)-Mi2*log((M2-Mj2)/M2));
K = 1./(Mi2-Mj2)*(1.+Complex(M2*J)-Complex(Mj2*I2));
}
}
diff --git a/Models/Susy/SSGVFSVertex.cc b/Models/Susy/SSGVFSVertex.cc
--- a/Models/Susy/SSGVFSVertex.cc
+++ b/Models/Susy/SSGVFSVertex.cc
@@ -1,122 +1,127 @@
// -*- C++ -*-
//
// SSGVFSVertex.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 SSGVFSVertex class.
//
#include "SSGVFSVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace ThePEG::Helicity;
using namespace Herwig;
SSGVFSVertex::SSGVFSVertex() : MPlanck_(2.4e18*GeV) {
//quarks
for(long ix=1;ix<7;++ix){
addToList( ParticleID::SUSY_Gravitino, ix, -(1000000+ix) );
addToList( ParticleID::SUSY_Gravitino, ix, -(2000000+ix) );
addToList( ParticleID::SUSY_Gravitino, -ix, (1000000+ix) );
addToList( ParticleID::SUSY_Gravitino, -ix, (2000000+ix) );
}
//leptons
for(long ix=11;ix<17;++ix) {
addToList( ParticleID::SUSY_Gravitino, ix, -(1000000+ix) );
addToList( ParticleID::SUSY_Gravitino, -ix, (1000000+ix) );
if( ix % 2 != 0 ) {
addToList( ParticleID::SUSY_Gravitino, ix, -(2000000+ix) );
addToList( ParticleID::SUSY_Gravitino, -ix, (2000000+ix) );
}
}
}
void SSGVFSVertex::persistentOutput(PersistentOStream & os) const {
os << stop_ << sbot_ << stau_ << ounit(MPlanck_,GeV);
}
void SSGVFSVertex::persistentInput(PersistentIStream & is, int) {
is >> stop_ >> sbot_ >> stau_ >> iunit(MPlanck_,GeV);
}
void SSGVFSVertex::doinit() {
RFSVertex::doinit();
tMSSMPtr model = dynamic_ptr_cast<tMSSMPtr>(generator()->standardModel());
if( !model )
throw InitException() << "SSGVFSVertex::doinit() - "
<< "The model pointer is null."
<< Exception::abortnow;
MPlanck_ = model->MPlanck();
stop_ = model->stopMix();
sbot_ = model->sbottomMix();
stau_ = model->stauMix();
orderInGem(1);
orderInGs(0);
}
ClassDescription<SSGVFSVertex> SSGVFSVertex::initSSGVFSVertex;
// Definition of the static class description member.
void SSGVFSVertex::Init() {
static ClassDocumentation<SSGVFSVertex> documentation
("The SSGVFSVertex implements the coupling of the gravitino to "
"a fermion-sfermion");
}
-void SSGVFSVertex::setCoupling(Energy2 ,tcPDPtr part1,
+void SSGVFSVertex::setCoupling(Energy2 ,
+#ifndef NDEBUG
+ tcPDPtr part1,
+#else
+ tcPDPtr,
+#endif
tcPDPtr part2,tcPDPtr part3) {
assert(part1->id()==ParticleID::SUSY_Gravitino);
assert(part3->iSpin()==PDT::Spin0);
norm(double(sqrt(2.)/MPlanck_*UnitRemoval::E));
// sfermion mass eigenstate
unsigned int alpha(abs(part3->id())/1000000 - 1);
unsigned int ism(abs(part2->id()));
Complex lc,rc;
//heavy quarks/sleptons
if( ism == 5 || ism == 6 || ism == 15 ) {
Complex ma1(0.), ma2(0.);
if( ism == 5 ) {
ma1 = (*sbot_)(alpha,0);
ma2 = (*sbot_)(alpha,1);
}
else if( ism == 6 ) {
ma1 = (*stop_)(alpha,0);
ma2 = (*stop_)(alpha,1);
}
else {
ma1 = (*stau_)(alpha,0);
ma2 = (*stau_)(alpha,1);
}
lc = - ma2;
rc = + ma1;
}
else {
if( alpha == 0 ) {
lc = 0.;
rc = 1.;
}
else {
lc = -1.;
rc = 0.;
}
}
// determine the helicity order of the vertex
if( part2->id() < 0 ) {
left (conj(rc));
right(conj(lc));
}
else {
left (lc);
right(rc);
}
}
diff --git a/Models/Susy/SSGVNHVertex.cc b/Models/Susy/SSGVNHVertex.cc
--- a/Models/Susy/SSGVNHVertex.cc
+++ b/Models/Susy/SSGVNHVertex.cc
@@ -1,101 +1,106 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SSGVNHVertex class.
//
#include "SSGVNHVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "MSSM.h"
using namespace Herwig;
SSGVNHVertex::SSGVNHVertex() : sa_(0.), sb_(0.), ca_(0.), cb_(0.),
MPlanck_(2.4e18*GeV) {
long neu[4] = {ParticleID::SUSY_chi_10, ParticleID::SUSY_chi_20,
ParticleID::SUSY_chi_30, ParticleID::SUSY_chi_40};
long higgs[3] = {25, 35, 36};
for(unsigned int i = 0; i < 3; ++i) {
for(unsigned int j = 0; j < 4; ++j) {
addToList(ParticleID::SUSY_Gravitino, neu[j], higgs[i]);
}
}
}
IBPtr SSGVNHVertex::clone() const {
return new_ptr(*this);
}
IBPtr SSGVNHVertex::fullclone() const {
return new_ptr(*this);
}
void SSGVNHVertex::persistentOutput(PersistentOStream & os) const {
os << sa_ << sb_ << ca_ << cb_ << nmix_ << ounit(MPlanck_,GeV);
}
void SSGVNHVertex::persistentInput(PersistentIStream & is, int) {
is >> sa_ >> sb_ >> ca_ >> cb_ >> nmix_ >> iunit(MPlanck_,GeV);
}
ClassDescription<SSGVNHVertex> SSGVNHVertex::initSSGVNHVertex;
// Definition of the static class description member.
void SSGVNHVertex::Init() {
static ClassDocumentation<SSGVNHVertex> documentation
("The SSGVNHVertex class implments the coupling of the Higgs"
" bosons to a gravitino and a neutralino");
}
void SSGVNHVertex::doinit() {
RFSVertex::doinit();
tMSSMPtr model = dynamic_ptr_cast<tMSSMPtr>(generator()->standardModel());
if( !model )
throw InitException()
<< "SSGVNHVertex::doinit() - The pointer to the MSSM object is null!"
<< Exception::abortnow;
double tanb = model->tanBeta();
sb_ = tanb/sqrt(1. + sqr(tanb));
cb_ = sqrt( 1. - sqr(sb_) );
sa_ = sin(model->higgsMixingAngle());
ca_ = sqrt(1. - sqr(sa_));
nmix_ = model->neutralinoMix();
MPlanck_ = model->MPlanck();
orderInGem(1);
orderInGs(0);
}
-void SSGVNHVertex::setCoupling(Energy2 ,tcPDPtr part1,
+void SSGVNHVertex::setCoupling(Energy2 ,
+#ifndef NDEBUG
+ tcPDPtr part1,
+#else
+ tcPDPtr,
+#endif
tcPDPtr part2,tcPDPtr part3) {
assert(part1->id()==ParticleID::SUSY_Gravitino);
assert(part3->iSpin()==PDT::Spin0);
unsigned int neut = part2->id() - ParticleID::SUSY_chi_10;
if(neut>1) neut = ( neut == 13 ) ? 3 : 2;
int hid = part3->id();
Complex coup;
switch(hid) {
case ParticleID::h0 :
left (1.);
right(1.);
coup = -(*nmix_)(neut,2)*sa_+(*nmix_)(neut,3)*ca_;
break;
case ParticleID::H0 :
left (1.);
right(1.);
coup = (*nmix_)(neut,2)*ca_+(*nmix_)(neut,3)*sa_;
break;
case ParticleID::A0 :
left (Complex(0.,-1.));
right(Complex(0., 1.));
coup = (*nmix_)(neut,2)*sb_+(*nmix_)(neut,3)*cb_;
break;
default :
assert(false);
}
norm(coup/MPlanck_*UnitRemoval::E);
}
diff --git a/Models/Susy/SSGVNVVertex.cc b/Models/Susy/SSGVNVVertex.cc
--- a/Models/Susy/SSGVNVVertex.cc
+++ b/Models/Susy/SSGVNVVertex.cc
@@ -1,111 +1,116 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SSGVNVVertex class.
//
#include "SSGVNVVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "MSSM.h"
using namespace Herwig;
SSGVNVVertex::SSGVNVVertex() : sw_(0.), cw_(0.), sb_(0.), cb_(0.),
mz_(91.1876*GeV), MPlanck_(2.4e18*GeV) {
long neu[4] = {ParticleID::SUSY_chi_10, ParticleID::SUSY_chi_20,
ParticleID::SUSY_chi_30, ParticleID::SUSY_chi_40};
for(unsigned int j = 0; j < 4; ++j) {
addToList(ParticleID::SUSY_Gravitino, neu[j], ParticleID::gamma);
addToList(ParticleID::SUSY_Gravitino, neu[j], ParticleID::Z0);
}
addToList(ParticleID::SUSY_Gravitino, ParticleID::SUSY_g, ParticleID::g);
}
IBPtr SSGVNVVertex::clone() const {
return new_ptr(*this);
}
IBPtr SSGVNVVertex::fullclone() const {
return new_ptr(*this);
}
void SSGVNVVertex::persistentOutput(PersistentOStream & os) const {
os << sw_ << cw_ << sb_ << cb_ << ounit(mz_,GeV) << nmix_ << ounit(MPlanck_,GeV);
}
void SSGVNVVertex::persistentInput(PersistentIStream & is, int) {
is >> sw_ >> cw_ >> sb_ >> cb_ >> iunit(mz_,GeV) >> nmix_ >> iunit(MPlanck_,GeV);
}
ClassDescription<SSGVNVVertex> SSGVNVVertex::initSSGVNVVertex;
// Definition of the static class description member.
void SSGVNVVertex::Init() {
static ClassDocumentation<SSGVNVVertex> documentation
("The SSGVNVVertex class implements the coupling of the gravitino"
" to the neutralino and a photon or Z boson, or the gluino and gluon.");
}
void SSGVNVVertex::doinit() {
RFVVertex::doinit();
tMSSMPtr model = dynamic_ptr_cast<tMSSMPtr>(generator()->standardModel());
if( !model )
throw InitException()
<< "SSGVNVVertex::doinit() - The pointer to the MSSM object is null!"
<< Exception::abortnow;
double tanb = model->tanBeta();
sb_ = tanb/sqrt(1. + sqr(tanb));
cb_ = sqrt( 1. - sqr(sb_) );
sw_ = sqrt(sin2ThetaW());
cw_ = sqrt(1. - sin2ThetaW());
nmix_ = model->neutralinoMix();
MPlanck_ = model->MPlanck();
orderInGem(1);
orderInGs(0);
}
-void SSGVNVVertex::setCoupling(Energy2 ,tcPDPtr part1,
+void SSGVNVVertex::setCoupling(Energy2 ,
+#ifndef NDEBUG
+ tcPDPtr part1,
+#else
+ tcPDPtr,
+#endif
tcPDPtr part2,tcPDPtr part3) {
assert(part1->id()==ParticleID::SUSY_Gravitino);
assert(part3->iSpin()==PDT::Spin1);
unsigned int neut = part2->id() - ParticleID::SUSY_chi_10;
if(neut>1) neut = ( neut == 13 ) ? 3 : 2;
int bid = part3->id();
Complex coup[2];
vector<Complex> lV,rV;
switch(bid) {
case ParticleID::gamma :
coup[0] = (*nmix_)(neut,0)*cw_+(*nmix_)(neut,1)*sw_;
lV.push_back(-coup[0]*part2->mass()*UnitRemoval::InvE);
lV.push_back( coup[0]);
lV.push_back(0.);
rV=lV;
break;
case ParticleID::Z0 :
coup[0] = -(*nmix_)(neut,0)*sw_+(*nmix_)(neut,1)*cw_;
coup[1] = -(*nmix_)(neut,2)*cb_+(*nmix_)(neut,3)*sb_;
lV.push_back((-coup[0]*part2->mass()-mz_*coup[1])*UnitRemoval::InvE);
lV.push_back( coup[0]);
lV.push_back(0.);
rV=lV;
rV[0] = (-coup[0]*part2->mass()+mz_*coup[1])*UnitRemoval::InvE;
break;
case ParticleID::g :
lV.push_back(-double(part2->mass()*UnitRemoval::InvE));
lV.push_back(1.);
lV.push_back(0.);
rV=lV;
break;
default :
assert(false);
}
left (lV);
right(rV);
norm(double(1./MPlanck_*UnitRemoval::E));
}
diff --git a/Models/Susy/SSNNPVertex.cc b/Models/Susy/SSNNPVertex.cc
--- a/Models/Susy/SSNNPVertex.cc
+++ b/Models/Susy/SSNNPVertex.cc
@@ -1,347 +1,351 @@
// -*- C++ -*-
//
// SSNNPVertex.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 SSNNPVertex class.
//
#include "SSNNPVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Models/Susy/MixingMatrix.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig++/Utilities/Maths.h"
using namespace ThePEG::Helicity;
using namespace Herwig;
SSNNPVertex::SSNNPVertex() : _sw(0.), _cw(0.), _id1last(0),
_id2last(0), _q2last(ZERO), _couplast(0.),
_leftlast(ZERO), _rightlast(ZERO) {
int ineu[5] = {1000022,1000023,1000025,1000035,1000045};
for(unsigned int i = 0; i < 5; ++i) {
for(unsigned int j = 0; j < 5; ++j) {
addToList(ineu[i], ineu[j], 22);
}
}
}
void SSNNPVertex::doinit() {
GeneralFFVVertex::doinit();
tMSSMPtr theSS = dynamic_ptr_cast<tMSSMPtr>(generator()->standardModel());
if(!theSS)
throw InitException() << "SSNNPVertex::doinit() - "
<< "The model pointer is null."
<< Exception::abortnow;
_theN = theSS->neutralinoMix();
_theU = theSS->charginoUMix();
_theV = theSS->charginoVMix();
if(!_theN || !_theU || ! _theV)
throw InitException() << "SSNNPVertex::doinit - The neutralino "
<< "mixing matrix pointer is null."
<< Exception::abortnow;
_sw = sqrt(sin2ThetaW());
_cw = sqrt(1 - _sw*_sw);
_mw = getParticleData(ParticleID::Wplus)->mass();
double tb = theSS->tanBeta();
_sb = tb/sqrt(1 + sqr(tb));
_cb = sqrt(1 - sqr(_sb));
_stop = theSS->stopMix();
_sbot = theSS->sbottomMix();
_stau = theSS->stauMix();
orderInGem(3);
orderInGs(0);
}
void SSNNPVertex::persistentOutput(PersistentOStream & os) const {
os << _sw << _cw << _theN << ounit(_mw,GeV) << _sb << _cb
<< _stop << _sbot << _stau << _theU << _theV;
}
void SSNNPVertex::persistentInput(PersistentIStream & is, int) {
is >> _sw >> _cw >> _theN >> iunit(_mw,GeV) >> _sb >> _cb
>> _stop >> _sbot >> _stau >> _theU >> _theV;
}
ClassDescription<SSNNPVertex> SSNNPVertex::initSSNNPVertex;
// Definition of the static class description member.
void SSNNPVertex::Init() {
static ClassDocumentation<SSNNPVertex> documentation
("The coupling of a Z-boson to a pair of neutralinos");
}
void SSNNPVertex::setCoupling(Energy2 q2, tcPDPtr part1,
+#ifndef NDEBUG
tcPDPtr part2,tcPDPtr part3) {
+#else
+ tcPDPtr part2,tcPDPtr) {
+#endif
int o[2]={1,0};
long in1 = part1->id();
long in2 = part2->id();
Energy Mj = part1->mass();
Energy Mi = part2->mass();
// checks of the particle ids
assert(part3->id()==ParticleID::gamma);
assert(in1 == ParticleID::SUSY_chi_10 || in1 == ParticleID::SUSY_chi_20 ||
in1 == ParticleID::SUSY_chi_30 || in1 == ParticleID::SUSY_chi_40 ||
in1 == 1000045 );
assert(in2 == ParticleID::SUSY_chi_10 || in2 == ParticleID::SUSY_chi_20 ||
in2 == ParticleID::SUSY_chi_30 || in2 == ParticleID::SUSY_chi_40 ||
in2 == 1000045 );
// normal couplings are zero
setLeft (0.);
setRight(0.);
if(in1==in2) {
_leftlast = ZERO;
_rightlast = ZERO;
setLeftSigma (_leftlast );
setRightSigma(_rightlast);
return;
}
if(q2 != _q2last || _couplast==0.) {
_q2last = q2;
_couplast = sqr(weakCoupling(q2))*
electroMagneticCoupling(q2)/32./sqr(Constants::pi);
}
if(in1 != _id1last || in2 != _id2last) {
_leftlast = ZERO;
_rightlast = ZERO;
_id1last = in1;
_id2last = in2;
unsigned int neu1(in1 - 1000022), neu2(in2 - 1000022);
if(neu1 > 1) neu1 = (in1-1000005)/10;
if(neu2 > 1) neu2 = (in2-1000005)/10;
Complex n1prime[2] = { (*_theN)(neu2,0)*_cw + (*_theN)(neu2,1)*_sw ,
(*_theN)(neu1,0)*_cw + (*_theN)(neu1,1)*_sw };
Complex n2prime[2] = { (*_theN)(neu2,1)*_cw - (*_theN)(neu2,0)*_sw ,
(*_theN)(neu1,1)*_cw - (*_theN)(neu1,0)*_sw };
// sfermion/fermion loops
for(long iferm=1;iferm<16;++iferm) {
if(iferm==7) iferm=11;
if(iferm%2==0&&iferm>11) ++iferm;
tcPDPtr smf = getParticleData(iferm);
Energy mf = smf->mass();
double qf = smf->charge()/eplus;
double y = 0.5*mf/_mw;
Complex bracketl[2] = { qf*_sw*( conj(n1prime[0]) - _sw*conj(n2prime[0])/_cw ) ,
qf*_sw*( conj(n1prime[1]) - _sw*conj(n2prime[1])/_cw ) };
double lambda(0.);
//neutralino mixing element
Complex nlf[2]={0.,0.};
if( iferm % 2 == 0 ) {
y /= _sb;
lambda = -0.5 + qf*sqr(_sw);
nlf[0] = (*_theN)(neu2,3);
nlf[1] = (*_theN)(neu1,3);
}
else {
y /= _cb;
lambda = 0.5 + qf*sqr(_sw);
nlf[0] = (*_theN)(neu2,2);
nlf[1] = (*_theN)(neu1,2);
}
Complex bracketr[2] = { _sw*qf*n1prime[0] - n2prime[0]*lambda/_cw ,
_sw*qf*n1prime[1] - n2prime[1]*lambda/_cw };
for(long iy=0;iy<2;++iy) {
long isf = 1000000*(1+iy)+iferm;
Energy msf = getParticleData(isf)->mass();
if(mf+msf<Mj||mf+msf<Mi) continue;
Complex g[2][2];
Complex ma1(0.), ma2(0.);
// heavy fermions
if( iferm == 5 || iferm == 6 || iferm == 15 ) {
if( iferm == 5 ) {
ma1 = (*_sbot)(iy,0);
ma2 = (*_sbot)(iy,1);
}
else if( iferm == 6 ) {
ma1 = (*_stop)(iy,0);
ma2 = (*_stop)(iy,1);
}
else {
ma1 = (*_stau)(iy,0);
ma2 = (*_stau)(iy,1);
}
}
else if(iy==0) {
ma1 = 1.;
}
else {
ma2 = 1.;
}
for(unsigned int ix=0;ix<2;++ix) {
g[ix][0] = y*conj(nlf[ix])*ma1 - ma2*bracketl[ix];
g[ix][1] = y*nlf[ix]*ma2 + ma1*bracketr[ix];
}
swap(g[0][0],g[0][1]);
complex<InvEnergy2> I,J,K,I2;
loopIntegrals(Mi,Mj,msf,mf,I,J,K,I2);
complex<InvEnergy> coup[2];
for(unsigned int ix=0;ix<2;++ix) {
coup[ix] = Mj*(I2-K)*(g[0][ix]*g[1][o[ix]]-conj(g[0][o[ix]]*g[1][ix]))
+Mi*K*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]]))
+mf*I*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]]));
}
double fact = 4.*qf;
if(iferm<=6) fact *=3.;
_leftlast += fact*coup[0];
_rightlast += fact*coup[1];
}
}
// the chargino W contribution
for(unsigned int ic=0;ic<2;++ic) {
long id = ic==0 ?
ParticleID::SUSY_chi_1plus : ParticleID::SUSY_chi_2plus;
Energy Mk = getParticleData(id)->mass();
if(Mk+_mw<Mj||Mk+_mw<Mi) continue;
complex<InvEnergy2> I,J,K,I2;
loopIntegrals(Mi,Mj,_mw,Mk,I,J,K,I2);
Complex g[2][2];
for(unsigned int ix=0;ix<2;++ix) {
unsigned int in = ix==0 ? neu2 : neu1;
g[ix][0] =
conj((*_theN)(in, 1))*(*_theV)(ic, 0) -
conj((*_theN)(in, 3))*(*_theV)(ic, 1)/sqrt(2);
g[ix][1] =
(*_theN)(in, 1)*conj((*_theU)(ic, 0)) +
(*_theN)(in, 2)*conj((*_theU)(ic, 1))/sqrt(2);
}
complex<InvEnergy> coup[2];
for(unsigned int ix=0;ix<2;++ix) {
coup[ix] =
Mj*(I2-J-K)*(g[0][o[ix]]*g[1][o[ix]]-conj(g[0][ix]*g[1][ix]))-
Mi*(J-K)*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]]))+
2.*Mk*J*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]]));
}
_leftlast += 4.*coup[0];
_rightlast += 4.*coup[1];
}
// the chargino charged higgs contribution
Energy mh = getParticleData(ParticleID::Hplus)->mass();
for(unsigned int ic=0;ic<2;++ic) {
long id = ic==0 ?
ParticleID::SUSY_chi_1plus : ParticleID::SUSY_chi_2plus;
Energy Mk = getParticleData(id)->mass();
if(Mk+mh<Mj||Mk+mh<Mi) continue;
complex<InvEnergy2> I,J,K,I2;
loopIntegrals(Mi,Mj,mh,Mk,I,J,K,I2);
Complex g[2][2];
for(unsigned int ix=0;ix<2;++ix) {
unsigned int in = ix==0 ? neu2 : neu1;
g[ix][0] = (*_theN)(in, 3)*(*_theV)(ic,0)
+ ((*_theN)(in,1) + (*_theN)(in,0)*_sw/_cw)*
(*_theV)(ic,1)/sqrt(2);
g[ix][0] *= _cb;
g[ix][1] = conj((*_theN)(in, 2)*(*_theU)(ic,0)
- ((*_theN)(in,1) + (*_theN)(in,0)*_sw/_cw)*
(*_theU)(ic,1)/sqrt(2));
g[ix][1] *= _sb;
}
swap(g[1][0],g[1][1]);
complex<InvEnergy> coup[2];
for(unsigned int ix=0;ix<2;++ix) {
coup[ix] = Mj*(I2-K)*(g[0][ix]*g[1][o[ix]]-conj(g[0][o[ix]]*g[1][ix]))
+Mi*K*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]]))
+Mk*I*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]]));
}
_leftlast += 2.*coup[0];
_rightlast += 2.*coup[1];
}
// the chargino goldstone contribution
for(unsigned int ic=0;ic<2;++ic) {
long id = ic==0 ?
ParticleID::SUSY_chi_1plus : ParticleID::SUSY_chi_2plus;
Energy Mk = getParticleData(id)->mass();
if(Mk+_mw<Mj||Mk+_mw<Mi) continue;
complex<InvEnergy2> I,J,K,I2;
loopIntegrals(Mi,Mj,_mw,Mk,I,J,K,I2);
Complex g[2][2];
for(unsigned int ix=0;ix<2;++ix) {
unsigned int in = ix==0 ? neu2 : neu1;
g[ix][0] = (*_theN)(in, 3)*(*_theV)(ic,0)
+ ((*_theN)(in,1) + (*_theN)(in,0)*_sw/_cw)*
(*_theV)(ic,1)/sqrt(2);
g[ix][0] *= _sb;
g[ix][1] = conj((*_theN)(in, 2)*(*_theU)(ic,0)
- ((*_theN)(in,1) + (*_theN)(in,0)*_sw/_cw)*
(*_theU)(ic,1)/sqrt(2));
g[ix][1] *= _cb;
}
swap(g[1][0],g[1][1]);
complex<InvEnergy> coup[2];
for(unsigned int ix=0;ix<2;++ix) {
coup[ix] = Mj*(I2-K)*(g[0][ix]*g[1][o[ix]]-conj(g[0][o[ix]]*g[1][ix]))
+Mi*K*(g[0][o[ix]]*g[1][ix]-conj(g[0][ix]*g[1][o[ix]]))
+Mk*I*(g[0][ix]*g[1][ix]-conj(g[0][o[ix]]*g[1][o[ix]]));
}
_leftlast += 2.*coup[0];
_rightlast += 2.*coup[1];
}
}
norm(_couplast);
setLeftSigma ( _leftlast);
setRightSigma(_rightlast);
}
void SSNNPVertex::loopIntegrals(Energy Mi, Energy Mj, Energy M, Energy m,
complex<InvEnergy2> & I, complex<InvEnergy2> & J,
complex<InvEnergy2> & K, complex<InvEnergy2> & I2) {
static const Complex ii(0.,1.);
static const Energy eps(100.*MeV);
Energy2 m2(sqr(m)),M2(sqr(M)),Mi2(sqr(Mi)),Mj2(sqr(Mj));
using Math::Li2;
// general form
if(m>eps) {
Energy4 li = sqr(m2+M2-Mi2)-4.*sqr(m*M);
complex<Energy2> rli = li<ZERO ? ii*sqrt(-li) : sqrt(li);
Energy4 lj = sqr(m2+M2-Mj2)-4.*sqr(m*M);
complex<Energy2> rlj = lj<ZERO ? ii*sqrt(-lj) : sqrt(lj);
Complex arg[6]={0.5/m2*(Mj2+m2-M2+rlj) ,0.5/m2*(Mj2+m2-M2-rlj),
0.5/m2*(Mi2+m2-M2+rli) ,0.5/m2*(Mi2+m2-M2-rli),
0.5/m/M*(m2+M2-Mj2+rlj),0.5/m/M*(m2+M2-Mi2+rli)};
I = 1./(Mi2-Mj2)*(Li2(arg[0])+Li2(arg[1])-
Li2(arg[2])-Li2(arg[3]));
J = 1./(Mj2-Mi2)*(sqr(log(arg[4]))-sqr(log(arg[5])))-I;
Complex Itest[2];
for(unsigned int ix=0;ix<2;++ix) {
Complex a,b;
if(ix==0) {
a = 0.5*(M2+Mj2-m2)/Mj2;
b = 0.5*rlj/Mj2;
}
else {
a = 0.5*(M2+Mi2-m2)/Mi2;
b = 0.5*rli/Mi2;
}
Itest[ix] = -b*log(b-a)+a*log(b-a)+log(-a-b)*a
+log(-a-b)*b+log(1.+b-a)+log(1.+b-a)*b-log(1.+b-a)*a+log(1.-a-b)
-log(1.-a-b)*a-log(1.-a-b)*b-2.;
}
I2 = (Itest[0]-Itest[1]+log(Mj2/Mi2))/(Mj2-Mi2);
// I2 = (M2-m2)/Mi2/Mj2*log(m/M)
// +1./(Mj2-Mi2)*(0.5*rlj/Mj2*log((m2+M2-Mj2-rlj)/
// (m2+M2-Mj2+rlj))-
// 0.5*rli/Mi2*log((m2+M2-Mi2-rli)/
// (m2+M2-Mi2+rli)));
K = 1./(Mi2-Mj2)*(1.+Complex(m2*I+M2*J-Mj2*I2));
}
// leading term for small m
else {
I = 1./(Mj2-Mi2)*(-Li2(double(Mj2/(Mj2-M2)))+Li2(double(Mi2/(Mi2-M2)))
-2.*log(m/M)*log((M2-Mj2)/(M2-Mi2))
+0.5*sqr(log((M2-Mj2)/M2))-0.5*sqr(log((M2-Mi2)/M2)));
J = 1./(Mj2-Mi2)*(Li2(double(Mj2/(Mj2-M2)))-Li2(double(Mi2/(Mi2-M2)))
-0.5*sqr(log((M2-Mi2)/M2))+0.5*sqr(log((M2-Mj2)/M2)));
I2 = 1./(Mj2-Mi2)*log((M2-Mj2)/(M2-Mi2))
+M2/(Mj2-Mi2)/sqr(Mi*Mj)*(Mj2*log((M2-Mi2)/M2)-Mi2*log((M2-Mj2)/M2));
K = 1./(Mi2-Mj2)*(1.+Complex(M2*J)-Complex(Mj2*I2));
}
}
diff --git a/Models/Susy/SSNNZVertex.cc b/Models/Susy/SSNNZVertex.cc
--- a/Models/Susy/SSNNZVertex.cc
+++ b/Models/Susy/SSNNZVertex.cc
@@ -1,118 +1,122 @@
// -*- C++ -*-
//
// SSNNZVertex.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 SSNNZVertex class.
//
#include "SSNNZVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "MixingMatrix.h"
#include "ThePEG/PDT/EnumParticles.h"
using namespace ThePEG::Helicity;
using namespace Herwig;
SSNNZVertex::SSNNZVertex() : _sw(0.), _cw(0.), _id1last(0),
_id2last(0), _q2last(), _couplast(0.),
_leftlast(0.), _rightlast(0.) {
long neu[] = { 1000022, 1000023, 1000025, 1000035, 1000045 };
for(unsigned int i = 0; i < 5; ++i)
for(unsigned int j = 0; j < 5; ++j)
addToList(neu[i], neu[j], 23);
}
void SSNNZVertex::doinit() {
FFVVertex::doinit();
tSusyBasePtr theSS = dynamic_ptr_cast<SusyBasePtr>(generator()->standardModel());
if(!theSS)
throw InitException() << "SSNNZVertex::doinit() - "
<< "The model pointer is null."
<< Exception::abortnow;
_theN = theSS->neutralinoMix();
if(!_theN)
throw InitException() << "SSNNZVertex::doinit - The neutralino "
<< "mixing matrix pointer is null."
<< Exception::abortnow;
_sw = sqrt(sin2ThetaW());
_cw = sqrt(1 - _sw*_sw);
orderInGem(1);
orderInGs(0);
}
void SSNNZVertex::persistentOutput(PersistentOStream & os) const {
os << _sw << _cw << _theN;
}
void SSNNZVertex::persistentInput(PersistentIStream & is, int) {
is >> _sw >> _cw >> _theN;
_id1last = 0;
_id2last = 0;
_q2last = ZERO;
_couplast = 0.;
_leftlast = 0.;
_rightlast = 0.;
}
ClassDescription<SSNNZVertex> SSNNZVertex::initSSNNZVertex;
// Definition of the static class description member.
void SSNNZVertex::Init() {
static ClassDocumentation<SSNNZVertex> documentation
("The coupling of a Z-boson to a pair of neutralinos");
}
void SSNNZVertex::setCoupling(Energy2 q2,tcPDPtr part1,
+#ifndef NDEBUG
tcPDPtr part2,tcPDPtr part3) {
+#else
+ tcPDPtr part2,tcPDPtr) {
+#endif
assert(part3->id() == ParticleID::Z0);
long ic1 = part2->id();
long ic2 = part1->id();
assert(ic1 == ParticleID::SUSY_chi_10 || ic1 == ParticleID::SUSY_chi_20 ||
ic1 == ParticleID::SUSY_chi_30 || ic1 == ParticleID::SUSY_chi_40 ||
ic1 == 1000045);
assert(ic2 == ParticleID::SUSY_chi_10 || ic2 == ParticleID::SUSY_chi_20 ||
ic2 == ParticleID::SUSY_chi_30 || ic2 == ParticleID::SUSY_chi_40 ||
ic2 == 1000045);
if(q2 != _q2last || _couplast==0.) {
_q2last = q2;
_couplast = weakCoupling(q2)/_cw;
}
if(ic1 != _id1last || ic2 != _id2last) {
_id1last = ic1;
_id2last = ic2;
unsigned int neu1(ic1 - 1000022), neu2(ic2 - 1000022);
if(neu1 > 1) {
if(ic1 == 1000025)
neu1 = 2;
else if(ic1 == 1000035)
neu1 = 3;
else
neu1 = 4;
}
if(neu2 > 1) {
if(ic2 == 1000025)
neu2 = 2;
else if(ic2 == 1000035)
neu2 = 3;
else
neu2 = 4;
}
_leftlast = 0.5*( (*_theN)(neu1, 3)*conj((*_theN)(neu2, 3)) -
(*_theN)(neu1, 2)*conj((*_theN)(neu2, 2)) );
_rightlast = -conj(_leftlast);
}
norm(_couplast);
left(_leftlast);
right(_rightlast);
}
diff --git a/Models/UED/UEDF1F1W0Vertex.cc b/Models/UED/UEDF1F1W0Vertex.cc
--- a/Models/UED/UEDF1F1W0Vertex.cc
+++ b/Models/UED/UEDF1F1W0Vertex.cc
@@ -1,151 +1,155 @@
// -*- C++ -*-
//
// UEDF1F1W0Vertex.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 UEDF1F1W0Vertex class.
//
#include "UEDF1F1W0Vertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
using namespace ThePEG::Helicity;
using namespace Herwig;
UEDF1F1W0Vertex::UEDF1F1W0Vertex(): theRadius(ZERO), theQ2Last(ZERO),
theCoupLast(0.),
thefermALast(0), thefermBLast(0) {
//outgoing W+
for( long i = 2; i < 17; i += 2 ) {
if( i == 7 ) i += 5;
addToList(-5100000 - i, 5100000 + i - 1, 24);
if( i < 7 ) {
addToList(-6100000 - i, 6100000 + i - 1, 24);
}
}
addToList(-6100006, 5100005, 24);
addToList(-5100005, 6100006, 24);
//outgoing W-
for( long i = 1; i < 16; i += 2 ) {
if( i == 6 ) i += 5;
addToList(-5100000 - i, 5100001 + i, -24);
if( i < 6 ) {
addToList(-6100000 - i, 6100001 + i, -24);
}
}
addToList(-6100005, 5100006, -24);
addToList(-5100005, 6100006, -24);
}
void UEDF1F1W0Vertex::doinit() {
FFVVertex::doinit();
tUEDBasePtr model = dynamic_ptr_cast<tUEDBasePtr>(generator()->standardModel());
if(!model)
throw InitException() << "UEDF1F1W0Vertex::doinit() - The pointer to "
<< "the UEDBase object is null!"
<< Exception::runerror;
theRadius = model->compactRadius();
orderInGs(0);
orderInGem(0);
}
void UEDF1F1W0Vertex::persistentOutput(PersistentOStream & os) const {
os << ounit(theRadius,1/GeV);
}
void UEDF1F1W0Vertex::persistentInput(PersistentIStream & is, int) {
is >> iunit(theRadius,1/GeV);
}
ClassDescription<UEDF1F1W0Vertex> UEDF1F1W0Vertex::initUEDF1F1W0Vertex;
// Definition of the static class description member.
void UEDF1F1W0Vertex::Init() {
static ClassDocumentation<UEDF1F1W0Vertex> documentation
("This class implements the coupling of a pair of level-1 KK fermions"
"to an SM W boson");
}
void UEDF1F1W0Vertex::setCoupling(Energy2 q2, tcPDPtr part1, tcPDPtr part2,
+#ifndef NDEBUG
tcPDPtr part3) {
+#else
+ tcPDPtr) {
+#endif
long ianti(abs(part1->id())), iferm(abs(part2->id()));
assert( abs(part3->id()) == 24 );
bool ferma = (iferm >= 5100001 && iferm <= 5100006) ||
(iferm >= 6100001 && iferm <= 6100006) ||
(iferm >= 5100011 && iferm <= 5100016) ||
(iferm >= 6100011 && iferm <= 6100016);
bool fermb = (ianti >= 5100001 && ianti <= 5100006) ||
(ianti >= 6100001 && ianti <= 6100006) ||
(ianti >= 5100011 && ianti <= 5100016) ||
(ianti >= 6100011 && ianti <= 6100016);
if( !ferma || !fermb )
throw HelicityLogicalError() << "UEDF1F1W0Vertex::setCoupling - "
<< "There is an unknown particle(s) in the "
<< "UED F^(1) F^(1) W^(0) vertex. ID: "
<< ianti << " " << iferm
<< Exception::runerror;
if(q2 != theQ2Last || theCoupLast == 0. ) {
theQ2Last = q2;
theCoupLast = sqrt(0.5)*weakCoupling(q2);
}
if(iferm != thefermALast || ianti != thefermBLast) {
thefermALast = iferm;
thefermBLast = ianti;
int stateA(ianti/1000000), stateB(iferm/1000000);
long sma = (stateA == 6) ? ianti - 6100000 : ianti - 5100000;
long smb = (stateB == 6) ? iferm - 6100000 : iferm - 5100000;
double afu(0.), afd(0.);
if( sma % 2 == 0 ) {
afu = atan(getParticleData(sma)->mass()*theRadius)/2.;
afd = atan(getParticleData(smb)->mass()*theRadius)/2.;
}
else {
afd = atan(getParticleData(sma)->mass()*theRadius)/2.;
afu = atan(getParticleData(smb)->mass()*theRadius)/2.;
}
if( stateA == stateB ) {
if( stateA == 5 ) {
left(cos(afu)*cos(afd));
right(cos(afu)*cos(afd));
}
else {
left(sin(afu)*sin(afd));
right(sin(afu)*sin(afd));
}
}
else {
if( sma % 2 == 0 ) {
if( stateA == 5 ) {
left(cos(afu)*sin(afd));
right(-cos(afu)*sin(afd));
}
else {
left(sin(afu)*cos(afd));
right(-sin(afu)*cos(afd));
}
}
else {
if( stateA == 5 ) {
left(sin(afu)*cos(afd));
right(-sin(afu)*cos(afd));
}
else {
left(cos(afu)*sin(afd));
right(-cos(afu)*sin(afd));
}
}
}
}
norm(theCoupLast);
}
diff --git a/Shower/Base/PartnerFinder.cc b/Shower/Base/PartnerFinder.cc
--- a/Shower/Base/PartnerFinder.cc
+++ b/Shower/Base/PartnerFinder.cc
@@ -1,232 +1,236 @@
// -*- C++ -*-
//
// PartnerFinder.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 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"
using namespace Herwig;
// 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<ThePEG::ColourLine>::transient_pointer
CL(const ShowerParticleVector::const_iterator & a) {
return (*a)->colourLine();
}
inline Ptr<ThePEG::ColourLine>::transient_pointer
ACL(const ShowerParticleVector::const_iterator & a) {
return (*a)->antiColourLine();
}
}
void PartnerFinder::persistentOutput(PersistentOStream & os) const {
os << _approach;
}
void PartnerFinder::persistentInput(PersistentIStream & is, int) {
is >> _approach;
}
AbstractClassDescription<PartnerFinder> PartnerFinder::initPartnerFinder;
// Definition of the static class description member.
void PartnerFinder::Init() {
static ClassDocumentation<PartnerFinder> 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 Parameter<PartnerFinder,int> approach
("Approximation",
"This is a test variable to consider the different approaches of "
"which colour dipoles of a hard process will shower.",
&PartnerFinder::_approach, 0, 1, 0,false,false,false);
}
bool PartnerFinder::setInitialEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
+#ifndef NDEBUG
ShowerInteraction::Type type,
+#else
+ ShowerInteraction::Type,
+#endif
const bool setPartners) {
assert(type==ShowerInteraction::QCD);
return setInitialQCDEvolutionScales(particles,isDecayCase,setPartners);
}
bool 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, or if both are
// final (outgoing) state particles, then both must have the
// same (non-null) colourLine() or the same (non-null) antiColourLine();
// --- if one is an initial (incoming) state particle and the other is
// a final (outgoing) state particle, then the (non-null) colourLine()
// of one of them must match the (non-null) antiColourLine() of the other.
// 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) {
if(!(*cit)->data().coloured()) continue;
// We now have a coloured particle
tShowerParticleVector partners;
for(cjt = particles.begin(); cjt != particles.end(); ++cjt) {
if(!(*cjt)->data().coloured()||cit==cjt) continue;
bool isPartner = false;
if(FS(*cit) != FS(*cjt) &&
((CL(cit) && CL(cit)==CL(cjt)) || (ACL(cit) && ACL(cit)==ACL(cjt))))
isPartner = true;
else if((CL(cit) && CL(cit)==ACL(cjt)) || (ACL(cit) && ACL(cit)==CL(cjt)))
isPartner = true;
if(isPartner) partners.push_back(*cjt);
}
if (partners.empty()) {
// special for RPV
tColinePtr col = CL(cit);
if(FS(*cit)&&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(*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(*cjt);
}
}
}
col = ACL(cit);
if(FS(*cit)&&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(*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(*cjt);
}
}
}
if(partners.empty()) {
throw Exception() << "`Failed to make colour connections in "
<< "PartnerFinder::setQCDInitialEvolutionScales"
<< (**cit)
<< Exception::eventerror;
}
}
// In the case of more than one candidate colour partners,
// our treatment 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".
int position = UseRandom::irnd(partners.size());
pair<Energy,Energy> pairScales =
calculateInitialEvolutionScales(ShowerPPair(*cit,partners[position]),
isDecayCase);
switch(_approach) {
case 0: // Totally random
(*cit)->setEvolutionScale(pairScales.first);
(*cit)->setPartner(partners[position]);
break;
case 1: // Partner is also set, if it has already been set, pick 50/50
if(!(*cit)->partner() || UseRandom::rndbool()) {
(*cit)->setEvolutionScale(pairScales.first);
(*cit)->setPartner(partners[position]);
}
if(!partners[position]->partner() || UseRandom::rndbool()) {
partners[position]->setEvolutionScale(pairScales.second);
partners[position]->setPartner(*cit);
}
break;
default:
exit(2);
throw Exception() << "Invalid approach for setting colour partner in"
<< " PartnerFinder::setQCDInitialEvolutionScale()"
<< Exception::abortnow;
}
}
}
// partners all ready set only do the scales
else {
for(ShowerParticleVector::const_iterator cit = particles.begin();
cit != particles.end(); ++cit) {
if(!(**cit).dataPtr()->coloured()) continue;
tShowerParticlePtr partner = (**cit).partner();
pair<Energy,Energy> pairScales =
calculateInitialEvolutionScales(ShowerPPair(*cit,partner),
isDecayCase);
(*cit)->setEvolutionScale(pairScales.first);
}
}
return true;
}
pair<Energy,Energy> 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<Energy,Energy> rval = calculateInitialFinalScales(a,isDecayCase);
return pair<Energy,Energy>(rval.second,rval.first);
}
else if(!FS1 &&FS2)
return calculateInitialFinalScales(particlePair,isDecayCase);
else
return calculateInitialInitialScales(particlePair);
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 3, 6:41 AM (22 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4983118
Default Alt Text
(304 KB)

Event Timeline