Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/MatrixElement/DIS/MEChargedCurrentDIS.cc b/MatrixElement/DIS/MEChargedCurrentDIS.cc
--- a/MatrixElement/DIS/MEChargedCurrentDIS.cc
+++ b/MatrixElement/DIS/MEChargedCurrentDIS.cc
@@ -1,281 +1,287 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEChargedCurrentDIS class.
//
#include "MEChargedCurrentDIS.h"
#include "ThePEG/Utilities/SimplePhaseSpace.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/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Handlers/StandardXComb.h"
using namespace Herwig;
+MEChargedCurrentDIS::MEChargedCurrentDIS()
+ : _maxflavour(6), _massopt(0) {
+ massOption(true ,1);
+ massOption(false,_massopt);
+}
+
void MEChargedCurrentDIS::doinit() throw(InitException) {
HwME2to2Base::doinit();
_wp = getParticleData(ThePEG::ParticleID::Wplus );
_wm = getParticleData(ThePEG::ParticleID::Wminus);
// cast the SM pointer to the Herwig SM pointer
tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>(standardModel());
if(!hwsm) throw InitException()
<< "Must be the Herwig++ StandardModel class in "
<< "MEChargedCurrentDIS::doinit" << Exception::abortnow;
// vertices
_theFFWVertex = hwsm->vertexFFW();
}
void MEChargedCurrentDIS::getDiagrams() const {
// possible quarks
typedef std::vector<pair<long,long> > Pairvector;
Pairvector quarkpair;
quarkpair.reserve(6);
// don't even think of putting 'break' in here!
switch(_maxflavour) {
case 6:
quarkpair.push_back(make_pair(ParticleID::s, ParticleID::t));
quarkpair.push_back(make_pair(ParticleID::d, ParticleID::t));
quarkpair.push_back(make_pair(ParticleID::b, ParticleID::t));
case 5:
quarkpair.push_back(make_pair(ParticleID::b, ParticleID::c));
quarkpair.push_back(make_pair(ParticleID::b, ParticleID::u));
case 4:
quarkpair.push_back(make_pair(ParticleID::s, ParticleID::c));
quarkpair.push_back(make_pair(ParticleID::d, ParticleID::c));
case 3:
quarkpair.push_back(make_pair(ParticleID::s, ParticleID::u));
case 2:
quarkpair.push_back(make_pair(ParticleID::d, ParticleID::u));
default:
;
}
// create the diagrams
for(unsigned int il1=11;il1<=14;++il1) {
int il2 = il1%2==0 ? il1-1 : il1+1;
for(unsigned int iz=0;iz<2;++iz) {
tcPDPtr lepin = iz==1 ? getParticleData(il1) : getParticleData(-il1);
tcPDPtr lepout = iz==1 ? getParticleData(il2) : getParticleData(-il2);
tcPDPtr inter = lepin->iCharge()-lepout->iCharge()==3 ? _wp : _wm;
for(unsigned int iq=0;iq<quarkpair.size();++iq) {
tcPDPtr first = getParticleData(quarkpair[iq].first );
tcPDPtr second = getParticleData(quarkpair[iq].second);
if(inter==_wp) {
add(new_ptr((Tree2toNDiagram(3), lepin, inter, first ,
1, lepout, 2, second , -1)));
add(new_ptr((Tree2toNDiagram(3), lepin, inter, second->CC(),
1, lepout, 2, first->CC(), -2)));
}
else {
add(new_ptr((Tree2toNDiagram(3), lepin, inter, second ,
1, lepout, 2, first , -1)));
add(new_ptr((Tree2toNDiagram(3), lepin, inter, first->CC(),
1, lepout, 2, second->CC(), -2)));
}
}
}
}
}
Energy2 MEChargedCurrentDIS::scale() const {
return -tHat();
}
unsigned int MEChargedCurrentDIS::orderInAlphaS() const {
return 0;
}
unsigned int MEChargedCurrentDIS::orderInAlphaEW() const {
return 2;
}
Selector<const ColourLines *>
MEChargedCurrentDIS::colourGeometries(tcDiagPtr diag) const {
static ColourLines c1("3 5");
static ColourLines c2("-3 -5");
Selector<const ColourLines *> sel;
if ( diag->id() == -1 )
sel.insert(1.0, &c1);
else
sel.insert(1.0, &c2);
return sel;
}
void MEChargedCurrentDIS::persistentOutput(PersistentOStream & os) const {
os << _theFFWVertex << _maxflavour << _wp << _wm << _massopt;
}
void MEChargedCurrentDIS::persistentInput(PersistentIStream & is, int) {
is >> _theFFWVertex >> _maxflavour >> _wp >> _wm >> _massopt;
}
ClassDescription<MEChargedCurrentDIS> MEChargedCurrentDIS::initMEChargedCurrentDIS;
// Definition of the static class description member.
void MEChargedCurrentDIS::Init() {
static ClassDocumentation<MEChargedCurrentDIS> documentation
("The MEChargedCurrentDIS class implements the matrix elements "
"for leading-order charged current deep inelastic scattering");
static Parameter<MEChargedCurrentDIS,unsigned int> interfaceMaxFlavour
( "MaxFlavour",
"The heaviest incoming quark flavour this matrix element is allowed to handle "
"(if applicable).",
&MEChargedCurrentDIS::_maxflavour, 6, 2, 6, false, false, true);
static Switch<MEChargedCurrentDIS,unsigned int> interfaceMassOption
("MassOption",
"Option for the treatment of the mass of the outgoing quarks",
&MEChargedCurrentDIS::_massopt, 0, false, false);
static SwitchOption interfaceMassOptionMassless
(interfaceMassOption,
"Massless",
"Treat the outgoing quarks as massless",
0);
static SwitchOption interfaceMassOptionMassive
(interfaceMassOption,
"Massive",
"Treat the outgoing quarks as massive",
1);
}
Selector<MEBase::DiagramIndex>
MEChargedCurrentDIS::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) sel.insert(1., i);
return sel;
}
double MEChargedCurrentDIS::helicityME(vector<SpinorWaveFunction> & f1,
vector<SpinorWaveFunction> & f2,
vector<SpinorBarWaveFunction> & a1,
vector<SpinorBarWaveFunction> & a2,
bool lorder, bool qorder,
bool calc) const {
// scale
Energy2 mb2(scale());
// matrix element to be stored
ProductionMatrixElement menew(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// pick a W boson
tcPDPtr ipart = (mePartonData()[0]->iCharge()-mePartonData()[1]->iCharge())==3 ?
_wp : _wm;
// declare the variables we need
VectorWaveFunction inter;
double me(0.);
Complex diag;
// sum over helicities to get the matrix element
unsigned int hel[4];
unsigned int lhel1,lhel2,qhel1,qhel2;
for(lhel1=0;lhel1<2;++lhel1) {
for(lhel2=0;lhel2<2;++lhel2) {
// intermediate W
inter = _theFFWVertex->evaluate(mb2,3,ipart,f1[lhel1],a1[lhel2]);
for(qhel1=0;qhel1<2;++qhel1) {
for(qhel2=0;qhel2<2;++qhel2) {
hel[0] = lhel1;
hel[1] = qhel1;
hel[2] = lhel2;
hel[3] = qhel2;
if(!lorder) swap(hel[0],hel[2]);
if(!qorder) swap(hel[1],hel[3]);
diag = _theFFWVertex->evaluate(mb2,f2[qhel1],a2[qhel2],inter);
me += norm(diag);
if(calc) menew(hel[0],hel[1],hel[2],hel[3]) = diag;
}
}
}
}
// spin and colour factor
me *= 0.25;
if(calc) _me.reset(menew);
return me;
}
double MEChargedCurrentDIS::me2() const {
vector<SpinorWaveFunction> f1,f2;
vector<SpinorBarWaveFunction> a1,a2;
bool lorder,qorder;
SpinorWaveFunction l1,q1;
SpinorBarWaveFunction l2,q2;
// lepton wave functions
if(mePartonData()[0]->id()>0) {
lorder=true;
l1 = SpinorWaveFunction (meMomenta()[0],mePartonData()[0],incoming);
l2 = SpinorBarWaveFunction(meMomenta()[2],mePartonData()[2],outgoing);
}
else {
lorder=false;
l1 = SpinorWaveFunction (meMomenta()[2],mePartonData()[2],outgoing);
l2 = SpinorBarWaveFunction(meMomenta()[0],mePartonData()[0],incoming);
}
// quark wave functions
if(mePartonData()[1]->id()>0) {
qorder = true;
q1 = SpinorWaveFunction (meMomenta()[1],mePartonData()[1],incoming);
q2 = SpinorBarWaveFunction(meMomenta()[3],mePartonData()[3],outgoing);
}
else {
qorder = false;
q1 = SpinorWaveFunction (meMomenta()[3],mePartonData()[3],outgoing);
q2 = SpinorBarWaveFunction(meMomenta()[1],mePartonData()[1],incoming);
}
// wavefunctions for various helicities
for(unsigned int ix=0;ix<2;++ix) {
l1.reset(ix); f1.push_back(l1);
l2.reset(ix); a1.push_back(l2);
q1.reset(ix); f2.push_back(q1);
q2.reset(ix); a2.push_back(q2);
}
return helicityME(f1,f2,a1,a2,lorder,qorder,false);
}
void MEChargedCurrentDIS::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
hard.push_back(sub->outgoing()[1]);
unsigned int order[4]={0,1,2,3};
bool lorder(true),qorder(true);
if(hard[0]->id()<0) {
swap(order[0],order[2]);
lorder = false;
}
if(hard[1]->id()<0) {
swap(order[1],order[3]);
qorder = false;
}
vector<SpinorWaveFunction> f1,f2;
vector<SpinorBarWaveFunction> a1,a2;
SpinorWaveFunction (f1,hard[order[0]],incoming,!lorder,true);
SpinorWaveFunction (f2,hard[order[1]],incoming,!qorder,true);
SpinorBarWaveFunction(a1,hard[order[2]],outgoing, lorder,true);
SpinorBarWaveFunction(a2,hard[order[3]],outgoing, qorder,true);
helicityME(f1,f2,a1,a2,lorder,qorder,false);
// get the spin info objects
SpinfoPtr spin[4];
for(unsigned int ix=0;ix<4;++ix) {
spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo());
}
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) {
spin[ix]->setProductionVertex(hardvertex);
}
}
diff --git a/MatrixElement/DIS/MEChargedCurrentDIS.fh b/MatrixElement/DIS/MEChargedCurrentDIS.fh
deleted file mode 100644
--- a/MatrixElement/DIS/MEChargedCurrentDIS.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEChargedCurrentDIS class.
-//
-#ifndef HERWIG_MEChargedCurrentDIS_FH
-#define HERWIG_MEChargedCurrentDIS_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEChargedCurrentDIS;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEChargedCurrentDIS,MEChargedCurrentDISPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/DIS/MEChargedCurrentDIS.h b/MatrixElement/DIS/MEChargedCurrentDIS.h
--- a/MatrixElement/DIS/MEChargedCurrentDIS.h
+++ b/MatrixElement/DIS/MEChargedCurrentDIS.h
@@ -1,264 +1,261 @@
// -*- C++ -*-
#ifndef HERWIG_MEChargedCurrentDIS_H
#define HERWIG_MEChargedCurrentDIS_H
//
// This is the declaration of the MEChargedCurrentDIS class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "MEChargedCurrentDIS.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MEChargedCurrentDIS class provides the matrix elements for
* charged current DIS.
*
* By default both the incoming and outgong quarks are assumed to be massless
* although the mass of the outgoing quark can be included if required. This
* option should be used if top production is included.
*
* @see \ref MEChargedCurrentDISInterfaces "The interfaces"
* defined for MEChargedCurrentDIS.
*/
class MEChargedCurrentDIS: public HwME2to2Base {
public:
/**
* The default constructor.
*/
- inline MEChargedCurrentDIS();
+ MEChargedCurrentDIS();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Matrix element for \f$\ell q\to \gamma/Z \to \ell q\f$.
* @param f1 Fermion on lepton line
* @param a1 Anti-fermion on lepton line
* @param f2 Fermion on quark line
* @param a2 Anti-fermion on quark line
* @param lorder The order of particles on the lepton line
* @param qorder The order of particles on the quark line
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double helicityME(vector<SpinorWaveFunction> & f1 ,
vector<SpinorWaveFunction> & f2,
vector<SpinorBarWaveFunction> & a1 ,
vector<SpinorBarWaveFunction> & a2,
bool lorder, bool qorder,
bool me) const;
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEChargedCurrentDIS> initMEChargedCurrentDIS;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEChargedCurrentDIS & operator=(const MEChargedCurrentDIS &);
private:
/**
* Pointer to the vertex for the helicity calculations
*/
AbstractFFVVertexPtr _theFFWVertex;
/**
* The allowed flavours of the incoming quarks
*/
unsigned int _maxflavour;
/**
* Option for the mass of the outgoing quarks
*/
unsigned int _massopt;
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
/**
* Pointers to the intermediates resonances
*/
//@{
/**
* Pointer to the \f$W^+\f$
*/
tcPDPtr _wp;
/**
* Pointer to the \f$W^-\f$
*/
tcPDPtr _wm;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEChargedCurrentDIS. */
template <>
struct BaseClassTrait<Herwig::MEChargedCurrentDIS,1> {
/** Typedef of the first base class of MEChargedCurrentDIS. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEChargedCurrentDIS class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEChargedCurrentDIS>
: public ClassTraitsBase<Herwig::MEChargedCurrentDIS> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEChargedCurrentDIS"; }
/**
* The name of a file containing the dynamic library where the class
* MEChargedCurrentDIS is implemented. It may also include several, space-separated,
* libraries if the class MEChargedCurrentDIS depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEDIS.so"; }
};
/** @endcond */
}
-#include "MEChargedCurrentDIS.icc"
-
#endif /* HERWIG_MEChargedCurrentDIS_H */
diff --git a/MatrixElement/DIS/MEChargedCurrentDIS.icc b/MatrixElement/DIS/MEChargedCurrentDIS.icc
deleted file mode 100644
--- a/MatrixElement/DIS/MEChargedCurrentDIS.icc
+++ /dev/null
@@ -1,23 +0,0 @@
-// -*- C++ -*-
-//
-// This is the implementation of the inlined member functions of
-// the MEChargedCurrentDIS class.
-//
-
-namespace Herwig {
-
-inline MEChargedCurrentDIS::MEChargedCurrentDIS()
- : _maxflavour(6), _massopt(0) {
- massOption(true ,1);
- massOption(false,_massopt);
-}
-
-inline IBPtr MEChargedCurrentDIS::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEChargedCurrentDIS::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/DIS/MENeutralCurrentDIS.cc b/MatrixElement/DIS/MENeutralCurrentDIS.cc
--- a/MatrixElement/DIS/MENeutralCurrentDIS.cc
+++ b/MatrixElement/DIS/MENeutralCurrentDIS.cc
@@ -1,298 +1,304 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MENeutralCurrentDIS class.
//
#include "MENeutralCurrentDIS.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Handlers/StandardXComb.h"
using namespace Herwig;
+MENeutralCurrentDIS::MENeutralCurrentDIS()
+ : _minflavour(1), _maxflavour(5), _gammaZ(0) {
+ massOption(true ,1);
+ massOption(false,0);
+}
+
void MENeutralCurrentDIS::doinit() throw(InitException) {
HwME2to2Base::doinit();
_z0 = getParticleData(ThePEG::ParticleID::Z0);
_gamma = getParticleData(ThePEG::ParticleID::gamma);
// cast the SM pointer to the Herwig SM pointer
tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>(standardModel());
if(!hwsm) throw InitException()
<< "Must be the Herwig++ StandardModel class in "
<< "MENeutralCurrentDIS::doinit" << Exception::abortnow;
// vertices
_theFFZVertex = hwsm->vertexFFZ();
_theFFPVertex = hwsm->vertexFFP();
}
void MENeutralCurrentDIS::getDiagrams() const {
// which intermediates to include
bool gamma = _gammaZ==0 || _gammaZ==1;
bool Z0 = _gammaZ==0 || _gammaZ==2;
// create the diagrams
for(unsigned int ix=11;ix<=14;++ix) {
for(unsigned int iz=0;iz<2;++iz) {
tPDPtr lep = getParticleData(ix);
if(iz==1) lep = lep->CC();
for(unsigned int iy=_minflavour;iy<=_maxflavour;++iy) {
tPDPtr quark = getParticleData(iy);
// lepton quark scattering via gamma and Z
if(gamma) add(new_ptr((Tree2toNDiagram(3), lep, _gamma, quark,
1, lep, 2, quark, -1)));
if(Z0) add(new_ptr((Tree2toNDiagram(3), lep, _z0 , quark,
1, lep, 2, quark, -2)));
// lepton antiquark scattering via gamma and Z
quark = quark->CC();
if(gamma) add(new_ptr((Tree2toNDiagram(3), lep, _gamma, quark,
1, lep, 2, quark, -3)));
if(Z0) add(new_ptr((Tree2toNDiagram(3), lep, _z0 , quark,
1, lep, 2, quark, -4)));
}
}
}
}
Energy2 MENeutralCurrentDIS::scale() const {
return -tHat();
}
unsigned int MENeutralCurrentDIS::orderInAlphaS() const {
return 0;
}
unsigned int MENeutralCurrentDIS::orderInAlphaEW() const {
return 2;
}
Selector<const ColourLines *>
MENeutralCurrentDIS::colourGeometries(tcDiagPtr diag) const {
static ColourLines c1("3 5");
static ColourLines c2("-3 -5");
Selector<const ColourLines *> sel;
if ( diag->id() == -1 || diag->id() == -2 )
sel.insert(1.0, &c1);
else
sel.insert(1.0, &c2);
return sel;
}
void MENeutralCurrentDIS::persistentOutput(PersistentOStream & os) const {
os << _minflavour << _maxflavour << _gammaZ << _theFFZVertex << _theFFPVertex
<< _gamma << _z0;
}
void MENeutralCurrentDIS::persistentInput(PersistentIStream & is, int) {
is >> _minflavour >> _maxflavour >> _gammaZ >> _theFFZVertex >> _theFFPVertex
>> _gamma >> _z0;
}
ClassDescription<MENeutralCurrentDIS> MENeutralCurrentDIS::initMENeutralCurrentDIS;
// Definition of the static class description member.
void MENeutralCurrentDIS::Init() {
static ClassDocumentation<MENeutralCurrentDIS> documentation
("The MENeutralCurrentDIS class implements the matrix elements for leading-order "
"neutral current deep inelastic scattering.");
static Parameter<MENeutralCurrentDIS,unsigned int> interfaceMaxFlavour
("MaxFlavour",
"The highest incoming quark flavour this matrix element is allowed to handle",
&MENeutralCurrentDIS::_maxflavour, 5, 1, 5,
false, false, Interface::limited);
static Parameter<MENeutralCurrentDIS,unsigned int> interfaceMinFlavour
("MinFlavour",
"The lightest incoming quark flavour this matrix element is allowed to handle",
&MENeutralCurrentDIS::_minflavour, 1, 1, 5,
false, false, Interface::limited);
static Switch<MENeutralCurrentDIS,unsigned int> interfaceGammaZ
("GammaZ",
"Which terms to include",
&MENeutralCurrentDIS::_gammaZ, 0, false, false);
static SwitchOption interfaceGammaZAll
(interfaceGammaZ,
"All",
"Include both gamma and Z terms",
0);
static SwitchOption interfaceGammaZGamma
(interfaceGammaZ,
"Gamma",
"Only include the photon",
1);
static SwitchOption interfaceGammaZZ
(interfaceGammaZ,
"Z",
"Only include the Z",
2);
}
Selector<MEBase::DiagramIndex>
MENeutralCurrentDIS::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if ( diags[i]->id() == -1 || diags[i]->id() == -3 ) sel.insert(meInfo()[0], i);
else if ( diags[i]->id() == -2 || diags[i]->id() == -4 ) sel.insert(meInfo()[1], i);
}
return sel;
}
double MENeutralCurrentDIS::helicityME(vector<SpinorWaveFunction> & f1,
vector<SpinorWaveFunction> & f2,
vector<SpinorBarWaveFunction> & a1,
vector<SpinorBarWaveFunction> & a2,
bool lorder, bool qorder,
bool calc) const {
// scale
Energy2 mb2(scale());
// matrix element to be stored
ProductionMatrixElement menew(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// which intermediates to include
bool gamma = _gammaZ==0 || _gammaZ==1;
bool Z0 = _gammaZ==0 || _gammaZ==2;
// declare the variables we need
VectorWaveFunction inter[2];
double me[3]={0.,0.,0.};
Complex diag1,diag2;
// sum over helicities to get the matrix element
unsigned int hel[4];
unsigned int lhel1,lhel2,qhel1,qhel2;
for(lhel1=0;lhel1<2;++lhel1) {
for(lhel2=0;lhel2<2;++lhel2) {
// intermediate for photon
if(gamma) inter[0]=_theFFPVertex->evaluate(mb2,1,_gamma,f1[lhel1],a1[lhel2]);
// intermediate for Z
if(Z0) inter[1]=_theFFZVertex->evaluate(mb2,1,_z0 ,f1[lhel1],a1[lhel2]);
for(qhel1=0;qhel1<2;++qhel1) {
for(qhel2=0;qhel2<2;++qhel2) {
hel[0] = lhel1;
hel[1] = qhel1;
hel[2] = lhel2;
hel[3] = qhel2;
if(!lorder) swap(hel[0],hel[2]);
if(!qorder) swap(hel[1],hel[3]);
// first the photon exchange diagram
diag1 = gamma ?
_theFFPVertex->evaluate(mb2,f2[qhel1],a2[qhel2],inter[0]) : 0.;
// then the Z exchange diagram
diag2 = Z0 ?
_theFFZVertex->evaluate(mb2,f2[qhel1],a2[qhel2],inter[1]) : 0.;
// add up squares of individual terms
me[1] += norm(diag1);
me[2] += norm(diag2);
// the full thing including interference
diag1 += diag2;
me[0] += norm(diag1);
if(calc) menew(hel[0],hel[1],hel[2],hel[3]) = diag1;
}
}
}
}
// spin and colour factor
double colspin = 0.25;
// results
for(int ix=0;ix<3;++ix) me[ix] *= colspin;
DVector save;
save.push_back(me[1]);
save.push_back(me[2]);
meInfo(save);
if(calc) _me.reset(menew);
// analytic expression for testing
// double test = 8.*sqr(4.*Constants::pi*generator()->standardModel()->alphaEM(mb2))*
// sqr(double(mePartonData()[1]->iCharge())/3.)/sqr(tHat())
// *(sqr(sHat())+sqr(uHat())+4.*sqr(mePartonData()[0]->mass())*tHat())/4.;
// cerr << "testing me " << me[0]/test << "\n";
return me[0];
}
double MENeutralCurrentDIS::me2() const {
vector<SpinorWaveFunction> f1,f2;
vector<SpinorBarWaveFunction> a1,a2;
bool lorder,qorder;
SpinorWaveFunction l1,q1;
SpinorBarWaveFunction l2,q2;
// lepton wave functions
if(mePartonData()[0]->id()>0) {
lorder=true;
l1 = SpinorWaveFunction (meMomenta()[0],mePartonData()[0],incoming);
l2 = SpinorBarWaveFunction(meMomenta()[2],mePartonData()[2],outgoing);
}
else {
lorder=false;
l1 = SpinorWaveFunction (meMomenta()[2],mePartonData()[2],outgoing);
l2 = SpinorBarWaveFunction(meMomenta()[0],mePartonData()[0],incoming);
}
// quark wave functions
if(mePartonData()[1]->id()>0) {
qorder = true;
q1 = SpinorWaveFunction (meMomenta()[1],mePartonData()[1],incoming);
q2 = SpinorBarWaveFunction(meMomenta()[3],mePartonData()[3],outgoing);
}
else {
qorder = false;
q1 = SpinorWaveFunction (meMomenta()[3],mePartonData()[3],outgoing);
q2 = SpinorBarWaveFunction(meMomenta()[1],mePartonData()[1],incoming);
}
// wavefunctions for various helicities
for(unsigned int ix=0;ix<2;++ix) {
l1.reset(ix); f1.push_back(l1);
l2.reset(ix); a1.push_back(l2);
q1.reset(ix); f2.push_back(q1);
q2.reset(ix); a2.push_back(q2);
}
return helicityME(f1,f2,a1,a2,lorder,qorder,false);
}
void MENeutralCurrentDIS::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
hard.push_back(sub->outgoing()[1]);
unsigned int order[4]={0,1,2,3};
bool lorder(true),qorder(true);
if(hard[0]->id()<0) {
swap(order[0],order[2]);
lorder = false;
}
if(hard[1]->id()<0) {
swap(order[1],order[3]);
qorder = false;
}
vector<SpinorWaveFunction> f1,f2;
vector<SpinorBarWaveFunction> a1,a2;
SpinorWaveFunction (f1,hard[order[0]],incoming,!lorder,true);
SpinorWaveFunction (f2,hard[order[1]],incoming,!qorder,true);
SpinorBarWaveFunction(a1,hard[order[2]],outgoing, lorder,true);
SpinorBarWaveFunction(a2,hard[order[3]],outgoing, qorder,true);
helicityME(f1,f2,a1,a2,lorder,qorder,false);
// get the spin info objects
SpinfoPtr spin[4];
for(unsigned int ix=0;ix<4;++ix) {
spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo());
}
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) {
spin[ix]->setProductionVertex(hardvertex);
}
}
diff --git a/MatrixElement/DIS/MENeutralCurrentDIS.fh b/MatrixElement/DIS/MENeutralCurrentDIS.fh
deleted file mode 100644
--- a/MatrixElement/DIS/MENeutralCurrentDIS.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MENeutralCurrentDIS class.
-//
-#ifndef HERWIG_MENeutralCurrentDIS_FH
-#define HERWIG_MENeutralCurrentDIS_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MENeutralCurrentDIS;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MENeutralCurrentDIS,MENeutralCurrentDISPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/DIS/MENeutralCurrentDIS.h b/MatrixElement/DIS/MENeutralCurrentDIS.h
--- a/MatrixElement/DIS/MENeutralCurrentDIS.h
+++ b/MatrixElement/DIS/MENeutralCurrentDIS.h
@@ -1,283 +1,280 @@
// -*- C++ -*-
#ifndef HERWIG_MENeutralCurrentDIS_H
#define HERWIG_MENeutralCurrentDIS_H
//
// This is the declaration of the MENeutralCurrentDIS class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "MENeutralCurrentDIS.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MENeutralCurrentDIS class provides the matrix elements for
* neutral current DIS.
*
* For consistency both the incoming and outgoing quarks are assumed to be massless.
*
* @see \ref MENeutralCurrentDISInterfaces "The interfaces"
* defined for MENeutralCurrentDIS.
*/
class MENeutralCurrentDIS: public HwME2to2Base {
public:
/**
* The default constructor.
*/
- inline MENeutralCurrentDIS();
+ MENeutralCurrentDIS();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
inline virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Matrix element for \f$\ell q\to \gamma/Z \to \ell q\f$.
* @param f1 Fermion on lepton line
* @param a1 Anti-fermion on lepton line
* @param f2 Fermion on quark line
* @param a2 Anti-fermion on quark line
* @param lorder The order of particles on the lepton line
* @param qorder The order of particles on the quark line
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double helicityME(vector<SpinorWaveFunction> & f1 ,
vector<SpinorWaveFunction> & f2,
vector<SpinorBarWaveFunction> & a1 ,
vector<SpinorBarWaveFunction> & a2,
bool lorder, bool qorder,
bool me) const;
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MENeutralCurrentDIS> initMENeutralCurrentDIS;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MENeutralCurrentDIS & operator=(const MENeutralCurrentDIS &);
private:
/**
* Pointer to the vertices for the helicity calculations
*/
//@{
/**
* Pointer to the Z vertex
*/
AbstractFFVVertexPtr _theFFZVertex;
/**
* Pointer to the photon vertex
*/
AbstractFFVVertexPtr _theFFPVertex;
//@}
/**
* Pointers to the intermediate resonances
*/
//@{
/**
* Pointer to the Z ParticleData object
*/
tcPDPtr _z0;
/**
* Pointer to the photon ParticleData object
*/
tcPDPtr _gamma;
//@}
/**
* Switches to control the particles in the hard process
*/
//@{
/**
* Minimumflavour of the incoming quarks
*/
unsigned int _minflavour;
/**
* Maximum flavour of the incoming quarks
*/
unsigned int _maxflavour;
/**
* Whether to include both \f$Z^0\f$ and \f$\gamma\f$ or only one
*/
unsigned int _gammaZ;
//@}
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MENeutralCurrentDIS. */
template <>
struct BaseClassTrait<Herwig::MENeutralCurrentDIS,1> {
/** Typedef of the first base class of MENeutralCurrentDIS. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MENeutralCurrentDIS class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MENeutralCurrentDIS>
: public ClassTraitsBase<Herwig::MENeutralCurrentDIS> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MENeutralCurrentDIS"; }
/**
* The name of a file containing the dynamic library where the class
* MENeutralCurrentDIS is implemented. It may also include several, space-separated,
* libraries if the class MENeutralCurrentDIS depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEDIS.so"; }
};
/** @endcond */
}
-#include "MENeutralCurrentDIS.icc"
-
#endif /* HERWIG_MENeutralCurrentDIS_H */
diff --git a/MatrixElement/DIS/MENeutralCurrentDIS.icc b/MatrixElement/DIS/MENeutralCurrentDIS.icc
deleted file mode 100644
--- a/MatrixElement/DIS/MENeutralCurrentDIS.icc
+++ /dev/null
@@ -1,23 +0,0 @@
-// -*- C++ -*-
-//
-// This is the implementation of the inlined member functions of
-// the MENeutralCurrentDIS class.
-//
-
-namespace Herwig {
-
-inline MENeutralCurrentDIS::MENeutralCurrentDIS()
- : _minflavour(1), _maxflavour(5), _gammaZ(0) {
- massOption(true ,1);
- massOption(false,0);
-}
-
-inline IBPtr MENeutralCurrentDIS::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MENeutralCurrentDIS::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/DIS/Makefile.am b/MatrixElement/DIS/Makefile.am
--- a/MatrixElement/DIS/Makefile.am
+++ b/MatrixElement/DIS/Makefile.am
@@ -1,7 +1,5 @@
pkglib_LTLIBRARIES = HwMEDIS.la
HwMEDIS_la_SOURCES = \
MENeutralCurrentDIS.cc MENeutralCurrentDIS.h \
-MENeutralCurrentDIS.icc MENeutralCurrentDIS.fh \
-MEChargedCurrentDIS.cc MEChargedCurrentDIS.h \
-MEChargedCurrentDIS.icc MEChargedCurrentDIS.fh
+MEChargedCurrentDIS.cc MEChargedCurrentDIS.h
HwMEDIS_la_LDFLAGS = -module -version-info 1:0:0
diff --git a/MatrixElement/GammaGamma/MEGammaGamma2ff.fh b/MatrixElement/GammaGamma/MEGammaGamma2ff.fh
deleted file mode 100644
--- a/MatrixElement/GammaGamma/MEGammaGamma2ff.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEGammaGamma2ff class.
-//
-#ifndef HERWIG_MEGammaGamma2ff_FH
-#define HERWIG_MEGammaGamma2ff_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEGammaGamma2ff;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEGammaGamma2ff,MEGammaGamma2ffPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/GammaGamma/MEGammaGamma2ff.h b/MatrixElement/GammaGamma/MEGammaGamma2ff.h
--- a/MatrixElement/GammaGamma/MEGammaGamma2ff.h
+++ b/MatrixElement/GammaGamma/MEGammaGamma2ff.h
@@ -1,230 +1,227 @@
// -*- C++ -*-
#ifndef HERWIG_MEGammaGamma2ff_H
#define HERWIG_MEGammaGamma2ff_H
//
// This is the declaration of the MEGammaGamma2ff class.
//
#include "ThePEG/MatrixElement/ME2to2Base.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
-#include "MEGammaGamma2ff.fh"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the MEGammaGamma2ff class.
*
* @see \ref MEGammaGamma2ffInterfaces "The interfaces"
* defined for MEGammaGamma2ff.
*/
class MEGammaGamma2ff: public ME2to2Base {
public:
/**
* The default constructor.
*/
- inline MEGammaGamma2ff();
+ inline MEGammaGamma2ff() : _process(0) {}
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Matrix element for \f$\gamma\gamma\to q\bar{q}\f$
* @param p1 The wavefunctions for the first incoming photon
* @param p2 The wavefunctions for the second incoming photon
* @param f The wavefunction for the outgoing fermion
* @param fbar The wavefunction for the outgoing antifermion
* @param calc Whether or not to calculate the matrix element
*/
double helicityME(vector<VectorWaveFunction> &p1,vector<VectorWaveFunction> &p2,
vector<SpinorBarWaveFunction> & f,
vector<SpinorWaveFunction> & fbar, bool calc) const;
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEGammaGamma2ff> initMEGammaGamma2ff;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEGammaGamma2ff & operator=(const MEGammaGamma2ff &);
private:
/**
* Which processes to include
*/
unsigned int _process;
/**
* Pointer to the photon vertex
*/
AbstractFFVVertexPtr _theFFPVertex;
/**
* Matrix element
*/
mutable ProductionMatrixElement _me;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEGammaGamma2ff. */
template <>
struct BaseClassTrait<Herwig::MEGammaGamma2ff,1> {
/** Typedef of the first base class of MEGammaGamma2ff. */
typedef ME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEGammaGamma2ff class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEGammaGamma2ff>
: public ClassTraitsBase<Herwig::MEGammaGamma2ff> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEGammaGamma2ff"; }
/**
* The name of a file containing the dynamic library where the class
* MEGammaGamma2ff is implemented. It may also include several, space-separated,
* libraries if the class MEGammaGamma2ff depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEGamma.so"; }
};
/** @endcond */
}
-#include "MEGammaGamma2ff.icc"
-
#endif /* HERWIG_MEGammaGamma2ff_H */
diff --git a/MatrixElement/GammaGamma/MEGammaGamma2ff.icc b/MatrixElement/GammaGamma/MEGammaGamma2ff.icc
deleted file mode 100644
--- a/MatrixElement/GammaGamma/MEGammaGamma2ff.icc
+++ /dev/null
@@ -1,19 +0,0 @@
-// -*- C++ -*-
-//
-// This is the implementation of the inlined member functions of
-// the MEGammaGamma2ff class.
-//
-
-namespace Herwig {
-
-inline MEGammaGamma2ff::MEGammaGamma2ff() : _process(0) {}
-
-inline IBPtr MEGammaGamma2ff::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEGammaGamma2ff::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/GammaGamma/Makefile.am b/MatrixElement/GammaGamma/Makefile.am
--- a/MatrixElement/GammaGamma/Makefile.am
+++ b/MatrixElement/GammaGamma/Makefile.am
@@ -1,5 +1,4 @@
pkglib_LTLIBRARIES = HwMEGamma.la
HwMEGamma_la_SOURCES = \
-MEGammaGamma2ff.cc MEGammaGamma2ff.h \
-MEGammaGamma2ff.icc MEGammaGamma2ff.fh
+MEGammaGamma2ff.cc MEGammaGamma2ff.h
HwMEGamma_la_LDFLAGS = -module -version-info 1:0:0
diff --git a/MatrixElement/General/HardVertex.cc b/MatrixElement/General/HardVertex.cc
deleted file mode 100644
--- a/MatrixElement/General/HardVertex.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// -*- C++ -*-
-//
-// HardVertex.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 HardVertex class.
-//
-// Author: Peter Richardson
-//
-
-#include "HardVertex.h"
-#include "ThePEG/Interface/ClassDocumentation.h"
-#include "ThePEG/Helicity/SpinInfo.h"
-#ifdef ThePEG_TEMPLATES_IN_CC_FILE
-// #include "HardVertex.tcc"
-#endif
-
-namespace Herwig {
-
-using ThePEG::Helicity::SpinInfo;
-using ThePEG::Helicity::tcSpinfoPtr;
-
-using namespace ThePEG;
-
-NoPIOClassDescription<HardVertex> HardVertex::initHardVertex;
- // Definition of the static class description member.
-
-void HardVertex::Init() {
-
- static ClassDocumentation<HardVertex> documentation
- ("The HardVertex class implements the vertex for a hard "
- "interaction for the Herwig++ spin correlation algorithm");
-
-}
-
-// method to get the rho matrix for a given outgoing particle
-RhoDMatrix HardVertex::getRhoMatrix(int i)
-{
- // get the rho matrices for the outgoing particles
- vector<RhoDMatrix> rhoout;
- for(unsigned int ix=0,N=outgoing().size();ix<N;++ix)
- {
- if(int(ix)!=i)
- {rhoout.push_back(dynamic_ptr_cast<tcSpinfoPtr>(outgoing()[ix])->DMatrix());}
- }
- // calculate the spin density matrix
- RhoDMatrix temp=_matrixelement.calculateRhoMatrix(i,dynamic_ptr_cast<tcSpinfoPtr>(incoming()[0])->DMatrix(),dynamic_ptr_cast<tcSpinfoPtr>(incoming()[1])->DMatrix(),rhoout);
- return temp;
-}
-
-// method to get the D matrix for an incoming particle
-RhoDMatrix HardVertex::getDMatrix(int i)
-{
- // get rho rho matrices for the outgoing particles
- vector<RhoDMatrix> rhoout;
- for(unsigned int ix=0,N=outgoing().size();ix<N;++ix)
- {rhoout.push_back(dynamic_ptr_cast<tcSpinfoPtr>(outgoing()[ix])->DMatrix());}
- // calculate the decay matrix
- int j=0;if(i==0){j=1;}
- RhoDMatrix temp=_matrixelement.calculateDMatrix(i,dynamic_ptr_cast<tcSpinfoPtr>(incoming()[1])->DMatrix(),rhoout);
- return temp;
-}
-}
-
diff --git a/MatrixElement/General/HardVertex.fh b/MatrixElement/General/HardVertex.fh
deleted file mode 100644
--- a/MatrixElement/General/HardVertex.fh
+++ /dev/null
@@ -1,18 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the HardVertex class.
-//
-#ifndef HERWIG_HardVertex_FH
-#define HERWIG_HardVertex_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-using namespace ThePEG;
-
-class HardVertex;
-ThePEG_DECLARE_POINTERS(HardVertex,HardVertexPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/HardVertex.h b/MatrixElement/General/HardVertex.h
deleted file mode 100644
--- a/MatrixElement/General/HardVertex.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// -*- C++ -*-
-//
-// HardVertex.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_HardVertex_H
-#define HERWIG_HardVertex_H
-//
-// This is the declaration of the HardVertex class.
-
-#include "ThePEG/Helicity/HelicityVertex.h"
-#include "ProductionMatrixElement.h"
-#include "HardVertex.fh"
-// #include "HardVertex.xh"
-
-namespace Herwig {
-using ThePEG::Helicity::HelicityVertex;
-
-using namespace ThePEG;
-
-/** \ingroup Helicity
- * \author Peter Richardson
- *
- * The HardVertex class is designed to implement the vertex for a
- * hard interaction for the Herwig++ spin correlation algorithm.
- * It inherits from the HelicityVertex class of ThePEG and implements
- * the methods to calculate the \f$\rho\f$ and \f$D\f$ matrices.
- *
- * The ProductionMatrixElement class is used to store the matrix element
- * and this class performs the calculations of the matrices.
- *
- * @see HelicityVertex
- * @see ProductionMatrixElement
- */
-
-class HardVertex: public HelicityVertex {
-
-public:
-
- /**
- * Access to the matrix element
- */
- //@{
- /**
- * Get the matrix element
- */
- inline const ProductionMatrixElement & ME() const;
-
- /**
- * Set the matrix element
- */
- inline void ME(const ProductionMatrixElement &) const;
- //@}
-
-public:
-
- /**
- * Standard Init function used to initialize the interfaces.
- */
- static void Init();
-
-public:
-
- /**
- * Method to calculate the \f$\rho\f$ matrix for one of the outgoing particles
- * @param iout The outgoing particle we are calculating the \f$\rho\f$ matrix for.
- */
- virtual RhoDMatrix getRhoMatrix(int iout);
-
- /**
- * Method to calculate the \f$D\f$ matrix for an incoming particle.
- * @param in The incoming particle we are calculating the \f$D\f$ matrix for.
- */
- virtual RhoDMatrix getDMatrix(int in);
-
-private:
-
- /**
- * Describe a concrete class without persistent data.
- */
- static NoPIOClassDescription<HardVertex> initHardVertex;
-
- /**
- * Private and non-existent assignment operator.
- */
- HardVertex & operator=(const HardVertex &);
-
-private:
-
- /**
- * Storage of the matrix element.
- */
- ProductionMatrixElement _matrixelement;
-
-};
-}
-
-
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/**
- * The following template specialization informs ThePEG about the
- * base class of HardVertex.
- */
-template <>
-struct BaseClassTrait<Herwig::HardVertex,1> {
- /** Typedef of the base class of HardVertex. */
- typedef ThePEG::Helicity::HelicityVertex NthBase;
-};
-
-/**
- * The following template specialization informs ThePEG about the
- * name of this class and the shared object where it is defined.
- */
-template <>
-struct ClassTraits<Herwig::HardVertex>
- : public ClassTraitsBase<Herwig::HardVertex> {
-
- /**
- * Return the class name.
- */
- static string className() { return "Herwig::HardVertex"; }
-};
-
-/** @endcond */
-
-}
-
-#include "HardVertex.icc"
-
-#endif /* HERWIG_HardVertex_H */
diff --git a/MatrixElement/General/HardVertex.icc b/MatrixElement/General/HardVertex.icc
deleted file mode 100644
--- a/MatrixElement/General/HardVertex.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// HardVertex.icc 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 inlined member functions of
-// the HardVertex class.
-//
-// Author: Peter Richardson
-//
-
-namespace Herwig {
-using namespace ThePEG;
-
-// get ME
-inline const ProductionMatrixElement & HardVertex::ME() const
-{return _matrixelement;}
-
-// set ME
-inline void HardVertex::ME(const ProductionMatrixElement & in) const
-{_matrixelement.reset(in);}
-}
diff --git a/MatrixElement/General/MEff2ff.cc b/MatrixElement/General/MEff2ff.cc
--- a/MatrixElement/General/MEff2ff.cc
+++ b/MatrixElement/General/MEff2ff.cc
@@ -1,993 +1,993 @@
// -*- C++ -*-
//
// MEff2ff.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 MEff2ff class.
//
#include "MEff2ff.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include <numeric>
using namespace Herwig;
using ThePEG::Helicity::VectorWaveFunction;
using ThePEG::Helicity::ScalarWaveFunction;
using ThePEG::Helicity::TensorWaveFunction;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
using ThePEG::Helicity::SpinfoPtr;
void MEff2ff::doinit() throw(InitException) {
GeneralHardME::doinit();
size_t ndiags = numberOfDiags();
theScaV.resize(ndiags);
theVecV.resize(ndiags);
theTenV.resize(ndiags);
for(size_t ix = 0;ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(offshell->iSpin() == PDT::Spin0) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
theScaV[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
theVecV[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractFFTVertexPtr vert1 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.first);
AbstractFFTVertexPtr vert2 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.second);
theTenV[ix] = make_pair(vert1, vert2);
}
}
}
double MEff2ff::me2() const {
tcPDPtr ina(mePartonData()[0]), inb(mePartonData()[1]),
outa(mePartonData()[2]), outb(mePartonData()[3]);
bool majorana(false);
if( (!outa->CC() && !outb->CC() ) ||
((abs(outa->id()) > 1000000 && abs(outa->id()) < 2000000) &&
(abs(outb->id()) > 1000000 && abs(outb->id()) < 2000000)) )
majorana = true;
double full_me(0.);
vector<SpinorWaveFunction> spA(2), spB(2);
vector<SpinorBarWaveFunction> spbA(2), spbB(2);
if( ina->id() > 0 && inb->id() < 0) {
for(unsigned int ih = 0; ih < 2; ++ih) {
spA[ih] = SpinorWaveFunction(rescaledMomenta()[0], ina, ih,
incoming);
spbA[ih] = SpinorBarWaveFunction(rescaledMomenta()[1], inb, ih,
incoming);
spB[ih] = SpinorWaveFunction(rescaledMomenta()[3], outb, ih, outgoing);
spbB[ih] = SpinorBarWaveFunction(rescaledMomenta()[2], outa, ih, outgoing);
}
if(majorana) {
vector<SpinorWaveFunction> spC(2);
vector<SpinorBarWaveFunction> spbC(2);
for(unsigned int ih = 0; ih < 2; ++ih) {
spC[ih] = SpinorWaveFunction(rescaledMomenta()[2], outa, ih, outgoing);
spbC[ih] = SpinorBarWaveFunction(rescaledMomenta()[3], outb, ih, outgoing);
}
ffb2mfmfHeME(spA, spbA, spbB, spB, spC, spbC, full_me);
SpinorWaveFunction spOut2(rescaledMomenta()[2], outa, outgoing);
SpinorBarWaveFunction spbarOut2(rescaledMomenta()[3], outb, outgoing);
}
else {
ffb2ffbHeME(spA, spbA, spbB, spB, full_me);
}
}
else if( ina->id() > 0 && inb->id() > 0 ) {
SpinorVector spA(2), spB(2);
SpinorBarVector spbA(2), spbB(2);
for(unsigned int ih = 0; ih < 2; ++ih) {
spA[ih] = SpinorWaveFunction(rescaledMomenta()[0], ina, ih,
incoming);
spB[ih] = SpinorWaveFunction(rescaledMomenta()[1], inb, ih,
incoming);
spbA[ih] = SpinorBarWaveFunction(rescaledMomenta()[2], outa, ih,
outgoing);
spbB[ih] = SpinorBarWaveFunction(rescaledMomenta()[3], outb, ih,
outgoing);
}
ff2ffHeME(spA, spB, spbA, spbB, full_me);
}
else if( ina->id() < 0 && inb->id() < 0 ) {
SpinorVector spA(2), spB(2);
SpinorBarVector spbA(2), spbB(2);
for(unsigned int ih = 0; ih < 2; ++ih) {
spbA[ih] = SpinorBarWaveFunction(rescaledMomenta()[0], ina, ih,
incoming);
spbB[ih] = SpinorBarWaveFunction(rescaledMomenta()[1], inb, ih,
incoming);
spA[ih] = SpinorWaveFunction(rescaledMomenta()[2], outa, ih,
outgoing);
spB[ih] = SpinorWaveFunction(rescaledMomenta()[3], outb, ih,
outgoing);
}
fbfb2fbfbHeME(spbA, spbB, spA, spB, full_me);
}
else
throw MEException()
<< "MEff2ff::me2() - Cannot find correct function to deal with process "
<< ina->PDGName() << "," << inb->PDGName() << "->" << outa->PDGName()
<< "," << outb->PDGName() << "\n";
#ifndef NDEBUG
if( debugME() ) debug(full_me);
#endif
return full_me;
}
ProductionMatrixElement
MEff2ff::ffb2ffbHeME(SpinorVector & fin, SpinorBarVector & fbin,
SpinorBarVector & fbout, SpinorVector & fout,
double & me2) const {
const HPCount ndiags = numberOfDiags();
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors(getColourFactors());
const Energy2 m2(scale());
vector<Complex> diag(ndiags, Complex(0.)), flows(ncf, Complex(0.));
vector<double> me(ndiags, 0.);
ScalarWaveFunction interS; VectorWaveFunction interV;
TensorWaveFunction interT;
ProductionMatrixElement prodME(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1Half,
PDT::Spin1Half);
for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) {
for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) {
for(unsigned int ofhel1 = 0; ofhel1 < 2; ++ofhel1) {
for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) {
flows = vector<Complex>(ncf, Complex(0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(current.channelType == HPDiagram::tChannel) {
if(offshell->iSpin() == PDT::Spin0) {
interS = theScaV[ix].second->evaluate(m2, 3, offshell,
fout[ofhel2], fbin[ifhel2]);
diag[ix] = theScaV[ix].first->evaluate(m2, fin[ifhel1],
fbout[ofhel1], interS);
}
else if(offshell->iSpin() == PDT::Spin1) {
interV = theVecV[ix].second->evaluate(m2, 3, offshell,
fout[ofhel2], fbin[ifhel2]);
diag[ix] = -theVecV[ix].first->evaluate(m2, fin[ifhel1],
fbout[ofhel1], interV);
}
else if(offshell->iSpin() == PDT::Spin2) {
interT = theTenV[ix].second->evaluate(m2, 3, offshell,
fout[ofhel2], fbin[ifhel2]);
diag[ix] = theTenV[ix].first->evaluate(m2, fin[ifhel1],
fbout[ofhel1], interT);
}
}
else if(current.channelType == HPDiagram::sChannel) {
if(offshell->iSpin() == PDT::Spin0) {
interS = theScaV[ix].second->evaluate(m2, 1, offshell,
fout[ofhel2],fbout[ofhel1]);
diag[ix] = theScaV[ix].first->evaluate(m2, fin[ifhel1],
fbin[ifhel2], interS);
}
else if(offshell->iSpin() == PDT::Spin1) {
interV = theVecV[ix].second->evaluate(m2, 1, offshell,
fout[ofhel2],fbout[ofhel1]);
diag[ix] = theVecV[ix].first->evaluate(m2, fin[ifhel1],
fbin[ifhel2], interV);
}
else if(offshell->iSpin() == PDT::Spin2) {
interT = theTenV[ix].second->evaluate(m2, 1, offshell,
fout[ofhel2],fbout[ofhel1]);
diag[ix] = theTenV[ix].first->evaluate(m2, fin[ifhel1],
fbin[ifhel2], interT);
}
}
else {
throw MEException() << "Incorrect diagram type in matrix element "
<< fullName()
<< Exception::warning;
diag[ix] = 0.;
}
me[ix] += norm(diag[ix]);
//Compute flows
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//diagram loop
//Now add flows to me2 with appropriate colour factors
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
prodME(ifhel1, ifhel2, ofhel1, ofhel2) =
std::accumulate(flows.begin(), flows.end(), Complex(0., 0.));
}//end of first helicity loop
}
}
}
const double identfact = mePartonData()[2]->id() == mePartonData()[3]->id()
? 0.5 : 1.;
const double colfact = mePartonData()[0]->iColour() == PDT::Colour3 ?
1./9. : 1;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*identfact*colfact*me[ix];
meInfo(save);
me2 *= 0.25*identfact*colfact;
return prodME;
}
ProductionMatrixElement
MEff2ff:: ff2ffHeME(SpinorVector & fin, SpinorVector & fin2,
SpinorBarVector & fbout, SpinorBarVector & fbout2,
double & me2) const {
const HPCount ndiags = getProcessInfo().size();
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors(getColourFactors());
const Energy2 q2(scale());
vector<Complex> diag(ndiags, Complex(0.)), flows(ncf, Complex(0.));
vector<double> me(ndiags, 0.);
ScalarWaveFunction interS; VectorWaveFunction interV;
TensorWaveFunction interT;
ProductionMatrixElement prodME(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1Half,
PDT::Spin1Half);
for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) {
for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) {
for(unsigned int ofhel1 = 0; ofhel1 < 2; ++ofhel1) {
for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) {
flows = vector<Complex>(ncf, Complex(0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(current.channelType == HPDiagram::tChannel) {
if(offshell->iSpin() == PDT::Spin0) {
if(current.ordered.second) {
interS = theScaV[ix].second->evaluate(q2, 3, offshell,
fin2[ifhel2],
fbout2[ofhel2]);
diag[ix] = theScaV[ix].first->evaluate(q2, fin[ifhel1],
fbout[ofhel1], interS);
}
else {
interS = theScaV[ix].second->evaluate(q2, 3, offshell,
fin2[ifhel2],
fbout[ofhel1]);
diag[ix] = theScaV[ix].first->evaluate(q2, fin[ifhel1],
fbout2[ofhel2], interS);
}
}
else if(offshell->iSpin() == PDT::Spin1) {
if(current.ordered.second) {
interV = theVecV[ix].second->evaluate(q2, 3, offshell,
fin2[ifhel2],
fbout2[ofhel2]);
diag[ix] = theVecV[ix].first->evaluate(q2, fin[ifhel1],
fbout[ofhel1], interV);
}
else {
interV = theVecV[ix].second->evaluate(q2, 3, offshell,
fin2[ifhel2],
fbout[ofhel1]);
diag[ix] = -theVecV[ix].first->evaluate(q2, fin[ifhel1],
fbout2[ofhel2], interV);
}
}
else if(offshell->iSpin() == PDT::Spin2) {
if(current.ordered.second) {
interT = theTenV[ix].second->evaluate(q2, 3, offshell,
fin2[ifhel2],
fbout2[ofhel2]);
diag[ix] = theTenV[ix].first->evaluate(q2, fin[ifhel1],
fbout[ofhel1], interT);
}
else {
interT = theTenV[ix].second->evaluate(q2, 3, offshell,
fin2[ifhel2],
fbout[ofhel1]);
diag[ix] = theTenV[ix].first->evaluate(q2, fin[ifhel1],
fbout2[ofhel2],
interT);
}
}
}
else {
throw MEException() << "Incorrect diagram type in matrix element "
<< fullName()
<< Exception::warning;
diag[ix] = 0.;
}
me[ix] += norm(diag[ix]);
//Compute flows
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//diagram loop
//Now add flows to me2 with appropriate colour factors
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
prodME(ifhel1, ifhel2, ofhel1, ofhel2) =
std::accumulate(flows.begin(), flows.end(), Complex(0., 0.));
}
}
}
}
const double identfact = mePartonData()[2]->id() == mePartonData()[3]->id()
? 0.5 : 1.;
const double colfact = mePartonData()[0]->iColour() == PDT::Colour3 ? 1./9. : 1;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*identfact*colfact*me[ix];
meInfo(save);
me2 = 0.25*identfact*colfact*me2;
return prodME;
}
ProductionMatrixElement
MEff2ff::fbfb2fbfbHeME(SpinorBarVector & fbin, SpinorBarVector & fbin2,
SpinorVector & fout, SpinorVector & fout2,
double & me2) const {
const HPCount ndiags = getProcessInfo().size();
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors(getColourFactors());
const Energy2 q2(scale());
vector<Complex> diag(ndiags, Complex(0.)), flows(ncf, Complex(0.));
vector<double> me(ndiags, 0.);
ScalarWaveFunction interS; VectorWaveFunction interV;
TensorWaveFunction interT;
ProductionMatrixElement prodME(PDT::Spin1Half, PDT::Spin1Half, PDT::Spin1Half,
PDT::Spin1Half);
for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) {
for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) {
for(unsigned int ofhel1 = 0; ofhel1 < 2; ++ofhel1) {
for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) {
flows = vector<Complex>(ncf, Complex(0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(current.channelType == HPDiagram::tChannel) {
if(offshell->iSpin() == PDT::Spin0) {
if(current.ordered.second) {
interS = theScaV[ix].second->evaluate(q2, 3, offshell,
fout2[ofhel2],
fbin2[ifhel2]);
diag[ix] = theScaV[ix].first->evaluate(q2, fout[ofhel1],
fbin[ifhel1], interS);
}
else {
interS = theScaV[ix].second->evaluate(q2, 3, offshell,
fout[ofhel1],
fbin2[ifhel2]);
diag[ix] = -theScaV[ix].first->evaluate(q2, fout2[ofhel2],
fbin[ifhel1], interS);
}
}
else if(offshell->iSpin() == PDT::Spin1) {
if(current.ordered.second) {
interV = theVecV[ix].second->evaluate(q2, 3, offshell,
fout2[ofhel2],
fbin2[ifhel2]);
diag[ix] = theVecV[ix].first->evaluate(q2, fout[ofhel1],
fbin[ifhel1], interV);
}
else {
interV = theVecV[ix].second->evaluate(q2, 3, offshell,
fout[ofhel1],
fbin2[ifhel2]);
diag[ix] = -theVecV[ix].first->evaluate(q2, fout2[ofhel2],
fbin[ifhel1], interV);
}
}
else if(offshell->iSpin() == PDT::Spin2) {
if(current.ordered.second) {
interT = theTenV[ix].second->evaluate(q2, 3, offshell,
fout2[ofhel2],
fbin2[ifhel2]);
diag[ix] = theTenV[ix].first->evaluate(q2, fout[ofhel1],
fbin[ifhel1], interT);
}
else {
interT = theTenV[ix].second->evaluate(q2, 3, offshell,
fout[ofhel1],
fbin2[ifhel2]);
diag[ix] = -theTenV[ix].first->evaluate(q2, fout2[ofhel2],
fbin[ifhel1], interT);
}
}
}
me[ix] += norm(diag[ix]);
//Compute flows
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//diagram loop
//Now add flows to me2 with appropriate colour factors
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
prodME(ifhel1, ifhel2, ofhel1, ofhel2) =
std::accumulate(flows.begin(), flows.end(), Complex(0., 0.));
}
}
}
}
const double identfact = mePartonData()[2]->id() == mePartonData()[3]->id()
? 0.5 : 1.;
const double colfact = (mePartonData()[0]->iColour() == PDT::Colour3bar)
? 1./9. : 1;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*identfact*colfact*me[ix];
meInfo(save);
me2 *= 0.25*identfact*colfact;
return prodME;
}
ProductionMatrixElement
MEff2ff::ffb2mfmfHeME(SpinorVector & fin, SpinorBarVector & fbin,
SpinorBarVector & fbout, SpinorVector & fout,
SpinorVector & fout2, SpinorBarVector & fbout2,
double & me2) const {
//useful constants
const HPCount ndiags = numberOfDiags();
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors(getColourFactors());
const Energy2 m2(scale());
//store results
vector<Complex> diag(ndiags, Complex(0.)), flows(ncf, Complex(0.));
vector<double> me(ndiags, 0.);
//intermediate wavefunctions
ScalarWaveFunction interS; VectorWaveFunction interV;
TensorWaveFunction interT;
//ProductionMatrixElement object
ProductionMatrixElement prodME(PDT::Spin1Half, PDT::Spin1Half,
PDT::Spin1Half, PDT::Spin1Half);
for(unsigned int ifhel1 = 0; ifhel1 < 2; ++ifhel1) {
for(unsigned int ifhel2 = 0; ifhel2 < 2; ++ifhel2) {
for(unsigned int ofhel1 = 0; ofhel1 < 2; ++ofhel1) {
for(unsigned int ofhel2 = 0; ofhel2 < 2; ++ofhel2) {
flows = vector<Complex>(ncf, Complex(0.));
for(size_t ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(current.channelType == HPDiagram::tChannel) {
if(offshell->iSpin() == PDT::Spin0) {
if(current.ordered.second) {
interS = theScaV[ix].second->evaluate(m2, 3, offshell,
fout[ofhel2],
fbin[ifhel2]);
diag[ix] = theScaV[ix].first->evaluate(m2, fin[ifhel1],
fbout[ofhel1],
interS);
}
else {
interS = theScaV[ix].second->evaluate(m2, 3, offshell,
fout2[ofhel1],
fbin[ifhel2]);
diag[ix] = -theScaV[ix].first->evaluate(m2, fin[ifhel1],
fbout2[ofhel2],
interS);
}
}
else if(offshell->iSpin() == PDT::Spin1) {
if(current.ordered.second) {
interV = theVecV[ix].second->evaluate(m2, 3, offshell,
fout[ofhel2],
fbin[ifhel2]);
diag[ix] = theVecV[ix].first->evaluate(m2, fin[ifhel1],
fbout[ofhel1],
interV);
}
else {
interV = theVecV[ix].second->evaluate(m2, 3, offshell,
fout2[ofhel1],
fbin[ifhel2]);
diag[ix] = theVecV[ix].first->evaluate(m2, fin[ifhel1],
fbout2[ofhel2],
interV);
}
}
else if(offshell->iSpin() == PDT::Spin2) {
if(current.ordered.second) {
interT = theTenV[ix].second->evaluate(m2, 3, offshell,
fout[ofhel2],
fbin[ifhel2]);
diag[ix] = theTenV[ix].first->evaluate(m2, fin[ifhel1],
fbout[ofhel1],
interT);
}
else {
interT = theTenV[ix].second->evaluate(m2, 3, offshell,
fout2[ofhel1],
fbin[ifhel2]);
diag[ix] = theTenV[ix].first->evaluate(m2, fin[ifhel1],
fbout2[ofhel2],
interT);
}
}
}
else if(current.channelType == HPDiagram::sChannel) {
if(offshell->iSpin() == PDT::Spin0) {
interS = theScaV[ix].second->evaluate(m2, 1, offshell,
fout[ofhel2],fbout[ofhel1]);
diag[ix] = theScaV[ix].first->evaluate(m2, fin[ifhel1],
fbin[ifhel2], interS);
}
else if(offshell->iSpin() == PDT::Spin1) {
interV = theVecV[ix].second->evaluate(m2, 1, offshell,
fout[ofhel2],fbout[ofhel1]);
diag[ix] = theVecV[ix].first->evaluate(m2, fin[ifhel1],
fbin[ifhel2], interV);
}
else if(offshell->iSpin() == PDT::Spin2) {
interT = theTenV[ix].second->evaluate(m2, 1, offshell,
fout[ofhel2],fbout[ofhel1]);
diag[ix] = theTenV[ix].first->evaluate(m2, fin[ifhel1],
fbin[ifhel2], interT);
}
}
else {
throw MEException() << "Incorrect diagram type in matrix element "
<< fullName()
<< Exception::warning;
diag[ix] = 0.;
}
me[ix] += norm(diag[ix]);
// Compute flows
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//diagram loop
//Now add flows to me2 with appropriate colour factors
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
prodME(ifhel1, ifhel2, ofhel1, ofhel2) =
std::accumulate(flows.begin(), flows.end(), Complex(0., 0.));
}// ofhel2 loop
}
}
}
const double identfact = mePartonData()[2]->id() == mePartonData()[3]->id()
? 0.5 : 1.;
const double colfact = mePartonData()[0]->coloured() ? 1./9. : 1;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*identfact*colfact*me[ix];
meInfo(save);
me2 *= 0.25*identfact*colfact;
return prodME;
}
Selector<const ColourLines *>
MEff2ff::colourGeometries(tcDiagPtr diag) const {
static vector<ColourLines> cf(24);
//33b->11
cf[0] = ColourLines("1 2 -3");
cf[1] = ColourLines("1 -2");
//33b->18
cf[2] = ColourLines("1 2 5, -3 -5");
cf[3] = ColourLines("1 5, -5 2 -3");
//33b->33bar
cf[4] = ColourLines("1 2 -3, 4 -2 -5");
cf[5] = ColourLines("1 3 4, -2 -3 -5");
cf[6] = ColourLines("1 4, -3 -5");
cf[7] = ColourLines("1 -2, 4 -5");
//33b->88
cf[8] = ColourLines("1 4, -4 2 5, -5 -3");
cf[9] = ColourLines("1 5, -5 2 4, -4 -3");
cf[10] = ColourLines("1 3 4, -5 -3 -2, -4 5");
cf[11] = ColourLines("1 3 5, -4 -3 -2, -5 4");
//33->33
cf[12] = ColourLines("1 2 5, 3 -2 4");
cf[13] = ColourLines("1 2 4, 3 -2 5");
cf[14] = ColourLines("1 4, 3 5");
cf[15] = ColourLines("1 5, 3 4");
//3b->3b
cf[16] = ColourLines("-1 -2 -5, -3 2 -4");
cf[17] = ColourLines("-1 -2 -4, -3 2 -5");
cf[18] = ColourLines("-1 -4, -3 -5");
cf[19] = ColourLines("-1 -5, -3 -4");
//33b->81
cf[20]= ColourLines("1 4, -4 2 -3");
cf[21]= ColourLines("-3 -4, 1 2 4");
//11->33bar
cf[22] = ColourLines("4 -5");
//11->11
cf[23] = ColourLines("");
HPDiagram current = getProcessInfo()[abs(diag->id()) - 1];
//select appropriate set of diagrams
PDT::Colour inac(mePartonData()[0]->iColour());
PDT::Colour inbc(mePartonData()[1]->iColour());
PDT::Colour outac(mePartonData()[2]->iColour());
PDT::Colour outbc(mePartonData()[3]->iColour());
vector<ColourLines>::size_type cl(0);
if(inac == PDT::Colour3 && inbc == PDT::Colour3) {
if(current.intermediate->iColour() == PDT::Colour8)
cl = current.ordered.second ? 12 : 13;
else
cl = current.ordered.second ? 14 : 15;
}
else if(inac == PDT::Colour3bar && inbc == PDT::Colour3bar) {
if(current.intermediate->iColour() == PDT::Colour8)
cl = current.ordered.second ? 16 : 17;
else
cl = current.ordered.second ? 18 : 19;
}
else if(inac == PDT::Colour0 && inbc == PDT::Colour0)
cl = (outac == PDT::Colour0) ? 23 : 22;
else {
if(outac == PDT::Colour0 || outbc == PDT::Colour0 ) {
if(current.channelType == HPDiagram::tChannel) {
if(outac == outbc)
cl = 0;
else if( outbc == PDT::Colour8 )
cl = current.ordered.second ? 2 : 3;
else
cl = current.ordered.second ? 20 : 21;
}
else
cl = 1;
}
else if(outbc == PDT::Colour3bar) {
if(current.channelType == HPDiagram::tChannel)
cl = (current.intermediate->iColour() == PDT::Colour8) ? 4 : 6;
else
cl = (current.intermediate->iColour() == PDT::Colour8) ? 5 : 7;
}
else {
if(current.channelType == HPDiagram::tChannel)
cl = current.ordered.second ? 8 : 9;
else
cl = 10 + rnd2(0.5, 0.5);
}
}
Selector<const ColourLines *> sel;
sel.insert(1., &cf[cl]);
return sel;
}
void MEff2ff::constructVertex(tSubProPtr subp) {
// Hard proces external particles
ParticleVector hardpro(4);
hardpro[0] = subp->incoming().first;
hardpro[1] = subp->incoming().second;
hardpro[2] = subp->outgoing()[0];
hardpro[3] = subp->outgoing()[1];
//ensure particle ordering is the same as it was when
//the diagrams were created
if( hardpro[0]->id() != getIncoming().first )
swap(hardpro[0], hardpro[1]);
if( hardpro[2]->id() != getOutgoing().first )
swap(hardpro[2], hardpro[3]);
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = hardpro[i]->dataPtr();
momenta[i] = hardpro[i]->momentum();
}
rescaleMomenta(momenta, data);
double dummy(0.);
//pick which process we are doing
if( hardpro[0]->id() > 0) {
//common spinors
SpinorVector spA;
SpinorBarVector spbB;
SpinorWaveFunction(spA, hardpro[0], incoming, false, true);
SpinorBarWaveFunction(spbB, hardpro[2], outgoing,true, true);
//ME spinors
SpinorWaveFunction sp1r(rescaledMomenta()[0], data[0], incoming);
SpinorBarWaveFunction spb2r(rescaledMomenta()[2], data[2], outgoing);
//majorana
if(!hardpro[2]->dataPtr()->CC() || hardpro[2]->id() == 1000024 ||
hardpro[2]->id() == 1000037) {
SpinorVector spB, spC;
SpinorBarVector spbA, spbC;
SpinorBarWaveFunction(spbA, hardpro[1], incoming, false, true);
SpinorWaveFunction(spB, hardpro[3], outgoing, true, true);
//ME spinors
SpinorBarWaveFunction spb1r(rescaledMomenta()[1], data[1], incoming);
SpinorWaveFunction sp2r(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
sp1r.reset(ihel);
spA[ihel] = sp1r;
spb1r.reset(ihel);
spbA[ihel] = spb1r;
spb2r.reset(ihel);
spbB[ihel] = spb2r;
sp2r.reset(ihel);
spB[ihel] = sp2r;
//extra spinors
spC.push_back(SpinorWaveFunction(-spbB[ihel].getMomentum(),
spbB[ihel].getParticle(),
spbB[ihel].wave().bar().conjugate(),
spbB[ihel].direction()));
spbC.push_back(SpinorBarWaveFunction(-spB[ihel].getMomentum(),
spB[ihel].getParticle(),
spB[ihel].wave().bar().conjugate(),
spB[ihel].direction()));
}
ProductionMatrixElement prodME = ffb2mfmfHeME(spA, spbA, spbB, spB, spC,
spbC, dummy);
HardVertexPtr hardvertex = new_ptr(HardVertex());
hardvertex->ME(prodME);
for(ParticleVector::size_type i = 0; i < 4; ++i) {
dynamic_ptr_cast<SpinfoPtr>(hardpro[i]->spinInfo())->
setProductionVertex(hardvertex);
}
}
//ffbar->ffbar
else if( hardpro[1]->id() < 0 ) {
SpinorVector spB;
SpinorBarVector spbA;
SpinorBarWaveFunction(spbA, hardpro[1], incoming, false, true);
SpinorWaveFunction(spB, hardpro[3], outgoing, true, true);
//ME spinors
SpinorBarWaveFunction spb1r(rescaledMomenta()[1], data[1], incoming);
SpinorWaveFunction sp2r(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
sp1r.reset(ihel);
spA[ihel] = sp1r;
spb1r.reset(ihel);
spbA[ihel] = spb1r;
spb2r.reset(ihel);
spbB[ihel] = spb2r;
sp2r.reset(ihel);
spB[ihel] = sp2r;
}
ProductionMatrixElement prodME = ffb2ffbHeME(spA, spbA, spbB, spB,
dummy);
HardVertexPtr hardvertex = new_ptr(HardVertex());
hardvertex->ME(prodME);
for(ParticleVector::size_type i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(hardpro[i]->spinInfo())->
setProductionVertex(hardvertex);
}
//ff2ff
else {
SpinorVector spB;
SpinorBarVector spbA;
SpinorWaveFunction(spB,hardpro[1],incoming, false, true);
SpinorBarWaveFunction(spbA, hardpro[3], outgoing, true, true);
SpinorWaveFunction sp2r(rescaledMomenta()[1], data[1], incoming);
SpinorBarWaveFunction spb1r(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
sp1r.reset(ihel);
spA[ihel] = sp1r;
sp2r.reset(ihel);
spB[ihel] = sp2r;
spb2r.reset(ihel);
spbB[ihel] = spb2r;
spb1r.reset(ihel);
spbA[ihel] = spb1r;
}
ProductionMatrixElement prodME = ff2ffHeME(spA, spB, spbB, spbA,
dummy);
HardVertexPtr hardvertex = new_ptr(HardVertex());
hardvertex->ME(prodME);
for(ParticleVector::size_type i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(hardpro[i]->spinInfo())->
setProductionVertex(hardvertex);
}
}
//fbarfbar->fbarfbar
else {
SpinorVector spA, spB;
SpinorBarVector spbA, spbB;
SpinorBarWaveFunction(spbA,hardpro[0],incoming, false, true);
SpinorBarWaveFunction(spbB,hardpro[1],incoming, false, true);
SpinorWaveFunction(spA, hardpro[2], outgoing, true, true);
SpinorWaveFunction(spB, hardpro[3], outgoing, true, true);
//ME spinors
SpinorBarWaveFunction spb1r(rescaledMomenta()[0], data[0], incoming);
SpinorBarWaveFunction spb2r(rescaledMomenta()[1], data[1], incoming);
SpinorWaveFunction sp1r(rescaledMomenta()[2], data[2], outgoing);
SpinorWaveFunction sp2r(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
spb1r.reset(ihel);
spbA[ihel] = spb1r;
spb2r.reset(ihel);
spbB[ihel] = spb2r;
sp1r.reset(ihel);
spA[ihel] = sp1r;
sp2r.reset(ihel);
spB[ihel] = sp2r;
}
ProductionMatrixElement prodME = fbfb2fbfbHeME(spbA, spbB, spA, spB,
dummy);
HardVertexPtr hardvertex = new_ptr(HardVertex());
hardvertex->ME(prodME);
for(ParticleVector::size_type i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(hardpro[i]->spinInfo())->
setProductionVertex(hardvertex);
}
#ifndef NDEBUG
if( debugME() ) debug(dummy);
#endif
}
void MEff2ff::persistentOutput(PersistentOStream & os) const {
os << theScaV << theVecV << theTenV;
}
void MEff2ff::persistentInput(PersistentIStream & is, int) {
is >> theScaV >> theVecV >> theTenV;
}
ClassDescription<MEff2ff> MEff2ff::initMEff2ff;
// Definition of the static class description member.
void MEff2ff::Init() {
static ClassDocumentation<MEff2ff> documentation
("This is the implementation of the matrix element for fermion-"
"antifermion -> fermion-antifermion.");
}
void MEff2ff::debug(double me2) const {
if( !generator()->logfile().is_open() ) return;
long id1 = mePartonData()[0]->id();
long id2 = mePartonData()[1]->id();
long id3 = mePartonData()[2]->id();
long id4 = mePartonData()[3]->id();
long aid1 = abs(mePartonData()[0]->id());
long aid2 = abs(mePartonData()[1]->id());
long aid3 = abs(mePartonData()[2]->id());
long aid4 = abs(mePartonData()[3]->id());
if( (aid1 != 1 && aid1 != 2) || (aid2 != 1 && aid2 != 2) ) return;
double analytic(0.);
if( id3 == id4 && id3 == 1000021 ) {
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
int Nc = sm->Nc();
double Cf = (sqr(Nc) - 1.)/2./Nc;
Energy2 mgo2 = meMomenta()[3].m2();
long squark = (aid1 == 1) ? 1000001 : 1000002;
Energy2 muL2 = sqr(getParticleData(squark)->mass());
Energy2 deltaL = muL2 - mgo2;
Energy2 muR2 = sqr(getParticleData(squark + 1000000)->mass());
Energy2 deltaR = muR2 - mgo2;
Energy2 s(sHat());
Energy2 m3s = meMomenta()[2].m2();
Energy2 m4s = meMomenta()[3].m2();
Energy4 spt2 = uHat()*tHat() - m3s*m4s;
Energy2 t3(tHat() - m3s), u4(uHat() - m4s);
double Cl = 2.*spt2*( (u4*u4 - deltaL*deltaL) + (t3*t3 - deltaL*deltaL)
- (s*s/Nc/Nc) )/s/s/(u4 - deltaL)/(t3 - deltaL);
Cl += deltaL*deltaL*( (1./sqr(t3 - deltaL)) + (1./sqr(u4 - deltaL))
- ( sqr( (1./(t3 - deltaL)) -
(1./(u4 - deltaL)) )/Nc/Nc ) );
double Cr = 2.*spt2*( (u4*u4 - deltaR*deltaR) + (t3*t3 - deltaR*deltaR)
- (s*s/Nc/Nc) )/s/s/(u4 - deltaR)/(t3 - deltaR);
Cr += deltaR*deltaR*( (1./sqr(t3 - deltaR)) + (1./sqr(u4 - deltaR))
- ( sqr( (1./(t3 - deltaR))
- (1./(u4 - deltaR)) )/Nc/Nc ) );
analytic = gs4*Cf*(Cl + Cr)/4.;
}
else if( (aid3 == 5100001 || aid3 == 5100002 ||
aid3 == 6100001 || aid3 == 6100002) &&
(aid4 == 5100001 || aid4 == 5100002 ||
aid4 == 6100001 || aid4 == 6100002) ) {
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
Energy2 s(sHat());
Energy2 mf2 = meMomenta()[2].m2();
Energy2 t3(tHat() - mf2), u4(uHat() - mf2);
Energy4 s2(sqr(s)), t3s(sqr(t3)), u4s(sqr(u4));
bool iflav = (aid2 - aid1 == 0);
int alpha(aid3/1000000), beta(aid4/1000000);
bool oflav = ((aid3 - aid1) % 10 == 0);
if( alpha != beta ) {
if( ( id1 > 0 && id2 > 0) ||
( id1 < 0 && id2 < 0) ) {
if( iflav )
analytic = gs4*( mf2*(2.*s2*s/t3s/u4s - 4.*s/t3/u4)
+ 2.*sqr(s2)/t3s/u4s - 8.*s2/t3/u4 + 5. )/9.;
else
analytic = gs4*( -2.*mf2*(1./t3 + u4/t3s) + 0.5 + 2.*u4s/t3s)/9.;
}
else
analytic = gs4*( 2.*mf2*(1./t3 + u4/t3s) + 5./2. + 4.*u4/t3
+ 2.*u4s/t3s)/9.;
}
else {
if( ( id1 > 0 && id2 > 0) ||
( id1 < 0 && id2 < 0) ) {
if( iflav ) {
analytic = gs4*( mf2*(6.*t3/u4s + 6.*u4/t3s - s/t3/u4)
+ 2.*(3.*t3s/u4s + 3.*u4s/t3s
+ 4.*s2/t3/u4 - 5.) )/27.;
}
else
analytic = 2.*gs4*( -mf2*s/t3s + 0.25 + s2/t3s )/9.;
}
else {
if( iflav ) {
if( oflav )
analytic = gs4*( 2.*mf2*(4./s + s/t3s - 1./t3) + 23./6.+ 2.*s2/t3s
+ 8.*s/3./t3 + 6.*t3/s + 8.*t3s/s2 )/9.;
else
analytic = 4.*gs4*( 2.*mf2/s + (t3s + u4s)/s2)/9.;
}
else
analytic = gs4*(4.*mf2*s/t3s + 5. + 4.*s2/t3s + 8.*s/t3 )/18.;
}
}
if( id3 == id4 ) analytic /= 2.;
}
else return;
double diff = abs(analytic - me2);
if( diff > 1e-4 ) {
generator()->log()
<< mePartonData()[0]->PDGName() << ","
<< mePartonData()[1]->PDGName() << "->"
<< mePartonData()[2]->PDGName() << ","
<< mePartonData()[3]->PDGName() << " difference: "
<< setprecision(10) << diff << " ratio: " << analytic/me2
<< '\n';
}
}
diff --git a/MatrixElement/General/MEff2ff.fh b/MatrixElement/General/MEff2ff.fh
deleted file mode 100644
--- a/MatrixElement/General/MEff2ff.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEff2ff class.
-//
-#ifndef HERWIG_MEff2ff_FH
-#define HERWIG_MEff2ff_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEff2ff;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEff2ff,MEff2ffPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEff2ff.h b/MatrixElement/General/MEff2ff.h
--- a/MatrixElement/General/MEff2ff.h
+++ b/MatrixElement/General/MEff2ff.h
@@ -1,281 +1,278 @@
// -*- C++ -*-
//
// MEff2ff.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_MEff2ff_H
#define HERWIG_MEff2ff_H
//
// This is the declaration of the MEff2ff class.
//
#include "GeneralHardME.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h"
-#include "MEff2ff.fh"
namespace Herwig {
using namespace ThePEG;
using Helicity::SpinorWaveFunction;
using Helicity::SpinorBarWaveFunction;
/**
* This is the implementation of the \f$ 2\to 2\f$ matrix element for
* a \f$ \Psi \Psi \to \Psi \Psi\f$ process. It inherits from
* GeneralHardME and implements the appropriate virtual functions.
*
* @see \ref MEff2ffInterfaces "The Interfaces"
* defined for MEff2ff.
* @see GeneralHardME
*/
class MEff2ff: public GeneralHardME {
public:
/** Vector of SpinorWaveFunctions. */
typedef vector<SpinorWaveFunction> SpinorVector;
/** Vector of SpinorBarWaveFunctions. */
typedef vector<SpinorBarWaveFunction> SpinorBarVector;
public:
/**
* The default constructor.
*/
- inline MEff2ff();
+ inline MEff2ff() : theScaV(0), theVecV(0), theTenV(0) {}
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
private:
/** @name Functions to compute the ProductionMatrixElement. */
//@{
/**
* Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$
* @param fin Spinors for first incoming particle
* @param fbin SpinorBar Wavefunctions for second incoming particle
* @param fbout SpinorBar Wavefunctions for outgoing particle
* @param fout Spinors for first outgoing particle
* @param me2 colour averaged, spin summed ME
* @return ProductionMatrixElement containing results of
* helicity calculations
*/
ProductionMatrixElement
ffb2ffbHeME(SpinorVector & fin, SpinorBarVector & fbin,
SpinorBarVector & fbout, SpinorVector & fout,
double & me2) const;
/**
* Compute the matrix element for \f$\Psi\Psi\to\Psi\Psi\f$
* @param fin Spinors for first incoming particle
* @param fin2 Spinors for second incoming particle
* @param fbout SpinorBar for first outgoing particle
* @param fbout2 SpinorBar Wavefunctions for outgoing particle
* @param me2 colour averaged, spin summed ME
* @return ProductionMatrixElement containing results of
* helicity calculations
*/
ProductionMatrixElement
ff2ffHeME(SpinorVector & fin, SpinorVector & fin2,
SpinorBarVector & fbout, SpinorBarVector & fbout2,
double & me2) const;
/**
* Compute the matrix element for
* \f$\bar{\Psi}\bar{\Psi}\to\bar{\Psi}\bar{\Psi}\f$
* @param fbin SpinorBars for first incoming particle
* @param fbin2 SpinorBars for second incoming particle
* @param fout Spinors for first outgoing particle
* @param fout2 Spinors Wavefunctions for outgoing particle
* @param me2 colour averaged, spin summed ME
* @return ProductionMatrixElement containing results of
* helicity calculations
*/
ProductionMatrixElement
fbfb2fbfbHeME(SpinorBarVector & fbin, SpinorBarVector & fbin2,
SpinorVector & fout, SpinorVector & fout2,
double & me2) const;
/**
* Compute the matrix element for \f$\Psi\bar{\Psi}\to\lambda\lambda\f$
* @param fin Spinors for first incoming particle
* @param fbin SpinorBar Wavefunctions for second incoming particle
* @param fbout SpinorBar Wavefunctions for first outgoing particle
* @param fout Spinors for second outgoing particle
* @param fout2 Spinor Wavefunctions for first outgoing particle
* @param fbout2 SpinorBar Wavefunctions for second outgoing particle
* @param me2 colour averaged, spin summed ME
* @return ProductionMatrixElement containing results of
* helicity calculations
*/
ProductionMatrixElement
ffb2mfmfHeME(SpinorVector & fin, SpinorBarVector & fbin,
SpinorBarVector & fbout, SpinorVector & fout,
SpinorVector & fout2, SpinorBarVector & fbout2,
double & me2) const;
//@}
/**
* Construct the vertex information for the spin correlations
* @param sub Pointer to the relevent SubProcess
*/
virtual void constructVertex(tSubProPtr sub);
protected:
/**
* A debugging function to test the value of me2 against an
* analytic function.
* @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$
*/
virtual void debug(double me2) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEff2ff> initMEff2ff;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEff2ff & operator=(const MEff2ff &);
private:
/**
* Store the vector of FFSVertex pairs
*/
vector<pair<AbstractFFSVertexPtr, AbstractFFSVertexPtr> > theScaV;
/**
* Store the vector of FFVVertex pairs
*/
vector<pair<AbstractFFVVertexPtr, AbstractFFVVertexPtr> > theVecV;
/**
* Store the vector of FFTVertex pairs
*/
vector<pair<AbstractFFTVertexPtr, AbstractFFTVertexPtr> > theTenV;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEff2ff. */
template <>
struct BaseClassTrait<Herwig::MEff2ff,1> {
/** Typedef of the first base class of MEff2ff. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEff2ff class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEff2ff>
: public ClassTraitsBase<Herwig::MEff2ff> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEff2ff"; }
};
/** @endcond */
}
-#include "MEff2ff.icc"
-
#endif /* HERWIG_MEff2ff_H */
diff --git a/MatrixElement/General/MEff2ff.icc b/MatrixElement/General/MEff2ff.icc
deleted file mode 100644
--- a/MatrixElement/General/MEff2ff.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// MEff2ff.icc 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 inlined member functions of
-// the MEff2ff class.
-//
-
-namespace Herwig {
-
-inline MEff2ff::MEff2ff() : theScaV(0), theVecV(0), theTenV(0) {}
-
-inline IBPtr MEff2ff::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEff2ff::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/General/MEff2ss.cc b/MatrixElement/General/MEff2ss.cc
--- a/MatrixElement/General/MEff2ss.cc
+++ b/MatrixElement/General/MEff2ss.cc
@@ -1,361 +1,361 @@
// -*- C++ -*-
//
// MEff2ss.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 MEff2ss class.
//
#include "MEff2ss.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/PDT/EnumParticles.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include <numeric>
using namespace Herwig;
using ThePEG::Helicity::VectorWaveFunction;
using ThePEG::Helicity::TensorWaveFunction;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
void MEff2ss::doinit() throw(InitException) {
GeneralHardME::doinit();
HPCount ndiags(numberOfDiags());
theFerm.resize(ndiags);
theVec.resize(ndiags);
theTen.resize(ndiags);
for(HPCount i = 0; i < ndiags; ++i) {
HPDiagram current = getProcessInfo()[i];
if(current.channelType == HPDiagram::tChannel) {
if(current.intermediate->iSpin() == PDT::Spin1Half)
theFerm[i] =
make_pair(dynamic_ptr_cast<AbstractFFSVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractFFSVertexPtr>(current.vertices.second));
}
else if(current.channelType == HPDiagram::sChannel) {
if(current.intermediate->iSpin() == PDT::Spin1)
theVec[i] =
make_pair(dynamic_ptr_cast<AbstractFFVVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractVSSVertexPtr>(current.vertices.second));
if(current.intermediate->iSpin() == PDT::Spin2)
theTen[i] =
make_pair(dynamic_ptr_cast<AbstractFFTVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractSSTVertexPtr>(current.vertices.second));
}
else
throw InitException() << "MEFF2ss:doinit() - Cannot find correct "
<< "channel from diagram. Vertex not cast! "
<< Exception::runerror;
}
}
double MEff2ss::me2() const {
//first setup wavefunctions for external particles
SpinorVector sp(2);
SpinorBarVector sbar(2);
for( unsigned int i = 0; i < 2; ++i ) {
sp[i] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], i,
incoming);
sbar[i] = SpinorBarWaveFunction(rescaledMomenta()[1], mePartonData()[1], i,
incoming);
}
ScalarWaveFunction sca1(rescaledMomenta()[2], mePartonData()[2],
Complex(1.), outgoing);
ScalarWaveFunction sca2(rescaledMomenta()[3], mePartonData()[3],
Complex(1.), outgoing);
double full_me(0.);
ff2ssME(sp, sbar, sca1, sca2, full_me);
#ifndef NDEBUG
if( debugME() ) debug(full_me);
#endif
return full_me;
}
ProductionMatrixElement
MEff2ss::ff2ssME(const SpinorVector & sp, const SpinorBarVector & sbar,
const ScalarWaveFunction & sca1,
const ScalarWaveFunction & sca2, double & me2) const {
//Define factors
const Energy2 q2(scale());
const vector<vector<double> > cfactors = getColourFactors();
const HPCount ndiags = numberOfDiags();
const size_t ncf = numberOfFlows();
vector<double> me(ndiags, 0.);
vector<Complex> diag(ndiags, Complex(0.)), flows(ncf, Complex(0.));
ScalarWaveFunction interS; VectorWaveFunction interV;
SpinorBarWaveFunction interFB; TensorWaveFunction interT;
ProductionMatrixElement pme(PDT::Spin1Half, PDT::Spin1Half,
PDT::Spin0, PDT::Spin0);
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 2; ++if2) {
flows = vector<Complex>(ncf, Complex(0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr internal(current.intermediate);
if(current.channelType == HPDiagram::tChannel &&
internal->iSpin() == PDT::Spin1Half) {
if(current.ordered.second) {
interFB = theFerm[ix].second->evaluate(q2, 3, internal, sbar[if2],
sca2);
diag[ix] = theFerm[ix].first->evaluate(q2, sp[if1], interFB, sca1);
}
else {
interFB = theFerm[ix].second->evaluate(q2, 3, internal, sbar[if2],
sca1);
diag[ix] = theFerm[ix].first->evaluate(q2, sp[if1], interFB, sca2);
}
}
else if(current.channelType == HPDiagram::sChannel) {
if(internal->iSpin() == PDT::Spin1) {
interV = theVec[ix].first->evaluate(q2, 1, internal, sp[if1],
sbar[if2]);
diag[ix] = theVec[ix].second->evaluate(q2, interV, sca2, sca1);
}
else if(internal->iSpin() == PDT::Spin2) {
interT = theTen[ix].first->evaluate(q2, 1, internal, sp[if1],
sbar[if2]);
diag[ix] = theTen[ix].second ->evaluate(q2, sca2, sca1, interT);
}
else
diag[ix] = 0.;
}
me[ix] += norm(diag[ix]);
//colourflows
for(unsigned int iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//end of diag loop
//set the appropriate element of the ProductionMatrixElement
pme(if1, if2, 0, 0) =
std::accumulate(flows.begin(), flows.end(), Complex(0.0,0.0));
for(unsigned int ii = 0; ii < ncf; ++ii)
for(unsigned int ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
}
}
const double identFact = mePartonData()[2]->id() == mePartonData()[3]->id()
? 0.5 : 1;
int cola = mePartonData()[0]->iColour();
const double colourAvg = ( abs(cola) == 3 ) ? 1./9. : 1.;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*identFact*colourAvg*me[ix];
meInfo(save);
me2 *= 0.25*identFact*colourAvg;
return pme;
}
Selector<const ColourLines *>
MEff2ss::colourGeometries(tcDiagPtr diag) const {
static vector<ColourLines> cf(16);
//33b->33b
cf[0] = ColourLines("1 2 -3, 4 -2 -5");
cf[1] = ColourLines("1 3 4, -2 -3 -5");
cf[2] = ColourLines("1 4, -3 -5");
cf[3] = ColourLines("1 -2, 4 -5");
//33->33
cf[4] = ColourLines("1 2 5, 3 -2 4");
cf[5] = ColourLines("1 2 4, 3 -2 5");
cf[6] = ColourLines("1 4, 3 5");
cf[7] = ColourLines("1 5, 3 4");
//3b3b->3b3b
cf[8] = ColourLines("-1 -2 -5, -3 2 -4");
cf[9] = ColourLines("-1 -2 -4, -3 2 -5");
cf[10] = ColourLines("-1 -4, -3 -5");
cf[11] = ColourLines("-1 -5, -3 -4");
//33b->11
cf[12] = ColourLines("1 2 -3");
cf[13] = ColourLines("1 -2");
//11->11
cf[14] = ColourLines("");
//11->33b
cf[15] = ColourLines("4 -5");
HPDiagram current = getProcessInfo()[abs(diag->id()) - 1];
vector<ColourLines>::size_type cl(0);
PDT::Colour inac(mePartonData()[0]->iColour());
PDT::Colour inbc(mePartonData()[1]->iColour());
PDT::Colour outac(mePartonData()[2]->iColour());
if(inac == PDT::Colour0 && inbc == PDT::Colour0) {
cl = outac == PDT::Colour0 ? 14 : 15;
}
else if(inac == PDT::Colour3 && inbc == PDT::Colour3) {
if(current.intermediate->iColour() == PDT::Colour8)
cl = current.ordered.second ? 4 : 5;
else
cl = current.ordered.second ? 6 : 7;
}
else if(inac == PDT::Colour3bar && inbc == PDT::Colour3bar) {
if(current.intermediate->iColour() == PDT::Colour8)
cl = current.ordered.second ? 8 : 9;
else
cl = current.ordered.second ? 10 : 11 ;
}
else {
if(outac == PDT::Colour3) {
if(current.intermediate->iColour() == PDT::Colour8)
cl = current.channelType == HPDiagram::tChannel ? 0 : 1;
else
cl = current.channelType == HPDiagram::tChannel ? 2 : 3;
}
else
cl = current.channelType == HPDiagram::tChannel ? 12 : 13;
}
Selector<const ColourLines *> sel;
sel.insert(1., &cf[cl]);
return sel;
}
void MEff2ss::persistentOutput(PersistentOStream & os) const {
os << theFerm << theVec << theTen;
}
void MEff2ss::persistentInput(PersistentIStream & is, int) {
is >> theFerm >> theVec >> theTen;
}
ClassDescription<MEff2ss> MEff2ss::initMEff2ss;
// Definition of the static class description member.
void MEff2ss::Init() {
static ClassDocumentation<MEff2ss> documentation
("MEff2ss implements the ME calculation of the fermion-antifermion "
"to scalar-scalar hard process.");
}
void MEff2ss::constructVertex(tSubProPtr sub) {
//get particles
ParticleVector ext(4);
ext[0] = sub->incoming().first;
ext[1] = sub->incoming().second;
ext[2] = sub->outgoing()[0];
ext[3] = sub->outgoing()[1];
if( ext[0]->id() != mePartonData()[0]->id() ) swap(ext[0], ext[1]);
if( ext[2]->id() != mePartonData()[2]->id() ) swap(ext[2], ext[3]);
//First calculate wave functions with off-shell momenta
//to calculate correct spin information
SpinorVector sp;
SpinorWaveFunction(sp, ext[0], incoming, false, true);
SpinorBarVector sbar;
SpinorBarWaveFunction(sbar, ext[1], incoming, false, true);
ScalarWaveFunction sca1(ext[2], outgoing, true, true);
ScalarWaveFunction sca2(ext[3], outgoing, true, true);
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = ext[i]->dataPtr();
momenta[i] = ext[i]->momentum();
}
rescaleMomenta(momenta, data);
SpinorWaveFunction spr(rescaledMomenta()[0], data[0], incoming);
SpinorBarWaveFunction sbr(rescaledMomenta()[1], data[1],incoming);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
spr.reset(ihel);
sp[ihel] = spr;
sbr.reset(ihel);
sbar[ihel] = sbr;
}
sca1 = ScalarWaveFunction(rescaledMomenta()[2], data[2], outgoing);
sca2 = ScalarWaveFunction(rescaledMomenta()[3], data[3], outgoing);
double dummy(0.);
ProductionMatrixElement pme = ff2ssME(sp, sbar, sca1, sca2, dummy);
#ifndef NDEBUG
if( debugME() ) debug(dummy);
#endif
HardVertexPtr hv = new_ptr(HardVertex());
hv->ME(pme);
for(unsigned int i = 0; i < 4; ++i )
dynamic_ptr_cast<SpinfoPtr>(ext[i]->spinInfo())->setProductionVertex(hv);
}
void MEff2ss::debug(double me2) const {
if( !generator()->logfile().is_open() ) return;
long id1 = mePartonData()[0]->id();
long id2 = mePartonData()[1]->id();
long id3 = mePartonData()[2]->id();
long id4 = mePartonData()[3]->id();
if( (abs(id1) != 1 && abs(id1) != 2) || (abs(id2) != 1 && abs(id2) != 2) ||
( abs(id3) != 1000001 && abs(id3) != 1000002 &&
abs(id3) != 2000001 && abs(id3) != 2000002 ) ||
( abs(id4) != 1000001 && abs(id4) != 1000002 &&
abs(id4) != 2000001 && abs(id4) != 2000002 ) ) return;
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
int Nc = sm->Nc();
double Cf = (sqr(Nc) - 1)/2./Nc;
Energy2 s(sHat());
Energy2 mgos = sqr( getParticleData(ParticleID::SUSY_g)->mass());
Energy2 m3s = sqr(mePartonData()[2]->mass());
Energy2 m4s = sqr(mePartonData()[3]->mass());
Energy4 spt2 = uHat()*tHat() - m3s*m4s;
Energy2 tgl(tHat() - mgos), ugl(uHat() - mgos);
unsigned int alpha = abs(id3)/1000000;
unsigned int beta = abs(id4)/1000000;
bool iflav = ( abs(id1) == abs(id2) );
unsigned int oflav = ( abs(id3) - abs(id1) ) % 10;
double analytic(0.);
if( alpha != beta ) {
if( ( id1 > 0 && id2 > 0) ||
( id1 < 0 && id2 < 0) ) {
analytic = spt2/sqr(tgl);
if( iflav ) analytic += spt2/sqr(ugl);
}
else {
analytic = s*mgos/sqr(tgl);
}
}
else {
if( oflav != 0 ) {
analytic = 2.*spt2/sqr(s);
}
else if( ( id1 > 0 && id2 > 0) ||
( id1 < 0 && id2 < 0) ) {
analytic = s*mgos/sqr(tgl);
if( iflav ) {
analytic += s*mgos/sqr(ugl) - 2.*s*mgos/Nc/tgl/ugl;
}
analytic /= ( iflav ? 2. : 1.);
}
else {
analytic = spt2/sqr(tgl);
if( iflav ) {
analytic += 2.*spt2/sqr(s) - 2.*spt2/Nc/s/tgl;
}
}
}
analytic *= gs4*Cf/2./Nc;
double diff = abs(analytic - me2);
if( diff > 1e-4 ) {
generator()->log()
<< mePartonData()[0]->PDGName() << ","
<< mePartonData()[1]->PDGName() << "->"
<< mePartonData()[2]->PDGName() << ","
<< mePartonData()[3]->PDGName() << " difference: "
<< setprecision(10) << diff << " ratio: " << analytic/me2
<< '\n';
}
}
diff --git a/MatrixElement/General/MEff2ss.fh b/MatrixElement/General/MEff2ss.fh
deleted file mode 100644
--- a/MatrixElement/General/MEff2ss.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEff2ss class.
-//
-#ifndef HERWIG_MEff2ss_FH
-#define HERWIG_MEff2ss_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEff2ss;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEff2ss,MEff2ssPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEff2ss.h b/MatrixElement/General/MEff2ss.h
--- a/MatrixElement/General/MEff2ss.h
+++ b/MatrixElement/General/MEff2ss.h
@@ -1,235 +1,232 @@
// -*- C++ -*-
//
// MEff2ss.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_MEff2ss_H
#define HERWIG_MEff2ss_H
//
// This is the declaration of the MEff2ss class.
//
#include "GeneralHardME.h"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
-#include "ProductionMatrixElement.h"
-#include "MEff2ss.fh"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
using ThePEG::Helicity::SpinorWaveFunction;
using ThePEG::Helicity::SpinorBarWaveFunction;
using ThePEG::Helicity::ScalarWaveFunction;
/**
* The MEff2ss class is designed to implement the matrix element for a
* fermion-antifermion to scalar-scalar hard process. It inherits from
* GeneralHardME and implements the appropriate virtual functions for this
* specific spin combination.
*
* @see \ref MEff2ssInterfaces "The interfaces"
* defined for MEff2ss.
* @see GeneralHardME
*/
class MEff2ss: public GeneralHardME {
public:
/** Vector of SpinorWaveFunctions objects */
typedef vector<SpinorWaveFunction> SpinorVector;
/** Vector of SpinorBarWaveFunction objects. */
typedef vector<SpinorBarWaveFunction> SpinorBarVector;
public:
/**
* The default constructor.
*/
- inline MEff2ss();
+ inline MEff2ss() : theFerm(0), theVec(0), theTen(0) {}
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
/**
* Construct the vertex information for the spin correlations
* @param sub Pointer to the relevent SubProcess
*/
virtual void constructVertex(tSubProPtr sub);
protected:
/**
* A debugging function to test the value of me2 against an
* analytic function.
* @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$
*/
virtual void debug(double me2) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEff2ss> initMEff2ss;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEff2ss & operator=(const MEff2ss &);
private:
/**
* Calculate the matrix element
* @param sp A vector of SpinorWaveFunction objects
* @param sbar A vector of SpinorBarWaveFunction objects
* @param sca1 A ScalarWaveFunction for an outgoing scalar
* @param sca2 A ScalarWaveFunction for the other outgoing scalar
* @param me2 The spin averaged matrix element
*/
ProductionMatrixElement ff2ssME(const SpinorVector & sp,
const SpinorBarVector & sbar,
const ScalarWaveFunction & sca1,
const ScalarWaveFunction & sca2,
double & me2) const;
private:
/**
* Storage for dynamically cast vertices for a diagram with intermediate
* fermion
*/
vector<pair<AbstractFFSVertexPtr, AbstractFFSVertexPtr> > theFerm;
/**
* Storage for dynamically cast vertices for a diagram with intermediate
* vector
*/
vector<pair<AbstractFFVVertexPtr, AbstractVSSVertexPtr> > theVec;
/**
* Storage for dynamically cast vertices for a diagram with intermediate
* tensor
*/
vector<pair<AbstractFFTVertexPtr, AbstractSSTVertexPtr> > theTen;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEff2ss. */
template <>
struct BaseClassTrait<Herwig::MEff2ss,1> {
/** Typedef of the first base class of MEff2ss. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEff2ss class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEff2ss>
: public ClassTraitsBase<Herwig::MEff2ss> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEff2ss"; }
};
/** @endcond */
}
-#include "MEff2ss.icc"
-
#endif /* HERWIG_MEff2ss_H */
diff --git a/MatrixElement/General/MEff2ss.icc b/MatrixElement/General/MEff2ss.icc
deleted file mode 100644
--- a/MatrixElement/General/MEff2ss.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// MEff2ss.icc 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 inlined member functions of
-// the MEff2ss class.
-//
-
-namespace Herwig {
-
-inline MEff2ss::MEff2ss() : theFerm(0), theVec(0), theTen(0) {}
-
-inline IBPtr MEff2ss::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEff2ss::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/General/MEff2vs.cc b/MatrixElement/General/MEff2vs.cc
--- a/MatrixElement/General/MEff2vs.cc
+++ b/MatrixElement/General/MEff2vs.cc
@@ -1,283 +1,283 @@
// -*- C++ -*-
//
// MEff2vs.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 MEff2vs class.
//
#include "MEff2vs.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include <numeric>
using namespace Herwig;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
void MEff2vs::doinit() throw(InitException) {
GeneralHardME::doinit();
HPCount ndiags(numberOfDiags());
theSca.resize(ndiags);
theVec.resize(ndiags);
theFerm.resize(ndiags);
for(HPCount i = 0; i < ndiags; ++i) {
HPDiagram current = getProcessInfo()[i];
if( current.channelType == HPDiagram::sChannel ) {
if( current.intermediate->iSpin() == PDT::Spin0 )
theSca[i] =
make_pair(dynamic_ptr_cast<AbstractFFSVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractVSSVertexPtr>(current.vertices.second));
else if( current.intermediate->iSpin() == PDT::Spin1 )
theVec[i] =
make_pair(dynamic_ptr_cast<AbstractFFVVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractVVSVertexPtr>(current.vertices.second));
}
else if( current.channelType == HPDiagram::tChannel ) {
if(current.intermediate->iSpin() == PDT::Spin1Half) {
if( current.ordered.second )
theFerm[i] =
make_pair(dynamic_ptr_cast<AbstractFFVVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractFFSVertexPtr>(current.vertices.second));
else
theFerm[i] =
make_pair(dynamic_ptr_cast<AbstractFFVVertexPtr>(current.vertices.second),
dynamic_ptr_cast<AbstractFFSVertexPtr>(current.vertices.first));
}
}
}
}
void MEff2vs::persistentOutput(PersistentOStream & os) const {
os << theSca << theVec << theFerm;
}
void MEff2vs::persistentInput(PersistentIStream & is, int) {
is >> theSca >> theVec >> theFerm;
}
ClassDescription<MEff2vs> MEff2vs::initMEff2vs;
// Definition of the static class description member.
void MEff2vs::Init() {
static ClassDocumentation<MEff2vs> documentation
("MEff2vs implements the ME calculation of the fermion-antifermion "
"to vector-scalar hard process.");
}
double MEff2vs::me2() const {
//set up wavefunctions
SpinorVector ina(2);
SpinorBarVector inb(2);
VBVector outa(3);
ScalarWaveFunction sca(rescaledMomenta()[3], mePartonData()[3], Complex(1.),
outgoing);
for(unsigned int ih = 0; ih < 2; ++ih) {
ina[ih] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0],
ih, incoming);
inb[ih] = SpinorBarWaveFunction(rescaledMomenta()[1], mePartonData()[1],
ih, incoming);
outa[2*ih] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2],
2*ih, outgoing);
}
if( mePartonData()[2]->mass() > 0.0*MeV ) {
outa[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2],
1, outgoing);
}
double full_me(0.);
ffb2vsHeME(ina, inb, outa, sca, full_me);
return full_me;
}
ProductionMatrixElement
MEff2vs::ffb2vsHeME(SpinorVector & sp, SpinorBarVector & spbar,
VBVector & vec, ScalarWaveFunction & sca,
double & me2) const {
Energy2 m2(scale());
const vector<DVector> cfactors = getColourFactors();
const HPCount ndiags = numberOfDiags();
const size_t ncf = numberOfFlows();
vector<double> me(ndiags, 0.);
vector<Complex> diag(ndiags, Complex(0.)), flows(ncf, Complex(0.));
me2 = 0.;
ScalarWaveFunction interS; VectorWaveFunction interV;
SpinorBarWaveFunction interFB;
bool mv(false);
if( mePartonData()[2]->mass() == 0.0*MeV ) mv = true;
ProductionMatrixElement prodme(PDT::Spin1Half, PDT::Spin1Half,
PDT::Spin1,PDT::Spin0);
for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) {
for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) {
for(unsigned int ovhel = 0; ovhel < 3; ++ovhel) {
if( mv ) continue;
flows = vector<Complex>(ncf, Complex(0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell(current.intermediate);
if( current.channelType == HPDiagram::sChannel ) {
if( offshell->iSpin() == PDT::Spin0 ) {
interS = theSca[ix].first->evaluate(m2, 1, offshell, sp[ihel1],
spbar[ihel2]);
diag[ix] = theSca[ix].second->evaluate(m2, vec[ovhel], sca, interS);
}
else if( offshell->iSpin() == PDT::Spin1 ) {
interV = theVec[ix].first->evaluate(m2, 1, offshell, sp[ihel1],
spbar[ihel2]);
diag[ix] = theVec[ix].second->evaluate(m2, vec[ovhel], interV, sca);
}
else diag[ix] = 0.0;
}
else if( current.channelType == HPDiagram::tChannel ) {
if( offshell->iSpin() == PDT::Spin1Half ) {
if( current.ordered.second ) {
interFB = theFerm[ix].second->evaluate(m2, 3, offshell,
spbar[ihel2], sca);
diag[ix] = theFerm[ix].first->evaluate(m2, sp[ihel1],
interFB, vec[ovhel]);
}
else {
interFB = theFerm[ix].first->evaluate(m2, 3, offshell,
spbar[ihel2], vec[ovhel]);
diag[ix] = theFerm[ix].second->evaluate(m2, sp[ihel1],
interFB, sca);
}
}
}
else diag[ix] = 0.0;
me[ix] += norm(diag[ix]);
//add to appropriate colourflow(s)
for(unsigned int iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//end of diagram loop
for(unsigned int ii = 0; ii < ncf; ++ii)
for(unsigned int ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
prodme(ihel1, ihel2, ovhel, 0) =
std::accumulate(flows.begin(), flows.end(), Complex(0.));
}
}
}
const double colourAvg = mePartonData()[0]->iColour() == PDT::Colour3
? 1./9. : 1.;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*colourAvg*me[ix];
meInfo(save);
me2 *= 0.25*colourAvg;
return prodme;
}
Selector<const ColourLines *>
MEff2vs::colourGeometries(tcDiagPtr diag) const {
static vector<ColourLines> cf(5);
//11->11
cf[0] = ColourLines("");
//33b->11
cf[1] = ColourLines("1 -2");
cf[2] = ColourLines("1 2 -3");
//33b->81
cf[3] = ColourLines("1 4, -4 2 -3");
cf[4] = ColourLines("1 2 4, -4 -3");
HPDiagram current = getProcessInfo()[abs(diag->id()) - 1];
PDT::Colour ca = getParticleData(current.incoming.first)->iColour();
PDT::Colour cb = getParticleData(current.incoming.second)->iColour();
PDT::Colour cc = getParticleData(current.outgoing.first)->iColour();
PDT::Colour cd = getParticleData(current.outgoing.second)->iColour();
Selector<const ColourLines *> sel;
if( ca == PDT::Colour0 && cb == PDT::Colour0 &&
cc == PDT::Colour0 && cd == PDT::Colour0 )
sel.insert(1., &cf[0]);
else if( ca == PDT::Colour3 && cb == PDT::Colour3bar ) {
if( cc == PDT::Colour0 && cd == PDT::Colour0 ) {
if( current.channelType == HPDiagram::sChannel )
sel.insert(1., &cf[1]);
else
sel.insert(1., &cf[2]);
}
else if( cc == PDT::Colour8 && cd == PDT::Colour0 ) {
if( current.ordered.second )
sel.insert(1., &cf[3]);
else
sel.insert(1., &cf[4]);
}
}
else
throw MEException()
<< "MEff2vs::colourGeometries() - Unknown incoming colour configuration "
<< ca << " " << cb << Exception::runerror;
return sel;
}
void MEff2vs::constructVertex(tSubProPtr sub) {
// Hard proces external particles
ParticleVector hdp(4);
hdp[0] = sub->incoming().first;
hdp[1] = sub->incoming().second;
hdp[2] = sub->outgoing()[0];
hdp[3] = sub->outgoing()[1];
//check ordering
if( hdp[0]->id() < hdp[1]->id() ) swap(hdp[0], hdp[1]);
if( hdp[2]->dataPtr()->iSpin() == PDT::Spin0 ) swap(hdp[2], hdp[3]);
SpinorVector sp;
SpinorWaveFunction(sp, hdp[0], incoming, false, true);
SpinorBarVector spbar;
SpinorBarWaveFunction(spbar, hdp[1], incoming, false, true);
VBVector vec;
bool mv(hdp[2]->dataPtr()->mass() == 0.0*MeV);
VectorWaveFunction(vec, hdp[2], outgoing, true, mv,true);
ScalarWaveFunction sca(hdp[3], outgoing, true, true);
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = hdp[i]->dataPtr();
momenta[i] = hdp[i]->momentum();
}
rescaleMomenta(momenta, data);
SpinorWaveFunction spr(rescaledMomenta()[0], data[0], incoming);
SpinorBarWaveFunction sbr(rescaledMomenta()[1], data[1],incoming);
VectorWaveFunction vr(rescaledMomenta()[2], data[2], mv, outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
spr.reset(ihel);
sp[ihel] = spr;
sbr.reset(ihel);
spbar[ihel] = sbr;
vr.reset(2*ihel);
vec[2*ihel] = vr;
}
if( !mv ) {
vr.reset(1);
vec[1] = vr;
}
sca = ScalarWaveFunction(rescaledMomenta()[3], data[3], outgoing);
double dummy(0.);
ProductionMatrixElement prodme = ffb2vsHeME(sp, spbar, vec, sca, dummy);
HardVertexPtr hardvertex = new_ptr(HardVertex());
hardvertex->ME(prodme);
for(ParticleVector::size_type i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(hdp[i]->spinInfo())->
setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/General/MEff2vs.fh b/MatrixElement/General/MEff2vs.fh
deleted file mode 100644
--- a/MatrixElement/General/MEff2vs.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEff2vs class.
-//
-#ifndef HERWIG_MEff2vs_FH
-#define HERWIG_MEff2vs_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEff2vs;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEff2vs,MEff2vsPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEff2vs.h b/MatrixElement/General/MEff2vs.h
--- a/MatrixElement/General/MEff2vs.h
+++ b/MatrixElement/General/MEff2vs.h
@@ -1,243 +1,240 @@
// -*- C++ -*-
//
// MEff2vs.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_MEff2vs_H
#define HERWIG_MEff2vs_H
//
// This is the declaration of the MEff2vs class.
//
#include "GeneralHardME.h"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
-#include "ProductionMatrixElement.h"
-#include "MEff2vs.fh"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::SpinorWaveFunction;
using Helicity::SpinorBarWaveFunction;
using Helicity::VectorWaveFunction;
using Helicity::ScalarWaveFunction;
/**
* The MEff2vs class is designed to implement the matrix element for a
* fermion-antifermion to vector-scalar hard process. It inherits from
* GeneralHardME and implements the appropriate virtual functions for this
* specific spin combination.
*
* @see \ref MEff2vsInterfaces "The interfaces"
* defined for MEff2vs.
* @see GeneralHardME
*/
class MEff2vs: public GeneralHardME {
public:
/** @name Typedefs */
//@{
/**
* A vector of SpinorWaveFunctions
*/
typedef vector<SpinorWaveFunction> SpinorVector;
/**
* A vector of SpinorWaveBarFunctions
*/
typedef vector<SpinorBarWaveFunction> SpinorBarVector;
/**
* A vector of VectorWaveFunctions
*/
typedef vector<VectorWaveFunction> VBVector;
//@}
public:
/**
* The default constructor.
*/
- inline MEff2vs();
+ inline MEff2vs() : theSca(0), theVec(0), theFerm(0) {}
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
/**
* Construct the vertex information for the spin correlations
* @param sub Pointer to the relevent SubProcess
*/
virtual void constructVertex(tSubProPtr sub);
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEff2vs> initMEff2vs;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEff2vs & operator=(const MEff2vs &);
private:
/** @name Functions to compute the ProductionMatrixElement. */
//@{
/**
* Compute the matrix element for \f$\Psi\bar{\Psi}\to\Psi\bar{\Psi}\f$
* @param sp Spinors for first incoming particle
* @param spbar SpinorBar Wavefunctions for second incoming particle
* @param vec VectorWaveFunctions for outgoing vector
* @param sca Outgoing ScalarWaveFunction
* @param me2 colour averaged, spin summed ME
* @return ProductionMatrixElement containing results of
* helicity calculations
*/
ProductionMatrixElement
ffb2vsHeME(SpinorVector & sp, SpinorBarVector & spbar,
VBVector & vec, ScalarWaveFunction & sca,
double & me2) const;
//@}
private:
/**
* Storage for dynamically cast vertices for a diagram with intermediate
* scalar
*/
vector<pair<AbstractFFSVertexPtr, AbstractVSSVertexPtr> > theSca;
/**
* Storage for dynamically cast vertices for a diagram with intermediate
* vector
*/
vector<pair<AbstractFFVVertexPtr, AbstractVVSVertexPtr> > theVec;
/**
* Storage for dynamically cast vertices for a diagram with intermediate
* fermion
*/
vector<pair<AbstractFFVVertexPtr, AbstractFFSVertexPtr> > theFerm;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEff2vs. */
template <>
struct BaseClassTrait<Herwig::MEff2vs,1> {
/** Typedef of the first base class of MEff2vs. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEff2vs class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEff2vs>
: public ClassTraitsBase<Herwig::MEff2vs> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEff2vs"; }
};
/** @endcond */
}
-#include "MEff2vs.icc"
-
#endif /* HERWIG_MEff2vs_H */
diff --git a/MatrixElement/General/MEff2vs.icc b/MatrixElement/General/MEff2vs.icc
deleted file mode 100644
--- a/MatrixElement/General/MEff2vs.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// MEff2vs.icc 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 inlined member functions of
-// the MEff2vs class.
-//
-
-namespace Herwig {
-
-inline MEff2vs::MEff2vs() : theSca(0), theVec(0), theFerm(0) {}
-
-inline IBPtr MEff2vs::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEff2vs::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/General/MEff2vv.cc b/MatrixElement/General/MEff2vv.cc
--- a/MatrixElement/General/MEff2vv.cc
+++ b/MatrixElement/General/MEff2vv.cc
@@ -1,361 +1,361 @@
// -*- C++ -*-
//
// MEff2vv.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 MEff2vv class.
//
#include "MEff2vv.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include<numeric>
using namespace Herwig;
using ThePEG::Helicity::ScalarWaveFunction;
using ThePEG::Helicity::TensorWaveFunction;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
void MEff2vv::doinit() throw(InitException) {
GeneralHardME::doinit();
HPCount ndiags(numberOfDiags());
theFerm.resize(ndiags); theVec.resize(ndiags);
theTen.resize(ndiags);
theSca.resize(ndiags);
for(HPCount i = 0; i < ndiags; ++i) {
HPDiagram current = getProcessInfo()[i];
if(current.channelType == HPDiagram::tChannel) {
if(current.intermediate->iSpin() == PDT::Spin1Half)
theFerm[i] =
make_pair(dynamic_ptr_cast<AbstractFFVVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractFFVVertexPtr>(current.vertices.second));
}
else if(current.channelType == HPDiagram::sChannel) {
if(current.intermediate->iSpin() == PDT::Spin0)
theSca[i] =
make_pair(dynamic_ptr_cast<AbstractFFSVertexPtr>(current.vertices.first ),
dynamic_ptr_cast<AbstractVVSVertexPtr>(current.vertices.second));
if(current.intermediate->iSpin() == PDT::Spin1)
theVec[i] =
make_pair(dynamic_ptr_cast<AbstractFFVVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractVVVVertexPtr>(current.vertices.second));
if(current.intermediate->iSpin() == PDT::Spin2)
theTen[i] =
make_pair(dynamic_ptr_cast<AbstractFFTVertexPtr>(current.vertices.first),
dynamic_ptr_cast<AbstractVVTVertexPtr>(current.vertices.second));
}
}
}
double MEff2vv::me2() const {
SpinorVector sp(2);
SpinorBarVector sbar(2);
// vector
bool mc = !(mePartonData()[2]->mass() > 0.*MeV);
bool md = !(mePartonData()[3]->mass() > 0.*MeV);
VBVector v1(3), v2(3);
for( unsigned int i = 0; i < 2; ++i ) {
sp[i] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], i, incoming);
sbar[i] = SpinorBarWaveFunction(rescaledMomenta()[1], mePartonData()[1], i,
incoming);
v1[2*i] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2],2*i ,
outgoing);
v2[2*i] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], 2*i,
outgoing);
}
if( !mc ) v1[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1,
outgoing);
if( !md ) v2[1] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], 1,
outgoing);
double full_me(0.);
ff2vvME(sp, sbar, v1, mc, v2, md, full_me);
#ifndef NDEBUG
if( debugME() ) debug(full_me);
#endif
return full_me;
}
ProductionMatrixElement
MEff2vv::ff2vvME(const SpinorVector & sp, const SpinorBarVector sbar,
const VBVector & v1, bool m1, const VBVector & v2, bool m2,
double & me2) const {
//Define vectors to store diagrams and square elements
const HPCount ndiags(numberOfDiags());
const size_t ncf(numberOfFlows());
vector<Complex> diag(ndiags, Complex(0.));
vector<double> me(ndiags, 0.);
const Energy2 q2 = scale();
const vector<vector<double> > cfactors = getColourFactors();
//Intermediate wavefunctions
ScalarWaveFunction interS; SpinorWaveFunction interF;
VectorWaveFunction interV; TensorWaveFunction interT;
ProductionMatrixElement pme(PDT::Spin1Half, PDT::Spin1Half,
PDT::Spin1, PDT::Spin1);
//Loop over helicities and calculate diagrams
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 2; ++if2) {
for(unsigned int vh1 = 0; vh1 < 3; ++vh1) {
if( vh1 == 1 && m1 ) ++vh1;
for(unsigned int vh2 = 0; vh2 < 3; ++vh2) {
if( vh2 == 1 && m2 ) ++vh2;
//loop and calculate diagrams
vector<Complex> flows = vector<Complex>(ncf, Complex(0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(current.channelType == HPDiagram::tChannel) {
if(current.intermediate->iSpin() == PDT::Spin1Half) {
if(current.ordered.second) {
interF = theFerm[ix].first->evaluate(q2, 3, offshell, sp[if1],
v1[vh1]);
diag[ix] = theFerm[ix].second->evaluate(q2, interF, sbar[if2],
v2[vh2]);
}
else {
interF = theFerm[ix].first->evaluate(q2, 3 , offshell, sp[if1],
v2[vh2]);
diag[ix] = theFerm[ix].second->evaluate(q2, interF, sbar[if2],
v1[vh1]);
}
}
}
else if(current.channelType == HPDiagram::sChannel) {
if(current.intermediate->iSpin() == PDT::Spin0) {
interS = theSca[ix].first->evaluate(q2, 1, offshell,
sp[if1], sbar[if2]);
diag[ix] = theSca[ix].second->evaluate(q2, v1[if1], v2[if2],
interS);
}
else if(current.intermediate->iSpin() == PDT::Spin1) {
interV = theVec[ix].first->evaluate(q2, 1, offshell, sp[if1],
sbar[if2]);
diag[ix] = theVec[ix].second->evaluate(q2, v1[vh1],
v2[vh2], interV);
}
else if(current.intermediate->iSpin() == PDT::Spin2) {
interT = theTen[ix].first->evaluate(q2, 1, offshell, sp[if1],
sbar[if2]);
diag[ix] = theTen[ix].second->evaluate(q2, v1[vh1], v2[vh2],
interT);
}
}
//compute individual diagram squared and save for diagram sel
me[ix] += norm(diag[ix]);
//find out which colourflow this diag belongs to and add to it
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second*diag[ix];
}//end-of-diagram loop
//set appropriate element in the ProductionMatrixElement
pme(if1, if2, vh1, vh2) =
std::accumulate(flows.begin(), flows.end(), Complex(0.0, 0.0));
//Add results, with appropriate colour factors to me2
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
}
}
}
}
const double cAvg = mePartonData()[0]->coloured() ? 1./9. : 1.;
const double ifact = mePartonData()[2]->id() == mePartonData()[3]->id() ?
0.5 : 1;
DVector save(ndiags);
for(DVector::size_type idx = 0; idx < ndiags; ++idx)
save[idx] = 0.25*cAvg*ifact*me[idx];
meInfo(save);
me2 *= 0.25*cAvg*ifact;
return pme;
}
Selector<const ColourLines *>
MEff2vv::colourGeometries(tcDiagPtr diag) const {
static vector<ColourLines> cf(10);
//33b->11
cf[0] = ColourLines("1 2 -3");
cf[1] = ColourLines("1 -2");
//33b->88
cf[2] = ColourLines("1 4, -4 2 5, -5 -3");
cf[3] = ColourLines("1 5, -5 2 4, -4 -3");
cf[4] = ColourLines("1 3 4, -5 -3 -2, -4 5");
cf[5] = ColourLines("1 3 5, -4 -3 -2, -5 4");
cf[6] = ColourLines("1 -2, 4 -5, 5 -4");
//33b->81
cf[7] = ColourLines("1 4, -4 2 -3");
cf[8] = ColourLines("1 2 5, -5 -3");
//no colour
cf[9] = ColourLines("");
HPDiagram current = getProcessInfo()[abs(diag->id()) - 1];
vector<ColourLines>::size_type cl(0);
if(mePartonData()[2]->iColour() == PDT::Colour8 &&
mePartonData()[3]->iColour() == PDT::Colour8 ) {
if(current.channelType == HPDiagram::tChannel)
cl = current.ordered.second ? 2 : 3;
else {
if(current.intermediate->iColour() == PDT::Colour0)
cl = 6;
else
cl = 4 + rnd2(0.5, 0.5);
}
}
else if(mePartonData()[2]->iColour() == PDT::Colour0 &&
mePartonData()[3]->iColour() == PDT::Colour0 ) {
if( mePartonData()[0]->iColour() == PDT::Colour0 &&
mePartonData()[1]->iColour() == PDT::Colour0 )
cl = 9;
else
cl = (current.channelType == HPDiagram::tChannel) ? 0 : 1;
}
else if(mePartonData()[2]->iColour() == PDT::Colour8 &&
mePartonData()[3]->iColour() == PDT::Colour0 )
cl = (current.channelType == HPDiagram::tChannel) ? 7 : 8;
else if(mePartonData()[2]->iColour() == PDT::Colour0 &&
mePartonData()[3]->iColour() == PDT::Colour8 )
cl = (current.channelType == HPDiagram::tChannel) ? 8 : 7;
else {
return Selector<const ColourLines *>();
}
Selector<const ColourLines *> sel;
sel.insert(1., &cf[cl]);
return sel;
}
void MEff2vv::persistentOutput(PersistentOStream & os) const {
os << theFerm << theVec << theTen << theSca;
}
void MEff2vv::persistentInput(PersistentIStream & is, int) {
is >> theFerm >> theVec >> theTen >> theSca;
}
ClassDescription<MEff2vv> MEff2vv::initMEff2vv;
// Definition of the static class description member.
void MEff2vv::Init() {
static ClassDocumentation<MEff2vv> documentation
("This class implements the matrix element calculation of the 2->2 "
"process, fermion-antifermion -> vector vector");
}
void MEff2vv::constructVertex(tSubProPtr sub) {
//get particles
ParticleVector ext(4);
ext[0] = sub->incoming().first;
ext[1] = sub->incoming().second;
ext[2] = sub->outgoing()[0];
ext[3] = sub->outgoing()[1];
//Ensure correct particle ordering
if( ext[0]->id() != getIncoming().first ) swap(ext[0], ext[1]);
if( ext[2]->id() != getOutgoing().first ) swap(ext[2], ext[3]);
vector<SpinorWaveFunction> sp;
SpinorWaveFunction(sp, ext[0], incoming, false, true);
vector<SpinorBarWaveFunction> sbar;
SpinorBarWaveFunction(sbar, ext[1], incoming, false, true);
vector<VectorWaveFunction> v1, v2;
bool mc = !(ext[2]->data().mass() > 0.*MeV);
bool md = !(ext[3]->data().mass() > 0.*MeV);
VectorWaveFunction(v1, ext[2], outgoing, true, mc, true);
VectorWaveFunction(v2, ext[3], outgoing, true, md, true);
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = ext[i]->dataPtr();
momenta[i] = ext[i]->momentum();
}
rescaleMomenta(momenta, data);
SpinorWaveFunction spr(rescaledMomenta()[0], data[0], incoming);
SpinorBarWaveFunction sbr(rescaledMomenta()[1], data[1], incoming);
VectorWaveFunction vr1(rescaledMomenta()[2], data[2], outgoing);
VectorWaveFunction vr2(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
spr.reset(ihel);
sp[ihel] = spr;
sbr.reset(ihel);
sbar[ihel] = sbr;
vr1.reset(2*ihel);
v1[2*ihel] = vr1;
vr2.reset(2*ihel);
v2[2*ihel] = vr2;
}
if( !mc ) {
vr1.reset(1);
v1[1] = vr1;
}
if( !md ) {
vr2.reset(1);
v2[1] = vr2;
}
double dummy(0.);
ProductionMatrixElement pme = ff2vvME(sp, sbar, v1, mc, v2, md, dummy);
#ifndef NDEBUG
if( debugME() ) debug(dummy);
#endif
//create and set the hardvertex for the process
HardVertexPtr hv = new_ptr(HardVertex());
hv->ME(pme);
for( ParticleVector::size_type i = 0; i < 4; ++i )
dynamic_ptr_cast<SpinfoPtr>(ext[i]->spinInfo())->
setProductionVertex(hv);
}
void MEff2vv::debug(double me2) const {
if( !generator()->logfile().is_open() ) return;
if( (mePartonData()[0]->id() != 1 && mePartonData()[0]->id() != 2) ||
(mePartonData()[1]->id() != -1 && mePartonData()[1]->id() != -2) ||
mePartonData()[2]->id() != 5100021 ||
mePartonData()[3]->id() != 5100021 ) return;
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
Energy2 s(sHat());
Energy2 mf2 = meMomenta()[2].m2();
Energy2 t3(tHat() - mf2), u4(uHat() - mf2);
double analytic = gs4*( mf2*( (57.*s/t3/u4) - (4.*s*s*s/t3/t3/u4/u4)
- (108./s) )
+ (20.*s*s/t3/u4) - 93. + (108.*t3*u4/s/s) )/27.;
double diff = abs( analytic - me2 );
if( diff > 1e-4 ) {
generator()->log()
<< mePartonData()[0]->PDGName() << ","
<< mePartonData()[1]->PDGName() << "->"
<< mePartonData()[2]->PDGName() << ","
<< mePartonData()[3]->PDGName() << " difference: "
<< setprecision(10) << diff << " ratio: "
<< analytic/me2 << '\n';
}
}
diff --git a/MatrixElement/General/MEff2vv.fh b/MatrixElement/General/MEff2vv.fh
deleted file mode 100644
--- a/MatrixElement/General/MEff2vv.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEff2vv class.
-//
-#ifndef HERWIG_MEff2vv_FH
-#define HERWIG_MEff2vv_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEff2vv;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEff2vv,MEff2vvPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEff2vv.h b/MatrixElement/General/MEff2vv.h
--- a/MatrixElement/General/MEff2vv.h
+++ b/MatrixElement/General/MEff2vv.h
@@ -1,242 +1,239 @@
// -*- C++ -*-
//
// MEff2vv.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_MEff2vv_H
#define HERWIG_MEff2vv_H
//
// This is the declaration of the MEff2vv class.
//
#include "GeneralHardME.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
-#include "ProductionMatrixElement.h"
-#include "MEff2vv.fh"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
using ThePEG::Helicity::SpinorWaveFunction;
using ThePEG::Helicity::SpinorBarWaveFunction;
using ThePEG::Helicity::VectorWaveFunction;
/**
* This class implements the matrix element calculation for a generic
* \f$\Psi \Psi \rightarrow V^{\mu} V^{\nu}\f$ process.
*
* @see \ref MEff2vvInterfaces "The interfaces"
* defined for MEff2vv.
*/
class MEff2vv: public GeneralHardME {
public:
/** Vector of SpinorWaveFunctions objects */
typedef vector<SpinorWaveFunction> SpinorVector;
/** Vector of SpinorBarWaveFunction objects. */
typedef vector<SpinorBarWaveFunction> SpinorBarVector;
/** Vector of VectorWaveFunction objects. */
typedef vector<VectorWaveFunction> VBVector;
public:
/**
* The default constructor.
*/
- inline MEff2vv();
+ inline MEff2vv() : theVec(0), theTen(0), theSca(0) {}
/** @name Virtual functions required by the GeneralHardME class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
/**
* Construct the vertex information for the spin correlations
* @param sub Pointer to the relevent SubProcess
*/
virtual void constructVertex(tSubProPtr sub);
protected:
/**
* A debugging function to test the value of me2 against an
* analytic function.
* @param me2 \f$ |\bar{\mathcal{M}}|^2 \f$
*/
virtual void debug(double me2) const;
private:
/**
* Compute the production matrix element.
* @param sp Spinors for first incoming fermion
* @param sbar SpinorBar Wavefunctions for incoming anti-fermion
* @param v1 A vector of VectorWaveFunction objects for the first vector
* @param m1 Whether v1 is massless or not
* @param v2 A vector of VectorWaveFunction objects for the second vector
* @param m2 Whether v2 is massless or not
* @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$
*/
ProductionMatrixElement
ff2vvME(const SpinorVector & sp, const SpinorBarVector sbar,
const VBVector & v1, bool m1, const VBVector & v2, bool m2,
double & me2) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEff2vv> initMEff2vv;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEff2vv & operator=(const MEff2vv &);
private:
/**
* Storage for a dynamically cast vertices for a tchannel vector
* intermediate
*/
vector<pair<AbstractFFVVertexPtr, AbstractFFVVertexPtr> > theFerm;
/**
* Storage for a dynamically cast vertices for a schannel vector
* intermediate
*/
vector<pair<AbstractFFVVertexPtr, AbstractVVVVertexPtr> > theVec;
/**
* Storage for a dynamically cast vertices for a schannel scalar
* intermediate
*/
vector<pair<AbstractFFTVertexPtr, AbstractVVTVertexPtr> > theTen;
/**
* Storage for a dynamically cast vertices for a schannel scalar
* intermediate for massless external vector bosons
*/
vector<pair<AbstractFFSVertexPtr, AbstractVVSVertexPtr> > theSca;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEff2vv. */
template <>
struct BaseClassTrait<Herwig::MEff2vv,1> {
/** Typedef of the first base class of MEff2vv. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEff2vv class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEff2vv>
: public ClassTraitsBase<Herwig::MEff2vv> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEff2vv"; }
};
/** @endcond */
}
-#include "MEff2vv.icc"
-
#endif /* HERWIG_MEff2vv_H */
diff --git a/MatrixElement/General/MEff2vv.icc b/MatrixElement/General/MEff2vv.icc
deleted file mode 100644
--- a/MatrixElement/General/MEff2vv.icc
+++ /dev/null
@@ -1,27 +0,0 @@
-// -*- C++ -*-
-//
-// MEff2vv.icc 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 inlined member functions of
-// the MEff2vv class.
-//
-
-namespace Herwig {
-
-inline MEff2vv::MEff2vv() : theVec(0), theTen(0), theSca(0) {}
-
-inline IBPtr MEff2vv::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEff2vv::fullclone() const {
- return new_ptr(*this);
-}
-
-
-}
diff --git a/MatrixElement/General/MEfv2fs.cc b/MatrixElement/General/MEfv2fs.cc
--- a/MatrixElement/General/MEfv2fs.cc
+++ b/MatrixElement/General/MEfv2fs.cc
@@ -1,437 +1,437 @@
// -*- C++ -*-
//
// MEfv2fs.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 MEfv2fs class.
//
#include "MEfv2fs.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Helicity/SpinInfo.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
#include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h"
#include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include <numeric>
using namespace Herwig;
using ThePEG::Helicity::SpinfoPtr;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
void MEfv2fs::doinit() throw(InitException) {
GeneralHardME::doinit();
size_t ndiags(numberOfDiags());
theScaV.resize(ndiags);
theFermV.resize(ndiags);
for(size_t ix = 0; ix < ndiags; ++ix) {
HPDiagram curr = getProcessInfo()[ix];
if(curr.channelType == HPDiagram::tChannel) {
AbstractFFSVertexPtr ffs =
dynamic_ptr_cast<AbstractFFSVertexPtr>(curr.vertices.first);
if( curr.intermediate->iSpin() == PDT::Spin0 ) {
AbstractVSSVertexPtr vss =
dynamic_ptr_cast<AbstractVSSVertexPtr>(curr.vertices.second);
theScaV[ix] = make_pair(ffs, vss);
}
else {
AbstractFFVVertexPtr ffv =
dynamic_ptr_cast<AbstractFFVVertexPtr>(curr.vertices.second);
theFermV[ix] = make_pair(ffs, ffv);
}
}
else {
AbstractFFVVertexPtr ffv =
dynamic_ptr_cast<AbstractFFVVertexPtr>(curr.vertices.first);
AbstractFFSVertexPtr ffs =
dynamic_ptr_cast<AbstractFFSVertexPtr>(curr.vertices.second);
theFermV[ix] = make_pair(ffs, ffv);
}
}
}
double MEfv2fs::me2() const {
//massless vector
VecWFVector vecIn(2);
ScalarWaveFunction scaOut(rescaledMomenta()[3], mePartonData()[3],
Complex(1.,0.), outgoing);
double fullme(0.);
if( mePartonData()[0]->id() > 0 ) {
SpinorVector spIn(2);
SpinorBarVector spbOut(2);
for(size_t ih = 0; ih < 2; ++ih) {
spIn[ih] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], ih,
incoming);
spbOut[ih] = SpinorBarWaveFunction(rescaledMomenta()[2], mePartonData()[2], ih,
outgoing);
vecIn[ih] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*ih,
incoming);
}
fv2fbsHeME(spIn, vecIn, spbOut, scaOut, fullme);
}
else {
SpinorBarVector spbIn(2);
SpinorVector spOut(2);
for(size_t ih = 0; ih < 2; ++ih) {
spbIn[ih] = SpinorBarWaveFunction(rescaledMomenta()[0], mePartonData()[0], ih,
incoming);
spOut[ih] = SpinorWaveFunction(rescaledMomenta()[2], mePartonData()[2], ih,
outgoing);
vecIn[ih] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*ih,
incoming);
}
fbv2fsHeME(spbIn, vecIn, spOut, scaOut, fullme);
}
#ifndef NDEBUG
if( debugME() ) debug(fullme);
#endif
return fullme;
}
ProductionMatrixElement
MEfv2fs::fv2fbsHeME(const SpinorVector & spIn, const VecWFVector & vecIn,
const SpinorBarVector & spbOut,
const ScalarWaveFunction & scaOut,
double & fullme) const {
const Energy2 q2(scale());
const HPCount ndiags(numberOfDiags());
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors = getColourFactors();
vector<double> me(ndiags, 0.);
vector<Complex> diag(ndiags, Complex(0.));
fullme = 0.;
//intermediate wave functions
SpinorWaveFunction interF; ScalarWaveFunction interS;
SpinorBarWaveFunction interFB;
//vertex pointers
FFSVertexPtr ffs; FFVVertexPtr ffv;
VSSVertexPtr vss;
ProductionMatrixElement prodME(PDT::Spin1Half, PDT::Spin1,
PDT::Spin1Half, PDT::Spin0);
for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) {
for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) {
for(unsigned int ohel1 = 0; ohel1 < 2; ++ohel1) {
vector<Complex> flows = vector<Complex>(ncf, Complex(0.));
for(size_t ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( current.channelType == HPDiagram::tChannel ) {
if( offshell->iSpin() == PDT::Spin0 ) {
interS = theScaV[ix].first->evaluate(q2, 3, offshell, spIn[ihel1],
spbOut[ohel1]);
diag[ix] = theScaV[ix].second->evaluate(q2, vecIn[ihel2],
scaOut, interS);
}
else if( offshell->iSpin() == PDT::Spin1Half ) {
interFB = theFermV[ix].second->evaluate(q2, 3, offshell,
spbOut[ohel1],
vecIn[ihel2]);
diag[ix] = theFermV[ix].first->evaluate(q2, spIn[ihel1],
interFB, scaOut);
}
else diag[ix] = 0.0;
}
else if( current.channelType == HPDiagram::sChannel ) {
interF = theFermV[ix].second->evaluate(q2, 1, offshell, spIn[ihel1],
vecIn[ihel2]);
diag[ix] = theFermV[ix].first->evaluate(q2, interF, spbOut[ohel1],
scaOut);
}
else diag[ix] = 0.0;
// save
me[ix] += norm(diag[ix]);
//add to correct flow
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//end of diag loop
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
fullme += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
prodME(ihel1, 2*ihel2, ohel1, 0) =
std::accumulate(flows.begin(), flows.end(), Complex(0., 0.));
}
}
}
double clrAvg = (mePartonData()[0]->iColour() == PDT::Colour3) ? 1./3. : 1.;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = clrAvg*me[ix]/32.;
meInfo(save);
fullme *= clrAvg/32.;
return prodME;
}
ProductionMatrixElement
MEfv2fs::fbv2fsHeME(const SpinorBarVector & spbIn, const VecWFVector & vecIn,
const SpinorVector & spOut,
const ScalarWaveFunction & scaOut,
double & fullme) const {
const Energy2 q2(scale());
const HPCount ndiags(numberOfDiags());
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors = getColourFactors();
vector<double> me(ndiags, 0.);
vector<Complex> diag(ndiags, Complex(0.));
fullme = 0.;
//intermediate wave functions
ScalarWaveFunction interS;
SpinorBarWaveFunction interFB;
//vertex pointers
ProductionMatrixElement prodME(PDT::Spin1Half, PDT::Spin1, PDT::Spin1Half,
PDT::Spin0);
for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) {
for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) {
for(unsigned int ohel1 = 0; ohel1 < 2; ++ohel1) {
vector<Complex> flows = vector<Complex>(ncf, Complex(0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( current.channelType == HPDiagram::tChannel ) {
if( offshell->iSpin() == PDT::Spin0 ) {
interS = theScaV[ix].first->evaluate(q2, 3, offshell,
spOut[ohel1],
spbIn[ihel1]);
diag[ix] = theScaV[ix].second->evaluate(q2, vecIn[ihel2],
interS, scaOut);
}
else if( offshell->iSpin() == PDT::Spin1Half ) {
interFB = theFermV[ix].first->evaluate(q2, 3, offshell,
spbIn[ihel1], scaOut);
diag[ix] = theFermV[ix].second->evaluate(q2, spOut[ohel1],
interFB, vecIn[ihel2]);
}
else diag[ix] = 0.0;
}
else if( current.channelType == HPDiagram::sChannel ) {
interFB = theFermV[ix].second->evaluate(q2, 1, offshell,
spbIn[ihel1],
vecIn[ihel2]);
diag[ix] = theFermV[ix].first->evaluate(q2, spOut[ohel1],
interFB, scaOut);
}
else diag[ix] = 0.0;
// save
me[ix] += norm(diag[ix]);
//add to correct flow
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//end of diag loop
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
fullme += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
prodME(ihel1, 2*ihel2, ohel1, 0) =
std::accumulate(flows.begin(), flows.end(), Complex(0., 0.));
}
}
}
double clrAvg = (mePartonData()[0]->iColour() == PDT::Colour3bar) ? 1./3. : 1.;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = clrAvg*me[ix]/32.;
meInfo(save);
fullme *= clrAvg/32.;
return prodME;
}
Selector<const ColourLines *>
MEfv2fs::colourGeometries(tcDiagPtr diag) const {
static vector<ColourLines> cl(10);
//38->83
cl[0] = ColourLines("1 4, -4 2 -3, 3 5");
cl[1] = ColourLines("1 -2, 2 3 4, 5 -4 ");
cl[2] = ColourLines("1 2 -3, -4 -2 5, 3 4");
//3b8->83b
cl[3] = ColourLines("-1 -4, 3 2 4, -3 -5");
cl[4] = ColourLines("-1 2, -4 -3 -2, 4 -5");
cl[5] = ColourLines("-1 -2 3, -5 2 4, -3 -4");
//38->13
cl[6] = ColourLines("1 2 -3, 3 5");
cl[7] = ColourLines("1-2, 2 3 5");
//3b8->13b
cl[8] = ColourLines("-1 2 3, -3 -5");
cl[9] = ColourLines("-1 2, -5 -3 -2");
vector<ColourLines>::size_type offset;
if(mePartonData()[0]->id() > 0 &&
mePartonData()[2]->iColour() == PDT::Colour8 ) offset = 0;
else if(mePartonData()[0]->id() < 0 &&
mePartonData()[2]->iColour() == PDT::Colour8 ) offset = 3;
else if(mePartonData()[0]->id() > 0 &&
mePartonData()[2]->iColour() == PDT::Colour0 ) offset = 6;
else offset = 8;
HPDiagram current = getProcessInfo().at(abs(diag->id()) - 1);
Selector<const ColourLines *> sel;
if(current.channelType == HPDiagram::tChannel &&
(current.intermediate->iColour() == PDT::Colour3 ||
current.intermediate->iColour() == PDT::Colour3bar))
sel.insert(1., &cl[offset]);
else if(current.channelType == HPDiagram::sChannel)
sel.insert(1., &cl[offset + 1]);
else
sel.insert(1., &cl[offset + 2]);
return sel;
}
void MEfv2fs::persistentOutput(PersistentOStream & os) const {
os << theScaV << theFermV;
}
void MEfv2fs::persistentInput(PersistentIStream & is, int) {
is >> theScaV >> theFermV;
}
ClassDescription<MEfv2fs> MEfv2fs::initMEfv2fs;
// Definition of the static class description member.
void MEfv2fs::Init() {
static ClassDocumentation<MEfv2fs> documentation
("This class implements the matrix element for a fermion-vector to "
"a fermioin-scalar.");
}
void MEfv2fs::constructVertex(tSubProPtr subp) {
//get external particles
ParticleVector external(4);
external[0] = subp->incoming().first;
external[1] = subp->incoming().second;
external[2] = subp->outgoing()[0];
external[3] = subp->outgoing()[1];
//make sure the order is correct
if( external[0]->dataPtr()->iSpin() > external[1]->dataPtr()->iSpin() )
swap(external[0], external[1]);
if( external[2]->dataPtr()->iSpin() < external[3]->dataPtr()->iSpin() )
swap(external[2], external[3]);
//calculate production ME
VecWFVector vecIn;
VectorWaveFunction(vecIn, external[1], incoming, false, true, true);
//function to calculate me2 expects massless incoming vectors
// and this constructor sets the '1' polarisation at element [2]
//in the vector
vecIn[1] = vecIn[2];
ScalarWaveFunction scaOut(external[3], outgoing, true, true);
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = external[i]->dataPtr();
momenta[i] = external[i]->momentum();
}
rescaleMomenta(momenta, data);
double dummy(0.);
if( external[0]->id() > 0 ) {
SpinorVector spIn;
SpinorWaveFunction(spIn, external[0], incoming, false, true);
SpinorBarVector spbOut;
SpinorBarWaveFunction(spbOut, external[2], outgoing, true, true);
SpinorWaveFunction spr(rescaledMomenta()[0], data[0], incoming);
VectorWaveFunction vr(rescaledMomenta()[1], data[1], incoming);
SpinorBarWaveFunction sbr(rescaledMomenta()[2], data[2], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
spr.reset(ihel);
spIn[ihel] = spr;
vr.reset(2*ihel);
vecIn[ihel] = vr;
sbr.reset(ihel);
spbOut[ihel] = sbr;
}
scaOut = ScalarWaveFunction(rescaledMomenta()[3], data[3], outgoing);
ProductionMatrixElement prodME = fv2fbsHeME(spIn, vecIn, spbOut,
scaOut, dummy);
HardVertexPtr hardvertex = new_ptr(HardVertex());
hardvertex->ME(prodME);
for(ParticleVector::size_type i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(external[i]->spinInfo())->
setProductionVertex(hardvertex);
}
else {
SpinorBarVector spbIn;
SpinorBarWaveFunction(spbIn, external[0], incoming, false, true);
SpinorVector spOut;
SpinorWaveFunction(spOut, external[2], outgoing, true, true);
SpinorBarWaveFunction sbr(rescaledMomenta()[0], data[0], incoming);
VectorWaveFunction vr(rescaledMomenta()[1], data[1], incoming);
SpinorWaveFunction spr(rescaledMomenta()[2], data[2], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
sbr.reset(ihel);
spbIn[ihel] = sbr;
vr.reset(2*ihel);
vecIn[ihel] = vr;
spr.reset(ihel);
spOut[ihel] = spr;
}
scaOut = ScalarWaveFunction(rescaledMomenta()[3], data[3], outgoing);
ProductionMatrixElement prodME = fbv2fsHeME(spbIn, vecIn, spOut,
scaOut, dummy);
HardVertexPtr hardvertex = new_ptr(HardVertex());
hardvertex->ME(prodME);
for(ParticleVector::size_type i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(external[i]->spinInfo())->
setProductionVertex(hardvertex);
}
#ifndef NDEBUG
if( debugME() ) debug(dummy);
#endif
}
void MEfv2fs::debug(double me2) const {
if( !generator()->logfile().is_open() ) return;
long id1 = abs(mePartonData()[0]->id());
long id4 = abs(mePartonData()[3]->id());
if( (id1 != 1 && id1 != 2) || mePartonData()[1]->id() != 21 ||
mePartonData()[2]->id() != 1000021 ||
(id4 != 1000001 && id4 != 1000002 && id4 != 2000001 &&
id4 != 2000002) ) return;
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
int Nc = sm->Nc();
Energy2 m3s = sqr(mePartonData()[2]->mass());
Energy2 m4s = sqr(mePartonData()[3]->mass());
//formula has vf->fs so swap t and u
Energy2 s(sHat()), t3(uHat() - m3s), u4(tHat() - m4s);
double analytic = -gs4*( u4 + 2.*(m4s - m3s)*(1. + m3s/t3 + m4s/u4) )*
( sqr(u4) + sqr(s) - sqr(t3)/sqr(Nc) )/s/t3/u4/4.;
double diff = abs( analytic - me2);
if( diff > 1e-4 ) {
generator()->log()
<< mePartonData()[0]->PDGName() << ","
<< mePartonData()[1]->PDGName() << "->"
<< mePartonData()[2]->PDGName() << ","
<< mePartonData()[3]->PDGName() << " difference: "
<< setprecision(10) << diff << " ratio: " << analytic/me2 << '\n';
}
}
diff --git a/MatrixElement/General/MEfv2fs.fh b/MatrixElement/General/MEfv2fs.fh
deleted file mode 100644
--- a/MatrixElement/General/MEfv2fs.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEfv2fs class.
-//
-#ifndef HERWIG_MEfv2fs_FH
-#define HERWIG_MEfv2fs_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEfv2fs;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEfv2fs,MEfv2fsPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEfv2fs.h b/MatrixElement/General/MEfv2fs.h
--- a/MatrixElement/General/MEfv2fs.h
+++ b/MatrixElement/General/MEfv2fs.h
@@ -1,247 +1,244 @@
// -*- C++ -*-
//
// MEfv2fs.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_MEfv2fs_H
#define HERWIG_MEfv2fs_H
//
// This is the declaration of the MEfv2fs class.
//
#include "GeneralHardME.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
-#include "ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.fh"
-#include "MEfv2fs.fh"
namespace Herwig {
using namespace ThePEG;
using ThePEG::Helicity::SpinorWaveFunction;
using ThePEG::Helicity::SpinorBarWaveFunction;
using ThePEG::Helicity::VectorWaveFunction;
using ThePEG::Helicity::ScalarWaveFunction;
/**
* This class is designed to implement the matrix element for
* fermion-vector to fermion scalar. It inherits from GeneralHardME
* and implements the required virtual functions.
*
* @see @see \ref MEfv2fsInterfaces "The Interfaces"
* defined for MEfv2fs.
* @see GeneralHardME
*/
class MEfv2fs: public GeneralHardME {
/** Vector of SpinorWaveFunctions. */
typedef vector<SpinorWaveFunction> SpinorVector;
/** Vector of SpinorBarWaveFunctions. */
typedef vector<SpinorBarWaveFunction> SpinorBarVector;
/** Vector of VectorWaveFunctions. */
typedef vector<VectorWaveFunction> VecWFVector;
public:
/**
* The default constructor.
*/
- inline MEfv2fs();
+ inline MEfv2fs() : theScaV(0), theFermV(0) {}
public:
/** @name Virtual functions required by the GeneralHardME class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
/**
* Construct the vertex information for the spin correlations
* @param subp Pointer to the relevent SubProcess
*/
virtual void constructVertex(tSubProPtr subp);
private:
/** @name Functions to calculate production matrix elements and me2. */
//@{
/**
* Calculate me2 and the production matrix element for the normal mode.
* @param spIn Vector of SpinorWaveFunction for the incoming fermion
* @param vecIn Vector of VectorWaveFunction for incoming boson
* @param spbOut Vector of SpinorBarWaveFunction for outgoing fermion
* @param scaOut ScalarWaveFunction for outgoing scalar.
* @param full_me The value of me2 calculation
*/
ProductionMatrixElement fv2fbsHeME(const SpinorVector & spIn,
const VecWFVector & vecIn,
const SpinorBarVector & spbOut,
const ScalarWaveFunction & scaOut,
double & full_me) const;
/**
* Calculate me2 and the production matrix element for the cc mode.
* @param spbIn Vector of SpinorBarWaveFunction for the incoming fermion
* @param vecIn Vector of VectorWaveFunction for incoming boson
* @param spOut Vector of SpinorWaveFunction for outgoing fermion
* @param scaOut ScalarWaveFunction for outgoing scalar.
* @param full_me The value of me2 calculation
*/
ProductionMatrixElement fbv2fsHeME(const SpinorBarVector & spbIn,
const VecWFVector & vecIn,
const SpinorVector & spOut,
const ScalarWaveFunction & scaOut,
double & full_me) const;
//@}
protected:
/**
* A debugging function to test the value of me2 against an
* analytic function.
* @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$
*/
virtual void debug(double me2) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
void doinit() throw(InitException);
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEfv2fs> initMEfv2fs;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEfv2fs & operator=(const MEfv2fs &);
private:
/**
* Store a pair of FFSVertex and VSSVertex pointers
*/
vector<pair<AbstractFFSVertexPtr, AbstractVSSVertexPtr> > theScaV;
/**
* Store a pair of FFSVertex and FFVVertex pointers
*/
vector<pair<AbstractFFSVertexPtr, AbstractFFVVertexPtr> > theFermV;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEfv2fs. */
template <>
struct BaseClassTrait<Herwig::MEfv2fs,1> {
/** Typedef of the first base class of MEfv2fs. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEfv2fs class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEfv2fs>
: public ClassTraitsBase<Herwig::MEfv2fs> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEfv2fs"; }
};
/** @endcond */
}
-#include "MEfv2fs.icc"
-
#endif /* HERWIG_MEfv2fs_H */
diff --git a/MatrixElement/General/MEfv2fs.icc b/MatrixElement/General/MEfv2fs.icc
deleted file mode 100644
--- a/MatrixElement/General/MEfv2fs.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// MEfv2fs.icc 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 inlined member functions of
-// the MEfv2fs class.
-//
-
-namespace Herwig {
-
-inline MEfv2fs::MEfv2fs() : theScaV(0), theFermV(0) {}
-
-inline IBPtr MEfv2fs::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEfv2fs::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/General/MEfv2vf.cc b/MatrixElement/General/MEfv2vf.cc
--- a/MatrixElement/General/MEfv2vf.cc
+++ b/MatrixElement/General/MEfv2vf.cc
@@ -1,448 +1,448 @@
// -*- C++ -*-
//
// MEfv2vf.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 MEfv2vf class.
//
#include "MEfv2vf.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include <numeric>
using namespace Herwig;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
using ThePEG::Helicity::SpinorWaveFunction;
using ThePEG::Helicity::SpinorBarWaveFunction;
using ThePEG::Helicity::VectorWaveFunction;
void MEfv2vf::doinit() throw(InitException) {
GeneralHardME::doinit();
HPCount ndiags = numberOfDiags();
theFerm.resize(ndiags);
theVec.resize(ndiags);
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram diagram = getProcessInfo()[ix];
PDT::Spin offspin = diagram.intermediate->iSpin();
if(diagram.channelType == HPDiagram::sChannel ||
( diagram.channelType == HPDiagram::tChannel
&& offspin == PDT::Spin1Half)) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(diagram.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(diagram.vertices.second);
theFerm[ix] = make_pair(vert1, vert2);
}
else {
if(offspin == PDT::Spin1) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(diagram.vertices.first);
AbstractVVVVertexPtr vert2 = dynamic_ptr_cast<AbstractVVVVertexPtr>
(diagram.vertices.second);
theVec[ix] = make_pair(vert1, vert2);
}
}
}
}
double MEfv2vf::me2() const {
//wavefunctions
SpinorVector sp(2);
VBVector vecIn(2), vecOut(3);
SpinorBarVector spb(2);
double fullme(0.);
bool mc = !(mePartonData()[2]->mass() > 0.*MeV);
if(mePartonData()[0]->id() > 0) {
for(unsigned int i = 0; i < 2; ++i) {
sp[i] = SpinorWaveFunction(rescaledMomenta()[0], mePartonData()[0], i,
incoming);
vecIn[i] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*i,
incoming);
vecOut[2*i] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 2*i,
outgoing);
spb[i] = SpinorBarWaveFunction(rescaledMomenta()[3], mePartonData()[3], i,
outgoing);
}
if( !mc )
vecOut[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1,
outgoing);
fv2vfHeME(sp, vecIn, vecOut, mc, spb, fullme);
}
else {
for(unsigned int i = 0; i < 2; ++i) {
spb[i] = SpinorBarWaveFunction(rescaledMomenta()[0], mePartonData()[0], i,
incoming);
vecIn[i] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*i,
incoming);
vecOut[2*i] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 2*i,
outgoing);
sp[i] = SpinorWaveFunction(rescaledMomenta()[3], mePartonData()[3], i,
outgoing);
}
if( !mc )
vecOut[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1,
outgoing);
fbv2vfbHeME(spb, vecIn, vecOut, mc, sp, fullme);
}
#ifndef NDEBUG
if( debugME() ) debug(fullme);
#endif
return fullme;
}
ProductionMatrixElement
MEfv2vf::fv2vfHeME(const SpinorVector & spIn, const VBVector & vecIn,
const VBVector & vecOut, bool mc,
const SpinorBarVector & spbOut, double & mesq) const {
const HPCount ndiags = numberOfDiags();
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors(getColourFactors());
const Energy2 q2(scale());
ProductionMatrixElement prodME(PDT::Spin1Half, PDT::Spin1, PDT::Spin1,
PDT::Spin1Half);
vector<Complex> diag(ndiags, Complex(0., 0.));
vector<double> me(ndiags, 0.);
//intermediate wave functions
SpinorBarWaveFunction interFB; VectorWaveFunction interV;
SpinorWaveFunction interF;
//loop over helicities
for(unsigned int ifh = 0; ifh < 2; ++ifh) {
for(unsigned int ivh = 0; ivh < 2; ++ivh) {
for(unsigned int ovh = 0; ovh < 3; ++ovh) {
if(mc && ovh == 1) ++ovh;
for(unsigned int ofh = 0; ofh < 2; ++ofh) {
//store the flows
vector<Complex> cflows(ncf, Complex(0. ,0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram diagram = getProcessInfo()[ix];
tcPDPtr offshell = diagram.intermediate;
if(diagram.channelType == HPDiagram::tChannel) {
//t-chan spin-1/2
if(offshell->iSpin() == PDT::Spin1Half) {
interFB = theFerm[ix].second->evaluate(q2, 3, offshell,
spbOut[ofh], vecIn[ivh]);
diag[ix] = theFerm[ix].first->evaluate(q2, spIn[ifh], interFB,
vecOut[ovh]);
}
else if(offshell->iSpin() == PDT::Spin1) {
interV = theVec[ix].second->evaluate(q2, 3, offshell,
vecIn[ivh], vecOut[ovh]);
diag[ix] = theVec[ix].first->evaluate(q2, spIn[ifh],
spbOut[ofh], interV);
}
else
diag[ix] = 0.0;
}
else if(diagram.channelType == HPDiagram::sChannel) {
interFB = theFerm[ix].second->evaluate(q2, 1, offshell,
spbOut[ofh], vecOut[ovh]);
diag[ix] = theFerm[ix].first->evaluate(q2, spIn[ifh], interFB,
vecIn[ivh]);
}
me[ix] += norm(diag[ix]);
//Compute flows
for(size_t iy = 0; iy < diagram.colourFlow.size(); ++iy)
cflows[diagram.colourFlow[iy].first - 1] +=
diagram.colourFlow[iy].second * diag[ix];
}//end of diag loop
//Now add flows to me2 with appropriate colour factors
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
mesq += cfactors[ii][ij]*(cflows[ii]*conj(cflows[ij])).real();
prodME(ifh, 2*ivh, ovh, ofh) =
std::accumulate(cflows.begin(), cflows.end(), Complex(0., 0.));
}
}
}
}
const double colfact = mePartonData()[0]->iColour() == PDT::Colour3 ?
1./24. : 1;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*colfact*me[ix];
meInfo(save);
mesq *= 0.25*colfact;
return prodME;
}
ProductionMatrixElement
MEfv2vf::fbv2vfbHeME(const SpinorBarVector & spbIn, const VBVector & vecIn,
const VBVector & vecOut, bool mc,
const SpinorVector & spOut, double & mesq) const {
const HPCount ndiags = numberOfDiags();
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors(getColourFactors());
const Energy2 q2(scale());
ProductionMatrixElement prodME(PDT::Spin1Half, PDT::Spin1, PDT::Spin1,
PDT::Spin1Half);
vector<Complex> diag(ndiags, Complex(0., 0.));
vector<double> me(ndiags, 0.);
//intermediate wave functions
SpinorBarWaveFunction interFB; VectorWaveFunction interV;
SpinorWaveFunction interF;
//loop over helicities
for(unsigned int ifh = 0; ifh < 2; ++ifh) {
for(unsigned int ivh = 0; ivh < 2; ++ivh) {
for(unsigned int ovh = 0; ovh < 3; ++ovh) {
if(mc && ovh == 1) ++ovh;
for(unsigned int ofh = 0; ofh < 2; ++ofh) {
//store the flows
vector<Complex> cflows(ncf, Complex(0. ,0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram diagram = getProcessInfo()[ix];
tcPDPtr offshell = diagram.intermediate;
if(diagram.channelType == HPDiagram::tChannel) {
if(offshell->iSpin() == PDT::Spin1Half) {
interFB = theFerm[ix].first->evaluate(q2, 3, offshell,
spbIn[ifh], vecOut[ovh]);
diag[ix] = theFerm[ix].second->evaluate(q2, spOut[ofh], interFB,
vecIn[ivh]);
}
else if(offshell->iSpin() == PDT::Spin1) {
interV = theVec[ix].first->evaluate(q2, 3, offshell,
spOut[ofh], spbIn[ifh]);
diag[ix] = theVec[ix].second->evaluate(q2, vecIn[ivh], interV,
vecOut[ovh]);
}
else diag[ix] = 0.0;
}
else if(diagram.channelType == HPDiagram::sChannel) {
if(offshell->iSpin() == PDT::Spin1Half) {
interFB = theFerm[ix].first->evaluate(q2, 1, offshell, spbIn[ifh],
vecIn[ivh]);
diag[ix] = theFerm[ix].second->evaluate(q2, spOut[ofh], interFB,
vecOut[ovh]);
}
}
me[ix] += norm(diag[ix]);
//Compute flows
for(size_t iy = 0; iy < diagram.colourFlow.size(); ++iy)
cflows[diagram.colourFlow[iy].first - 1] +=
diagram.colourFlow[iy].second * diag[ix];
}//end of diag loop
//Now add flows to me2 with appropriate colour factors
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
mesq += cfactors[ii][ij]*(cflows[ii]*conj(cflows[ij])).real();
prodME(ifh, ivh, ovh, ofh) =
std::accumulate(cflows.begin(), cflows.end(), Complex(0., 0.));
}
}
}
}
const double colfact = mePartonData()[0]->iColour() == PDT::Colour3bar ?
1./24. : 1;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*colfact*me[ix];
meInfo(save);
mesq *= 0.25*colfact;
return prodME;
}
Selector<const ColourLines *>
MEfv2vf::colourGeometries(tcDiagPtr diag) const {
static vector<ColourLines> cf(10);
//3 8->8 3
cf[0] = ColourLines("1 4, -4 2 -3, 3 5");
cf[1] = ColourLines("1 2 -3, -4 -2 5, 3 4");
cf[2] = ColourLines("1 -2, 2 3 4, -4 5");
//3b 8 -> 8 3b
cf[3] = ColourLines("-4 -1, 3 2 4, -5 -3");
cf[4] = ColourLines("3 2 -1, -5 -2 4, -4 -3");
cf[5] = ColourLines("2 -1, -4 -3 -2, -5 4");
//3 8 -> 0 3
cf[6] = ColourLines("1 2 -3, 3 5");
cf[7] = ColourLines("1 -2, 2 3 5");
//3b 8 -> 0 3b
cf[8] = ColourLines("3 2 -1, -3 -5");
cf[9] = ColourLines("2 -1, -5 -3 -2");
HPDiagram current = getProcessInfo()[abs(diag->id()) - 1];
PDT::Colour offcolour = current.intermediate->iColour();
bool octetC = (mePartonData()[2]->iColour() == PDT::Colour8);
bool cc(mePartonData()[0]->id() < 0);
Selector<const ColourLines *> select;
int icf(-1);
if(current.channelType == HPDiagram::sChannel)
if(octetC) icf = cc ? 5 : 2;
else icf = cc ? 9 : 7;
else if(current.channelType == HPDiagram::tChannel) {
if(offcolour == PDT::Colour3 || offcolour == PDT::Colour3bar) {
if(octetC) icf = cc ? 3 : 0;
else icf = cc ? 8 : 6;
}
else if(offcolour == PDT::Colour8)
icf = cc ? 4 : 1;
else
throw MEException() << "MEfv2vf::colourGeometries - There is an incorrect "
<< "coloured object in a t-channel diagram. "
<< "No colour lines set."
<< Exception::warning;
}
else
throw MEException() << "MEfv2vf::colourGeometries - Incorrect diagram type "
<< "encountered. No colour lines set."
<< Exception::warning;
if(icf >= 0) select.insert(1., &cf[icf]);
return select;
}
void MEfv2vf::persistentOutput(PersistentOStream & os) const {
os << theFerm << theVec;
}
void MEfv2vf::persistentInput(PersistentIStream & is, int) {
is >> theFerm >> theVec;
}
ClassDescription<MEfv2vf> MEfv2vf::initMEfv2vf;
// Definition of the static class description member.
void MEfv2vf::Init() {
static ClassDocumentation<MEfv2vf> documentation
("This is the implementation of the matrix element for a fermion-vector boson"
"to a vector-fermion.");
}
void MEfv2vf::constructVertex(tSubProPtr sub) {
ParticleVector ext(4);
ext[0] = sub->incoming().first;
ext[1] = sub->incoming().second;
ext[2] = sub->outgoing()[0];
ext[3] = sub->outgoing()[1];
if( ext[0]->data().iSpin() > ext[1]->data().iSpin() ) swap(ext[0], ext[1]);
if( ext[2]->data().iSpin() < ext[3]->data().iSpin() ) swap(ext[2], ext[3]);
VBVector v1, v3;
VectorWaveFunction(v1, ext[1], incoming, false, true, true);
//function to calculate me2 expects massless incoming vectors
// and this constructor sets the '1' polarisation at element [2]
//in the vector
v1[1] = v1[2];
bool mc = !(ext[2]->data().mass() > 0.*MeV);
VectorWaveFunction(v3, ext[2], outgoing, true, mc, true);
SpinorVector sp; SpinorBarVector sbar;
double dummy(0.);
HardVertexPtr hv = new_ptr(HardVertex());
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = ext[i]->dataPtr();
momenta[i] = ext[i]->momentum();
}
rescaleMomenta(momenta, data);
VectorWaveFunction vir(rescaledMomenta()[1], data[1], incoming);
VectorWaveFunction vor(rescaledMomenta()[2], data[2], outgoing);
if( ext[0]->id() > 0 ) {
SpinorWaveFunction(sp, ext[0], incoming, false, true);
SpinorBarWaveFunction(sbar, ext[3], outgoing, true, true);
SpinorWaveFunction spr(rescaledMomenta()[0], data[0], incoming);
SpinorBarWaveFunction sbr(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
spr.reset(ihel);
sp[ihel] = spr;
vir.reset(2*ihel);
v1[ihel] = vir;
vor.reset(2*ihel);
v3[2*ihel] = vor;
sbr.reset(ihel);
sbar[ihel] = sbr;
}
if( !mc ) {
vor.reset(1);
v3[1] = vor;
}
ProductionMatrixElement pme = fv2vfHeME(sp, v1, v3, mc, sbar, dummy);
hv->ME(pme);
for(unsigned int i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(ext[i]->spinInfo())->setProductionVertex(hv);
}
else {
SpinorBarWaveFunction(sbar, ext[0], incoming, false, true);
SpinorWaveFunction(sp, ext[3], outgoing, true, true);
SpinorBarWaveFunction sbr(rescaledMomenta()[0], data[0], incoming);
SpinorWaveFunction spr(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
sbr.reset(ihel);
sbar[ihel] = sbr;
vir.reset(2*ihel);
v1[ihel] = vir;
vor.reset(2*ihel);
v3[2*ihel] = vor;
spr.reset(ihel);
sp[ihel] = spr;
}
if( !mc ) {
vor.reset(1);
v3[1] = vor;
}
ProductionMatrixElement pme = fbv2vfbHeME(sbar, v1, v3, mc, sp, dummy);
hv->ME(pme);
for(unsigned int i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(ext[i]->spinInfo())->setProductionVertex(hv);
}
#ifndef NDEBUG
if( debugME() ) debug(dummy);
#endif
}
void MEfv2vf::debug(double me2) const {
if( !generator()->logfile().is_open() ) return;
long id1 = abs(mePartonData()[0]->id());
long id4 = abs(mePartonData()[3]->id());
if( (id1 != 1 && id1 != 2) || mePartonData()[1]->id() != 21 ||
mePartonData()[2]->id() != 5100021 ||
(id4 != 5100001 && id4 != 5100002 &&
id4 != 6100001 && id4 != 6100002) ) return;
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
Energy2 s(sHat());
Energy2 mf2 = meMomenta()[2].m2();
// Energy4 spt2 = uHat()*tHat() - sqr(mf2);
//swap t and u as formula defines process vf->vf
Energy2 t3(uHat() - mf2), u4(tHat() - mf2);
Energy4 s2(sqr(s)), t3s(sqr(t3)), u4s(sqr(u4));
double analytic = -gs4*( 5.*s2/12./t3s + s2*s/t3s/u4 + 11.*s*u4/6./t3s
+ 5.*u4s/12./t3s + u4s*u4/s/t3s)/3.;
double diff = abs(analytic - me2);
if( diff > 1e-4 ) {
generator()->log()
<< mePartonData()[0]->PDGName() << ","
<< mePartonData()[1]->PDGName() << "->"
<< mePartonData()[2]->PDGName() << ","
<< mePartonData()[3]->PDGName() << " difference: "
<< setprecision(10) << diff << " ratio: " << analytic/me2 << '\n';
}
}
diff --git a/MatrixElement/General/MEfv2vf.fh b/MatrixElement/General/MEfv2vf.fh
deleted file mode 100644
--- a/MatrixElement/General/MEfv2vf.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEfv2vf class.
-//
-#ifndef HERWIG_MEfv2vf_FH
-#define HERWIG_MEfv2vf_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEfv2vf;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEfv2vf,MEfv2vfPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEfv2vf.h b/MatrixElement/General/MEfv2vf.h
--- a/MatrixElement/General/MEfv2vf.h
+++ b/MatrixElement/General/MEfv2vf.h
@@ -1,245 +1,235 @@
// -*- C++ -*-
//
// MEfv2vf.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_MEfv2vf_H
#define HERWIG_MEfv2vf_H
//
// This is the declaration of the MEfv2vf class.
//
#include "GeneralHardME.h"
-#include "ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h"
-#include "MEfv2vf.fh"
namespace Herwig {
using namespace ThePEG;
/**
* This class implements the matrix element for a fermion and a vector
* boson to a fermion and a vector boson. It inherits from GeneralHardME
* and implements the appropriate virtual functions.
*
* @see \ref MEfv2vfInterfaces "The interfaces"
* defined for MEfv2vf.
*/
class MEfv2vf: public GeneralHardME {
public:
/** A vector of SpinorWaveFunctions. */
typedef vector<Helicity::SpinorWaveFunction> SpinorVector;
/** A vector of SpinorBarWaveFunctions. */
typedef vector<Helicity::SpinorBarWaveFunction> SpinorBarVector;
/** A vector of VectorWaveFunctions. */
typedef vector<Helicity::VectorWaveFunction> VBVector;
public:
- /**
- * The default constructor.
- */
- inline MEfv2vf();
-
-public:
-
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
/**
* Construct the vertex information for the spin correlations
* @param sub Pointer to the relevent SubProcess
*/
virtual void constructVertex(tSubProPtr sub);
private:
/** @name Functions to calculate the Helicity MatrixElement.*/
//@{
/**
* Calculate the matrix element for an incoming fermion
* @param spIn A vector of spinors for the incoming fermion
* @param vecIn A vector of VectorWaveFunctions for the incoming boson
* @param spbOut A vector of SpinorBarWaveFunctions for the outgoing fermion
* @param vecOut A vector of VectorWaveFunctions for the outgoing boson
* @param mc If the outgoing vector is massless or not
* @param mesq The matrix element squared
*/
ProductionMatrixElement
fv2vfHeME(const SpinorVector & spIn, const VBVector & vecIn,
const VBVector & vecOut, bool mc,
const SpinorBarVector & spbOut, double & mesq) const;
/**
* Calculate the matrix element for an incoming anti-fermion
* @param spbIn A vector of SpinorBarWaveFunctions for the incoming anti-fermion
* @param vecIn A vector of VectorWaveFunctions for the incoming boson
* @param spOut A vector of Spinors for the outgoing antifermion
* @param vecOut A vector of VectorWaveFunctions for the outgoing boson
* @param mc If the outgoing vector is massless or not
* @param mesq The matrix element squared
*/
ProductionMatrixElement
fbv2vfbHeME(const SpinorBarVector & spbIn, const VBVector & vecIn,
const VBVector & vecOut, bool mc,
const SpinorVector & spOut, double & mesq) const;
//@}
protected:
/**
* A debugging function to test the value of me2 against an
* analytic function.
* @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$
*/
virtual void debug(double me2) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEfv2vf> initMEfv2vf;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEfv2vf & operator=(const MEfv2vf &);
private:
/** @name Store dynamically casted vertices. */
//@{
/**
* A pair off FFVVertex pointers
*/
vector<pair<AbstractFFVVertexPtr, AbstractFFVVertexPtr> > theFerm;
/**
* A pair of FFVVertex, VVVertex pointers
*/
vector<pair<AbstractFFVVertexPtr, AbstractVVVVertexPtr> > theVec;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEfv2vf. */
template <>
struct BaseClassTrait<Herwig::MEfv2vf,1> {
/** Typedef of the first base class of MEfv2vf. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEfv2vf class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEfv2vf>
: public ClassTraitsBase<Herwig::MEfv2vf> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEfv2vf"; }
};
/** @endcond */
}
-#include "MEfv2vf.icc"
-
#endif /* HERWIG_MEfv2vf_H */
diff --git a/MatrixElement/General/MEfv2vf.icc b/MatrixElement/General/MEfv2vf.icc
deleted file mode 100644
--- a/MatrixElement/General/MEfv2vf.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// MEfv2vf.icc 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 inlined member functions of
-// the MEfv2vf class.
-//
-
-namespace Herwig {
-
-inline MEfv2vf::MEfv2vf() {}
-
-inline IBPtr MEfv2vf::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEfv2vf::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/General/MEvv2ff.cc b/MatrixElement/General/MEvv2ff.cc
--- a/MatrixElement/General/MEvv2ff.cc
+++ b/MatrixElement/General/MEvv2ff.cc
@@ -1,346 +1,346 @@
// -*- C++ -*-
//
// MEvv2ff.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 MEvv2ff class.
//
#include "MEvv2ff.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include <numeric>
using namespace Herwig;
using ThePEG::Helicity::TensorWaveFunction;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
void MEvv2ff::doinit() throw(InitException) {
GeneralHardME::doinit();
size_t ndiags = numberOfDiags();
theFerm.resize(ndiags); theVec.resize(ndiags);
theTen.resize(ndiags);
for( size_t i = 0; i < ndiags; ++i ) {
HPDiagram dg = getProcessInfo()[i];
if( dg.channelType == HPDiagram::tChannel ) {
AbstractFFVVertexPtr ffv1 =
dynamic_ptr_cast<AbstractFFVVertexPtr>(dg.vertices.first);
AbstractFFVVertexPtr ffv2 =
dynamic_ptr_cast<AbstractFFVVertexPtr>(dg.vertices.second);
theFerm[i] = make_pair(ffv1, ffv2);
}
else if( dg.channelType == HPDiagram::sChannel ) {
if( dg.intermediate->iSpin() == PDT::Spin1) {
AbstractVVVVertexPtr vvv =
dynamic_ptr_cast<AbstractVVVVertexPtr>(dg.vertices.first);
AbstractFFVVertexPtr ffv =
dynamic_ptr_cast<AbstractFFVVertexPtr>(dg.vertices.second);
theVec[i] = make_pair(vvv,ffv);
}
else if(dg.intermediate->iSpin() == PDT::Spin2) {
AbstractVVTVertexPtr vvt =
dynamic_ptr_cast<AbstractVVTVertexPtr>(dg.vertices.first);
AbstractFFTVertexPtr fft =
dynamic_ptr_cast<AbstractFFTVertexPtr>(dg.vertices.second);
theTen[i] = make_pair(vvt,fft);
}
}
}
}
double MEvv2ff::me2() const {
// Set up wavefuctions
VBVector v1(2), v2(2);
SpinorVector sp(2); SpinorBarVector sbar(2);
for( size_t i = 0; i < 2; ++i ) {
v1[i] = VectorWaveFunction(rescaledMomenta()[0],mePartonData()[0], 2*i,
incoming);
v2[i] = VectorWaveFunction(rescaledMomenta()[1],mePartonData()[1], 2*i,
incoming);
sbar[i] = SpinorBarWaveFunction(rescaledMomenta()[2], mePartonData()[2], i,
outgoing);
sp[i] = SpinorWaveFunction(rescaledMomenta()[3], mePartonData()[3], i,
outgoing);
}
double full_me(0.);
vv2ffME(v1, v2, sbar, sp, full_me);
#ifndef NDEBUG
if( debugME() ) debug(full_me);
#endif
return full_me;
}
ProductionMatrixElement
MEvv2ff::vv2ffME(const VBVector & v1, const VBVector & v2,
const SpinorBarVector & sbar,const SpinorVector & sp,
double & me2) const {
const HPCount ndiags(numberOfDiags());
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors = getColourFactors();
const Energy mass = sp[0].mass();
//vectors to store results
vector<double> me(ndiags, 0.);
vector<Complex> diag(ndiags, Complex(0.));
//offshell wavefunctions
SpinorWaveFunction interF; VectorWaveFunction interV;
TensorWaveFunction interT;
const Energy2 q2 = scale();
ProductionMatrixElement pme(PDT::Spin1, PDT::Spin1,
PDT::Spin1Half, PDT::Spin1Half);
//sum over vector helicities
for(unsigned int iv1 = 0; iv1 < 2; ++iv1) {
for(unsigned int iv2 = 0; iv2 < 2; ++iv2) {
//sum over fermion helicities
for(unsigned int of1 = 0; of1 < 2; ++of1) {
for(unsigned int of2 = 0; of2 < 2; ++of2) {
//for each helicity calculate diagram
vector<Complex> flows = vector<Complex>(ncf, Complex(0,0.));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
PDPtr offshell = current.intermediate;
if(current.channelType == HPDiagram::tChannel &&
offshell->iSpin() == PDT::Spin1Half) {
if(current.ordered.second) {
interF = theFerm[ix].second->evaluate(q2, 3, offshell, sp[of2],
v2[iv2], mass);
diag[ix] = theFerm[ix].first->evaluate(q2, interF, sbar[of1],
v1[iv1]);
}
else {
interF = theFerm[ix].second->evaluate(q2, 3, offshell, sp[of2],
v1[iv1], mass);
diag[ix] = theFerm[ix].first->evaluate(q2, interF, sbar[of1],
v2[iv2]);
}
}
else if(current.channelType == HPDiagram::sChannel) {
if(offshell->iSpin() == PDT::Spin1) {
interV = theVec[ix].first->evaluate(q2, 1, offshell, v1[iv1],
v2[iv2]);
diag[ix] = theVec[ix].second->evaluate(q2, sp[of2], sbar[of1],
interV);
}
else if(offshell->iSpin() == PDT::Spin2) {
interT = theTen[ix].first->evaluate(q2, 1, offshell, v1[iv1],
v2[iv2]);
diag[ix] = theTen[ix].second->evaluate(q2, sp[of2], sbar[of1],
interT);
}
}
else diag[ix] = 0.;
me[ix] += norm(diag[ix]);
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy) {
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}
}//end of diag loop
//set appropriate element of ProductionMatrixElement
pme(iv1, iv2, of1, of2) =
std::accumulate(flows.begin(), flows.end(), Complex(0.0, 0.0));
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
}
}
}
}
const double identFact = mePartonData()[2]->id() == mePartonData()[3]->id()
? 0.5 : 1.;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = identFact*me[ix]/256.;
meInfo(save);
me2 *= identFact/256;
return pme;
}
Selector<const ColourLines *>
MEvv2ff::colourGeometries(tcDiagPtr diag) const {
static vector<ColourLines> cf(18);
//88->33bar
cf[0] = ColourLines("1 4, -3 -5, 3 2 -1");
cf[1] = ColourLines("1 -5, 1 2 -3, 3 4 ");
cf[2] = ColourLines("2 -1, 1 3 4, -2 -3 -5");
cf[3] = ColourLines("1 -2, -1 -3 -5, 2 3 4");
cf[4] = ColourLines("1 -2, 2 -1, 4 -5");
//88->88
cf[5] = ColourLines("1 4, -3 -5, 3 -2 -1, -4 2 5");
cf[6] = ColourLines("-1 -4, 3 5, -3 2 1, 4 -2 -5");
cf[7] = ColourLines("1 4, 3 5, -3 2 -4, -1 -2 -5");
cf[8] = ColourLines("-1 -4, -3 -5, 3 -2 4, 1 2 5");
cf[9] = ColourLines("1 5, -3 -4, 3 -2 -1, -5 2 4");
cf[10] = ColourLines("-1 -5, 3 4, -3 2 1, 5 -2 -4");
cf[11] = ColourLines("1 5, 3 4, -3 2 -5, -1 -2 -4");
cf[12] = ColourLines("-1 -5, -3 -4, 3 -2 5, 1 2 4");
cf[13] = ColourLines("1 -2, 2 3 5, -1 -3 -4, -5 4");
cf[14] = ColourLines("-1 2, -2 -3 -5, 1 3 4, 5 -4");
cf[15] = ColourLines("-1 2, -2 -3 -4, 1 3 5, -5 4");
cf[16] = ColourLines("1 -2, 2 3 4, -1 -3 -5, 5 -4");
//88->00
cf[17] = ColourLines("1 -2,2 -1");
HPDiagram current = getProcessInfo()[abs(diag->id()) - 1];
vector<ColourLines>::size_type offset(0);
if(current.channelType == HPDiagram::tChannel && current.ordered.first)
offset = 5;
else if(current.channelType == HPDiagram::tChannel && !current.ordered.first)
offset = 9;
else
offset = 13;
Selector<const ColourLines *> sel;
if(current.intermediate->iColour() == PDT::Colour0) {
if(getParticleData(current.outgoing.first)->iColour() == PDT::Colour0)
sel.insert(1., &cf[17]);
else
sel.insert(1., &cf[4]);
}
else if(getParticleData(current.outgoing.first)->iColour() == PDT::Colour8) {
sel.insert(0.25, &cf[offset]);
sel.insert(0.25, &cf[offset + 1]);
sel.insert(0.25, &cf[offset + 2]);
sel.insert(0.25, &cf[offset + 3]);
}
else {
if(offset == 5 || offset == 9)
sel.insert(1., &cf[(int)(offset/4) - 1]);
else {
sel.insert(0.5, &cf[2]);
sel.insert(0.5, &cf[3]);
}
}
return sel;
}
void MEvv2ff::persistentOutput(PersistentOStream & os) const {
os << theFerm << theVec << theTen;
}
void MEvv2ff::persistentInput(PersistentIStream & is, int) {
is >> theFerm >> theVec >> theTen;
}
ClassDescription<MEvv2ff> MEvv2ff::initMEvv2ff;
// Definition of the static class description member.
void MEvv2ff::Init() {
static ClassDocumentation<MEvv2ff> documentation
("The MEvv2ff class handles the ME calculation for the general "
"spin configuration vector-vector to fermion-antifermion\n.");
}
void MEvv2ff::constructVertex(tSubProPtr sub) {
ParticleVector ext(4);
ext[0] = sub->incoming().first;
ext[1] = sub->incoming().second;
ext[2] = sub->outgoing()[0];
ext[3] = sub->outgoing()[1];
if( ext[2]->id() < ext[3]->id() ) swap(ext[2], ext[3]);
VBVector v1, v2;
VectorWaveFunction(v1, ext[0], incoming, false, true, true);
VectorWaveFunction(v2, ext[1], incoming, false, true, true);
//function to calculate me2 expects massless incoming vectors
// and this constructor sets the '1' polarisation at element [2]
//in the vector
v1[1] = v1[2];
v2[1] = v2[2];
SpinorBarVector sbar;
SpinorBarWaveFunction(sbar, ext[2], outgoing, true, true);
SpinorVector sp;
SpinorWaveFunction(sp, ext[3], outgoing, true, true);
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = ext[i]->dataPtr();
momenta[i] = ext[i]->momentum();
}
rescaleMomenta(momenta, data);
VectorWaveFunction v1r(rescaledMomenta()[0], data[0], incoming),
v2r(rescaledMomenta()[1], data[1], incoming);
SpinorBarWaveFunction sbr(rescaledMomenta()[2], data[2], outgoing);
SpinorWaveFunction spr(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
v1r.reset(2*ihel);
v1[ihel] = v1r;
v2r.reset(2*ihel);
v2[ihel] = v2r;
sbr.reset(ihel);
sbar[ihel] = sbr;
spr.reset(ihel);
sp[ihel] = spr;
}
double dummy(0.);
ProductionMatrixElement pme = vv2ffME(v1, v2, sbar, sp, dummy);
#ifndef NDEBUG
if( debugME() ) debug(dummy);
#endif
HardVertexPtr hv = new_ptr(HardVertex());
hv->ME(pme);
for(unsigned int i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(ext[i]->spinInfo())->setProductionVertex(hv);
}
void MEvv2ff::debug(double me2) const {
if( !generator()->logfile().is_open() ) return;
long id3(abs(mePartonData()[2]->id())), id4(abs(mePartonData()[3]->id()));
if( mePartonData()[0]->id() != 21 || mePartonData()[1]->id() != 21 ||
id3 != id4 || (id3 != 1000021 && id3 != 5100002 && id3 != 5100001 &&
id3 != 6100002 && id3 != 6100001) )
return;
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
int Nc = sm->Nc();
Energy2 s(sHat());
Energy2 mf2 = meMomenta()[2].m2();
Energy4 spt2 = uHat()*tHat() - sqr(mf2);
Energy2 t3(tHat() - mf2), u4(uHat() - mf2);
double analytic(0.);
if( id3 == 1000021 ) {
analytic = gs4*sqr(Nc)*u4*t3*
( sqr(u4) + sqr(t3) + 4.*mf2*s*spt2/u4/t3 ) *
( 1./sqr(s*t3) + 1./sqr(s*u4) + 1./sqr(u4*t3) )/2./(Nc*Nc - 1.);
}
else {
double brac = sqr(s)/6./t3/u4 - 3./8.;
analytic = gs4*( -4.*sqr(mf2)*brac/t3/u4 + 4.*mf2*brac/s + brac
- 1./3. + 3.*t3*u4/4/s/s);
}
double diff = abs(analytic - me2);
if( diff > 1e-4 ) {
generator()->log()
<< mePartonData()[0]->PDGName() << ","
<< mePartonData()[1]->PDGName() << "->"
<< mePartonData()[2]->PDGName() << ","
<< mePartonData()[3]->PDGName() << " difference: "
<< setprecision(10) << diff << " ratio: " << analytic/me2 << '\n';
}
}
diff --git a/MatrixElement/General/MEvv2ff.fh b/MatrixElement/General/MEvv2ff.fh
deleted file mode 100644
--- a/MatrixElement/General/MEvv2ff.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEvv2ff class.
-//
-#ifndef HERWIG_MEvv2ff_FH
-#define HERWIG_MEvv2ff_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEvv2ff;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEvv2ff,MEvv2ffPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEvv2ff.h b/MatrixElement/General/MEvv2ff.h
--- a/MatrixElement/General/MEvv2ff.h
+++ b/MatrixElement/General/MEvv2ff.h
@@ -1,233 +1,223 @@
// -*- C++ -*-
//
// MEvv2ff.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_MEvv2ff_H
#define HERWIG_MEvv2ff_H
//
// This is the declaration of the MEvv2ff class.
//
#include "GeneralHardME.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
-#include "ProductionMatrixElement.h"
-#include "MEvv2ff.fh"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
using ThePEG::Helicity::SpinorWaveFunction;
using ThePEG::Helicity::SpinorBarWaveFunction;
using ThePEG::Helicity::VectorWaveFunction;
/**
* This class is designed to implement the matrix element for the
* \f$2 \rightarrow 2\f$ process vector-vector to fermion-antifermion pair. It
* inherits from GeneralHardME and implements the me2() virtual function.
*
* @see \ref MEvv2ffInterfaces "The Interfaces"
* defined for MEvv2ff.
* @see GeneralHardME
*
*/
class MEvv2ff: public GeneralHardME {
public:
/** A Vector of VectorWaveFunction objects. */
typedef vector<VectorWaveFunction> VBVector;
/** A vector of SpinorBarWaveFunction objects. */
typedef vector<SpinorWaveFunction> SpinorVector;
/** A vector of SpinorBarWaveFunction objects. */
typedef vector<SpinorBarWaveFunction> SpinorBarVector;
public:
- /**
- * The default constructor.
- */
- inline MEvv2ff();
-
-public:
-
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
/**
* Construct the vertex information for the spin correlations
* @param sub Pointer to the relevent SubProcess
*/
virtual void constructVertex(tSubProPtr sub);
private:
/**
* Calculate the value of the matrix element
*/
ProductionMatrixElement vv2ffME(const VBVector & v1, const VBVector & v2,
const SpinorBarVector & sbar,
const SpinorVector & sp, double & me2) const;
protected:
/**
* A debugging function to test the value of me2 against an
* analytic function.
* @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$
*/
virtual void debug(double me2) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEvv2ff> initMEvv2ff;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEvv2ff & operator=(const MEvv2ff &);
private:
/** @name Dynamically casted vertices. */
//@{
/**
* Intermediate fermion
*/
vector<pair<AbstractFFVVertexPtr, AbstractFFVVertexPtr> > theFerm;
/**
* Intermediate vector
*/
vector<pair<AbstractVVVVertexPtr, AbstractFFVVertexPtr> > theVec;
/**
* Intermediate tensor
*/
vector<pair<AbstractVVTVertexPtr, AbstractFFTVertexPtr> > theTen;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEvv2ff. */
template <>
struct BaseClassTrait<Herwig::MEvv2ff,1> {
/** Typedef of the first base class of MEvv2ff. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEvv2ff class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEvv2ff>
: public ClassTraitsBase<Herwig::MEvv2ff> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEvv2ff"; }
};
/** @endcond */
}
-#include "MEvv2ff.icc"
-
#endif /* HERWIG_MEvv2ff_H */
diff --git a/MatrixElement/General/MEvv2ff.icc b/MatrixElement/General/MEvv2ff.icc
deleted file mode 100644
--- a/MatrixElement/General/MEvv2ff.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// MEvv2ff.icc 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 inlined member functions of
-// the MEvv2ff class.
-//
-
-namespace Herwig {
-
-inline MEvv2ff::MEvv2ff() {}
-
-inline IBPtr MEvv2ff::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEvv2ff::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/General/MEvv2ss.cc b/MatrixElement/General/MEvv2ss.cc
--- a/MatrixElement/General/MEvv2ss.cc
+++ b/MatrixElement/General/MEvv2ss.cc
@@ -1,315 +1,315 @@
// -*- C++ -*-
//
// MEvv2ss.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 MEvv2ss class.
//
#include "MEvv2ss.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "ThePEG/Helicity/Vertex/Scalar/SSSVertex.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Helicity/SpinInfo.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include <numeric>
using namespace Herwig;
using ThePEG::Helicity::TensorWaveFunction;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
using ThePEG::Helicity::SpinfoPtr;
void MEvv2ss::doinit() throw(InitException) {
GeneralHardME::doinit();
size_t ndiags = numberOfDiags();
theSca.resize(ndiags); theVec.resize(ndiags);
theTen.resize(ndiags);
for(size_t i = 0; i < ndiags; ++i ) {
HPDiagram dg = getProcessInfo()[i];
if( !dg.intermediate ) {
theContact = dynamic_ptr_cast<AbstractVVSSVertexPtr>(dg.vertices.first);
}
else if(dg.channelType == HPDiagram::tChannel) {
AbstractVSSVertexPtr vss1 =
dynamic_ptr_cast<AbstractVSSVertexPtr>(dg.vertices.first);
AbstractVSSVertexPtr vss2 =
dynamic_ptr_cast<AbstractVSSVertexPtr>(dg.vertices.second);
theSca[i] = make_pair(vss1, vss2);
}
else {
if( dg.intermediate->iSpin() == PDT::Spin1 ) {
AbstractVVVVertexPtr vvv =
dynamic_ptr_cast<AbstractVVVVertexPtr>(dg.vertices.first);
AbstractVSSVertexPtr vss =
dynamic_ptr_cast<AbstractVSSVertexPtr>(dg.vertices.second);
theVec[i] = make_pair(vvv, vss);
}
else if( dg.intermediate->iSpin() == PDT::Spin2 ) {
AbstractVVTVertexPtr vvt =
dynamic_ptr_cast<AbstractVVTVertexPtr>(dg.vertices.first);
AbstractSSTVertexPtr sst =
dynamic_ptr_cast<AbstractSSTVertexPtr>(dg.vertices.second);
theTen[i] = make_pair(vvt, sst);
}
}
}
}
double MEvv2ss::me2() const {
VBVector v1(2), v2(2);
for( size_t i = 0; i < 2; ++i ) {
v1[i] = VectorWaveFunction(rescaledMomenta()[0],mePartonData()[0], 2*i,
incoming);
v2[i] = VectorWaveFunction(rescaledMomenta()[1],mePartonData()[1], 2*i,
incoming);
}
ScalarWaveFunction sca1(rescaledMomenta()[2],mePartonData()[2],
Complex(1.,0.),outgoing);
ScalarWaveFunction sca2(rescaledMomenta()[3],mePartonData()[3],
Complex(1.,0.),outgoing);
double full_me(0.);
vv2ssME(v1, v2, sca1, sca2, full_me);
#ifndef NDEBUG
if( debugME() ) debug(full_me);
#endif
return full_me;
}
ProductionMatrixElement
MEvv2ss::vv2ssME(const VBVector & v1, const VBVector & v2,
const ScalarWaveFunction & sca1,
const ScalarWaveFunction & sca2, double & me2) const {
const HPCount ndiags(numberOfDiags());
const size_t ncf(numberOfFlows());
const Energy2 m2(scale());
const vector<vector<double> > cfactors = getColourFactors();
const Energy masst = sca1.mass();
const Energy massu = sca2.mass();
vector<double> me(ndiags,0.);
vector<Complex> flows(ncf, Complex(0.)), diag(ndiags, Complex(0.));
ScalarWaveFunction interS; VectorWaveFunction interV;
TensorWaveFunction interT;
//keep location of contact diagram to zero me calc for this diagram
//so as not to add contact term to diagram selector
HPCount contact = ndiags;
//loop over vector helicities
ProductionMatrixElement pme(PDT::Spin1, PDT::Spin1, PDT::Spin0,
PDT::Spin0);
for(unsigned int iv1 = 0; iv1 < 2; ++iv1) {
for(unsigned int iv2 = 0; iv2 < 2; ++iv2) {
//loop over diagrams
flows = vector<Complex>(ncf, Complex(0.));
for(HPCount ix = 0; ix < ndiags; ++ix){
HPDiagram current = getProcessInfo()[ix];
//do four-point diag first
if(current.channelType == HPDiagram::fourPoint) {
diag[ix] = theContact->evaluate(m2, v1[iv1], v2[iv2], sca1, sca2);
contact = ix;
}
else {
tcPDPtr offshell = current.intermediate;
if(current.channelType == HPDiagram::tChannel) {
if(current.ordered.second) {
interS = theSca[ix].first->evaluate(m2, 3, offshell, v1[iv1],
sca1, masst);
diag[ix] = theSca[ix].second->evaluate(m2, v2[iv2], interS, sca2);
}
else {
interS = theSca[ix].first->evaluate(m2, 3, offshell, v1[iv1],
sca2, massu);
diag[ix] = theSca[ix].second->evaluate(m2, v2[iv2], interS, sca1);
}
}
else if(current.channelType == HPDiagram::sChannel) {
if(offshell->iSpin() == PDT::Spin1) {
interV = theVec[ix].first->evaluate(m2, 1, offshell, v1[iv1],
v2[iv2]);
diag[ix] = theVec[ix].second->evaluate(m2, interV, sca1, sca2);
}
else if(offshell->iSpin() == PDT::Spin2) {
interT = theTen[ix].first->evaluate(m2, 1, offshell, v1[iv1],
v2[iv2]);
diag[ix] = theTen[ix].second->evaluate(m2, sca1, sca2, interT);
}
}
else
diag[ix] = 0.;
}
me[ix] += norm(diag[ix]);
//set appropriate element in ProductionMatrixElement
pme(iv1, iv2, 0, 0) =
std::accumulate(flows.begin(), flows.end(), Complex(0.0, 0.0));
//colourflows
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
flows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
}//end of diagram loop
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
me2 += cfactors[ii][ij]*(flows[ii]*conj(flows[ij])).real();
}//iv2 end
}//iv1 end
DVector save(ndiags);
const double ifact = mePartonData()[2]->id() == mePartonData()[3]->id() ?
0.5 : 1.;
// contact must have been set during the loop run
assert(contact != ndiags);
me[contact] = 0.;
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = ifact*me[ix]/256.;
meInfo(save);
me2 *= ifact/256.;
return pme;
}
Selector<const ColourLines *>
MEvv2ss::colourGeometries(tcDiagPtr diag) const {
//88->33bar
static ColourLines cf1("1 4, -1 2 3, -3 -5");
static ColourLines cf2("-1 -5, 3 4, 1 2 -3");
static ColourLines cf3("1 3 4, -2 -3 -5, -1 2");
//88->11
static ColourLines cf4("1 -2, 2 -1");
HPDiagram current = getProcessInfo()[abs(diag->id()) - 1];
Selector<const ColourLines *> sel;
if(current.channelType == HPDiagram::tChannel ) {
if(current.ordered.second)
sel.insert(1., &cf1);
else
sel.insert(1., &cf2);
}
else if(current.channelType == HPDiagram::sChannel) {
if(mePartonData()[2]->iColour() == PDT::Colour0)
sel.insert(1., &cf4);
else
sel.insert(1., &cf3);
}
else
throw MEException() << "MEvv2ss::colourGeometries - "
<< "Cannot find correct colour configuration! \n"
<< Exception::warning;
return sel;
}
void MEvv2ss::persistentOutput(PersistentOStream & os) const {
os << theSca << theVec << theTen << theContact;
}
void MEvv2ss::persistentInput(PersistentIStream & is, int) {
is >> theSca >> theVec >> theTen >> theContact;
}
ClassDescription<MEvv2ss> MEvv2ss::initMEvv2ss;
// Definition of the static class description member.
void MEvv2ss::Init() {
static ClassDocumentation<MEvv2ss> documentation
("This class implements the ME for the vector-vector to scalar-scalar "
"hard-process");
}
void MEvv2ss::constructVertex(tSubProPtr sub) {
ParticleVector ext(4);
ext[0] = sub->incoming().first;
ext[1] = sub->incoming().second;
ext[2] = sub->outgoing()[0];
ext[3] = sub->outgoing()[1];
//Ensure particles are in the same order as specified in the diagrams
if( ext[0]->id() != getIncoming().first ) swap(ext[0], ext[1]);
if( ext[2]->id() != getOutgoing().first ) swap(ext[2], ext[3]);
VBVector v1, v2;
VectorWaveFunction(v1, ext[0], incoming, false, true, true);
VectorWaveFunction(v2, ext[1], incoming, false, true, true);
//function to calculate me2 expects massless incoming vectors
// and this constructor sets the '1' polarisation at element [2]
//in the vector
v1[1] = v1[2];
v2[1] = v2[2];
ScalarWaveFunction sca1(ext[2], outgoing, true, true);
ScalarWaveFunction sca2(ext[3], outgoing, true, true);
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = ext[i]->dataPtr();
momenta[i] = ext[i]->momentum();
}
rescaleMomenta(momenta, data);
VectorWaveFunction v1r(rescaledMomenta()[0], data[0], incoming),
v2r(rescaledMomenta()[1], data[1], incoming);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
v1r.reset(2*ihel);
v1[ihel] = v1r;
v2r.reset(2*ihel);
v2[ihel] = v2r;
}
sca1 = ScalarWaveFunction(rescaledMomenta()[2], data[2], outgoing);
sca2 = ScalarWaveFunction(rescaledMomenta()[3], data[3], outgoing);
double dummy(0.);
ProductionMatrixElement pme = vv2ssME(v1, v2, sca1, sca2, dummy);
#ifndef NDEBUG
if( debugME() ) debug(dummy);
#endif
HardVertexPtr hv = new_ptr(HardVertex());
hv->ME(pme);
for(unsigned int i = 0; i < 4; ++i )
dynamic_ptr_cast<SpinfoPtr>(ext[i]->spinInfo())->setProductionVertex(hv);
}
void MEvv2ss::debug(double me2) const {
if( !generator()->logfile().is_open() ) return;
//SUSY gg>~q~q
long id3 = abs(mePartonData()[2]->id());
long id4 = abs(mePartonData()[3]->id());
if( mePartonData()[0]->id() != 21 || mePartonData()[1]->id() != 21 ||
(id3 < 1000001 && id3 > 1000006 ) || (id3 < 2000001 && id3 > 2000006 ) ||
(id4 < 1000001 && id4 > 1000006 ) || (id4 < 2000001 && id4 > 2000006 ) )
return;
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
int Nc = sm->Nc();
Energy4 s2 = sqr(sHat());
Energy2 m3s = meMomenta()[2].m2();
Energy2 m4s = meMomenta()[3].m2();
Energy4 spt2 = uHat()*tHat() - m3s*m4s;
Energy4 t3s = sqr(tHat() - m3s);
Energy4 u4s = sqr(uHat() - m4s);
double analytic = gs4*Nc*( sqr(spt2) + s2*m3s*m4s ) *
( u4s + t3s - s2/sqr(Nc) )/2./(sqr(Nc) - 1.)/s2/t3s/u4s;
double diff = abs(analytic - me2);
if( diff > 1e-4 ) {
generator()->log()
<< mePartonData()[0]->PDGName() << ","
<< mePartonData()[1]->PDGName() << "->"
<< mePartonData()[2]->PDGName() << ","
<< mePartonData()[3]->PDGName() << " difference: "
<< setprecision(10) << diff << " ratio: " << analytic/me2 << '\n';
}
}
diff --git a/MatrixElement/General/MEvv2ss.fh b/MatrixElement/General/MEvv2ss.fh
deleted file mode 100644
--- a/MatrixElement/General/MEvv2ss.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEvv2ss class.
-//
-#ifndef HERWIG_MEvv2ss_FH
-#define HERWIG_MEvv2ss_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEvv2ss;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEvv2ss,MEvv2ssPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEvv2ss.h b/MatrixElement/General/MEvv2ss.h
--- a/MatrixElement/General/MEvv2ss.h
+++ b/MatrixElement/General/MEvv2ss.h
@@ -1,239 +1,229 @@
// -*- C++ -*-
//
// MEvv2ss.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_MEvv2ss_H
#define HERWIG_MEvv2ss_H
//
// This is the declaration of the MEvv2ss class.
//
#include "GeneralHardME.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSSVertex.h"
-#include "ProductionMatrixElement.h"
-#include "MEvv2ss.fh"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
using ThePEG::Helicity::VectorWaveFunction;
using ThePEG::Helicity::ScalarWaveFunction;
/**
* This is the implementation of the matrix element for the process
* vector-vector to scalar-scalar. It inherits from GeneralHardME and
* implements the required virtual functions.
*
* @see \ref MEff2ffInterfaces "The Interfaces"
* defined for MEff2ff.
* @see GeneralHardME
*/
class MEvv2ss: public GeneralHardME {
public:
/** A vector of VectorWaveFunction objects*/
typedef vector<VectorWaveFunction> VBVector;
public:
- /**
- * The default constructor.
- */
- inline MEvv2ss();
-
-public:
-
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
/**
* Set the Hardvertex for the spin correlations
* @param sub
*/
virtual void constructVertex(tSubProPtr sub);
private:
/**
* Calculate the matrix element.
* @param v1 A vector of VectorWaveFunction objects for the first boson
* @param v2 A vector of VectorWaveFunction objects for the second boson
* @param sca1 A ScalarWaveFunction for the first outgoing
* @param sca2 A ScalarWaveFunction for the second outgoing
* @param me2 The value of the spin-summed matrix element squared
* (to be calculated)
*/
ProductionMatrixElement vv2ssME(const VBVector & v1, const VBVector & v2,
const ScalarWaveFunction & sca1,
const ScalarWaveFunction & sca2,
double & me2) const;
protected:
/**
* A debugging function to test the value of me2 against an
* analytic function.
* @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$
*/
virtual void debug(double me2) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEvv2ss> initMEvv2ss;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEvv2ss & operator=(const MEvv2ss &);
private:
/** @name The dynamically casted vertices. */
//@{
/**
* Intermediate t-channel scalar
*/
vector<pair<AbstractVSSVertexPtr, AbstractVSSVertexPtr> > theSca;
/**
* Intermediate s-channel vector
*/
vector<pair<AbstractVVVVertexPtr, AbstractVSSVertexPtr> > theVec;
/**
* Intermediate s-channel tensor
*/
vector<pair<AbstractVVTVertexPtr, AbstractSSTVertexPtr> > theTen;
/**
* The contact vertex
*/
AbstractVVSSVertexPtr theContact;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEvv2ss. */
template <>
struct BaseClassTrait<Herwig::MEvv2ss,1> {
/** Typedef of the first base class of MEvv2ss. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEvv2ss class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEvv2ss>
: public ClassTraitsBase<Herwig::MEvv2ss> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEvv2ss"; }
};
/** @endcond */
}
-#include "MEvv2ss.icc"
-
#endif /* HERWIG_MEvv2ss_H */
diff --git a/MatrixElement/General/MEvv2ss.icc b/MatrixElement/General/MEvv2ss.icc
deleted file mode 100644
--- a/MatrixElement/General/MEvv2ss.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// MEvv2ss.icc 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 inlined member functions of
-// the MEvv2ss class.
-//
-
-namespace Herwig {
-
-inline MEvv2ss::MEvv2ss() {}
-
-inline IBPtr MEvv2ss::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEvv2ss::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/General/MEvv2vv.cc b/MatrixElement/General/MEvv2vv.cc
--- a/MatrixElement/General/MEvv2vv.cc
+++ b/MatrixElement/General/MEvv2vv.cc
@@ -1,397 +1,397 @@
// -*- C++ -*-
//
// MEvv2vv.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 MEvv2vv class.
//
#include "MEvv2vv.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "ThePEG/Helicity/Vertex/Tensor/VVTVertex.h"
#include "ThePEG/Helicity/SpinInfo.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
-#include "HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include <numeric>
using namespace Herwig;
using ThePEG::Helicity::ScalarWaveFunction;
using ThePEG::Helicity::TensorWaveFunction;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
using ThePEG::Helicity::SpinfoPtr;
void MEvv2vv::doinit() throw(InitException) {
GeneralHardME::doinit();
size_t ndiags = numberOfDiags();
theScaV.resize(ndiags);
theVecV.resize(ndiags);
theTenV.resize(ndiags);
for(size_t i = 0; i < ndiags; ++i) {
HPDiagram diag = getProcessInfo()[i];
tcPDPtr offshell = diag.intermediate;
if(!offshell)
theFPVertex = dynamic_ptr_cast<AbstractVVVVVertexPtr>
(diag.vertices.first);
else if(offshell->iSpin() == PDT::Spin0) {
AbstractVVSVertexPtr vert1 = dynamic_ptr_cast<AbstractVVSVertexPtr>
(diag.vertices.first);
AbstractVVSVertexPtr vert2 = dynamic_ptr_cast<AbstractVVSVertexPtr>
(diag.vertices.second);
theScaV[i] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractVVVVertexPtr vert1 = dynamic_ptr_cast<AbstractVVVVertexPtr>
(diag.vertices.first);
AbstractVVVVertexPtr vert2 = dynamic_ptr_cast<AbstractVVVVertexPtr>
(diag.vertices.second);
theVecV[i] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractVVTVertexPtr vert1 = dynamic_ptr_cast<AbstractVVTVertexPtr>
(diag.vertices.first);
AbstractVVTVertexPtr vert2 = dynamic_ptr_cast<AbstractVVTVertexPtr>
(diag.vertices.second);
theTenV[i] = make_pair(vert1, vert2);
}
}
}
double MEvv2vv::me2() const {
VBVector va(2), vb(2), vc(3), vd(3);
for(unsigned int i = 0; i < 2; ++i) {
va[i] = VectorWaveFunction(rescaledMomenta()[0], mePartonData()[0], 2*i,
incoming);
vb[i] = VectorWaveFunction(rescaledMomenta()[1], mePartonData()[1], 2*i,
incoming);
}
//always 0 and 2 polarisations
for(unsigned int i = 0; i < 2; ++i) {
vc[2*i] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 2*i,
outgoing);
vd[2*i] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], 2*i,
outgoing);
}
bool mc = !(mePartonData()[2]->mass() > 0.*MeV);
//massive vector, also 1
if( !mc )
vc[1] = VectorWaveFunction(rescaledMomenta()[2], mePartonData()[2], 1,
outgoing);
bool md = !(mePartonData()[3]->mass() > 0.*MeV);
if( !md )
vd[1] = VectorWaveFunction(rescaledMomenta()[3], mePartonData()[3], 1,
outgoing);
double full_me(0.);
vv2vvHeME(va, vb, vc, mc, vd, md, full_me);
#ifndef NDEBUG
if( debugME() ) debug(full_me);
#endif
return full_me;
}
ProductionMatrixElement
MEvv2vv::vv2vvHeME(VBVector & vin1, VBVector & vin2,
VBVector & vout1, bool mc, VBVector & vout2, bool md,
double & mesq) const {
const HPCount ndiags = numberOfDiags();
const size_t ncf(numberOfFlows());
const vector<vector<double> > cfactors(getColourFactors());
const Energy2 q2(scale());
const Energy mass = vout1[0].mass();
vector<Complex> diag(ndiags, Complex(0.));
vector<double> me(ndiags, 0.);
ScalarWaveFunction interS; VectorWaveFunction interV;
TensorWaveFunction interT;
ProductionMatrixElement prodME(PDT::Spin1, PDT::Spin1, PDT::Spin1, PDT::Spin1);
for(unsigned int ihel1 = 0; ihel1 < 2; ++ihel1) {
for(unsigned int ihel2 = 0; ihel2 < 2; ++ihel2) {
for(unsigned int ohel1 = 0; ohel1 < 3; ++ohel1) {
if(mc && ohel1 == 1) ++ohel1;
for(unsigned int ohel2 = 0; ohel2 < 3; ++ohel2) {
if(md && ohel2 == 1) ++ohel2;
vector<Complex> cflows(ncf, Complex(0.0));
for(HPCount ix = 0; ix < ndiags; ++ix) {
HPDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(!offshell) continue;
if(current.channelType == HPDiagram::sChannel) {
if(offshell->iSpin() == PDT::Spin1) {
interV = theVecV[ix].first->evaluate(q2, 1, offshell,
vin1[ihel1], vin2[ihel2]);
diag[ix] = theVecV[ix].second->evaluate(q2, vout1[ohel1],
vout2[ohel2], interV);
diag[ix] += theFPVertex->evaluate(q2, 0, vout1[ohel1], vin2[ihel2],
vout2[ohel2], vin1[ihel1]);
}
else if(offshell->iSpin() == PDT::Spin2) {
interT = theTenV[ix].first->evaluate(q2, 1, offshell,
vin1[ihel1], vin2[ihel2]);
diag[ix] = theTenV[ix].second->evaluate(q2, vout1[ohel1],
vout2[ohel2],interT);
}
}
else if(current.channelType == HPDiagram::tChannel) {
if(offshell->iSpin() == PDT::Spin1) {
if(current.ordered.second) {
interV = theVecV[ix].first->evaluate(q2, 3, offshell, vin1[ihel1],
vout1[ohel1], mass);
diag[ix] = theVecV[ix].second->evaluate(q2, vin2[ihel2], interV,
vout2[ohel2]);
diag[ix] += theFPVertex->evaluate(q2, 0, vin1[ihel1], vin2[ihel2],
vout1[ohel1], vout2[ohel2]);
}
else {
interV = theVecV[ix].first->evaluate(q2, 3, offshell, vin2[ihel2],
vout1[ohel1], mass);
diag[ix] = theVecV[ix].second->evaluate(q2, vin1[ihel1], interV,
vout2[ohel2]);
diag[ix] += theFPVertex->evaluate(q2, 0, vin2[ihel2], vin1[ihel1],
vout1[ohel1], vout2[ohel2]);
}
}
else if(offshell->iSpin() == PDT::Spin2) {
if(current.ordered.second) {
interT = theTenV[ix].first->evaluate(q2, 3, offshell, vin1[ihel1],
vout1[ohel1], mass);
diag[ix] = theTenV[ix].second->evaluate(q2, vin2[ihel2],
vout2[ohel2], interT);
}
else {
interT = theTenV[ix].first->evaluate(q2, 3, offshell, vin2[ihel2],
vout1[ohel1], mass);
diag[ix] = theTenV[ix].second->evaluate(q2, vin1[ihel1],
vout2[ohel2], interT);
}
}
}
else
diag[ix] = 0.0;
me[ix] += norm(diag[ix]);
//Compute flows
for(size_t iy = 0; iy < current.colourFlow.size(); ++iy)
cflows[current.colourFlow[iy].first - 1] +=
current.colourFlow[iy].second * diag[ix];
} //end of diagram loop
//set the appropriate element in ProductionMatrixElement
prodME(ihel1, ihel2, ohel1, ohel2) =
std::accumulate(cflows.begin(), cflows.end(), Complex(0.0, 0.0));
for(size_t ii = 0; ii < ncf; ++ii)
for(size_t ij = 0; ij < ncf; ++ij)
mesq += cfactors[ii][ij]*(cflows[ii]*conj(cflows[ij])).real();
}
}
}
}
const double identfact = mePartonData()[2]->id() == mePartonData()[3]->id()
? 0.5 : 1.;
const double colfact = mePartonData()[0]->iColour() == PDT::Colour8 ?
1./64. : 1;
DVector save(ndiags);
for(DVector::size_type ix = 0; ix < ndiags; ++ix)
save[ix] = 0.25*identfact*colfact*me[ix];
meInfo(save);
mesq *= 0.25*identfact*colfact;
return prodME;
}
Selector<const ColourLines *>
MEvv2vv::colourGeometries(tcDiagPtr diag) const {
static vector<ColourLines> colourflows(16);
//88->8->88
colourflows[0] = ColourLines("1 -2, -1 -3 -4, 4 -5, 2 3 5");
colourflows[1] = ColourLines("-1 2, 1 3 4, -4 5, -2 -3 -5");
colourflows[2] = ColourLines("1 -2, -1 -3 -5, 5 -4, 2 3 4");
colourflows[3] = ColourLines("-1 2, 1 3 5, -5 4, -2 -3 -4");
colourflows[4] = ColourLines("1 4, -1 -2 3, -3 -5, -4 2 5");
colourflows[5] = ColourLines("-1 -4, 1 2 -3, 3 5, 4 -2 -5");
colourflows[6] = ColourLines("1 4, -1 -2 -5, 3 5, -3 2 -4");
colourflows[7] = ColourLines("-1 -4, 1 2 5, -3 -5, 3 -2 4");
colourflows[8] = ColourLines("1 5, -1 -2 3, -3 -4, -5 2 4");
colourflows[9] = ColourLines("-1 -5, 1 2 -3, 3 4, 5 -2 -4");
colourflows[10] = ColourLines("1 5, -1 -2 -4, 3 4, -3 2 -5");
colourflows[11] = ColourLines("-1 -5, 1 2 4, -3 -4, 3 -2 5");
//88->0->88
colourflows[12] = ColourLines("1 -2, 2 -1, 4 -5, 5 -4");
colourflows[13] = ColourLines("1 4, -1 -4, 3 5, -5 -3");
colourflows[14] = ColourLines("1 5, -1 -5, 3 4, -3 -4");
//88->0->00
colourflows[15] = ColourLines("1 -2,2 -1");
HPDiagram current = getProcessInfo()[abs(diag->id()) - 1];
Selector<const ColourLines *> select;
if(current.channelType == HPDiagram::sChannel) {
if(current.intermediate->iColour() == PDT::Colour8) {
select.insert(0.25, &colourflows[0]);
select.insert(0.25, &colourflows[1]);
select.insert(0.25, &colourflows[2]);
select.insert(0.25, &colourflows[3]);
}
else {
if(getParticleData(current.outgoing.first)->iColour() == PDT::Colour0)
select.insert(1., &colourflows[15]);
else
select.insert(1., &colourflows[12]);
}
}
else if(current.channelType == HPDiagram::tChannel) {
if(current.ordered.second) {
if(current.intermediate->iColour() == PDT::Colour8) {
select.insert(0.25, &colourflows[4]);
select.insert(0.25, &colourflows[5]);
select.insert(0.25, &colourflows[6]);
select.insert(0.25, &colourflows[7]);
}
else
select.insert(1., &colourflows[13]);
}
else {
if(current.intermediate->iColour() == PDT::Colour8) {
select.insert(0.25, &colourflows[8]);
select.insert(0.25, &colourflows[9]);
select.insert(0.25, &colourflows[10]);
select.insert(0.25, &colourflows[11]);
}
else
select.insert(1., &colourflows[14]);
}
}
else
throw MEException() << "MEvv2vv::colourGeometries - Trying to set ColourLines "
<< "for an unknown diagram type. "
<< Exception::warning;
return select;
}
void MEvv2vv::persistentOutput(PersistentOStream & os) const {
os << theScaV << theVecV << theTenV << theFPVertex;
}
void MEvv2vv::persistentInput(PersistentIStream & is, int) {
is >> theScaV >> theVecV >> theTenV >> theFPVertex;
}
ClassDescription<MEvv2vv> MEvv2vv::initMEvv2vv;
// Definition of the static class description member.
void MEvv2vv::Init() {
static ClassDocumentation<MEvv2vv> documentation
("This is the implementation of the 2 to 2 ME for a pair"
"of massless vector-bosons to a pair of vector bosons");
}
void MEvv2vv::constructVertex(tSubProPtr sub) {
ParticleVector ext(4);
ext[0] = sub->incoming().first;
ext[1] = sub->incoming().second;
ext[2] = sub->outgoing()[0];
ext[3] = sub->outgoing()[1];
//Ensure particles are in the same order as specified in the diagrams
if( ext[0]->id() != getIncoming().first ) swap(ext[0], ext[1]);
if( ext[2]->id() != getOutgoing().first ) swap(ext[2], ext[3]);
VBVector v1, v2, v3, v4;
VectorWaveFunction(v1, ext[0], incoming, false, true, true);
VectorWaveFunction(v2, ext[1], incoming, false, true, true);
//function to calculate me2 expects massless incoming vectors
// and this constructor sets the '1' polarisation at element [2]
//in the vector
bool mc = !(ext[2]->data().mass() > 0.*MeV);
bool md = !(ext[3]->data().mass() > 0.*MeV);
VectorWaveFunction(v3, ext[2], outgoing, true, mc, true);
VectorWaveFunction(v4, ext[3], outgoing, true, md, true);
double dummy(0.);
//Need to use rescale momenta to calculate matrix element
cPDVector data(4);
vector<Lorentz5Momentum> momenta(4);
for( size_t i = 0; i < 4; ++i ) {
data[i] = ext[i]->dataPtr();
momenta[i] = ext[i]->momentum();
}
rescaleMomenta(momenta, data);
VectorWaveFunction vr1(rescaledMomenta()[0], data[0], incoming);
VectorWaveFunction vr2(rescaledMomenta()[1], data[1], incoming);
VectorWaveFunction vr3(rescaledMomenta()[2], data[2], outgoing);
VectorWaveFunction vr4(rescaledMomenta()[3], data[3], outgoing);
for( unsigned int ihel = 0; ihel < 2; ++ihel ) {
vr1.reset(2*ihel);
v1[ihel] = vr1;
vr2.reset(2*ihel);
v2[ihel] = vr2;
vr3.reset(2*ihel);
v3[2*ihel] = vr3;
vr4.reset(2*ihel);
v4[2*ihel] = vr4;
}
if( !mc ) {
vr3.reset(1);
v3[1] = vr3;
}
if( !md ) {
vr4.reset(1);
v4[1] = vr4;
}
ProductionMatrixElement pme = vv2vvHeME(v1, v2, v3, mc, v4, md, dummy);
#ifndef NDEBUG
if( debugME() ) debug(dummy);
#endif
HardVertexPtr hv = new_ptr(HardVertex());
hv->ME(pme);
for(unsigned int i = 0; i < 4; ++i)
dynamic_ptr_cast<SpinfoPtr>(ext[i]->spinInfo())->setProductionVertex(hv);
}
void MEvv2vv::debug(double me2) const {
if( !generator()->logfile().is_open() ) return;
if( mePartonData()[0]->id() != 21 || mePartonData()[1]->id() != 21 ||
mePartonData()[2]->id() != 5100021 ||
mePartonData()[3]->id() != 5100021 ) return;
tcSMPtr sm = generator()->standardModel();
double gs4 = sqr( 4.*Constants::pi*sm->alphaS(scale()) );
Energy2 s(sHat());
Energy2 mf2 = meMomenta()[2].m2();
Energy2 t3(tHat() - mf2), u4(uHat() - mf2);
Energy4 s2(sqr(s)), t3s(sqr(t3)), u4s(sqr(u4));
Energy4 num = s2 + t3s + u4s;
double analytic = 3.*mf2*( mf2*num/t3s/u4s - num/s/t3/u4 ) + 1.
+ sqr(num)*num/4./s2/t3s/u4s - t3*u4/s2;
analytic *= 9.*gs4/8.;
double diff = abs( analytic - me2 );
if( diff > 1e-4 ) {
generator()->log()
<< mePartonData()[0]->PDGName() << ","
<< mePartonData()[1]->PDGName() << "->"
<< mePartonData()[2]->PDGName() << ","
<< mePartonData()[3]->PDGName() << " difference: "
<< setprecision(10) << diff << " ratio: " << analytic/me2 << '\n';
}
}
diff --git a/MatrixElement/General/MEvv2vv.fh b/MatrixElement/General/MEvv2vv.fh
deleted file mode 100644
--- a/MatrixElement/General/MEvv2vv.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEvv2vv class.
-//
-#ifndef HERWIG_MEvv2vv_FH
-#define HERWIG_MEvv2vv_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEvv2vv;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEvv2vv,MEvv2vvPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/General/MEvv2vv.h b/MatrixElement/General/MEvv2vv.h
--- a/MatrixElement/General/MEvv2vv.h
+++ b/MatrixElement/General/MEvv2vv.h
@@ -1,234 +1,224 @@
// -*- C++ -*-
//
// MEvv2vv.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_MEvv2vv_H
#define HERWIG_MEvv2vv_H
//
// This is the declaration of the MEvv2vv class.
//
#include "GeneralHardME.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVVertex.h"
-#include "ProductionMatrixElement.h"
-#include "MEvv2vv.fh"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VectorWaveFunction;
/**
* This is the implementation of the matrix element for
* \f$2\to 2\f$ massless vector-boson pair to vector-boson pair. It inherits from
* GeneralHardME and implements the appropriate virtual member functions.
*
* @see \ref MEvv2vvInterfaces "The interfaces"
* defined for MEvv2vv.
*/
class MEvv2vv: public GeneralHardME {
public:
/**
* Typedef for VectorWaveFunction
*/
typedef vector<VectorWaveFunction> VBVector;
public:
- /**
- * The default constructor.
- */
- inline MEvv2vv();
-
-public:
-
/** @name Virtual functions required by the GeneralHardME class. */
//@{
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
/**
* Construct the vertex information for the spin correlations
* @param sub Pointer to the relevent SubProcess
*/
virtual void constructVertex(tSubProPtr sub);
private:
/**
* Compute the matrix element for \f$V\, V\to V\, V\f$
* @param vin1 VectorWaveFunctions for first incoming particle
* @param vin2 VectorWaveFunctions for second incoming particle
* @param vout1 VectorWaveFunctions for first outgoing particle
* @param mc Whether vout1 is massless or not
* @param vout2 VectorWaveFunctions for outgoing particle
* @param md Whether vout2 is massless or not
* @param me2 colour averaged, spin summed ME
* @return ProductionMatrixElement containing results of
* helicity calculations
*/
ProductionMatrixElement
vv2vvHeME(VBVector & vin1, VBVector & vin2,
VBVector & vout1, bool mc, VBVector & vout2, bool md,
double & me2) const;
protected:
/**
* A debugging function to test the value of me2 against an
* analytic function.
* @param me2 The value of the \f$ |\bar{\mathcal{M}}|^2 \f$
*/
virtual void debug(double me2) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const;
+ inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const;
+ inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEvv2vv> initMEvv2vv;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEvv2vv & operator=(const MEvv2vv &);
private:
/**
* Store the dynamically casted VVSVertex pointers
*/
vector<pair<AbstractVVSVertexPtr, AbstractVVSVertexPtr> > theScaV;
/**
* Store the dynamically casted VVVVertex pointers
*/
vector<pair<AbstractVVVVertexPtr, AbstractVVVVertexPtr> > theVecV;
/**
* Store the dynamically casted VVTVertex pointers
*/
vector<pair<AbstractVVTVertexPtr, AbstractVVTVertexPtr> > theTenV;
/**
* Store the dynamically casted VVVVVertex pointer
*/
AbstractVVVVVertexPtr theFPVertex;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEvv2vv. */
template <>
struct BaseClassTrait<Herwig::MEvv2vv,1> {
/** Typedef of the first base class of MEvv2vv. */
typedef Herwig::GeneralHardME NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEvv2vv class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEvv2vv>
: public ClassTraitsBase<Herwig::MEvv2vv> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEvv2vv"; }
};
/** @endcond */
}
-#include "MEvv2vv.icc"
-
#endif /* HERWIG_MEvv2vv_H */
diff --git a/MatrixElement/General/MEvv2vv.icc b/MatrixElement/General/MEvv2vv.icc
deleted file mode 100644
--- a/MatrixElement/General/MEvv2vv.icc
+++ /dev/null
@@ -1,26 +0,0 @@
-// -*- C++ -*-
-//
-// MEvv2vv.icc 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 inlined member functions of
-// the MEvv2vv class.
-//
-
-namespace Herwig {
-
-inline MEvv2vv::MEvv2vv() {}
-
-inline IBPtr MEvv2vv::clone() const {
- return new_ptr(*this);
-}
-
-inline IBPtr MEvv2vv::fullclone() const {
- return new_ptr(*this);
-}
-
-}
diff --git a/MatrixElement/General/Makefile.am b/MatrixElement/General/Makefile.am
--- a/MatrixElement/General/Makefile.am
+++ b/MatrixElement/General/Makefile.am
@@ -1,13 +1,13 @@
noinst_LTLIBRARIES = libHwGeneralME.la
libHwGeneralME_la_SOURCES = \
GeneralHardME.cc GeneralHardME.h GeneralHardME.icc GeneralHardME.fh \
-MEvv2ff.cc MEvv2ff.h MEvv2ff.fh MEvv2ff.icc MEvv2ss.cc MEvv2ss.h \
-MEvv2ss.icc MEvv2ss.fh MEfv2fs.cc MEfv2fs.h MEfv2fs.icc MEfv2fs.fh MEff2ss.cc \
-MEff2ss.h MEff2ss.icc MEff2ss.fh MEff2ff.cc MEff2ff.h MEff2ff.fh \
-MEff2ff.icc MEff2vv.cc MEff2vv.h MEff2vv.icc MEff2vv.fh \
-MEfv2vf.h MEfv2vf.fh MEfv2vf.icc MEfv2vf.cc \
-MEvv2vv.h MEvv2vv.fh MEvv2vv.icc MEvv2vv.cc \
-HardVertex.fh HardVertex.h HardVertex.icc HardVertex.cc \
-ProductionMatrixElement.h ProductionMatrixElement.icc ProductionMatrixElement.cc \
-MEff2vs.h MEff2vs.fh MEff2vs.icc MEff2vs.cc
+MEvv2ff.cc MEvv2ff.h \
+MEvv2ss.cc MEvv2ss.h \
+MEfv2fs.cc MEfv2fs.h \
+MEff2ss.cc MEff2ss.h \
+MEff2ff.cc MEff2ff.h \
+MEff2vv.cc MEff2vv.h \
+MEfv2vf.cc MEfv2vf.h \
+MEff2vs.h MEff2vs.cc \
+MEvv2vv.cc MEvv2vv.h
diff --git a/MatrixElement/General/ProductionMatrixElement.cc b/MatrixElement/General/ProductionMatrixElement.cc
deleted file mode 100644
--- a/MatrixElement/General/ProductionMatrixElement.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// -*- C++ -*-
-//
-// ProductionMatrixElement.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 ProductionMatrixElement class.
-//
-// Author: Peter Richardson
-//
-
-#include "ProductionMatrixElement.h"
-#include "ThePEG/Interface/ClassDocumentation.h"
-
-#ifdef ThePEG_TEMPLATES_IN_CC_FILE
-// #include "ProductionMatrixElement.tcc"
-#endif
-
-namespace Herwig {
-using namespace ThePEG;
-
-NoPIOClassDescription<ProductionMatrixElement> ProductionMatrixElement::initProductionMatrixElement;
-// Definition of the static class description member.
-
-void ProductionMatrixElement::Init() {
-
- static ClassDocumentation<ProductionMatrixElement> documentation
- ("The ProductionMatrixElement class is designed to store the "
- "matrix element for a hard interaction.");
-
-}
-
-// calculate a decay matrix for one of the incoming particles
-RhoDMatrix ProductionMatrixElement::calculateDMatrix(int id, RhoDMatrix rhoin,
- vector<RhoDMatrix> rhoout)
-{
- // vectors for the helicities
- vector<unsigned int> ihel1(_outspin.size()+2),ihel2(_outspin.size()+2);
- // rhomatrix to be returned
- RhoDMatrix output(_inspin[id]); output.zero();
- // loop over all helicity components of the matrix element
- // outer loop
- Complex temp;
- unsigned int ix,iy;
- int ixa,iya;
- for(ix=0;ix<_matrixelement.size();++ix)
- {
- // map the vector index to the helicities
- for(ixa=_outspin.size()+1;ixa>=0;--ixa)
- {ihel1[ixa]=(ix%_constants[ixa])/_constants[ixa+1];}
- // inner loop
- for(iy=0;iy<_matrixelement.size();++iy)
- {
- // map the vector index to the helicities
- for(iya=_outspin.size()+1;iya>=0;--iya)
- {ihel2[iya]=(iy%_constants[iya])/_constants[iya+1];}
- // matrix element piece
- temp=_matrixelement[ix]*conj(_matrixelement[iy]);
- // spin density matrices for the outgoing particles
- for(unsigned int iz=0;iz<_outspin.size();++iz)
- {temp*=rhoout[iz](ihel1[iz+2],ihel2[iz+2]);}
- // construct the spin density matrix
- if(id==0)
- {
- temp*=rhoin(ihel1[1],ihel2[1]);
- output(ihel1[0],ihel2[0])+=temp;
- }
- else
- {
- temp*=rhoin(ihel1[0],ihel2[0]);
- output(ihel1[1],ihel2[1])+=temp;
- }
- }
- }
- // return the answer
- return output;
-}
-
-// calculate the rho matrix for a given outgoing particle
-RhoDMatrix ProductionMatrixElement::calculateRhoMatrix(int id,
- RhoDMatrix rhoin0,
- RhoDMatrix rhoin1,
- vector<RhoDMatrix>rhoout)
-{
- unsigned int ix,iy;
- int ixa,iya;
- // vectors for the helicities
- vector<unsigned int> ihel1(_outspin.size()+2),ihel2(_outspin.size()+2);
- // rhomatrix to be returned
- RhoDMatrix output(_outspin[id]); output.zero();
- // loop over all helicity components of the matrix element
- // outer loop
- Complex temp;
- for(ix=0;ix<_matrixelement.size();++ix)
- {
- // map the vector index to the helicities
- for(ixa=_outspin.size()+1;ixa>=0;--ixa)
- {ihel1[ixa]=(ix%_constants[ixa])/_constants[ixa+1];}
- // inner loop
- for(iy=0;iy<_matrixelement.size();++iy)
- {
- // map the vector index to the helicities
- for(iya=_outspin.size()+1;iya>=0;--iya)
- {ihel2[iya]=(iy%_constants[iya])/_constants[iya+1];}
- // matrix element piece
- temp=_matrixelement[ix]*conj(_matrixelement[iy]);
- // spin denisty matrix for the incoming particles
- temp*=rhoin0(ihel1[0],ihel2[0]);
- temp*=rhoin1(ihel1[1],ihel2[1]);
- // spin density matrix for the outgoing particles
- for(unsigned int iz=0;iz<_outspin.size()-1;++iz)
- {
- if(int(iz)<id){temp*=rhoout[iz](ihel1[iz+2],ihel2[iz+2]);}
- else{temp*=rhoout[iz](ihel1[iz+3],ihel2[iz+3]);}
- }
- output(ihel1[id+2],ihel2[id+2])+=temp;
- }
- }
- // normalise the matrix so it has unit trace
- output.normalize();
- // return the answer
- return output;
-}
-
-}
diff --git a/MatrixElement/General/ProductionMatrixElement.h b/MatrixElement/General/ProductionMatrixElement.h
deleted file mode 100644
--- a/MatrixElement/General/ProductionMatrixElement.h
+++ /dev/null
@@ -1,454 +0,0 @@
-// -*- C++ -*-
-//
-// ProductionMatrixElement.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_ProductionMatrixElement_H
-#define HERWIG_ProductionMatrixElement_H
-//
-// This is the declaration of the ProductionMatrixElement class.
-
-#include <ThePEG/Config/ThePEG.h>
-#include <ThePEG/Utilities/ClassDescription.h>
-#include <ThePEG/Helicity/RhoDMatrix.h>
-// #include "ProductionMatrixElement.fh"
-// #include "ProductionMatrixElement.xh"
-
-namespace Herwig {
-using ThePEG::Helicity::RhoDMatrix;
-
-using namespace ThePEG;
-
-/** \ingroup Helicity
- *
- * The storage of the helicity amplitude expression for the matrix element
- * of a hard process. Two incoming particles and an arbitary number of
- * external particles are supported.
- *
- * @see DecayMatrixElement
- * @see RhoDMatrix
- * @see HardVertex
- *
- * \author Peter Richardson
- */
-
-class ProductionMatrixElement: public Base {
-
-public:
-
- /** @name Standard constructors and destructors. */
- //@{
- /**
- * Constructor for 2-1 scattering.
- * @param in1 \f$2S+1\f$ for the first incoming particle.
- * @param in2 \f$2S+1\f$ for the second incoming particle.
- * @param out \f$2S+1\f$ for the outgoing particle.
- */
- inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out);
-
- /**
- * Constructor for 2-2 scattering.
- * @param in1 \f$2S+1\f$ for the first incoming particle.
- * @param in2 \f$2S+1\f$ for the second incoming particle.
- * @param out1 \f$2S+1\f$ for the first outgoing particle.
- * @param out2 \f$2S+1\f$ for the second outgoing particle.
- */
- inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
- PDT::Spin out2);
-
- /**
- * Constructor for 2-3 scattering.
- * @param in1 \f$2S+1\f$ for the first incoming particle.
- * @param in2 \f$2S+1\f$ for the second incoming particle.
- * @param out1 \f$2S+1\f$ for the first outgoing particle.
- * @param out2 \f$2S+1\f$ for the second outgoing particle.
- * @param out3 \f$2S+1\f$ for the third outgoing particle.
- */
- inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
- PDT::Spin out2,PDT::Spin out3);
-
- /**
- * Constructor for 2-4 scattering.
- * @param in1 \f$2S+1\f$ for the first incoming particle.
- * @param in2 \f$2S+1\f$ for the second incoming particle.
- * @param out1 \f$2S+1\f$ for the first outgoing particle.
- * @param out2 \f$2S+1\f$ for the second outgoing particle.
- * @param out3 \f$2S+1\f$ for the third outgoing particle.
- * @param out4 \f$2S+1\f$ for the fourth outgoing particle.
- */
- inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
- PDT::Spin out2,PDT::Spin out3, PDT::Spin out4);
-
- /**
- * Constructor for 2-5 scattering.
- * @param in1 \f$2S+1\f$ for the first incoming particle.
- * @param in2 \f$2S+1\f$ for the second incoming particle.
- * @param out1 \f$2S+1\f$ for the first outgoing particle.
- * @param out2 \f$2S+1\f$ for the second outgoing particle.
- * @param out3 \f$2S+1\f$ for the third outgoing particle.
- * @param out4 \f$2S+1\f$ for the fourth outgoing particle.
- * @param out5 \f$2S+1\f$ for the fifth outgoing particle.
- */
- inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
- PDT::Spin out2,PDT::Spin out3, PDT::Spin out4,
- PDT::Spin out5);
-
- /**
- * Constructor for 2-6 scattering.
- * @param in1 \f$2S+1\f$ for the first incoming particle.
- * @param in2 \f$2S+1\f$ for the second incoming particle.
- * @param out1 \f$2S+1\f$ for the first outgoing particle.
- * @param out2 \f$2S+1\f$ for the second outgoing particle.
- * @param out3 \f$2S+1\f$ for the third outgoing particle.
- * @param out4 \f$2S+1\f$ for the fourth outgoing particle.
- * @param out5 \f$2S+1\f$ for the fifth outgoing particle.
- * @param out6 \f$2S+1\f$ for the sixth outgoing particle.
- */
- inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
- PDT::Spin out2,PDT::Spin out3, PDT::Spin out4,
- PDT::Spin out5, PDT::Spin out6);
-
- /**
- * Constructor for 2-n scattering.
- * @param in1 \f$2S+1\f$ for the first incoming particle.
- * @param in2 \f$2S+1\f$ for the second incoming particle.
- * @param out A vector containing \f$2S+1\f$ for the outgoing particles.
- */
- inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,vector<PDT::Spin> out);
-
- /**
- * Default constructor.
- */
- inline ProductionMatrixElement();
- //@}
-
-public:
-
- /** @name Access to the spins of the particles. */
- //@{
- /**
- * Get the spins of the incoming particles particle
- * @return A vector containing \f$2S+1\f$ for the two incoming particles.
- */
- inline vector<PDT::Spin> inspin();
-
- /**
- * Get the spins of the outgoing particles.
- * @return A vector containing \f$2S+1\f$ for the outgoing particles.
- */
- inline vector<PDT::Spin> outspin();
- //@}
-
-public:
-
- /** @name Access to the individual helicity components. */
- //@{
-
- /**
- * Access the helicity components for a 2-1 scattering. This method supplies
- * the component but does not allow it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel The helicity of the outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel) const;
-
- /**
- * Access the helicity components for a 2-1 scattering. This method supplies
- * the component and allows it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel The helicity of the outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel);
-
- /**
- * Access the helicity components for a 2-2 scattering. This method supplies
- * the component but does not allow it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2) const;
-
- /**
- * Access the helicity components for a 2-2 scattering. This method supplies
- * the component and allows it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2);
-
- /**
- * Access the helicity components for a 2-3 scattering. This method supplies
- * the component but does not allow it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @param outhel3 The helicity of the third outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2,
- unsigned int outhel3) const;
-
- /**
- * Access the helicity components for a 2-3 scattering. This method supplies
- * the component and allows it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @param outhel3 The helicity of the third outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2,
- unsigned int outhel3);
-
- /**
- * Access the helicity components for a 2-4 scattering. This method supplies
- * the component but does not allow it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @param outhel3 The helicity of the third outgoing particle.
- * @param outhel4 The helicity of the fourth outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2,
- unsigned int outhel3,unsigned int outhel4) const;
-
- /**
- * Access the helicity components for a 2-4 scattering. This method supplies
- * the component and allows it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @param outhel3 The helicity of the third outgoing particle.
- * @param outhel4 The helicity of the fourth outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2,
- unsigned int outhel3, unsigned int outhel4);
-
- /**
- * Access the helicity components for a 2-5 scattering. This method supplies
- * the component but does not allow it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @param outhel3 The helicity of the third outgoing particle.
- * @param outhel4 The helicity of the fourth outgoing particle.
- * @param outhel5 The helicity of the fifth outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2,
- unsigned int outhel3,unsigned int outhel4,
- unsigned int outhel5) const;
-
- /**
- * Access the helicity components for a 2-5 scattering. This method supplies
- * the component and allows it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @param outhel3 The helicity of the third outgoing particle.
- * @param outhel4 The helicity of the fourth outgoing particle.
- * @param outhel5 The helicity of the fifth outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2,
- unsigned int outhel3, unsigned int outhel4,
- unsigned int outhel5);
-
- /**
- * Access the helicity components for a 2-6 scattering. This method supplies
- * the component but does not allow it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @param outhel3 The helicity of the third outgoing particle.
- * @param outhel4 The helicity of the fourth outgoing particle.
- * @param outhel5 The helicity of the fifth outgoing particle.
- * @param outhel6 The helicity of the sixth outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2,
- unsigned int outhel3,unsigned int outhel4,
- unsigned int outhel5,unsigned int outhel6) const;
-
- /**
- * Access the helicity components for a 2-6 scattering. This method supplies
- * the component and allows it to be changed.
- * @param inhel1 The helicity of the first incoming particle.
- * @param inhel2 The helicity of the second incoming particle.
- * @param outhel1 The helicity of the first outgoing particle.
- * @param outhel2 The helicity of the second outgoing particle.
- * @param outhel3 The helicity of the third outgoing particle.
- * @param outhel4 The helicity of the fourth outgoing particle.
- * @param outhel5 The helicity of the fifth outgoing particle.
- * @param outhel6 The helicity of the sixth outgoing particle.
- * @return The matrix element for the given helicities.
- */
- inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
- unsigned int outhel1,unsigned int outhel2,
- unsigned int outhel3, unsigned int outhel4,
- unsigned int outhel5, unsigned int outhel6);
-
-
- /**
- * Access the helicity components for a 2-n scattering. This method supplies
- * the component but does not allow it to be changed.
- * @param hel The helicities of the incoming and outgoing particles
- * @return The matrix element for the given helicities.
- */
- inline Complex operator () (vector<unsigned int> hel) const;
-
- /**
- * Access the helicity components for a 2-n scattering. This method supplies
- * the component and allows it to be changed.
- * @param hel The helicities of the incoming and outgoing particles
- * @return The matrix element for the given helicities.
- */
- inline Complex & operator () (vector<unsigned int> hel);
- //@}
-
-public:
-
- /**
- * Calculate the decay matrix for an incoming particle.
- */
- RhoDMatrix calculateDMatrix(int,RhoDMatrix, vector<RhoDMatrix>);
-
- /**
- * Calculate the rho matrix for a given outgoing particle.
- */
- RhoDMatrix calculateRhoMatrix(int,RhoDMatrix,RhoDMatrix,
- vector<RhoDMatrix>);
-
-public:
-
- /**
- * Reset the matrix element.
- */
- inline void reset(const ProductionMatrixElement &) const;
-
-public:
-
- /**
- * Standard Init function used to initialize the interfaces.
- */
- static void Init();
-
-private:
-
- /**
- * Describe a concrete class without persistent data.
- */
- static NoPIOClassDescription<ProductionMatrixElement> initProductionMatrixElement;
-
- /**
- * Private and non-existent assignment operator.
- */
- ProductionMatrixElement & operator=(const ProductionMatrixElement& );
-
-private:
-
- /**
- * Set the size of the vector containing the matrix element.
- */
- inline void setMESize();
-
-private:
-
- /**
- * Number of outgoing particles.
- */
- mutable unsigned int _nout;
-
- /**
- * Spin of the incoming particles as 2s+1.
- */
- mutable vector<PDT::Spin> _inspin;
-
- /**
- * Spins of the outgoing particles.
- */
- mutable vector<PDT::Spin> _outspin;
-
- /**
- * Storage of the matrix element, a vector is better for memory usage.
- */
- mutable vector<Complex> _matrixelement;
-
- /**
- * Constants needed to map the index of the vector to a helicity structure.
- */
- mutable vector<int> _constants;
-
-};
-
-}
-
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/**
- * The following template specialization informs ThePEG about the
- * base class of ProductionMatrixElement.
- */
-template <>
-struct BaseClassTrait<Herwig::ProductionMatrixElement,1> {
- /** Typedef of the base class of ProductionMatrixElement. */
- typedef Base NthBase;
-};
-
-/**
- * The following template specialization informs ThePEG about the
- * name of this class and the shared object where it is defined.
- */
-template <>
-struct ClassTraits<Herwig::ProductionMatrixElement>
- : public ClassTraitsBase<Herwig::ProductionMatrixElement> {
-
- /**
- * Return the class name.
- */
- static string className() { return "Herwig::ProductionMatrixElement"; }
-};
-
-/** @endcond */
-
-}
-
-#include "ProductionMatrixElement.icc"
-
-#endif /* HERWIG_ProductionMatrixElement_H */
diff --git a/MatrixElement/General/ProductionMatrixElement.icc b/MatrixElement/General/ProductionMatrixElement.icc
deleted file mode 100644
--- a/MatrixElement/General/ProductionMatrixElement.icc
+++ /dev/null
@@ -1,402 +0,0 @@
-// -*- C++ -*-
-//
-// ProductionMatrixElement.icc 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 inlined member functions of
-// the ProductionMatrixElement class.
-//
-// Author: Peter Richardson
-//
-
-namespace Herwig {
-
-using namespace ThePEG;
-
-// default constructor
-inline ProductionMatrixElement::ProductionMatrixElement() {}
-
-// constructor for 2-1 scattering
-inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,
- PDT::Spin out1)
-{
- _nout=2;
- _inspin.resize(2);
- _inspin[0]=in1; _inspin[1]=in2;
- _outspin.push_back(out1);
- setMESize();
-}
-// constructor for 2-2 scattering
-inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,
- PDT::Spin out1,PDT::Spin out2)
-{
- _nout=2;
- _inspin.resize(2);
- _inspin[0]=in1; _inspin[1]=in2;
- _outspin.push_back(out1);_outspin.push_back(out2);
- setMESize();
-}
-
-// constructor for 2-3 scattering
-inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
- PDT::Spin out1,PDT::Spin out2,
- PDT::Spin out3)
-{
- _inspin.resize(2);
- _nout=3; _inspin[0]=in1; _inspin[1]=in2;
- _outspin.push_back(out1);_outspin.push_back(out2);_outspin.push_back(out3);
- setMESize();
-}
-
-// constructor for 2-4 scattering
- inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
- PDT::Spin out1,PDT::Spin out2,
- PDT::Spin out3,PDT::Spin out4)
-{
- _nout=4;
- _inspin.resize(2);
- _inspin[0]=in1; _inspin[1]=in2;
- _outspin.push_back(out1);_outspin.push_back(out2);
- _outspin.push_back(out3);_outspin.push_back(out4);
- setMESize();
-}
-
-// constructor for 2-5 scattering
-inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
- PDT::Spin out1,PDT::Spin out2,
- PDT::Spin out3,PDT::Spin out4,
- PDT::Spin out5)
-{
- _nout=5;
- _inspin.resize(2);
- _inspin[0]=in1; _inspin[1]=in2;
- _outspin.push_back(out1);_outspin.push_back(out2);
- _outspin.push_back(out3);_outspin.push_back(out4);_outspin.push_back(out5);
- setMESize();
-}
-
-// constructor for 2-6 scattering
-inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
- PDT::Spin out1,PDT::Spin out2,
- PDT::Spin out3,PDT::Spin out4,
- PDT::Spin out5,PDT::Spin out6)
-{
- _nout=6;
- _inspin.resize(2);
- _inspin[0]=in1; _inspin[1]=in2;
- _outspin.push_back(out1);_outspin.push_back(out2);
- _outspin.push_back(out3);_outspin.push_back(out4);
- _outspin.push_back(out5);_outspin.push_back(out6);
- setMESize();
-}
-
-// constructor for 2-n scattering
-inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
- vector<PDT::Spin> out)
-{
- _inspin.resize(2);
- _nout=out.size(); _inspin[0]=in1; _inspin[1]=in2;
- _outspin=out;setMESize();
-}
-
-// set the size of the vector containing the matrix element
-inline void ProductionMatrixElement::setMESize()
-{
- unsigned int ix;
- int isize=_inspin[0]*_inspin[1];
- for(ix=0;ix<_outspin.size();++ix){isize*=_outspin[ix];}
- // zero the matrix element
- _matrixelement.resize(isize,0.);
- // set up the constants for the mapping of helicity to vectro index
- _constants.resize(_outspin.size()+3);
- unsigned int temp=1;
- for(ix=_outspin.size()+1;ix>1;--ix){temp*=_outspin[ix-2];_constants[ix]=temp;}
- temp*=_inspin[1];_constants[1]=temp;
- temp*=_inspin[0];_constants[0]=temp;
- _constants[_outspin.size()+2]=1;
-}
-
-// get the spins of the incoming particles particle
-inline vector<PDT::Spin> ProductionMatrixElement::inspin(){return _inspin;}
-
-// get the spins of the outgoing particles
-inline vector<PDT::Spin> ProductionMatrixElement::outspin(){return _outspin;}
-
-// access to the individual helicity components (2-2 scattering)
-inline Complex ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1) const
-{
- // check this is really a 2-2 matrix element
- if(_outspin.size()!=1)
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Requested component of 2-1 matrix element"
- << " but matrix element is 2-"
- << _outspin.size() << Exception::abortnow;
- return 0.;
- }
- unsigned int iloc(0);
- iloc+=in1*_constants[1];
- iloc+=in2*_constants[2];
- iloc+=out1*_constants[3];
- if(iloc>=_matrixelement.size())
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Invalid component of 2-1 matrix element requested"
- << Exception::abortnow;
- return 0.;
- }
- return _matrixelement[iloc];
-}
-
-// access to the individual helicity components (2-2 scattering)
-inline Complex ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2) const
-{
- // check this is really a 2-2 matrix element
- if(_outspin.size()!=2)
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Requested component of 2-2 matrix element but matrix element is 2-"
- << _outspin.size() << Exception::abortnow;
- return 0.;
- }
- unsigned int iloc(0);
- iloc+=in1*_constants[1];
- iloc+=in2*_constants[2];
- iloc+=out1*_constants[3];
- iloc+=out2*_constants[4];
- if(iloc>=_matrixelement.size())
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Invalid component of 2-2 matrix element requested"
- << Exception::abortnow;
- return 0.;
- }
- return _matrixelement[iloc];
-}
-
-// access to the individual helicity components (2-3 scattering)
-inline Complex ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,
- unsigned int out1,unsigned int out2,unsigned int out3) const
-{
- if(_outspin.size()!=3)
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Requested component of 2-3 matrix element but matrix element is 2-"
- << _outspin.size() << Exception::abortnow;
- return 0.;
- }
- // map the indices to the location in the vector
- vector<unsigned int> ivec(5);
- ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
- return (*this)(ivec);
-}
-
-// access to the individual helicity components (2-4 scattering)
-inline Complex ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
- unsigned int out3,unsigned int out4) const
-{
- if(_outspin.size()!=4)
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Requested component of 2-4 matrix element but matrix element is 2-"
- << _outspin.size() << Exception::abortnow;
- return 0.;
- }
- vector<unsigned int> ivec(6);
- ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
- ivec[5]=out4;
- return (*this)(ivec);
-}
-
-
-// access to the individual helicity components (2-5 scattering)
-inline Complex ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
- unsigned int out3,unsigned int out4, unsigned int out5) const
-{
- if(_outspin.size()!=5)
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Requested component of 2-4 matrix element but matrix element is 2-"
- << _outspin.size() << Exception::abortnow;
- return 0.;
- }
- vector<unsigned int> ivec(7);
- ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
- ivec[5]=out4;ivec[6]=out5;
- return (*this)(ivec);
-}
-
-
-// access to the individual helicity components (2-6 scattering)
-inline Complex ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
- unsigned int out3,unsigned int out4, unsigned int out5, unsigned int out6) const
-{
- if(_outspin.size()!=6)
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Requested component of 2-6 matrix element but matrix element is 2-"
- << _outspin.size() << Exception::abortnow;
- return 0.;
- }
- vector<unsigned int> ivec(8);
- ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
- ivec[5]=out4;ivec[6]=out5;ivec[7]=out6;
- return (*this)(ivec);
-}
-
-
-// access to the individual helicity components (2-n scattering)
-inline Complex ProductionMatrixElement::operator ()
- (vector<unsigned int> in) const
-{
- if(_outspin.size()!=in.size()-2)
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Requested component of 2-" << in.size()
- << " matrix element but matrix element is 2-"
- << _outspin.size() << Exception::abortnow;
- return 0.;
- }
- unsigned int iloc(0),ix;
- // incoming and outgoing particles
- for(ix=0;ix<in.size();++ix){iloc+=in[ix]*_constants[ix+1];}
- if(iloc>=_matrixelement.size())
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Invalid component of 2-n matrix element requested"
- << Exception::abortnow;
- return 0.;
- }
- return _matrixelement[iloc];
-}
-
-// set the individual helicity components (2-1 scattering)
-inline Complex & ProductionMatrixElement::operator () (unsigned int in1,unsigned int in2,
- unsigned int out1)
-{
- static Complex dummy=0.;
- unsigned int iloc(0);
- iloc+= in1*_constants[1];
- iloc+= in2*_constants[2];
- iloc+=out1*_constants[3];
- if(iloc>=_matrixelement.size())
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Invalid component of 2-1 matrix element requested"
- << Exception::abortnow;
- return dummy;
- }
- return _matrixelement[iloc];
-}
-
-// set the individual helicity components (2-2 scattering)
-inline Complex & ProductionMatrixElement::operator () (unsigned int in1,
- unsigned int in2,
- unsigned int out1,
- unsigned int out2)
-{
- static Complex dummy=0.;
- unsigned int iloc(0);
- iloc+= in1*_constants[1];
- iloc+= in2*_constants[2];
- iloc+=out1*_constants[3];
- iloc+=out2*_constants[4];
- if(iloc>=_matrixelement.size())
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Invalid component of 2-2 matrix element requested"
- << Exception::abortnow;
- return dummy;
- }
- return _matrixelement[iloc];
-}
-
-// set the individual helicity components (2-3 scattering)
-inline Complex & ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
- unsigned int out3)
-{
- vector<unsigned int> ivec(5);
- ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
- return (*this)(ivec);
-}
-
-// set the individual helicity components (2-4 scattering)
-inline Complex & ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
- unsigned int out3, unsigned int out4)
-{
- vector<unsigned int> ivec(6);
- ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
- ivec[5]=out4;
- return (*this)(ivec);
-}
-
-// set the individual helicity components (2-5 scattering)
-inline Complex & ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
- unsigned int out3, unsigned int out4, unsigned int out5)
-{
- vector<unsigned int> ivec(7);
- ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
- ivec[5]=out4; ivec[6]=out5;
- return (*this)(ivec);
-}
-
-// set the individual helicity components (2-6 scattering)
-inline Complex & ProductionMatrixElement::operator ()
- (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
- unsigned int out3, unsigned int out4, unsigned int out5, unsigned int out6)
-{
- vector<unsigned int> ivec(8);
- ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
- ivec[5]=out4; ivec[6]=out5; ivec[7]=out6;
- return (*this)(ivec);
-}
-
-inline Complex & ProductionMatrixElement::operator ()
- (vector<unsigned int> in)
-{
- static Complex dummy=0;
- if(_outspin.size()!=in.size()-2)
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Requested component of 2-" << in.size()
- << " matrix element but matrix element is 2-"
- << _outspin.size() << Exception::abortnow;
- return dummy;
- }
- unsigned int iloc=0;
- // incoming particles
- for(unsigned int ix=0;ix<in.size();++ix){iloc+=in[ix]*_constants[ix+1];}
- if(iloc>=_matrixelement.size())
- {
- throw ThePEG::Helicity::HelicityConsistencyError()
- << "Invalid component of 2-n matrix element requested"
- << Exception::abortnow;
- return dummy;
- }
- return _matrixelement[iloc];
-}
-
-// reset the matrix element
-inline void ProductionMatrixElement::reset(const ProductionMatrixElement & x) const
-{
- _nout = x._nout;
- _inspin = x._inspin;
- _outspin =x._outspin;
- _matrixelement=x._matrixelement;
- _constants=x._constants;
-}
-
-}
diff --git a/MatrixElement/Hadron/MEPP2GammaGamma.cc b/MatrixElement/Hadron/MEPP2GammaGamma.cc
--- a/MatrixElement/Hadron/MEPP2GammaGamma.cc
+++ b/MatrixElement/Hadron/MEPP2GammaGamma.cc
@@ -1,358 +1,358 @@
// -*- C++ -*-
//
// MEPP2GammaGamma.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 MEPP2GammaGamma class.
//
#include "MEPP2GammaGamma.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
using namespace Herwig;
unsigned int MEPP2GammaGamma::orderInAlphaS() const {
return 0;
}
unsigned int MEPP2GammaGamma::orderInAlphaEW() const {
return 2;
}
void MEPP2GammaGamma::doinit() throw(InitException) {
// get the vedrtex pointers from the SM object
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm)
{_photonvertex = hwsm->vertexFFP();}
else throw InitException() << "Wrong type of StandardModel object in "
<< "MEPP2GammaGamma::doinit() the Herwig++"
<< " version must be used"
<< Exception::runerror;
// call the base class
HwME2to2Base::doinit();
}
void MEPP2GammaGamma::getDiagrams() const {
// diagrams for q qbar to gamma gamma
tcPDPtr p = getParticleData(ParticleID::gamma);
if(_process==0||_process==1) {
for ( int i = 1; i <= 5; ++i ) {
tcPDPtr q = getParticleData(i);
tcPDPtr qb = q->CC();
// t channel
add(new_ptr((Tree2toNDiagram(3), q, qb, qb, 1, p, 2, p, -1)));
// u channel
add(new_ptr((Tree2toNDiagram(3), q, qb, qb, 2, p, 1, p, -2)));
}
}
// diagrams for g g to gamma gamma (this is garbage)
tcPDPtr g = getParticleData(ParticleID::g);
if(_process==0||_process==2)
add(new_ptr((Tree2toNDiagram(2), g, g, 1, p, 3, p, 3, p, -3)));
}
Energy2 MEPP2GammaGamma::scale() const {
Energy2 s(sHat()),u(uHat()),t(tHat());
return 2.*s*t*u/(s*s+t*t+u*u);
}
Selector<MEBase::DiagramIndex>
MEPP2GammaGamma::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i )
if ( diags[i]->id() == -1 ) sel.insert(_diagwgt[0], i);
else if ( diags[i]->id() == -2 ) sel.insert(_diagwgt[1], i);
else if ( diags[i]->id() == -3 ) sel.insert(1.0, i);
return sel;
}
Selector<const ColourLines *>
MEPP2GammaGamma::colourGeometries(tcDiagPtr diag) const {
// q qbar colour lines
static const ColourLines cqqbar("1 -2 -3");
// g g colour lines
static const ColourLines cgluon("1 -2,-1 2");
// selector
Selector<const ColourLines *> sel;
if ( diag->id() == -1 || diag->id() == -2 ) sel.insert(1.0, &cqqbar);
else sel.insert(1.0, &cgluon);
return sel;
}
void MEPP2GammaGamma::persistentOutput(PersistentOStream & os) const {
os << _photonvertex << _maxflavour << _process;
}
void MEPP2GammaGamma::persistentInput(PersistentIStream & is, int) {
is >> _photonvertex >> _maxflavour >> _process;
}
ClassDescription<MEPP2GammaGamma> MEPP2GammaGamma::initMEPP2GammaGamma;
// Definition of the static class description member.
void MEPP2GammaGamma::Init() {
static ClassDocumentation<MEPP2GammaGamma> documentation
("The MEPP2GammaGamma class implements the matrix element for photon pair"
" production in hadron collisions.");
static Parameter<MEPP2GammaGamma,unsigned int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour of the quarks in the process",
&MEPP2GammaGamma::_maxflavour, 5, 1, 5,
false, false, Interface::limited);
static Switch<MEPP2GammaGamma,unsigned int> interfaceProcess
("Process",
"Subprocesses to include",
&MEPP2GammaGamma::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all the subprocesses",
0);
static SwitchOption interfaceProcessqqbar
(interfaceProcess,
"qqbar",
"Only include the incoming q qbar subproces",
1);
static SwitchOption interfaceProcessgg
(interfaceProcess,
"gg",
"Only include the incoming gg subprocess",
2);
}
double MEPP2GammaGamma::me2() const {
// total matrix element
double me(0.);
// g g to gamma gamma
if(mePartonData()[0]->id()==ParticleID::g) {
VectorWaveFunction g1in(meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction g2in(meMomenta()[1],mePartonData()[1],incoming);
VectorWaveFunction p1out(meMomenta()[2],mePartonData()[2],outgoing);
VectorWaveFunction p2out(meMomenta()[3],mePartonData()[3],outgoing);
vector<VectorWaveFunction> g1,g2,p1,p2;
for(unsigned int ix=0;ix<2;++ix) {
g1in.reset(2*ix) ;g1.push_back( g1in);
g2in.reset(2*ix) ;g2.push_back( g2in);
p1out.reset(2*ix);p1.push_back(p1out);
p2out.reset(2*ix);p2.push_back(p2out);
}
// calculate the matrix element
me = ggME(g1,g2,p1,p2,false);
}
// q qbar to gamma gamma
else {
unsigned int iq(1),iqb(0);
if(mePartonData()[0]->id()>0){iq=0;iqb=1;}
SpinorWaveFunction qin (meMomenta()[iq ],mePartonData()[iq ],incoming);
SpinorBarWaveFunction qbin(meMomenta()[iqb],mePartonData()[iqb],incoming);
VectorWaveFunction p1out(meMomenta()[ 2 ],mePartonData()[ 2 ],outgoing);
VectorWaveFunction p2out(meMomenta()[ 3 ],mePartonData()[ 3 ],outgoing);
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> p1,p2;
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ;fin.push_back( qin );
qbin.reset(ix) ;ain.push_back( qbin);
p1out.reset(2*ix); p1.push_back(p1out);
p2out.reset(2*ix); p2.push_back(p2out);
}
// calculate the matrix element
me= qqbarME(fin,ain,p1,p2,false);
}
return me;
}
double MEPP2GammaGamma::qqbarME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & p1,
vector<VectorWaveFunction> & p2,
bool calc) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming antifermion (vbar spinor)
// for the outgoing
// 0 first outgoing photon
// 1 second outgoing photon
// me to be returned
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1);
// wavefunction for the intermediate particles
SpinorWaveFunction inter;
unsigned int inhel1,inhel2,outhel1,outhel2;
Complex diag[3];
double me(0.),diag1(0.),diag2(0.);
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
// first diagram
inter = _photonvertex->evaluate(0.*GeV2,5,fin[inhel1].getParticle(),
fin[inhel1],p1[outhel1]);
diag[0] = _photonvertex->evaluate(0.*GeV2,inter,ain[inhel2],p2[outhel2]);
// second diagram
inter = _photonvertex->evaluate(0.*GeV2,5,fin[inhel1].getParticle(),
fin[inhel1],p2[outhel2]);
diag[1] = _photonvertex->evaluate(0.*GeV2,inter,ain[inhel2],p1[outhel1]);
// compute the running totals
diag[2]=diag[0]+diag[1];
diag1 += norm(diag[0]);
diag2 += norm(diag[1]);
me += norm(diag[2]);
// matrix element
if(calc) newme(inhel1,inhel2,2*outhel1,2*outhel2)=diag[2];
}
}
}
}
// save the info on the diagrams
if(!calc) {
_diagwgt[0]=diag1;
_diagwgt[1]=diag2;
}
// check versus analytic result
// Energy2 s(sHat()),u(uHat()),t(tHat());
// double test = 2./3.*sqr(4.*pi*SM().alphaEM(0.))*(t/u+u/t)*
// sqr(mePartonData()[0]->charge())*
// sqr(mePartonData()[0]->charge());
// cerr << "testing me " << 12./me*test << endl;
// return the answer (including colour and spin factor)
if(calc) _me.reset(newme);
return me/12;
}
double MEPP2GammaGamma::ggME(vector<VectorWaveFunction> &,
vector<VectorWaveFunction> &,
vector<VectorWaveFunction> &,
vector<VectorWaveFunction> &,
bool calc) const {
// we probably need some basis rotation here ?????
// get the scales
Energy2 s(sHat()),u(uHat()),t(tHat());
Complex me[2][2][2][2];
double charge(11./9.);
// ++++
me[1][1][1][1] = charge*ggme(s,t,u);
// +++-
me[1][1][1][0] =-charge;
// ++-+
me[1][1][0][1] =-charge;
// ++--
me[1][1][0][0] =-charge;
// +-++
me[1][0][1][1] =-charge;
// +-+-
me[1][0][1][0] = charge*ggme(u,t,s);
// +--+
me[1][0][0][1] = charge*ggme(t,s,u);
// +---
me[1][0][0][0] = charge;
// -+++
me[0][1][1][1] =-charge;
// -++-
me[0][1][1][0] =-me[1][0][0][1];
// -+-+
me[0][1][0][1] =-me[1][0][1][0];
// -+--
me[0][1][0][0] = charge;
// --++
me[0][0][1][1] = charge;
// --+-
me[0][0][1][0] = charge;
// ---+
me[0][0][0][1] = charge;
// ----
me[0][0][0][0] =-me[1][1][1][1];
ProductionMatrixElement newme(PDT::Spin1,PDT::Spin1,
PDT::Spin1,PDT::Spin1);
unsigned int inhel1,inhel2,outhel1,outhel2;
double sum(0.);
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
sum+=real( me[inhel1][inhel2][outhel1][outhel2]*
conj(me[inhel1][inhel2][outhel1][outhel2]));
// matrix element
if(calc) newme(2*inhel1,2*inhel2,
2*outhel1,2*outhel2)=me[inhel1][inhel2][outhel1][outhel2];
}
}
}
}
// double pi2(sqr(pi));
// Energy2 s2(sqr(s)),t2(sqr(t)),u2(sqr(u));
// double alntu=log(t/u);
// double alnst=log(-s/t);
// double alnsu=alnst+alntu;
// double test=5.*4.
// +sqr((2.*s2+2.*(u2-t2)*alntu+(t2+u2)*(sqr(alntu)+pi2))/s2)
// +sqr((2.*u2+2.*(t2-s2)*alnst+(t2+s2)* sqr(alnst) )/u2)
// +sqr((2.*t2+2.*(u2-s2)*alnsu+(u2+s2)* sqr(alnsu) )/t2)
// +4.*pi2*(sqr((t2-s2+(t2+s2)*alnst)/u2)+sqr((u2-s2+(u2+s2)*alnsu)/t2));
// cerr << "testing ratio " << sum/test/sqr(charge)*2. << endl;
// final factors
if(calc) _me.reset(newme);
return 0.5*sum*sqr(SM().alphaS(scale())*SM().alphaEM(0.*GeV2));
}
void MEPP2GammaGamma::constructVertex(tSubProPtr sub) {
SpinfoPtr spin[4];
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
// order of particles
unsigned int order[4]={0,1,2,3};
// identify the process and calculate matrix element
vector<VectorWaveFunction> g1,g2,p1,p2;
if(hard[0]->id()==ParticleID::g) {
VectorWaveFunction (g1,hard[order[0]],incoming,false,true,true);
VectorWaveFunction (g2,hard[order[1]],incoming,false,true,true);
VectorWaveFunction (p1,hard[order[2]],outgoing,true ,true,true);
VectorWaveFunction (p2,hard[order[3]],outgoing,true ,true,true);
g1[1]=g1[2];g2[1]=g2[2];p1[1]=p1[2];p2[1]=p2[2];
ggME(g1,g2,p1,p2,true);
}
else {
if(hard[order[0]]->id()<0) swap(order[0],order[1]);
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qb;
SpinorWaveFunction (q ,hard[order[0]],incoming,false,true);
SpinorBarWaveFunction(qb,hard[order[1]],incoming,false,true);
VectorWaveFunction (p1,hard[order[2]],outgoing,true ,true,true);
VectorWaveFunction (p2,hard[order[3]],outgoing,true ,true,true);
p1[1]=p1[2];p2[1]=p2[2];
qqbarME(q,qb,p1,p2,true);
}
// get the spin info objects
for(unsigned int ix=0;ix<4;++ix)
spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[order[ix]]->spinInfo());
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix)
spin[ix]->setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/Hadron/MEPP2GammaGamma.h b/MatrixElement/Hadron/MEPP2GammaGamma.h
--- a/MatrixElement/Hadron/MEPP2GammaGamma.h
+++ b/MatrixElement/Hadron/MEPP2GammaGamma.h
@@ -1,279 +1,279 @@
// -*- C++ -*-
//
// MEPP2GammaGamma.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_MEPP2GammaGamma_H
#define HERWIG_MEPP2GammaGamma_H
//
// This is the declaration of the MEPP2GammaGamma class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEPP2GammaGamma class implements the production of photon pairs in
* hadron hadron collisions.
*
* @see \ref MEPP2GammaGammaInterfaces "The interfaces"
* defined for MEPP2GammaGamma.
*/
class MEPP2GammaGamma: public HwME2to2Base {
public:
/**
* The default constructor.
*/
inline MEPP2GammaGamma();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* Members to return the matrix elements for the different subprocesses
*/
//@{
/**
* Matrix element for \f$q\bar{q}\to \gamma\gamma\f$.
* @param fin Spinors for incoming quark
* @param ain Spinors for incoming antiquark
* @param p1 Polarization vectors for the first outgoing photon
* @param p2 Polarization vectors for the second outgoing photon
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double qqbarME(vector<SpinorWaveFunction> & fin, vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & p1 , vector<VectorWaveFunction> & p2 ,
bool me) const;
/**
* Matrix element for \f$gg \to \gamma\gamma\f$.
* @param g1 Polarization vectors for the first incoming gluon
* @param g2 Polarization vectors for the second incoming gluon
* @param p1 Polarization vectors for the first outgoing photon
* @param p2 Polarization vectors for the second outgoing photon
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double ggME(vector<VectorWaveFunction> & g1 , vector<VectorWaveFunction> & g2 ,
vector<VectorWaveFunction> & p1 , vector<VectorWaveFunction> & p2 ,
bool me) const;
//@}
/**
* \f$gg\to\gamma\gamma\f$ matrix element for the \f$++++\f$ helicity configuration.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
*/
inline Complex ggme(Energy2 s,Energy2 t,Energy2 u) const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2GammaGamma> initMEPP2GammaGamma;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2GammaGamma & operator=(const MEPP2GammaGamma &);
private:
/**
* Pointer to the quark-antiquark-photon vertex
*/
AbstractFFVVertexPtr _photonvertex;
/**
* Maximum PDG code of the quarks allowed
*/
unsigned int _maxflavour;
/**
* Option for which processes to include
*/
unsigned int _process;
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
/**
* weights for the different quark annhilation diagrams
*/
mutable double _diagwgt[2];
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEPP2GammaGamma. */
template <>
struct BaseClassTrait<Herwig::MEPP2GammaGamma,1> {
/** Typedef of the first base class of MEPP2GammaGamma. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2GammaGamma class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2GammaGamma>
: public ClassTraitsBase<Herwig::MEPP2GammaGamma> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2GammaGamma"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2GammaGamma is implemented. It may also include several, space-separated,
* libraries if the class MEPP2GammaGamma depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#include "MEPP2GammaGamma.icc"
#endif /* HERWIG_MEPP2GammaGamma_H */
diff --git a/MatrixElement/Hadron/MEPP2GammaJet.cc b/MatrixElement/Hadron/MEPP2GammaJet.cc
--- a/MatrixElement/Hadron/MEPP2GammaJet.cc
+++ b/MatrixElement/Hadron/MEPP2GammaJet.cc
@@ -1,531 +1,531 @@
// -*- C++ -*-
//
// MEPP2GammaJet.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 MEPP2GammaJet class.
//
#include "MEPP2GammaJet.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
using namespace Herwig;
MEPP2GammaJet::MEPP2GammaJet() : _maxflavour(5), _processopt(0) {
massOption(true ,0);
massOption(false,0);
}
void MEPP2GammaJet::rebind(const TranslationMap & trans)
throw(RebindException) {
// dummy = trans.translate(dummy);
HwME2to2Base::rebind(trans);
_gluonvertex =trans.translate(_gluonvertex );
_photonvertex=trans.translate(_photonvertex);
}
IVector MEPP2GammaJet::getReferences() {
IVector ret = HwME2to2Base::getReferences();
ret.push_back(_gluonvertex);
ret.push_back(_photonvertex);
return ret;
}
void MEPP2GammaJet::doinit() throw(InitException) {
// get the vedrtex pointers from the SM object
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm) {
_gluonvertex = hwsm->vertexFFG();
_photonvertex = hwsm->vertexFFP();
}
else throw InitException() << "Wrong type of StandardModel object in "
<< "MEPP2GammaJet::doinit() the Herwig++"
<< " version must be used"
<< Exception::runerror;
// call the base class
HwME2to2Base::doinit();
}
void MEPP2GammaJet::getDiagrams() const {
// need the gluon and the photon in all processes
tcPDPtr g = getParticleData(ParticleID::g);
tcPDPtr p = getParticleData(ParticleID::gamma);
// for each quark species there are three subprocesses
for(unsigned int iq=1;iq<=_maxflavour;++iq) {
tcPDPtr q = getParticleData(iq);
tcPDPtr qb = q->CC();
// q qbar to gamma gluon (two diagrams)
if(_processopt==0||_processopt==1) {
add(new_ptr((Tree2toNDiagram(3), q, qb, qb, 1, p, 2, g, -1)));
add(new_ptr((Tree2toNDiagram(3), q, q, qb, 2, p, 1, g, -2)));
}
// q gluon to gamma q (two diagrams)
if(_processopt==0||_processopt==2) {
add(new_ptr((Tree2toNDiagram(3), q, q, g, 1, p, 2, q, -3)));
add(new_ptr((Tree2toNDiagram(2), q, g, 1, q , 3, p, 3, q, -4)));
}
// qbar gluon to gamma qbar (two diagrams)
if(_processopt==0||_processopt==3) {
add(new_ptr((Tree2toNDiagram(3), qb, qb, g, 1, p, 2, qb, -5)));
add(new_ptr((Tree2toNDiagram(2), qb, g, 1, qb , 3, p, 3, qb, -6)));
}
}
}
unsigned int MEPP2GammaJet::orderInAlphaS() const {
return 1;
}
unsigned int MEPP2GammaJet::orderInAlphaEW() const {
return 1;
}
Energy2 MEPP2GammaJet::scale() const {
Energy2 s(sHat()),u(uHat()),t(tHat());
return 2.*s*t*u/(s*s+t*t+u*u);
}
Selector<MEBase::DiagramIndex>
MEPP2GammaJet::diagrams(const DiagramVector & diags) const {
// This example corresponds to the diagrams specified in the example
// in the getDiagrams() function.
double diag1(0.5),diag2(0.5);
diag1 = meInfo()[0];
diag2 = meInfo()[1];
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if ( abs(diags[i]->id())%2 == 1 ) sel.insert(diag1, i);
else sel.insert(diag2, i);
}
return sel;
}
void MEPP2GammaJet::persistentOutput(PersistentOStream & os) const {
os << _gluonvertex << _photonvertex << _maxflavour << _processopt;
}
void MEPP2GammaJet::persistentInput(PersistentIStream & is, int) {
is >> _gluonvertex >> _photonvertex >> _maxflavour >> _processopt;
}
ClassDescription<MEPP2GammaJet> MEPP2GammaJet::initMEPP2GammaJet;
// Definition of the static class description member.
void MEPP2GammaJet::Init() {
static ClassDocumentation<MEPP2GammaJet> documentation
("The MEPP2GammaJet class implements the matrix element for"
" hadron-hadron to photon+jet");
static Parameter<MEPP2GammaJet,unsigned int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour of the quarks in the process",
&MEPP2GammaJet::_maxflavour, 5, 1, 5,
false, false, Interface::limited);
static Switch<MEPP2GammaJet,unsigned int> interfaceProcesses
("Process",
"Subprocesses to include",
&MEPP2GammaJet::_processopt, 0, false, false);
static SwitchOption interfaceProcessesAll
(interfaceProcesses,
"All",
"Include all the subprocesses",
0);
static SwitchOption interfaceProcessesqqbar
(interfaceProcesses,
"qqbar",
"Only include the incoming q qbar subprocess",
1);
static SwitchOption interfaceProcessesqg
(interfaceProcesses,
"qg",
"Only include the incoming q g subprocess",
2);
static SwitchOption interfaceProcessesqbarg
(interfaceProcesses,
"qbarg",
"Only include the incoming qbar g subprocess",
3);
}
Selector<const ColourLines *>
MEPP2GammaJet::colourGeometries(tcDiagPtr diag) const {
// q qbar to gamma gluon colour lines
static const ColourLines qqbar1("1 5, -5 -2 -3");
static const ColourLines qqbar2("1 2 5, -5 -3");
// q gluon to gamma q colour lines
static const ColourLines qg1("1 2 -3, 3 5");
static const ColourLines qg2("1 -2, 2 3 5");
// qbar gluon to gamma qbar lines
static const ColourLines qbarg1("-1 -2 3, -3 -5");
static const ColourLines qbarg2("-1 2, -2 -3 -5");
// only one flow per diagram so insert the right one
Selector<const ColourLines *> sel;
switch (diag->id()) {
case -1 :
sel.insert(1.0, &qqbar1);
break;
case -2 :
sel.insert(1.0, &qqbar2);
break;
case -3 :
sel.insert(1.0, &qg1);
break;
case -4 :
sel.insert(1.0, &qg2);
break;
case -5 :
sel.insert(1.0, &qbarg1);
break;
case -6 :
sel.insert(1.0, &qbarg2);
break;
}
return sel;
}
double MEPP2GammaJet::me2() const {
// total matrix element and the various components
double me(0.);
// first case, q qbar to gluon photon
if(mePartonData()[0]->id()==-mePartonData()[1]->id()) {
// order of the particles
unsigned int iq(1),iqb(0),ip(3),ig(2);
if(mePartonData()[0]->id()>0) swap(iq,iqb);
if(mePartonData()[3]->id()==ParticleID::g) swap(ig, ip);
// calculate the spinors and polarization vectors
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> pout,gout;
SpinorWaveFunction qin (meMomenta()[iq ],mePartonData()[iq ],incoming);
SpinorBarWaveFunction qbin(meMomenta()[iqb],mePartonData()[iqb],incoming);
VectorWaveFunction glout(meMomenta()[ig ],mePartonData()[ig ],outgoing);
VectorWaveFunction phout(meMomenta()[ip ],mePartonData()[ip ],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ; fin.push_back( qin );
qbin.reset(ix) ; ain.push_back( qbin);
glout.reset(2*ix);gout.push_back(glout);
phout.reset(2*ix);pout.push_back(phout);
}
// calculate the matrix element
me = qqbarME(fin,ain,gout,pout,false)/9.;
// Energy2 mt(scale());
// double coupling=sqr(4.*pi)*SM().alphaEM(0.)*SM().alphaS(mt)*
// sqr(mePartonData()[0]->charge());
// Energy2 t(tHat()),u(uHat());
// double me2=8./9./u/t*(t*t+u*u)*coupling;
// cerr << "testing matrix element A"
// << me << " "
// << me2 << " " << me/me2
// << endl;
}
else if(mePartonData()[0]->id()>0&&mePartonData()[1]->id()) {
// order of the particles
unsigned int iqin(0),iqout(2),ip(3),ig(1);
if(mePartonData()[0]->id()==ParticleID::g ) swap(iqin,ig);
if(mePartonData()[2]->id()==ParticleID::gamma) swap(ip,iqout);
// calculate the spinors and polarization vectors
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> fout;
vector<VectorWaveFunction> pout,gin;
SpinorWaveFunction qin (meMomenta()[iqin ],mePartonData()[iqin ],incoming);
SpinorBarWaveFunction qout(meMomenta()[iqout],mePartonData()[iqout],outgoing);
VectorWaveFunction glin(meMomenta()[ig ],mePartonData()[ig ],incoming);
VectorWaveFunction phout(meMomenta()[ip ],mePartonData()[ip ],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ;fin.push_back( qin );
qout.reset(ix) ;fout.push_back( qout);
glin.reset(2*ix) ;gin.push_back( glin);
phout.reset(2*ix);pout.push_back(phout);
}
// calculate the matrix element
me = qgME(fin,gin,pout,fout,false)/24.;
// Energy2 mt(scale());
// double coupling=sqr(4.*pi)*SM().alphaEM(0.)*SM().alphaS(mt);
// Energy2 s(sHat()),t(tHat()),u(uHat());
// double me2=-1./3./s/t*(s*s+t*t+2.*u*(s+t+u))*coupling*
// sqr(mePartonData()[0]->charge());
// cerr << "testing matrix element B"
// << me << " "
// << me2 << " " << me/me2
// << endl;
}
else {
// order of the particles
unsigned int iqin(0),iqout(2),ip(3),ig(1);
if(mePartonData()[0]->id()==ParticleID::g ) swap(iqin,ig);
if(mePartonData()[2]->id()==ParticleID::gamma) swap(ip,iqout);
// calculate the spinors and polarization vectors
vector<SpinorBarWaveFunction> ain;
vector<SpinorWaveFunction> aout;
vector<VectorWaveFunction> pout,gin;
SpinorBarWaveFunction qin (meMomenta()[iqin ],mePartonData()[iqin ],incoming);
SpinorWaveFunction qout(meMomenta()[iqout],mePartonData()[iqout],outgoing);
VectorWaveFunction glin(meMomenta()[ig ],mePartonData()[ig ],incoming);
VectorWaveFunction phout(meMomenta()[ip ],mePartonData()[ip ],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ;ain.push_back( qin );
qout.reset(ix) ;aout.push_back( qout);
glin.reset(2*ix) ;gin.push_back( glin);
phout.reset(2*ix);pout.push_back(phout);
}
// calculate the matrix element
me=qbargME(ain,gin,pout,aout,false)/24.;
// Energy2 mt(scale());
// double coupling=sqr(4.*pi)*SM().alphaEM(0.)*SM().alphaS(mt);
// Energy2 s(sHat()),t(tHat()),u(uHat());
// double me2=-1./3./s/t*(s*s+t*t+2.*u*(s+t+u))*coupling*
// sqr(mePartonData()[0]->charge());
// cerr << "testing matrix element C"
// << me << " "
// << me2 << " " << me/me2
// << endl;
}
return me;
}
double MEPP2GammaJet::qqbarME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & gout,
vector<VectorWaveFunction> & pout,
bool calc) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming antifermion (vbar spinor)
// for the outgoing
// 0 outgoing gluon
// 1 outgoing photon
// me to be returned
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1);
// wavefunction for the intermediate particles
SpinorWaveFunction inter;
unsigned int inhel1,inhel2,outhel1,outhel2;
Energy2 mt(scale());
Complex diag[3];
double me(0.),diag1(0.),diag2(0.);
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
// first diagram
inter = _gluonvertex->evaluate(mt,5,fin[inhel1].getParticle(),
fin[inhel1],gout[outhel1]);
diag[0] = _photonvertex->evaluate(0.*GeV2,inter,ain[inhel2],pout[outhel2]);
// second diagram
inter = _photonvertex->evaluate(0.*GeV2,5,fin[inhel1].getParticle(),
fin[inhel1],pout[outhel2]);
diag[1] = _gluonvertex->evaluate(mt,inter,ain[inhel2],gout[outhel1]);
// compute the running totals
diag[2]=diag[0]+diag[1];
diag1 +=norm(diag[0]);
diag2 +=norm(diag[1]);
me +=norm(diag[2]);
// matrix element
if(calc) newme(inhel1,inhel2,2*outhel1,2*outhel2)=diag[2];
}
}
}
}
// save the info on the diagrams
if(!calc) {
DVector save;
save.push_back(diag1);
save.push_back(diag2);
meInfo(save);
}
// return the answer
if(calc) _me.reset(newme);
return me;
}
double MEPP2GammaJet::qgME(vector<SpinorWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
vector<VectorWaveFunction> & pout,
vector<SpinorBarWaveFunction> & fout,
bool calc) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming gluon
// for the outgoing
// 0 outgoing photon
// 1 outgoing fermion (ubar spinor)
// me to be returned
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1,PDT::Spin1Half);
// wavefunction for the intermediate particles
SpinorWaveFunction inter;
unsigned int inhel1,inhel2,outhel1,outhel2;
Energy2 mt(scale());
Complex diag[3];
double me(0.),diag1(0.),diag2(0.);
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
// first diagram
inter = _photonvertex->evaluate(0.*GeV2,5,fin[inhel1].getParticle(),
fin[inhel1],pout[outhel1]);
diag[0]=_gluonvertex->evaluate(mt,inter,fout[outhel2],gin[inhel2]);
// second diagram
inter = _gluonvertex->evaluate(mt,5,fin[inhel1].getParticle(),
fin[inhel1],gin[inhel2]);
diag[1]=_photonvertex->evaluate(0.*GeV2,inter,fout[outhel2],pout[outhel1]);
// compute the running totals
diag[2]=diag[0]+diag[1];
diag1 +=norm(diag[0]);
diag2 +=norm(diag[1]);
me +=norm(diag[2]);
// matrix element
if(calc) newme(inhel1,2*inhel2,2*outhel1,outhel2)=diag[2];
}
}
}
}
// save the info on the diagrams
if(!calc) {
DVector save;
save.push_back(diag1);
save.push_back(diag2);
meInfo(save);
}
// return the answer
if(calc) _me.reset(newme);
return me;
}
double MEPP2GammaJet::qbargME(vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & gin,
vector<VectorWaveFunction> & pout,
vector<SpinorWaveFunction> & aout,
bool calc) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (vbar spinor)
// 1 incoming gluon
// for the outgoing
// 0 outgoing photon
// 1 outgoing fermion (v spinor)
//me to be returned
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1,PDT::Spin1Half);
// wavefunction for the intermediate particles
SpinorBarWaveFunction inter;
SpinorWaveFunction interb;
unsigned int inhel1,inhel2,outhel1,outhel2;
Energy2 mt(scale());
Complex diag[3];
double me(0.),diag1(0.),diag2(0.);
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
// first diagram
inter = _photonvertex->evaluate(0.*GeV2,5,ain[inhel1].getParticle(),
ain[inhel1],pout[outhel1]);
diag[0]=_gluonvertex->evaluate(mt,aout[outhel2],inter,gin[inhel2]);
// second diagram
inter = _gluonvertex->evaluate(mt,5,ain[inhel1].getParticle(),
ain[inhel1],gin[inhel2]);
diag[1]=_photonvertex->evaluate(0.*GeV2,aout[outhel2],inter,pout[outhel1]);
// compute the running totals
diag[2]=diag[0]+diag[1];
diag1 +=norm(diag[0]);
diag2 +=norm(diag[1]);
me +=norm(diag[2]);
// matrix element
if(calc) newme(inhel1,2*inhel2,2*outhel1,outhel2)=diag[2];
}
}
}
}
// save the info on the diagrams
if(!calc) {
DVector save;
save.push_back(diag1);
save.push_back(diag2);
meInfo(save);
}
// return the answer
if(calc) _me.reset(newme);
return me;
}
void MEPP2GammaJet::constructVertex(tSubProPtr sub) {
SpinfoPtr spin[4];
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
// order of particles
unsigned int order[4]={0,1,2,3};
// identify the process and calculate matrix element
if(hard[0]->id()==ParticleID::g||hard[1]->id()==ParticleID::g) {
if(hard[0]->id()==ParticleID::g ) swap(order[0],order[1]);
if(hard[3]->id()==ParticleID::gamma) swap(order[2],order[3]);
if(hard[order[0]]->id()>0) {
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qb;
vector<VectorWaveFunction> p,g;
SpinorWaveFunction (q ,hard[order[0]],incoming,false,true);
VectorWaveFunction (g ,hard[order[1]],incoming,false,true,true);
VectorWaveFunction (p ,hard[order[2]],outgoing,true ,true,true);
SpinorBarWaveFunction(qb,hard[order[3]],outgoing,true,true);
qgME(q,g,p,qb,true);
}
else {
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qb;
vector<VectorWaveFunction> p,g;
SpinorBarWaveFunction(qb,hard[order[0]],incoming,false,true);
VectorWaveFunction (g ,hard[order[1]],incoming,false,true,true);
VectorWaveFunction (p ,hard[order[2]],outgoing,true ,true,true);
SpinorWaveFunction (q ,hard[order[3]],outgoing,true,true);
qbargME(qb,g,p,q,true);
}
}
else {
if(hard[0]->id()<0) swap(order[0],order[1]);
if(hard[2]->id()==ParticleID::gamma) swap(order[2],order[3]);
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qb;
vector<VectorWaveFunction> p,g;
SpinorWaveFunction (q ,hard[order[0]],incoming,false,true);
SpinorBarWaveFunction(qb,hard[order[1]],incoming,false,true);
VectorWaveFunction (g ,hard[order[2]],outgoing,true ,true,true);
VectorWaveFunction (p ,hard[order[3]],outgoing,true ,true,true);
p[1]=p[2];g[1]=g[2];
qqbarME(q,qb,g,p,true);
}
// get the spin info objects
for(unsigned int ix=0;ix<4;++ix)
spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[order[ix]]->spinInfo());
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix)
spin[ix]->setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/Hadron/MEPP2GammaJet.h b/MatrixElement/Hadron/MEPP2GammaJet.h
--- a/MatrixElement/Hadron/MEPP2GammaJet.h
+++ b/MatrixElement/Hadron/MEPP2GammaJet.h
@@ -1,299 +1,299 @@
// -*- C++ -*-
//
// MEPP2GammaJet.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_MEPP2GammaJet_H
#define HERWIG_MEPP2GammaJet_H
//
// This is the declaration of the MEPP2GammaJet class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/** \ingroup MatrixElements
* The MEPP2GammaJet class implements the matrix element for photon+jet
* production in hadron-hadron collisions.
*
* @see \ref MEPP2GammaJetInterfaces "The interfaces"
* defined for MEPP2GammaJet.
*/
class MEPP2GammaJet: public HwME2to2Base {
public:
/**
* The default constructor.
*/
inline MEPP2GammaJet();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
throw(RebindException);
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
private:
/**
* Members to return the matrix elements for the different subprocesses
*/
//@{
/**
* Matrix element for \f$q\bar{q}\to g\gamma\f$.
* @param fin Spinors for incoming quark
* @param ain Spinors for incoming antiquark
* @param gout Polarization vectors for the outgoing gluon
* @param pout Polarization vectors for the outgoing photon
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double qqbarME(vector<SpinorWaveFunction> & fin, vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & gout, vector<VectorWaveFunction> & pout,
bool me) const;
/**
* Matrix element for \f$qg\to \gamma q\f$.
* @param fin Spinors for incoming quark
* @param gin Polarization vectors for the incoming gluon
* @param pout Polarization vectors for the outgoing photon
* @param fout Spinors for outgoing quark
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double qgME(vector<SpinorWaveFunction> & fin,vector<VectorWaveFunction> & gin,
vector<VectorWaveFunction> & pout,vector<SpinorBarWaveFunction> & fout,
bool me) const;
/**
* Matrix element for \f$\bar{q}g\to \gamma \bar{q}\f$.
* @param ain Spinors for the incoming antiquark
* @param gin Polarization vectors for the incoming gluon
* @param pout Polarization vectors for the outgoing photon
* @param aout Spinors for the outgoing antiquark
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double qbargME(vector<SpinorBarWaveFunction> & ain, vector<VectorWaveFunction> & gin,
vector<VectorWaveFunction> & pout, vector<SpinorWaveFunction> & aout,
bool me) const;
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2GammaJet> initMEPP2GammaJet;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2GammaJet & operator=(const MEPP2GammaJet &);
private:
/**
* Pointer to the quark-antiquark-gluon vertex
*/
AbstractFFVVertexPtr _gluonvertex;
/**
* Pointer to the quark-antiquark-photon vertex
*/
AbstractFFVVertexPtr _photonvertex;
/**
* Maximum PDG code of the quarks allowed
*/
unsigned int _maxflavour;
/**
* Option for which processes to include
*/
unsigned int _processopt;
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEPP2GammaJet. */
template <>
struct BaseClassTrait<Herwig::MEPP2GammaJet,1> {
/** Typedef of the first base class of MEPP2GammaJet. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2GammaJet class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2GammaJet>
: public ClassTraitsBase<Herwig::MEPP2GammaJet> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2GammaJet"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2GammaJet is implemented. It may also include several, space-separated,
* libraries if the class MEPP2GammaJet depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEPP2GammaJet_H */
diff --git a/MatrixElement/Hadron/MEPP2Higgs.cc b/MatrixElement/Hadron/MEPP2Higgs.cc
--- a/MatrixElement/Hadron/MEPP2Higgs.cc
+++ b/MatrixElement/Hadron/MEPP2Higgs.cc
@@ -1,337 +1,337 @@
// -*- C++ -*-
//
// MEPP2Higgs.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 MEPP2Higgs class.
//
#include "MEPP2Higgs.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
MEPP2Higgs::MEPP2Higgs() : shapeopt(2),
processopt(1),
minflavouropt(4),
maxflavouropt(5), _mh(0.*GeV),_wh(0.*GeV)
{}
ClassDescription<MEPP2Higgs> MEPP2Higgs::initMEPP2Higgs;
// Definition of the static class description member.
void MEPP2Higgs::persistentOutput(PersistentOStream & os) const {
os << hggvertex << ffhvertex << theSM << shapeopt << processopt
<< minflavouropt << maxflavouropt << _hmass << ounit(_mh,GeV) << ounit(_wh,GeV);
}
void MEPP2Higgs::persistentInput(PersistentIStream & is, int) {
is >> hggvertex >> ffhvertex >> theSM >> shapeopt >> processopt
>> minflavouropt >> maxflavouropt >> _hmass >> iunit(_mh,GeV) >> iunit(_wh,GeV);
}
void MEPP2Higgs::Init() {
static ClassDocumentation<MEPP2Higgs> documentation
("The MEPP2Higgs class implements the matrix elements for"
" Higgs production (with decay H->W-W+) in hadron-hadron collisions.");
static Switch<MEPP2Higgs,unsigned int> interfaceShapeOption
("ShapeScheme",
"Option for the treatment of the Higgs resonance shape",
&MEPP2Higgs::shapeopt, 1, false, false);
static SwitchOption interfaceStandardShapeFixed
(interfaceShapeOption,
"FixedBreitWigner",
"Breit-Wigner s-channel resonanse",
1);
static SwitchOption interfaceStandardShapeRunning
(interfaceShapeOption,
"MassGenerator",
"Use the mass generator to give the shape",
2);
static Switch<MEPP2Higgs,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEPP2Higgs::processopt, 1, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
1);
static SwitchOption interfaceProcess1
(interfaceProcess,
"qqbar",
"Only include the incoming q qbar subprocess",
2);
static SwitchOption interfaceProcessgg
(interfaceProcess,
"gg",
"Only include the incoming gg subprocess",
3);
static Parameter<MEPP2Higgs,unsigned int> interfaceMinimumFlavour
("MinimumFlavour",
"The minimum flavour of the incoming quarks in the hard process",
&MEPP2Higgs::minflavouropt, 4, 3, 5,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,unsigned int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour of the incoming quarks in the hard process",
&MEPP2Higgs::maxflavouropt, 5, 3, 5,
false, false, Interface::limited);
}
void MEPP2Higgs::doinit() throw(InitException) {
MEBase::doinit();
// get the vertex pointers from the SM object
theSM = dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(!theSM) {
throw InitException() << "Wrong type of StandardModel object in MEPP2Higgs::doinit(),"
<< " the Herwig++ version must be used"
<< Exception::runerror;
}
hggvertex = theSM->vertexHGG();
ffhvertex = theSM->vertexFFH();
// get the mass generator for the higgs
PDPtr h0 = getParticleData(ParticleID::h0);
_mh = h0->mass();
_wh = h0->generateWidth(_mh);
if(h0->massGenerator()) {
_hmass=dynamic_ptr_cast<SMHiggsMassGeneratorPtr>(h0->massGenerator());
}
if(shapeopt==2&&!_hmass) throw InitException()
<< "If using the mass generator for the line shape in MEPP2Higgs::doinit()"
<< "the mass generator must be an instance of the SMHiggsMassGenerator class"
<< Exception::runerror;
}
unsigned int MEPP2Higgs::orderInAlphaS() const {
return 2;
}
unsigned int MEPP2Higgs::orderInAlphaEW() const {
return 1;
}
Energy2 MEPP2Higgs::scale() const {
return sHat();
}
int MEPP2Higgs::nDim() const {
return 0;
}
bool MEPP2Higgs::generateKinematics(const double *) {
Lorentz5Momentum pout = meMomenta()[0] + meMomenta()[1];
pout.rescaleMass();
meMomenta()[2].setMass(pout.mass());
meMomenta()[2] = LorentzMomentum(pout.x(),pout.y(),pout.z(),pout.t());
jacobian(1.0);
// check whether it passes all the cuts: returns true if it does
vector<LorentzMomentum> out(1,meMomenta()[2]);
tcPDVector tout(1,mePartonData()[2]);
return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]);
}
void MEPP2Higgs::getDiagrams() const {
tcPDPtr h0=getParticleData(ParticleID::h0);
// gg -> H process
if(processopt==1||processopt==3) {
tcPDPtr g=getParticleData(ParticleID::g);
add(new_ptr((Tree2toNDiagram(2), g, g, 1, h0, -1)));
}
// q qbar -> H processes
if(processopt==1||processopt==2) {
for (unsigned int i = minflavouropt; i <= maxflavouropt; ++i) {
tcPDPtr q = getParticleData(i);
tcPDPtr qb = q->CC();
add(new_ptr((Tree2toNDiagram(2), q, qb, 1, h0, -2)));
}
}
}
CrossSection MEPP2Higgs::dSigHatDR() const {
using Constants::pi;
InvEnergy2 bwfact;
if(shapeopt==1) {
bwfact = mePartonData()[2]->generateWidth(sqrt(sHat()))*sqrt(sHat())/pi/
(sqr(sHat()-sqr(_mh))+sqr(_mh*_wh));
}
else {
bwfact = _hmass->BreitWignerWeight(sqrt(sHat()),0);
}
double cs = me2() * jacobian() * pi * double(UnitRemoval::E4 * bwfact/sHat());
return UnitRemoval::InvE2 * sqr(hbarc) * cs;
}
double MEPP2Higgs::me2() const {
double output(0.0);
useMe();
ScalarWaveFunction hout(meMomenta()[2],mePartonData()[2],outgoing);
// Safety code to garantee the reliable behaviour of Higgs shape limits
// (important for heavy and broad Higgs resonance).
Energy hmass = meMomenta()[2].m();
tcPDPtr h0 = mePartonData()[2];
Energy mass = h0->mass();
Energy halfmass = .5*mass;
if (.0*GeV > hmass) return 0.0;
// stricly speaking the condition is applicable if h0->widthUpCut() == h0->widthLoCut()...
if (h0->widthLoCut() > halfmass) {
if ((mass + h0->widthUpCut() < hmass || mass - h0->widthLoCut() > hmass)) return 0.0;
} else {
if (mass + halfmass < hmass || halfmass > hmass) return 0.0;
}
if (mePartonData()[0]->id() == ParticleID::g &&
mePartonData()[1]->id() == ParticleID::g) {
VectorWaveFunction gin1(meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction gin2(meMomenta()[1],mePartonData()[1],incoming);
vector<VectorWaveFunction> g1,g2;
for(unsigned int i = 0; i < 2; ++i) {
gin1.reset(2*i);
g1.push_back(gin1);
gin2.reset(2*i);
g2.push_back(gin2);
}
output = ggME(g1,g2,hout,false);
} else {
if (mePartonData()[0]->id() == -mePartonData()[1]->id()) {
SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction qbin(meMomenta()[1],mePartonData()[1],incoming);
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
for (unsigned int i = 0; i < 2; ++i) {
qin.reset(i);
fin.push_back(qin);
qbin.reset(i);
ain.push_back(qbin);
}
output = qqME(fin,ain,hout,false);
}
else {
throw Exception() << "Unknown subprocess in MEPP2Higgs::me2()"
<< Exception::runerror;
}
}
return output;
}
Selector<MEBase::DiagramIndex> MEPP2Higgs::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for (DiagramIndex i = 0; i < diags.size(); ++i)
sel.insert(1.0, i);
return sel;
}
Selector<const ColourLines *> MEPP2Higgs::colourGeometries(tcDiagPtr diag) const {
// colour lines
static const ColourLines line1("1 -2,2 -1");
static const ColourLines line2("1 -2");
// select the colour flow
Selector<const ColourLines *> sel;
if (diag->id() == -1) {
sel.insert(1.0, &line1);
} else {
sel.insert(1.0, &line2);
}
// return the answer
return sel;
}
void MEPP2Higgs::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
if(hard[0]->id() < hard[1]->id()) {
swap(hard[0],hard[1]);
}
// identify the process and calculate the matrix element
if(hard[0]->id() == ParticleID::g && hard[1]->id() == ParticleID::g) {
vector<VectorWaveFunction> g1,g2;
vector<SpinorBarWaveFunction> q;
vector<SpinorWaveFunction> qbar;
VectorWaveFunction (g1,hard[0],incoming,false,true,true);
VectorWaveFunction (g2,hard[1],incoming,false,true,true);
ScalarWaveFunction hout(hard[2],outgoing,true,true);
g1[1] = g1[2];
g2[1] = g2[2];
ggME(g1,g2,hout,true);
} else {
vector<SpinorWaveFunction> q1;
vector<SpinorBarWaveFunction> q2;
SpinorWaveFunction (q1,hard[0],incoming,false,true);
SpinorBarWaveFunction (q2,hard[1],incoming,false,true);
ScalarWaveFunction hout(hard[2],outgoing,true,true);
qqME(q1,q2,hout,true);
}
// construct the vertex
HardVertexPtr hardvertex = new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int i = 0; i < 3; ++i) {
dynamic_ptr_cast<SpinfoPtr>(hard[i]->spinInfo())->setProductionVertex(hardvertex);
}
}
double MEPP2Higgs::ggME(vector<VectorWaveFunction> g1,
vector<VectorWaveFunction> g2,
ScalarWaveFunction & in,
bool calc) const {
ProductionMatrixElement newme(PDT::Spin1,PDT::Spin1,PDT::Spin0);
Energy2 s(sHat());
double me2(0.0);
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
Complex diag = hggvertex->evaluate(s,g1[i],g2[j],in);
me2 += norm(diag);
if(calc) newme(2*i, 2*j, 0) = diag;
}
}
if(calc) _me.reset(newme);
// initial colour and spin factors: colour -> (8/64) and spin -> (1/4)
return me2/32.;
}
double MEPP2Higgs::qqME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
ScalarWaveFunction & in,
bool calc) const {
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0);
Energy2 s(scale());
double me2(0.0);
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
Complex diag = ffhvertex->evaluate(s,fin[i],ain[j],in);
me2+=norm(diag);
if(calc) newme(i, j, 0) = diag;
}
}
if(calc) _me.reset(newme);
// final colour/spin factors
return me2/12.;
}
diff --git a/MatrixElement/Hadron/MEPP2Higgs.h b/MatrixElement/Hadron/MEPP2Higgs.h
--- a/MatrixElement/Hadron/MEPP2Higgs.h
+++ b/MatrixElement/Hadron/MEPP2Higgs.h
@@ -1,325 +1,325 @@
// -*- C++ -*-
//
// MEPP2Higgs.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_MEPP2Higgs_H
#define HERWIG_MEPP2Higgs_H
//
// This is the declaration of the MEPP2Higgs class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
#include "Herwig++/PDT/SMHiggsMassGenerator.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEPP2Higgs class implements the matrix element for the process
* pp->Higgs with different Higgs shape prescriptions (see details in hep-ph/9505211)
* and the NLL corrected Higgs width (see details in the FORTRAN HERWIG manual).
*
* @see \ref MEPP2HiggsInterfaces "The interfaces"
* defined for MEPP2Higgs.
*/
class MEPP2Higgs: public MEBase {
public:
/**
* The default constructor.
*/
MEPP2Higgs();
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(). Uses
* me().
*/
virtual CrossSection dSigHatDR() const;
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *> colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2Higgs> initMEPP2Higgs;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2Higgs & operator=(const MEPP2Higgs &);
//@}
/**
* Members to return the matrix elements for the different subprocesses
*/
//@{
/**
* Calculates the matrix element for the process g,g->h (via quark loops)
* @param g1 a vector of wave functions of the first incoming gluon
* @param g2 a vector of wave functions of the second incoming gluon
* @param calc Whether or not to calculate the matrix element for spin correlations
* @return the amlitude value.
*/
double ggME(vector<VectorWaveFunction> g1,
vector<VectorWaveFunction> g2,
ScalarWaveFunction &,
bool calc) const;
/**
* Calculates the matrix element for the process q,qbar->h
* @param fin a vector of quark spinors
* @param ain a vector of anti-quark spinors
* @param calc Whether or not to calculate the matrix element for spin correlations
* @return the amlitude value.
*/
double qqME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
ScalarWaveFunction &,
bool calc) const;
//@}
private:
/**
* Defines the Higgs resonance shape
*/
unsigned int shapeopt;
/**
* The processes to be included (GG->H and/or qq->H)
*/
unsigned int processopt;
/**
* Minimum flavour of incoming quarks
*/
unsigned int minflavouropt;
/**
* Maximum flavour of incoming quarks
*/
unsigned int maxflavouropt;
/**
* Storage of the diagram weights for the \f$gg\to Hg\f$ subprocess
*/
mutable double diagwgt[3];
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
/**
* Pointer to the H->2gluons vertex (used in gg->H)
*/
AbstractVVSVertexPtr hggvertex;
/**
* Pointer to the fermion-fermion Higgs vertex (used in qq->H)
*/
AbstractFFSVertexPtr ffhvertex;
/**
* Pointer to the Standard Model instance used in the class
*/
tcHwSMPtr theSM;
/**
* The mass generator for the Higgs
*/
SMHiggsMassGeneratorPtr _hmass;
/**
* On-shell mass for the higgs
*/
Energy _mh;
/**
* On-shell width for the higgs
*/
Energy _wh;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the base classes of MEPP2Higgs. */
template <>
struct BaseClassTrait<Herwig::MEPP2Higgs,1> {
/** Typedef of the first base class of MEPP2Higgs. */
typedef MEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2Higgs class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2Higgs>
: public ClassTraitsBase<Herwig::MEPP2Higgs> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2Higgs"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2Higgs is implemented. It may also include several, space-separated,
* libraries if the class MEPP2Higgs depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEPP2Higgs_H */
diff --git a/MatrixElement/Hadron/MEPP2HiggsJet.cc b/MatrixElement/Hadron/MEPP2HiggsJet.cc
--- a/MatrixElement/Hadron/MEPP2HiggsJet.cc
+++ b/MatrixElement/Hadron/MEPP2HiggsJet.cc
@@ -1,867 +1,867 @@
// -*- C++ -*-
//
// MEPP2HiggsJet.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 MEPP2HiggsJet class.
//
#include "MEPP2HiggsJet.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
const Complex MEPP2HiggsJet::_epsi = Complex(0.,-1.e-20);
unsigned int MEPP2HiggsJet::orderInAlphaS() const {
return 3;
}
unsigned int MEPP2HiggsJet::orderInAlphaEW() const {
return 1;
}
void MEPP2HiggsJet::persistentOutput(PersistentOStream & os) const {
os << _shapeopt << _maxflavour << _process << _minloop << _maxloop << _massopt
<< ounit(_mh,GeV) << ounit(_wh,GeV) << _hmass;
}
void MEPP2HiggsJet::persistentInput(PersistentIStream & is, int) {
is >> _shapeopt >> _maxflavour >> _process >> _minloop >> _maxloop >> _massopt
>> iunit(_mh,GeV) >> iunit(_wh,GeV) >> _hmass;
}
ClassDescription<MEPP2HiggsJet> MEPP2HiggsJet::initMEPP2HiggsJet;
// Definition of the static class description member.
void MEPP2HiggsJet::Init() {
static ClassDocumentation<MEPP2HiggsJet> documentation
("The MEPP2HiggsJet class implements the matrix elements for"
" Higgs+Jet production in hadron-hadron collisions.",
"The theoretical calculations of \\cite{Baur:1989cm} and \\cite{Ellis:1987xu}"
"were used for the Higgs+jet matrix element in hadron-hadron collisions.",
"\\bibitem{Baur:1989cm} U.~Baur and E.~W.~N.~Glover,"
"Nucl.\\ Phys.\\ B {\\bf 339} (1990) 38.\n"
"\\bibitem{Ellis:1987xu} R.~K.~Ellis, I.~Hinchliffe, M.~Soldate and "
"J.~J.~van der Bij, Nucl.\\ Phys.\\ B {\\bf 297} (1988) 221.");
static Parameter<MEPP2HiggsJet,unsigned int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour of the quarks in the process",
&MEPP2HiggsJet::_maxflavour, 5, 1, 5,
false, false, Interface::limited);
static Switch<MEPP2HiggsJet,unsigned int> interfaceShapeOption
("ShapeScheme",
"Option for the treatment of the Higgs resonance shape",
&MEPP2HiggsJet::_shapeopt, 1, false, false);
static SwitchOption interfaceStandardShapeFixed
(interfaceShapeOption,
"FixedBreitWigner",
"Breit-Wigner s-channel resonanse",
1);
static SwitchOption interfaceStandardShapeRunning
(interfaceShapeOption,
"MassGenerator",
"Use the mass generator to give the shape",
2);
static Switch<MEPP2HiggsJet,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEPP2HiggsJet::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
0);
static SwitchOption interfaceProcess1
(interfaceProcess,
"qqbar",
"Only include the incoming q qbar subprocess",
1);
static SwitchOption interfaceProcessqg
(interfaceProcess,
"qg",
"Only include the incoming qg subprocess",
2);
static SwitchOption interfaceProcessqbarg
(interfaceProcess,
"qbarg",
"Only include the incoming qbar g subprocess",
3);
static SwitchOption interfaceProcessgg
(interfaceProcess,
"gg",
"Only include the incoming gg subprocess",
4);
static Parameter<MEPP2HiggsJet,unsigned int> interfaceMinimumInLoop
("MinimumInLoop",
"The minimum flavour of the quarks to include in the loops",
&MEPP2HiggsJet::_minloop, 6, 4, 6,
false, false, Interface::limited);
static Parameter<MEPP2HiggsJet,unsigned int> interfaceMaximumInLoop
("MaximumInLoop",
"The maximum flavour of the quarks to include in the loops",
&MEPP2HiggsJet::_maxloop, 6, 4, 6,
false, false, Interface::limited);
static Switch<MEPP2HiggsJet,unsigned int> interfaceMassOption
("MassOption",
"Option for the treatment of the masses in the loop diagrams",
&MEPP2HiggsJet::_massopt, 0, false, false);
static SwitchOption interfaceMassOptionFull
(interfaceMassOption,
"Full",
"Include the full mass dependence",
0);
static SwitchOption interfaceMassOptionLarge
(interfaceMassOption,
"Large",
"Use the heavy mass limit",
1);
}
bool MEPP2HiggsJet::generateKinematics(const double * r) {
Energy ptmin = max(lastCuts().minKT(mePartonData()[2]),
lastCuts().minKT(mePartonData()[3]));
Energy e = sqrt(sHat())/2.0;
// generate the mass of the higgs boson
Energy2 mhmax2 = sHat()-4.*ptmin*e;
Energy2 mhmin2 =0.*GeV2;
if(mhmax2<=mhmin2) return false;
double rhomin = atan((mhmin2-sqr(_mh))/_mh/_wh);
double rhomax = atan((mhmax2-sqr(_mh))/_mh/_wh);
Energy mh = sqrt(_mh*_wh*tan(rhomin+r[1]*(rhomax-rhomin))+sqr(_mh));
// assign masses
if(mePartonData()[2]->id()!=ParticleID::h0) {
meMomenta()[2].setMass(0.*GeV);
meMomenta()[3].setMass(mh);
}
else {
meMomenta()[3].setMass(0.*GeV);
meMomenta()[2].setMass(mh);
}
Energy q = 0.0*GeV;
try {
q = SimplePhaseSpace::
getMagnitude(sHat(), meMomenta()[2].mass(), meMomenta()[3].mass());
}
catch ( ImpossibleKinematics ) {
return false;
}
Energy2 m22 = meMomenta()[2].mass2();
Energy2 m32 = meMomenta()[3].mass2();
Energy2 e0e2 = 2.0*e*sqrt(sqr(q) + m22);
Energy2 e1e2 = 2.0*e*sqrt(sqr(q) + m22);
Energy2 e0e3 = 2.0*e*sqrt(sqr(q) + m32);
Energy2 e1e3 = 2.0*e*sqrt(sqr(q) + m32);
Energy2 pq = 2.0*e*q;
double ctmin = -1.0,ctmax = 1.0;
Energy2 thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[2]);
if ( thmin > 0.0*GeV2 ) ctmax = min(ctmax, (e0e2 - m22 - thmin)/pq);
thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[2]);
if ( thmin > 0.0*GeV2 ) ctmin = max(ctmin, (thmin + m22 - e1e2)/pq);
thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[3]);
if ( thmin > 0.0*GeV2 ) ctmax = min(ctmax, (e1e3 - m32 - thmin)/pq);
thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[3]);
if ( thmin > 0.0*GeV2 ) ctmin = max(ctmin, (thmin + m32 - e0e3)/pq);
if ( ptmin > 0.0*GeV ) {
double ctm = 1.0 - sqr(ptmin/q);
if ( ctm <= 0.0 ) return false;
ctmin = max(ctmin, -sqrt(ctm));
ctmax = min(ctmax, sqrt(ctm));
}
if ( ctmin >= ctmax ) return false;
double cth = getCosTheta(ctmin, ctmax, r);
Energy pt = q*sqrt(1.0-sqr(cth));
phi(rnd(2.0*Constants::pi));
meMomenta()[2].setX(pt*sin(phi()));
meMomenta()[2].setY(pt*cos(phi()));
meMomenta()[2].setZ(q*cth);
meMomenta()[3].setX(-pt*sin(phi()));
meMomenta()[3].setY(-pt*cos(phi()));
meMomenta()[3].setZ(-q*cth);
meMomenta()[2].rescaleEnergy();
meMomenta()[3].rescaleEnergy();
vector<LorentzMomentum> out(2);
out[0] = meMomenta()[2];
out[1] = meMomenta()[3];
tcPDVector tout(2);
tout[0] = mePartonData()[2];
tout[1] = mePartonData()[3];
if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) )
return false;
tHat(pq*cth + m22 - e0e2);
uHat(m22 + m32 - sHat() - tHat());
// main piece
jacobian((pq/sHat())*Constants::pi*jacobian());
// mass piece
jacobian((rhomax-rhomin)*jacobian());
return true;
}
void MEPP2HiggsJet::getDiagrams() const {
tcPDPtr h0=getParticleData(ParticleID::h0);
tcPDPtr g =getParticleData(ParticleID::g);
tcPDPtr q[6],qb[6];
for(int ix=0;ix<int(_maxflavour);++ix) {
q [ix]=getParticleData( ix+1);
qb[ix]=getParticleData(-ix-1);
}
// q qbar -> H g
if(_process==0||_process==1)
{for(unsigned int ix=0;ix<_maxflavour;++ix)
{add(new_ptr((Tree2toNDiagram(2), q[ix], qb[ix], 1, g , 3, h0, 3, g, -1)));}}
// q g -> H g
if(_process==0||_process==2)
{for(unsigned int ix=0;ix<_maxflavour;++ix)
{add(new_ptr((Tree2toNDiagram(3), q[ix], g, g, 2, h0, 1, q[ix], -2)));}}
// qbar g -> H qbar
if(_process==0||_process==3)
{for(unsigned int ix=0;ix<_maxflavour;++ix)
{add(new_ptr((Tree2toNDiagram(3), qb[ix], g, g, 2, h0, 1, qb[ix], -3)));}}
// g g -> H g
if(_process==0||_process==4)
{
// t channel
add(new_ptr((Tree2toNDiagram(3), g, g, g, 1, h0, 2, g, -4)));
// u channel
add(new_ptr((Tree2toNDiagram(3), g, g, g, 2, h0, 1, g, -5)));
// s channel
add(new_ptr((Tree2toNDiagram(2), g, g, 1, g , 3, h0, 3, g, -6)));
}
}
Energy2 MEPP2HiggsJet::scale() const {
return meMomenta()[2].perp2()+ meMomenta()[2].m2();
}
double MEPP2HiggsJet::me2() const {
useMe();
double output(0.);
// g g to H g
if(mePartonData()[0]->id()==ParticleID::g&&mePartonData()[1]->id()==ParticleID::g) {
// order of the particles
unsigned int ih(2),ig(3);
if(mePartonData()[3]->id()==ParticleID::h0){ig=2;ih=3;}
VectorWaveFunction glin1(meMomenta()[ 0],mePartonData()[ 0],incoming);
VectorWaveFunction glin2(meMomenta()[ 1],mePartonData()[ 1],incoming);
ScalarWaveFunction hout(meMomenta()[ih],mePartonData()[ih],outgoing);
VectorWaveFunction glout(meMomenta()[ig],mePartonData()[ig],outgoing);
vector<VectorWaveFunction> g1,g2,g4;
for(unsigned int ix=0;ix<2;++ix) {
glin1.reset(2*ix);g1.push_back(glin1);
glin2.reset(2*ix);g2.push_back(glin2);
glout.reset(2*ix);g4.push_back(glout);
}
// calculate the matrix element
output = ggME(g1,g2,hout,g4,false);
}
// qg -> H q
else if(mePartonData()[0]->id()>0&&mePartonData()[1]->id()==ParticleID::g) {
// order of the particles
unsigned int iq(0),iqb(3),ih(2),ig(1);
if(mePartonData()[0]->id()==ParticleID::g){iq=1;ig=0;}
if(mePartonData()[3]->id()==ParticleID::h0){iqb=2;ih=3;}
// calculate the spinors and polarization vectors
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> fout;
vector<VectorWaveFunction> gin;
SpinorWaveFunction qin (meMomenta()[iq ],mePartonData()[iq ],incoming);
VectorWaveFunction glin(meMomenta()[ig ],mePartonData()[ig ],incoming);
ScalarWaveFunction hout(meMomenta()[ih ],mePartonData()[ih ],outgoing);
SpinorBarWaveFunction qout(meMomenta()[iqb],mePartonData()[iqb],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ; fin.push_back( qin);
qout.reset(ix) ;fout.push_back(qout);
glin.reset(2*ix); gin.push_back(glin);
}
// calculate the matrix element
output = qgME(fin,gin,hout,fout,false);
}
// qbar g -> H q
else if(mePartonData()[0]->id()<0&&mePartonData()[1]->id()==ParticleID::g) {
// order of the particles
unsigned int iq(0),iqb(3),ih(2),ig(1);
if(mePartonData()[0]->id()==ParticleID::g){iq=1;ig=0;}
if(mePartonData()[3]->id()==ParticleID::h0){iqb=2;ih=3;}
// calculate the spinors and polarization vectors
vector<SpinorBarWaveFunction> fin;
vector<SpinorWaveFunction> fout;
vector<VectorWaveFunction> gin;
SpinorBarWaveFunction qin (meMomenta()[iq ],mePartonData()[iq ],incoming);
VectorWaveFunction glin(meMomenta()[ig ],mePartonData()[ig ],incoming);
ScalarWaveFunction hout(meMomenta()[ih ],mePartonData()[ih ],outgoing);
SpinorWaveFunction qout(meMomenta()[iqb],mePartonData()[iqb],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ; fin.push_back( qin);
qout.reset(ix) ;fout.push_back(qout);
glin.reset(2*ix); gin.push_back(glin);
}
// calculate the matrix element
output = qbargME(fin,gin,hout,fout,false);
}
// q qbar to H g
else if(mePartonData()[0]->id()==-mePartonData()[1]->id()) {
// order of the particles
unsigned int iq(0),iqb(1),ih(2),ig(3);
if(mePartonData()[0]->id()<0){iq=1;iqb=0;}
if(mePartonData()[2]->id()==ParticleID::g){ig=2;ih=3;}
// calculate the spinors and polarization vectors
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gout;
SpinorWaveFunction qin (meMomenta()[iq ],mePartonData()[iq ],incoming);
SpinorBarWaveFunction qbin(meMomenta()[iqb],mePartonData()[iqb],incoming);
ScalarWaveFunction hout(meMomenta()[ih ],mePartonData()[ih ],outgoing);
VectorWaveFunction glout(meMomenta()[ig ],mePartonData()[ig ],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ; fin.push_back( qin);
qbin.reset(ix) ; ain.push_back( qbin);
glout.reset(2*ix);gout.push_back(glout);
}
// calculate the matrix element
output = qqbarME(fin,ain,hout,gout,false);
}
else
throw Exception() << "Unknown subprocess in MEPP2HiggsJet::me2()"
<< Exception::runerror;
// return the answer
return output;
}
double MEPP2HiggsJet::qqbarME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
ScalarWaveFunction & hout,
vector<VectorWaveFunction> & gout,
bool calc) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming antifermion (vbar spinor)
// for the outgoing
// 0 outgoing higgs
// 1 outgoing gluon
// me to be returned
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin0,PDT::Spin1);
// get the kinematic invariants
Energy2 s(sHat()),u(uHat()),t(tHat()),mh2(hout.m2()),et(scale());
// calculate the loop function
complex<Energy2> A5 = Energy2();
for(unsigned int ix=_minloop;ix<=_maxloop;++ix) {
// full mass dependance
if(_massopt==0) {
Energy2 mf2=sqr(getParticleData(ix)->mass());
A5+= mf2*(4.+4.*double(s/(u+t))*(W1(s,mf2)-W1(mh2,mf2))
+(1.-4.*double(mf2/(u+t)))*(W2(s,mf2)-W2(mh2,mf2)));
}
// infinite mass limit
else {
A5+=2.*(s-mh2)/3.;
}
}
// multiply by the rest of the form factors
using Constants::pi;
double g(sqrt(4.*pi*SM().alphaEM(mh2)/SM().sin2ThetaW()));
double gs(sqrt(4.*pi*SM().alphaS(et)));
Energy mw(getParticleData(ParticleID::Wplus)->mass());
complex<InvEnergy> A5c = A5 * Complex(0.,1.)*g*sqr(gs)*gs/(32.*s*sqr(pi)*mw);
// compute the matrix element
LorentzPolarizationVectorE fcurrent;
complex<Energy2> fdotp;
complex<Energy> epsdot[2];
Complex diag;
Lorentz5Momentum ps(fin[0].getMomentum()+ain[0].getMomentum());
ps.rescaleMass();
for(unsigned int ix=0;ix<2;++ix){epsdot[ix]=gout[ix].wave().dot(ps);}
Energy2 denom(-ps*gout[0].getMomentum());
LorentzSpinorBar<double> atemp;
double output(0.);
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
// compute the fermion current
atemp=ain[ihel2].wave();
fcurrent=UnitRemoval::E*fin[ihel1].wave().vectorCurrent(atemp);
fdotp = -(fcurrent.dot(gout[0].getMomentum()));
for(unsigned int ghel=0;ghel<2;++ghel) {
// calculate the matrix element
diag=A5c*(fcurrent.dot(gout[ghel].wave())
-fdotp*epsdot[ghel]/denom);
// calculate the matrix element
output+=real(diag*conj(diag));
if(calc) newme(ihel1,ihel2,0,2*ghel)=diag;
}
}
}
// test with glover form
// final colour/spin factors
if(calc) _me.reset(newme);
return output/9.;
}
double MEPP2HiggsJet::qgME(vector<SpinorWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
ScalarWaveFunction & hout,
vector<SpinorBarWaveFunction> & fout,bool calc) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming gluon
// for the outgoing
// 0 outgoing higgs
// 1 outgoing fermion (ubar spinor)
// me to be returned
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1,
PDT::Spin0,PDT::Spin1Half);
// get the kinematic invariants
Energy2 s(sHat()),u(uHat()),t(tHat()),mh2(hout.m2()),et(scale());
// calculate the loop function
complex<Energy2> A5 = Energy2();
for(unsigned int ix=_minloop;ix<=_maxloop;++ix) {
if(_massopt==0) {
Energy2 mf2=sqr(getParticleData(ix)->mass());
A5+= mf2*(4.+4.*double(u/(s+t))*(W1(u,mf2)-W1(mh2,mf2))
+(1.-4.*double(mf2/(s+t)))*(W2(u,mf2)-W2(mh2,mf2)));
}
else {
A5+=2.*(u-mh2)/3.;
}
}
// multiply by the rest of the form factors
using Constants::pi;
double g(sqrt(4.*pi*SM().alphaEM(mh2)/SM().sin2ThetaW()));
double gs(sqrt(4.*pi*SM().alphaS(et)));
Energy mw(getParticleData(ParticleID::Wplus)->mass());
complex<InvEnergy> A5c =A5*Complex(0.,1.)*g*sqr(gs)*gs/(32.*u*sqr(pi)*mw);
// compute the matrix element
LorentzPolarizationVectorE fcurrent;
complex<Energy2> fdotp;
complex<Energy> epsdot[2];
Complex diag;
Lorentz5Momentum pu(fin[0].getMomentum()+fout[0].getMomentum());
pu.rescaleMass();
for(unsigned int ix=0;ix<2;++ix){epsdot[ix]=gin[ix].wave().dot(pu);}
Energy2 denom(pu*gin[0].getMomentum());
LorentzSpinorBar<double> atemp;
double output(0.);
for(unsigned int ihel=0;ihel<2;++ihel) {
for(unsigned int ohel=0;ohel<2;++ohel) {
// compute the fermion current
atemp=fout[ohel].wave();
fcurrent=UnitRemoval::E*fin[ihel].wave().vectorCurrent(atemp);
fdotp=fcurrent.dot(gin[0].getMomentum());
for(unsigned int ghel=0;ghel<2;++ghel) {
// calculate the matrix element
diag=A5c*(fcurrent.dot(gin[ghel].wave())-fdotp*epsdot[ghel]/denom);
// calculate the matrix element
output+=real(diag*conj(diag));
if(calc) newme(ihel,2*ghel,0,ohel)=diag;
}
}
}
// final colour/spin factors
if(calc) _me.reset(newme);
return output/24.;
}
double MEPP2HiggsJet::qbargME(vector<SpinorBarWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
ScalarWaveFunction & hout,
vector<SpinorWaveFunction> & fout,bool calc) const {
// the particles should be in the order
// for the incoming
// 0 incoming antifermion (vbar spinor)
// 1 incoming gluon
// for the outgoing
// 0 outgoing higgs
// 1 outgoing antifermion (v spinor)
// me to be returned
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1,
PDT::Spin0,PDT::Spin1Half);
// get the kinematic invariants
Energy2 s(sHat()),u(uHat()),t(tHat()),mh2(hout.m2()),et(scale());
// calculate the loop function
complex<Energy2> A5 = Energy2();
for(unsigned int ix=_minloop;ix<=_maxloop;++ix) {
if(_massopt==0) {
Energy2 mf2=sqr(getParticleData(ix)->mass());
A5+= mf2*(4.+4.*double(u/(s+t))*(W1(u,mf2)-W1(mh2,mf2))
+(1.-4.*double(mf2/(s+t)))*(W2(u,mf2)-W2(mh2,mf2)));
}
else {
A5+=2.*(u-mh2)/3.;
}
}
// multiply by the rest of the form factors
using Constants::pi;
double g(sqrt(4.*pi*SM().alphaEM(mh2)/SM().sin2ThetaW()));
double gs(sqrt(4.*pi*SM().alphaS(et)));
Energy mw(getParticleData(ParticleID::Wplus)->mass());
complex<InvEnergy> A5c = A5*Complex(0.,1.)*g*sqr(gs)*gs/(32.*u*sqr(pi)*mw);
// compute the matrix element
LorentzPolarizationVectorE fcurrent;
complex<Energy2> fdotp;
complex<Energy> epsdot[2];
Complex diag;
Lorentz5Momentum pu(fin[0].getMomentum()+fout[0].getMomentum());
pu.rescaleMass();
for(unsigned int ix=0;ix<2;++ix){epsdot[ix]=gin[ix].wave().dot(pu);}
Energy2 denom(pu*gin[0].getMomentum());
LorentzSpinorBar<double> atemp;
double output(0.);
for(unsigned int ihel=0;ihel<2;++ihel) {
for(unsigned int ohel=0;ohel<2;++ohel) {
// compute the fermion current
atemp=fin[ihel].wave();
fcurrent=UnitRemoval::E*fout[ohel].wave().vectorCurrent(atemp);
fdotp=fcurrent.dot(gin[0].getMomentum());
for(unsigned int ghel=0;ghel<2;++ghel) {
// calculate the matrix element
diag=A5c*(fcurrent.dot(gin[ghel].wave())-fdotp*epsdot[ghel]/denom);
// calculate the matrix element
output+=real(diag*conj(diag));
if(calc) newme(ihel,2*ghel,0,ohel)=diag;
}
}
}
// final colour/spin factors
if(calc) _me.reset(newme);
return output/24.;
}
Selector<MEBase::DiagramIndex>
MEPP2HiggsJet::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i )
{
if(abs(diags[i]->id())<4) sel.insert(1.0, i);
else sel.insert(_diagwgt[abs(diags[i]->id())-4], i);
}
return sel;
}
Selector<const ColourLines *>
MEPP2HiggsJet::colourGeometries(tcDiagPtr diag) const {
// colour lines for q qbar -> h0 g
static const ColourLines cqqbar("1 3 5,-2 -3 -5");
// colour lines for q g -> h0 q
static const ColourLines cqg("1 2 -3, 3 -2 5");
// colour lines for qbar q -> h0 qbar
static const ColourLines cqbarg("-1 -2 3, -3 2 -5");
// colour lines for g g -> h0 g
static const ColourLines cgg[6]={ColourLines("1 2 5, -3 -5, 3 -2 -1"),
ColourLines("-1 -2 -5, 3 5, -3 2 1"),
ColourLines("1 5, -1 -2 3, -3 2 -5"),
ColourLines("-1 -5, 1 2 -3, 3 -2 5"),
ColourLines("1 3 5, -5 -3 -2, 2 -1"),
ColourLines("-1 -3 -5, 5 3 2 ,-2 1")};
// select the colour flow
Selector<const ColourLines *> sel;
if ( diag->id() == -1) sel.insert(1.0, &cqqbar);
else if ( diag->id() == -2) sel.insert(1.0, &cqg);
else if ( diag->id() == -3) sel.insert(1.0, &cqbarg);
else
{
sel.insert(0.5, &cgg[2*(abs(diag->id())-4) ]);
sel.insert(0.5, &cgg[2*(abs(diag->id())-4)+1]);
}
// return the answer
return sel;
}
double MEPP2HiggsJet::ggME(vector<VectorWaveFunction> g1, vector<VectorWaveFunction> g2,
ScalarWaveFunction & hout, vector<VectorWaveFunction> g4,
bool calc) const {
// the particles should be in the order
// for the incoming
// 0 first incoming gluon
// 1 second incoming gluon
// for the outgoing
// 0 outgoing higgs
// 1 outgoing gluon
// me to be returned
ProductionMatrixElement newme(PDT::Spin1,PDT::Spin1,
PDT::Spin0,PDT::Spin1);
// get the kinematic invariants
Energy2 s(sHat()),u(uHat()),t(tHat()),mh2(hout.m2()),et(scale());
// calculate the loop functions
Complex A4stu(0.),A2stu(0.),A2tsu(0.),A2ust(0.);
Complex A5s(0.),A5t(0.),A5u(0.);
for(unsigned int ix=_minloop;ix<=_maxloop;++ix) {
Energy2 mf2=sqr(getParticleData(ix)->mass());
// loop functions
if(_massopt==0) {
A4stu+=A4(s,t,u,mf2);
A2stu+=A2(s,t,u,mf2);
A2tsu+=A2(u,s,t,mf2);
A2ust+=A2(t,s,u,mf2);
A5s+= mf2/s*(4.+4.*double(s/(u+t))*(W1(s,mf2)-W1(mh2,mf2))
+(1.-4.*double(mf2/(u+t)))*(W2(s,mf2)-W2(mh2,mf2)));
A5t+= mf2/t*(4.+4.*double(t/(s+u))*(W1(t,mf2)-W1(mh2,mf2))
+(1.-4.*double(mf2/(s+u)))*(W2(t,mf2)-W2(mh2,mf2)));
A5u+= mf2/u*(4.+4.*double(u/(s+t))*(W1(u,mf2)-W1(mh2,mf2))
+(1.-4.*double(mf2/(s+t)))*(W2(u,mf2)-W2(mh2,mf2)));
}
else {
A4stu=-1./3.;
A2stu=-sqr(s/mh2)/3.;
A2tsu=-sqr(t/mh2)/3.;
A2ust=-sqr(u/mh2)/3.;
A5s+=2.*(s-mh2)/3./s;
A5t+=2.*(t-mh2)/3./t;
A5u+=2.*(u-mh2)/3./u;
}
}
Complex A3stu=0.5*(A2stu+A2ust+A2tsu-A4stu);
// compute the dot products for the matrix element
complex<InvEnergy> eps[3][4][2];
Energy2 pdot[4][4];
pdot[0][0]=0.*GeV2;
pdot[0][1]= g1[0].getMomentum()*g2[0].getMomentum();
pdot[0][2]=-1.*g1[0].getMomentum()*g4[0].getMomentum();
pdot[0][3]=-1.*g1[0].getMomentum()*hout.getMomentum();
pdot[1][0]= pdot[0][1];
pdot[1][1]= 0.*GeV2;
pdot[1][2]=-1.*g2[0].getMomentum()*g4[0].getMomentum();
pdot[1][3]=-1.*g2[0].getMomentum()*hout.getMomentum();
pdot[2][0]= pdot[0][2];
pdot[2][1]= pdot[1][2];
pdot[2][2]= 0.*GeV2;
pdot[2][3]= g4[0].getMomentum()*hout.getMomentum();
pdot[3][0]=pdot[0][3];
pdot[3][1]=pdot[1][3];
pdot[3][2]=pdot[2][3];
pdot[3][3]=mh2;
for(unsigned int ix=0;ix<2;++ix)
{
eps[0][0][ix]=InvEnergy();
eps[0][1][ix]=g1[ix].wave().dot(g2[0].getMomentum())/pdot[0][1];
eps[0][2][ix]=-1.*g1[ix].wave().dot(g4[0].getMomentum())/pdot[0][2];
eps[0][3][ix]=-1.*g1[ix].wave().dot(hout.getMomentum())/ pdot[0][3];
eps[1][0][ix]=g2[ix].wave().dot(g1[0].getMomentum())/ pdot[1][0];
eps[1][1][ix]=InvEnergy();
eps[1][2][ix]=-1.*g2[ix].wave().dot(g4[0].getMomentum())/pdot[1][2];
eps[1][3][ix]=-1.*g2[ix].wave().dot(hout.getMomentum())/ pdot[1][3];
eps[2][0][ix]=g4[ix].wave().dot(g1[0].getMomentum())/ pdot[2][0];
eps[2][1][ix]=g4[ix].wave().dot(g2[0].getMomentum())/ pdot[2][1];
eps[2][2][ix]=InvEnergy();
eps[2][3][ix]=-1.*g4[ix].wave().dot(hout.getMomentum())/ pdot[2][3];
}
// prefactors
using Constants::pi;
double g(sqrt(4.*pi*SM().alphaEM(mh2)/SM().sin2ThetaW()));
double gs(sqrt(4.*pi*SM().alphaS(et)));
Energy mw(getParticleData(ParticleID::Wplus)->mass());
Energy3 pre=g*sqr(mh2)*gs*sqr(gs)/(32.*sqr(pi)*mw);
// compute the matrix element
double output(0.);
Complex diag[4],wdot[3][3];
_diagwgt[0]=0.;
_diagwgt[1]=0.;
_diagwgt[2]=0.;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel=0;ohel<2;++ohel) {
wdot[0][1]=g1[ihel1].wave().dot(g2[ihel2].wave());
wdot[0][2]=g1[ihel1].wave().dot(g4[ohel ].wave());
wdot[1][0]=wdot[0][1];
wdot[1][2]=g2[ihel2].wave().dot(g4[ohel ].wave());
wdot[2][0]=wdot[0][2];
wdot[2][1]=wdot[1][2];
// last piece
diag[3]=pre*A3stu*(eps[0][2][ihel1]*eps[1][0][ihel2]*eps[2][1][ohel]-
eps[0][1][ihel1]*eps[1][2][ihel2]*eps[2][0][ohel]+
(eps[2][0][ohel ]-eps[2][1][ohel ])*wdot[0][1]/pdot[0][1]+
(eps[1][2][ihel2]-eps[1][0][ihel2])*wdot[0][2]/pdot[0][2]+
(eps[0][1][ihel1]-eps[0][2][ihel1])*wdot[1][2]/pdot[1][2]);
// first piece
diag[3]+=pre*(
+A2stu*(eps[0][1][ihel1]*eps[1][0][ihel2]-wdot[0][1]/pdot[0][1])*
(eps[2][0][ohel ]-eps[2][1][ohel ])
+A2ust*(eps[0][2][ihel1]*eps[2][0][ohel ]-wdot[0][2]/pdot[0][2])*
(eps[1][2][ihel2]-eps[1][0][ihel2])
+A2tsu*(eps[1][2][ihel2]*eps[2][1][ohel ]-wdot[1][2]/pdot[1][2])*
(eps[0][1][ihel1]-eps[0][2][ihel1])
);
output+=real(diag[3]*conj(diag[3]));
// matrix element if needed
if(calc) newme(2*ihel1,2*ihel2,0,2*ohel)=diag[3];
// different diagrams
diag[0] = A5t*UnitRemoval::InvE*(-eps[0][3][ihel1]*
(-2.*eps[2][1][ohel ]*eps[1][0][ihel2]*pdot[2][1]*pdot[1][0]
-2.*eps[1][2][ihel2]*eps[2][0][ohel ]*pdot[1][2]*pdot[2][0]
+wdot[1][2]*(pdot[0][1]+pdot[0][2]))
-2.*eps[2][1][ohel ]*pdot[2][1]*wdot[0][1]
-2.*eps[1][2][ihel2]*pdot[1][2]*wdot[0][2]
+wdot[1][2]*(eps[0][1][ihel1]*pdot[0][1]+
eps[0][2][ihel1]*pdot[0][2]));
diag[1] = A5u*UnitRemoval::InvE*(-eps[1][3][ihel2]*
(+2.*eps[0][1][ihel1]*eps[2][0][ohel ]*pdot[0][1]*pdot[2][0]
+2.*eps[0][2][ihel1]*eps[2][1][ohel ]*pdot[0][2]*pdot[2][1]
-wdot[0][2]*(pdot[1][0]+pdot[1][2]))
+2.*eps[2][0][ohel ]*pdot[2][0]*wdot[0][1]
+2.*eps[0][2][ihel1]*pdot[0][2]*wdot[2][1]
-wdot[0][2]*(eps[1][0][ihel2]*pdot[1][0]+
eps[1][2][ihel2]*pdot[1][2]));
diag[2] = A5s*UnitRemoval::InvE*(-eps[2][3][ohel ]*
(+2.*eps[0][1][ihel1]*eps[1][2][ihel2]*pdot[0][1]*pdot[1][2]
-2.*eps[1][0][ihel2]*eps[0][2][ihel1]*pdot[1][0]*pdot[1][3]
+wdot[0][1]*(pdot[2][0]-pdot[2][1]))
+2.*eps[0][1][ihel1]*pdot[0][1]*wdot[1][2]
-2.*eps[1][0][ihel2]*pdot[1][0]*wdot[0][2]
+wdot[0][1]*(eps[2][0][ohel]*pdot[2][0]-
eps[2][1][ohel]*pdot[2][1]));
_diagwgt[0]+=real(diag[0]*conj(diag[0]));
_diagwgt[1]+=real(diag[1]*conj(diag[1]));
_diagwgt[2]+=real(diag[2]*conj(diag[2]));
}
}
}
// final colour and spin factors
if(calc){_me.reset(newme);}
return 3.*output/32.;
}
void MEPP2HiggsJet::constructVertex(tSubProPtr sub)
{
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
// ensure correct order or particles
if((hard[0]->id()==ParticleID::g&&hard[1]->id()!=ParticleID::g)||
(hard[0]->id()<0&&hard[1]->id()<6)) swap(hard[0],hard[1]);
if(hard[2]->id()!=ParticleID::h0) swap(hard[2],hard[3]);
// different processes
// g g to H g
if(hard[0]->id()==ParticleID::g) {
vector<VectorWaveFunction> g1,g2,g4;
VectorWaveFunction(g1,hard[0],incoming,false,true,true);
VectorWaveFunction(g2,hard[1],incoming,false,true,true);
VectorWaveFunction(g4,hard[3],outgoing,true ,true,true);
ScalarWaveFunction hout(hard[2],outgoing,true,true);
g1[1]=g1[2];g2[1]=g2[2];g4[1]=g4[2];
ggME(g1,g2,hout,g4,true);
}
// qg -> H q
else if(hard[0]->id()>0&&hard[1]->id()==ParticleID::g) {
vector<VectorWaveFunction> g2;
vector<SpinorWaveFunction> qin;
vector<SpinorBarWaveFunction> qout;
SpinorWaveFunction( qin,hard[0],incoming,false,true);
VectorWaveFunction( g2,hard[1],incoming,false,true,true);
SpinorBarWaveFunction(qout,hard[3],outgoing,true ,true);
ScalarWaveFunction hout(hard[2],outgoing,true,true);
g2[1]=g2[2];
qgME(qin,g2,hout,qout,true);
}
// qbar g -> H q
else if(hard[0]->id()<0&&hard[1]->id()==ParticleID::g) {
vector<VectorWaveFunction> g2;
vector<SpinorBarWaveFunction> qin;
vector<SpinorWaveFunction> qout;
SpinorBarWaveFunction( qin,hard[0],incoming,false,true);
VectorWaveFunction( g2,hard[1],incoming,false,true,true);
SpinorWaveFunction( qout,hard[3],outgoing,true ,true);
ScalarWaveFunction hout(hard[2],outgoing,true,true);
g2[1]=g2[2];
qbargME(qin,g2,hout,qout,true);
}
// q qbar to H g
else if(hard[0]->id()==-hard[1]->id()) {
vector<SpinorBarWaveFunction> qbar;
vector<SpinorWaveFunction> q;
vector<VectorWaveFunction> g4;
SpinorWaveFunction( q ,hard[0],incoming,false,true);
SpinorBarWaveFunction(qbar,hard[1],incoming,false,true);
VectorWaveFunction( g4,hard[3],outgoing,true ,true,true);
ScalarWaveFunction hout(hard[2],outgoing,true,true);
g4[1]=g4[2];
qqbarME(q,qbar,hout,g4,true);
}
else throw Exception() << "Unknown subprocess in MEPP2HiggsJet::constructVertex()"
<< Exception::runerror;
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) {
dynamic_ptr_cast<ThePEG::Helicity::SpinfoPtr>(hard[ix]->spinInfo())->
setProductionVertex(hardvertex);
}
}
int MEPP2HiggsJet::nDim() const {
return 2;
}
void MEPP2HiggsJet::doinit() throw(InitException) {
ME2to2Base::doinit();
tcPDPtr h0=getParticleData(ParticleID::h0);
_mh = h0->mass();
_wh = h0->generateWidth(_mh);
if(h0->massGenerator()) {
_hmass=dynamic_ptr_cast<SMHiggsMassGeneratorPtr>(h0->massGenerator());
}
if(_shapeopt==2&&!_hmass) throw InitException()
<< "If using the mass generator for the line shape in MEPP2HiggsJet::doinit()"
<< "the mass generator must be an instance of the SMHiggsMassGenerator class"
<< Exception::runerror;
}
CrossSection MEPP2HiggsJet::dSigHatDR() const {
using Constants::pi;
InvEnergy2 bwfact;
Energy moff = mePartonData()[2]->id()==ParticleID::h0 ?
meMomenta()[2].mass() : meMomenta()[3].mass();
if(_shapeopt==1) {
tcPDPtr h0 = mePartonData()[2]->id()==ParticleID::h0 ?
mePartonData()[2] : mePartonData()[3];
bwfact = h0->generateWidth(moff)*moff/pi/
(sqr(sqr(moff)-sqr(_mh))+sqr(_mh*_wh));
}
else {
bwfact = _hmass->BreitWignerWeight(moff,0);
}
return me2()*jacobian()/(16.0*sqr(Constants::pi)*sHat())*sqr(hbarc)*
(sqr(sqr(moff)-sqr(_mh))+sqr(_mh*_wh))/(_mh*_wh)*bwfact;
}
diff --git a/MatrixElement/Hadron/MEPP2HiggsJet.h b/MatrixElement/Hadron/MEPP2HiggsJet.h
--- a/MatrixElement/Hadron/MEPP2HiggsJet.h
+++ b/MatrixElement/Hadron/MEPP2HiggsJet.h
@@ -1,449 +1,449 @@
// -*- C++ -*-
//
// MEPP2HiggsJet.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_MEPP2HiggsJet_H
#define HERWIG_MEPP2HiggsJet_H
//
// This is the declaration of the MEPP2HiggsJet class.
//
#include "ThePEG/MatrixElement/ME2to2Base.h"
#include "Herwig++/Utilities/Maths.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig++/PDT/SMHiggsMassGenerator.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEPP2HiggsJet class implements the matrix element for Higgs+jet production.
*
* @see \ref MEPP2HiggsJetInterfaces "The interfaces"
* defined for MEPP2HiggsJet.
*/
class MEPP2HiggsJet: public ME2to2Base {
public:
/**
* The default constructor.
*/
inline MEPP2HiggsJet();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(). Uses
* me().
*/
virtual CrossSection dSigHatDR() const;
/**
* The number of internal degreed of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* Members to return the matrix elements for the different subprocesses
*/
//@{
/**
* Matrix element for \f$q\bar{q}\to Hg\f$.
* @param fin Spinors for incoming quark
* @param ain Spinors for incoming antiquark
* @param hout Wavefunction for the outgoing higgs
* @param gout Polarization vectors for the outgoing gluon
* @param me Whether or not to calculate the matrix element for spin correlations
**/
double qqbarME(vector<SpinorWaveFunction> & fin, vector<SpinorBarWaveFunction> & ain,
ScalarWaveFunction & hout, vector<VectorWaveFunction> & gout,
bool me) const;
/**
* Matrix element for \f$qg\to Hq\f$.
* @param fin Spinors for incoming quark
* @param gin Polarization vectors for the incoming gluon
* @param hout Wavefunction for the outgoing higgs
* @param fout Spinors for outgoing quark
* @param me Whether or not to calculate the matrix element for spin correlations
**/
double qgME(vector<SpinorWaveFunction> & fin,vector<VectorWaveFunction> & gin,
ScalarWaveFunction & hout, vector<SpinorBarWaveFunction> & fout,
bool me) const;
/**
* Matrix element for \f$\bar{q}g\to H\bar{q}\f$.
* @param fin Spinors for incoming antiquark
* @param gin Polarization vectors for the incoming gluon
* @param hout Wavefunction for the outgoing higgs
* @param fout Spinors for outgoing antiquark
* @param me Whether or not to calculate the matrix element for spin correlations
**/
double qbargME(vector<SpinorBarWaveFunction> & fin,vector<VectorWaveFunction> & gin,
ScalarWaveFunction & hout, vector<SpinorWaveFunction> & fout,
bool me) const;
/**
* Matrix element for \f$gg\to Hg\f$.
* @param g1 Polarization vectors for the first incoming gluon
* @param g2 Polarization vectors for the second incoming gluon
* @param hout Wavefunction for the outgoing higgs
* @param g4 Polarization vectors for the outgoing gluon
* @param me Whether or not to calculate the matrix element for spin correlations
**/
double ggME(vector<VectorWaveFunction> g1, vector<VectorWaveFunction> g2,
ScalarWaveFunction & hout, vector<VectorWaveFunction> g4,
bool me) const;
//@}
private:
/**
* Members to calculate the functions for the loop diagrams
*/
//@{
/**
* The \f$W_1(s)\f$ function of NPB297 (1988) 221-243.
* @param s The invariant
* @param mf2 The fermion mass squared
*/
inline Complex W1(Energy2 s,Energy2 mf2) const;
/**
* The \f$W_2(s)\f$ function of NPB297 (1988) 221-243.
* @param s The invariant
* @param mf2 The fermion mass squared
*/
inline Complex W2(Energy2 s,Energy2 mf2) const;
/**
* The \f$W_3(s,t,u,v)\f$ function of NPB297 (1988) 221-243.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param v The \f$u\f$ invariant
* @param mf2 The fermion mass squared.
*/
inline Complex W3(Energy2 s, Energy2 t, Energy2 u, Energy2 v, Energy2 mf2) const;
/**
* The \f$I_3(s,t,u,v)\f$ function of NPB297 (1988) 221-243.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param v The \f$v\f$ invariant
* @param mf2 The fermion mass squared
*/
inline Complex I3(Energy2 s, Energy2 t, Energy2 u, Energy2 v, Energy2 mf2) const;
/**
* The \f$b_2(s,t,u)\f$ function of NPB297 (1988) 221-243.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param mf2 The fermion mass squared.
*/
inline Complex b2(Energy2 s, Energy2 t, Energy2 u, Energy2 mf2) const;
/**
* The \f$b_2(s,t,u)\f$ function of NPB297 (1988) 221-243.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param mf2 The fermion mass squared.
*/
inline Complex b4(Energy2 s, Energy2 t, Energy2 u, Energy2 mf2) const;
/**
* The \f$A_2(s,t,u)\f$ function of NPB297 (1988) 221-243.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param mf2 The fermion mass squared.
*/
inline Complex A2(Energy2 s, Energy2 t, Energy2 u, Energy2 mf2) const;
/**
* The \f$A_4(s,t,u)\f$ function of NPB297 (1988) 221-243.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param mf2 The fermion mass squared.
*/
inline Complex A4(Energy2 s, Energy2 t, Energy2 u, Energy2 mf2) const;
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2HiggsJet> initMEPP2HiggsJet;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2HiggsJet & operator=(const MEPP2HiggsJet &);
private:
/**
* Defines the Higgs resonance shape
*/
unsigned int _shapeopt;
/**
* Maximum PDG code of the quarks allowed
*/
unsigned int _maxflavour;
/**
* Option for which processes to include
*/
unsigned int _process;
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
/**
* Minimum flavour of quarks to include in the loops
*/
unsigned int _minloop;
/**
* Maximum flavour of quarks to include in the loops
*/
unsigned int _maxloop;
/**
* Option for treatment of the fermion loops
*/
unsigned int _massopt;
/**
* Small complex number to regularize some integrals
*/
static const Complex _epsi;
/**
* On-shell mass for the higgs
*/
Energy _mh;
/**
* On-shell width for the higgs
*/
Energy _wh;
/**
* The mass generator for the Higgs
*/
SMHiggsMassGeneratorPtr _hmass;
/**
* Storage of the loop functions
*/
//@{
/**
* B functions
*/
mutable Complex _bi[5];
/**
* C functions
*/
mutable Complex _ci[8];
/**
* D functions
*/
mutable Complex _di[4];
//@}
/**
* Storage of the diagram weights for the \f$gg\to Hg\f$ subprocess
*/
mutable double _diagwgt[3];
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEPP2HiggsJet. */
template <>
struct BaseClassTrait<Herwig::MEPP2HiggsJet,1> {
/** Typedef of the first base class of MEPP2HiggsJet. */
typedef ME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2HiggsJet class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2HiggsJet>
: public ClassTraitsBase<Herwig::MEPP2HiggsJet> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2HiggsJet"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2HiggsJet is implemented. It may also include several, space-separated,
* libraries if the class MEPP2HiggsJet depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#include "MEPP2HiggsJet.icc"
#endif /* HERWIG_MEPP2HiggsJet_H */
diff --git a/MatrixElement/Hadron/MEPP2QQ.cc b/MatrixElement/Hadron/MEPP2QQ.cc
--- a/MatrixElement/Hadron/MEPP2QQ.cc
+++ b/MatrixElement/Hadron/MEPP2QQ.cc
@@ -1,490 +1,490 @@
// -*- C++ -*-
//
// MEPP2QQ.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 MEPP2QQ class.
//
#include "MEPP2QQ.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/Repository/EventGenerator.h"
using namespace Herwig;
MEPP2QQ::MEPP2QQ() : _quarkflavour(6), _process(0),
_bottomopt(1), _topopt(1) {
}
void MEPP2QQ::rebind(const TranslationMap & trans)
throw(RebindException) {
_gggvertex = trans.translate( _gggvertex);
_qqgvertex = trans.translate( _qqgvertex);
_gluon = trans.translate( _gluon);
for(unsigned int ix=0;ix<_quark.size();++ix)
{_quark[ix]=trans.translate(_quark[ix]);}
for(unsigned int ix=0;ix<_antiquark.size();++ix)
{_antiquark[ix]=trans.translate(_quark[ix]);}
HwME2to2Base::rebind(trans);
}
IVector MEPP2QQ::getReferences() {
IVector ret = HwME2to2Base::getReferences();
ret.push_back(_gggvertex);
ret.push_back(_qqgvertex);
ret.push_back(_gluon);
for(unsigned int ix=0;ix<_quark.size();++ix)
{ret.push_back(_quark[ix]);}
for(unsigned int ix=0;ix<_antiquark.size();++ix)
{ret.push_back(_antiquark[ix]);}
return ret;
}
void MEPP2QQ::doinit() throw(InitException) {
HwME2to2Base::doinit();
// handling of masses
if(_quarkflavour==6) {
massOption(true ,_topopt);
massOption(false,_topopt);
}
else {
massOption(true ,_bottomopt);
massOption(false,_bottomopt);
}
// get the vertex pointers from the SM object
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm) {
_qqgvertex = hwsm->vertexFFG();
_gggvertex = hwsm->vertexGGG();
}
else throw InitException() << "Wrong type of StandardModel object in "
<< "MEQCD2to2::doinit() the Herwig++ version must be used"
<< Exception::runerror;
// get the particle data objects
_gluon=getParticleData(ParticleID::g);
for(int ix=1;ix<=6;++ix) {
_quark.push_back( getParticleData( ix));
_antiquark.push_back(getParticleData(-ix));
}
}
Energy2 MEPP2QQ::scale() const {
Energy2 mq2(meMomenta()[2].mass2()),s(0.5*sHat()),
u(0.5*(uHat()-mq2)),t(0.5*(tHat()-mq2));
return 4.*s*t*u/(s*s+t*t+u*u);
}
void MEPP2QQ::persistentOutput(PersistentOStream & os) const {
os << _gggvertex << _qqgvertex << _quarkflavour << _bottomopt << _topopt
<< _process << _gluon << _quark << _antiquark;
}
void MEPP2QQ::persistentInput(PersistentIStream & is, int) {
is >> _gggvertex >> _qqgvertex >> _quarkflavour >> _bottomopt >> _topopt
>> _process >> _gluon >> _quark >> _antiquark;
}
unsigned int MEPP2QQ::orderInAlphaS() const {
return 2;
}
unsigned int MEPP2QQ::orderInAlphaEW() const {
return 0;
}
ClassDescription<MEPP2QQ> MEPP2QQ::initMEPP2QQ;
// Definition of the static class description member.
void MEPP2QQ::Init() {
static ClassDocumentation<MEPP2QQ> documentation
("The MEPP2QQ class implements the matrix element for"
" heavy quark pair production");
static Switch<MEPP2QQ,unsigned int> interfaceQuarkType
("QuarkType",
"The type of quark",
&MEPP2QQ::_quarkflavour, 6, false, false);
static SwitchOption interfaceQuarkTypeTop
(interfaceQuarkType,
"Top",
"Produce top-antitop",
6);
static Switch<MEPP2QQ,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEPP2QQ::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
0);
static SwitchOption interfaceProcess1
(interfaceProcess,
"gg2qqbar",
"Include only gg -> q qbar processes",
1);
static SwitchOption interfaceProcessqbarqbarqbarqbar
(interfaceProcess,
"qbarqbar2qbarqbar",
"Include only qbar qbar -> qbar qbar processes",
2);
static Switch<MEPP2QQ,unsigned int> interfaceTopMassOption
("TopMassOption",
"Option for the treatment of the top quark mass",
&MEPP2QQ::_topopt, 1, false, false);
static SwitchOption interfaceTopMassOptionOnMassShell
(interfaceTopMassOption,
"OnMassShell",
"The top is produced on its mass shell",
1);
static SwitchOption interfaceTopMassOption2
(interfaceTopMassOption,
"OffShell",
"The top is generated off-shell using the mass and width generator.",
2);
static Switch<MEPP2QQ,unsigned int> interfaceBottomMassOption
("BottomMassOption",
"Option for the treatment of bottom and lighter quark masses",
&MEPP2QQ::_bottomopt, 1, false, false);
static SwitchOption interfaceBottomMassOptionOnMassShell
(interfaceBottomMassOption,
"OnMassShell",
"The bottom is produced on its mass shell, the this mass used everywhere",
1);
static SwitchOption interfaceBottomMassOptionZeroMass
(interfaceBottomMassOption,
"ZeroMass",
"The bottom is generated on mass shell, but zero mass is used in"
" the matrix element",
0);
}
Selector<MEBase::DiagramIndex>
MEPP2QQ::diagrams(const DiagramVector & diags) const {
// select the diagram, this is easy for us as we have already done it
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if(diags[i]->id()==-int(_diagram)) sel.insert(1.0, i);
else sel.insert(0., i);
}
return sel;
}
double MEPP2QQ::gg2qqbarME(vector<VectorWaveFunction> &g1,
vector<VectorWaveFunction> &g2,
vector<SpinorBarWaveFunction> & q,
vector<SpinorWaveFunction> & qbar,
unsigned int iflow) const {
// scale
Energy2 mt(scale());
Energy mass = q[0].mass();
// matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1,
PDT::Spin1Half,PDT::Spin1Half));
// calculate the matrix element
double output(0.),sumdiag[3]={0.,0.,0.},sumflow[2]={0.,0.};
Complex diag[3],flow[2];
VectorWaveFunction interv;
SpinorWaveFunction inters;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
interv=_gggvertex->evaluate(mt,5,_gluon,g1[ihel1],g2[ihel2]);
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
//first t-channel diagram
inters =_qqgvertex->evaluate(mt,1,qbar[ohel2].getParticle(),
qbar[ohel2],g2[ihel2],mass);
diag[0]=_qqgvertex->evaluate(mt,inters,q[ohel1],g1[ihel1]);
//second t-channel diagram
inters =_qqgvertex->evaluate(mt,1,qbar[ohel2].getParticle(),
qbar[ohel2],g1[ihel1],mass);
diag[1]=_qqgvertex->evaluate(mt,inters,q[ohel1],g2[ihel2]);
// s-channel diagram
diag[2]=_qqgvertex->evaluate(mt,qbar[ohel2],q[ohel1],interv);
// colour flows
flow[0]=diag[0]+diag[2];
flow[1]=diag[1]-diag[2];
// sums
for(unsigned int ix=0;ix<3;++ix) sumdiag[ix] += norm(diag[ix]);
for(unsigned int ix=0;ix<2;++ix) sumflow[ix] += norm(flow[ix]);
// total
output +=real(flow[0]*conj(flow[0])+flow[1]*conj(flow[1])
-0.25*flow[0]*conj(flow[1]));
// store the me if needed
if(iflow!=0) _me(2*ihel1,2*ihel2,ohel1,ohel2)=flow[iflow-1];
}
}
}
}
// select a colour flow
_flow=1+UseRandom::rnd2(sumflow[0],sumflow[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=1+UseRandom::rnd3(sumdiag[0],sumdiag[1],sumdiag[2]);
// final part of colour and spin factors
// Energy2 mq2=sqr(getParticleData(6)->mass());
// double tau1=(tHat()-mq2)/sHat(),tau2=(uHat()-mq2)/sHat(),rho=4*mq2/sHat();
// double test=(1./6./tau1/tau2-3./8.)*sqr(4.*pi*SM().alphaS(mt))*
// (sqr(tau1)+sqr(tau2)+rho-0.25*sqr(rho)/tau1/tau2);
// cerr << "testing matrix element "
// << output/48./test << "\n";
return output/48.;
}
double MEPP2QQ::qqbar2qqbarME(vector<SpinorWaveFunction> & q1,
vector<SpinorBarWaveFunction> & q2,
vector<SpinorBarWaveFunction> & q3,
vector<SpinorWaveFunction> & q4,
unsigned int iflow) const {
// type of process
bool diagon[2]={q1[0].id()== -q2[0].id(),q1[0].id()== q3[0].id()};
// scale
Energy2 mt(scale());
// matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half));
// calculate the matrix element
double output(0.),sumdiag[2]={0.,0.};
Complex diag[2];
VectorWaveFunction interv;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
// first diagram
if(diagon[0]) {
interv = _qqgvertex->evaluate(mt,5,_gluon,q1[ihel1],q2[ihel2]);
diag[0] = _qqgvertex->evaluate(mt,q4[ohel2],q3[ohel1],interv);
}
else diag[0]=0.;
// second diagram
if(diagon[1]) {
interv = _qqgvertex->evaluate(mt,5,_gluon,q1[ihel1],q3[ohel1]);
diag[1]=_qqgvertex->evaluate(mt,q4[ohel2],q2[ihel2],interv);
}
else diag[1]=0.;
// sum of diagrams
for(unsigned int ix=0;ix<2;++ix) sumdiag[ix] += norm(diag[ix]);
// total
output +=real(diag[0]*conj(diag[0])+diag[1]*conj(diag[1])
+2./3.*diag[0]*conj(diag[1]));
// store the me if needed
if(iflow!=0) _me(ihel1,ihel2,ohel1,ohel2)=diag[iflow-1];
}
}
}
}
//select a colour flow
_flow=1+UseRandom::rnd2(sumdiag[0],sumdiag[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=3+UseRandom::rnd2(sumdiag[0],sumdiag[1]);
// final part of colour and spin factors
// Energy2 mq2=sqr(getParticleData(6)->mass());
// double tau1=(tHat()-mq2)/sHat(),tau2=(uHat()-mq2)/sHat(),rho=4*mq2/sHat();
// cerr << "testing matrix element "
// << output/18./(4./9.*sqr(4.*pi*SM().alphaS(mt))*(sqr(tau1)+sqr(tau2)+0.5*rho))
// << "\n";
return output/18.;
}
void MEPP2QQ::getDiagrams() const {
// gg -> q qbar subprocesses
if(_process==0||_process==1) {
// first t-channel
add(new_ptr((Tree2toNDiagram(3),_gluon,_antiquark[_quarkflavour-1],_gluon,
1,_quark[_quarkflavour-1], 2,_antiquark[_quarkflavour-1],-1)));
// interchange
add(new_ptr((Tree2toNDiagram(3),_gluon,_antiquark[_quarkflavour-1],_gluon,
2,_quark[_quarkflavour-1], 1,_antiquark[_quarkflavour-1],-2)));
// s-channel
add(new_ptr((Tree2toNDiagram(2),_gluon,_gluon, 1, _gluon,
3,_quark[_quarkflavour-1], 3, _antiquark[_quarkflavour-1], -3)));
}
// q qbar -> q qbar
if(_process==0||_process==2) {
for(unsigned int ix=1;ix<6;++ix) {
// gluon s-channel
add(new_ptr((Tree2toNDiagram(2),_quark[ix-1], _antiquark[ix-1],
1, _gluon, 3, _quark[_quarkflavour-1], 3,
_antiquark[_quarkflavour-1],-4)));
// gluon t-channel
if(ix==_quarkflavour)
add(new_ptr((Tree2toNDiagram(3),_quark[ix-1],_gluon,_antiquark[_quarkflavour-1],
1,_quark[ix-1],2,_antiquark[_quarkflavour-1],-5)));
}
}
}
Selector<const ColourLines *>
MEPP2QQ::colourGeometries(tcDiagPtr diag) const {
// colour lines for gg to q qbar
static const ColourLines cggqq[4]={ColourLines("1 4, -1 -2 3, -3 -5"),
ColourLines("3 4, -3 -2 1, -1 -5"),
ColourLines("2 -1, 1 3 4, -2 -3 -5"),
ColourLines("1 -2, -1 -3 -5, 2 3 4")};
// colour lines for q qbar -> q qbar
static const ColourLines cqqbqqb[2]={ColourLines("1 3 4,-2 -3 -5"),
ColourLines("1 2 -3,4 -2 -5")};
// select the colour flow (as all ready picked just insert answer)
Selector<const ColourLines *> sel;
switch(abs(diag->id())) {
// gg -> q qbar subprocess
case 1: case 2:
sel.insert(1.0, &cggqq[abs(diag->id())-1]);
break;
case 3:
sel.insert(1.0, &cggqq[1+_flow]);
break;
// q qbar -> q qbar subprocess
case 4: case 5:
sel.insert(1.0, &cqqbqqb[abs(diag->id())-4]);
break;
}
return sel;
}
double MEPP2QQ::me2() const {
// total matrix element
double me(0.);
// gg initiated processes
if(mePartonData()[0]->id()==ParticleID::g&&mePartonData()[1]->id()==ParticleID::g) {
VectorWaveFunction g1w(rescaledMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction g2w(rescaledMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction qw(rescaledMomenta()[2],mePartonData()[2],outgoing);
SpinorWaveFunction qbarw(rescaledMomenta()[3],mePartonData()[3],outgoing);
vector<VectorWaveFunction> g1,g2;
vector<SpinorBarWaveFunction> q;
vector<SpinorWaveFunction> qbar;
for(unsigned int ix=0;ix<2;++ix) {
g1w.reset(2*ix);g1.push_back(g1w);
g2w.reset(2*ix);g2.push_back(g2w);
qw.reset(ix);q.push_back(qw);
qbarw.reset(ix);qbar.push_back(qbarw);
}
// calculate the matrix element
me=gg2qqbarME(g1,g2,q,qbar,0);
}
// q qbar to q qbar
else {
SpinorWaveFunction q1w(rescaledMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction q2w(rescaledMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction q3w(rescaledMomenta()[2],mePartonData()[2],outgoing);
SpinorWaveFunction q4w(rescaledMomenta()[3],mePartonData()[3],outgoing);
vector<SpinorWaveFunction> q1,q4;
vector<SpinorBarWaveFunction> q2,q3;
for(unsigned int ix=0;ix<2;++ix) {
q1w.reset(ix);q1.push_back(q1w);
q2w.reset(ix);q2.push_back(q2w);
q3w.reset(ix);q3.push_back(q3w);
q4w.reset(ix);q4.push_back(q4w);
}
// calculate the matrix element
me = qqbar2qqbarME(q1,q2,q3,q4,0);
}
// return the answer
return me;
}
void MEPP2QQ::constructVertex(tSubProPtr sub) {
SpinfoPtr spin[4];
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
hard.push_back(sub->outgoing()[1]);
// identify the process and calculate the matrix element
if(hard[0]->id()==ParticleID::g&&hard[1]->id()==ParticleID::g) {
if(hard[2]->id()<0) swap(hard[2],hard[3]);
vector<VectorWaveFunction> g1,g2;
vector<SpinorBarWaveFunction> q;
vector<SpinorWaveFunction> qbar;
// off-shell wavefunctions for the spin correlations
VectorWaveFunction( g1,hard[0],incoming,false,true,true);
VectorWaveFunction( g2,hard[1],incoming,false,true,true);
SpinorBarWaveFunction(q ,hard[2],outgoing,true ,true);
SpinorWaveFunction( qbar,hard[3],outgoing,true ,true);
g1[1]=g1[2];g2[1]=g2[2];
// on-shell for matrix element
vector<Lorentz5Momentum> momenta;
cPDVector data;
for(unsigned int ix=0;ix<4;++ix) {
momenta.push_back(hard[ix]->momentum());
data .push_back(hard[ix]->dataPtr());
}
rescaleMomenta(momenta,data);
VectorWaveFunction g1w(rescaledMomenta()[0],data[0],incoming);
VectorWaveFunction g2w(rescaledMomenta()[1],data[1],incoming);
SpinorBarWaveFunction qw(rescaledMomenta()[2],data[2],outgoing);
SpinorWaveFunction qbarw(rescaledMomenta()[3],data[3],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
g1w.reset(2*ix); g1 [ix] = g1w ;
g2w.reset(2*ix); g2 [ix] = g2w ;
qw.reset(ix); q [ix] = qw ;
qbarw.reset(ix); qbar[ix] = qbarw;
}
gg2qqbarME(g1,g2,q,qbar,_flow);
}
// q qbar -> q qbar
else {
if(hard[0]->id()<0) swap(hard[0],hard[1]);
if(hard[2]->id()<0) swap(hard[2],hard[3]);
vector<SpinorWaveFunction> q1,q4;
vector<SpinorBarWaveFunction> q2,q3;
// off-shell for spin correlations
SpinorWaveFunction( q1,hard[0],incoming,false,true);
SpinorBarWaveFunction(q2,hard[1],incoming,false,true);
SpinorBarWaveFunction(q3,hard[2],outgoing,true ,true);
SpinorWaveFunction( q4,hard[3],outgoing,true ,true);
// on-shell for matrix element
vector<Lorentz5Momentum> momenta;
cPDVector data;
for(unsigned int ix=0;ix<4;++ix) {
momenta.push_back(hard[ix]->momentum());
data .push_back(hard[ix]->dataPtr());
}
rescaleMomenta(momenta,data);
SpinorWaveFunction q1w(rescaledMomenta()[0],data[0],incoming);
SpinorBarWaveFunction q2w(rescaledMomenta()[1],data[1],incoming);
SpinorBarWaveFunction q3w(rescaledMomenta()[2],data[2],outgoing);
SpinorWaveFunction q4w(rescaledMomenta()[3],data[3],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
q1w.reset(ix);q1[ix] = q1w;
q2w.reset(ix);q2[ix] = q2w;
q3w.reset(ix);q3[ix] = q3w;
q4w.reset(ix);q4[ix] = q4w;
}
qqbar2qqbarME(q1,q2,q3,q4,_flow);
}
// get the spin info objects
for(unsigned int ix=0;ix<4;++ix)
spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo());
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) spin[ix]->setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/Hadron/MEPP2QQ.h b/MatrixElement/Hadron/MEPP2QQ.h
--- a/MatrixElement/Hadron/MEPP2QQ.h
+++ b/MatrixElement/Hadron/MEPP2QQ.h
@@ -1,336 +1,336 @@
// -*- C++ -*-
//
// MEPP2QQ.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_MEPP2QQ_H
#define HERWIG_MEPP2QQ_H
//
// This is the declaration of the MEPP2QQ class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEPP2QQ class implements the production of a heavy quark-antiquark
* pair via QCD.
*
* @see \ref MEPP2QQInterfaces "The interfaces"
* defined for MEPP2QQ.
*/
class MEPP2QQ: public HwME2to2Base {
public:
/**
* The default constructor.
*/
MEPP2QQ();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Members to calculate the matrix elements
*/
//@{
/**
* Matrix element for \f$gg\to q\bar{q}\f$
* @param g1 The wavefunctions for the first incoming gluon
* @param g2 The wavefunctions for the second incoming gluon
* @param q The wavefunction for the outgoing quark
* @param qbar The wavefunction for the outgoing antiquark
* @param flow The colour flow
*/
double gg2qqbarME(vector<VectorWaveFunction> &g1,vector<VectorWaveFunction> &g2,
vector<SpinorBarWaveFunction> & q,vector<SpinorWaveFunction> & qbar,
unsigned int flow) const;
/**
* Matrix element for \f$q\bar{q}\to q\bar{q}\f$
* @param q1 The wavefunction for the incoming quark
* @param q2 The wavefunction for the incoming antiquark
* @param q3 The wavefunction for the outgoing quark
* @param q4 The wavefunction for the outgoing antiquark
* @param flow The colour flow
*/
double qqbar2qqbarME(vector<SpinorWaveFunction> & q1,
vector<SpinorBarWaveFunction> & q2,
vector<SpinorBarWaveFunction> & q3,
vector<SpinorWaveFunction> & q4,
unsigned int flow) const;
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
throw(RebindException);
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2QQ> initMEPP2QQ;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2QQ & operator=(const MEPP2QQ &);
private:
/**
* Vertices needed to compute the diagrams
*/
//@{
/**
* \f$ggg\f$ vertex
*/
AbstractVVVVertexPtr _gggvertex;
/**
* \f$q\bar{q}g\f$ vertex
*/
AbstractFFVVertexPtr _qqgvertex;
//@}
/**
* Quark Flavour
*/
unsigned int _quarkflavour;
/**
* Processes to include
*/
unsigned int _process;
/**
* Option for the treatment of bottom and lighter
* quark masses
*/
unsigned int _bottomopt;
/**
* Option for the treatment of top quark masses
*/
unsigned int _topopt;
/**
* Colour flow
*/
mutable unsigned int _flow;
/**
* Diagram
*/
mutable unsigned int _diagram;
/**
* Matrix element
*/
mutable ProductionMatrixElement _me;
/**
* ParticleData objects of the partons
*/
//@{
/**
* The gluon
*/
PDPtr _gluon;
/**
* the quarks
*/
vector<PDPtr> _quark;
/**
* the antiquarks
*/
vector<PDPtr> _antiquark;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEPP2QQ. */
template <>
struct BaseClassTrait<Herwig::MEPP2QQ,1> {
/** Typedef of the first base class of MEPP2QQ. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2QQ class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2QQ>
: public ClassTraitsBase<Herwig::MEPP2QQ> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2QQ"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2QQ is implemented. It may also include several, space-separated,
* libraries if the class MEPP2QQ depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEPP2QQ_H */
diff --git a/MatrixElement/Hadron/MEPP2WJet.cc b/MatrixElement/Hadron/MEPP2WJet.cc
--- a/MatrixElement/Hadron/MEPP2WJet.cc
+++ b/MatrixElement/Hadron/MEPP2WJet.cc
@@ -1,855 +1,855 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEPP2WJet class.
//
#include "MEPP2WJet.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Cuts/Cuts.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
MEPP2WJet::MEPP2WJet() : _process(0), _maxflavour(5), _plusminus(0),
_wdec(0), _widthopt(1)
{}
void MEPP2WJet::doinit() throw(InitException) {
MEBase::doinit();
_wplus = getParticleData(ThePEG::ParticleID::Wplus );
_wminus = getParticleData(ThePEG::ParticleID::Wminus);
// cast the SM pointer to the Herwig SM pointer
ThePEG::Ptr<Herwig::StandardModel>::transient_const_pointer
hwsm=ThePEG::dynamic_ptr_cast< ThePEG::Ptr<Herwig::StandardModel>
::transient_const_pointer>(standardModel());
// do the initialisation
if(!hwsm)
throw InitException() << "Must be Herwig::StandardModel in MEPP2WJet::doinit()"
<< Exception::runerror;
// set the vertex pointers
_theFFWVertex = hwsm->vertexFFW();
_theQQGVertex = hwsm->vertexFFG();
}
ClassDescription<MEPP2WJet> MEPP2WJet::initMEPP2WJet;
// Definition of the static class description member.
void MEPP2WJet::Init() {
static ClassDocumentation<MEPP2WJet> documentation
("The MEPP2WJet class implements the matrix element for W + jet production");
static Parameter<MEPP2WJet,unsigned int> interfaceMaxFlavour
( "MaxFlavour",
"The heaviest incoming quark flavour this matrix element is allowed to handle "
"(if applicable).",
&MEPP2WJet::_maxflavour, 5, 0, 8, false, false, true);
static Switch<MEPP2WJet,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEPP2WJet::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
0);
static SwitchOption interfaceProcessqqbar
(interfaceProcess,
"qqbar",
"Only include q qbar -> W g process",
1);
static SwitchOption interfaceProcessqg
(interfaceProcess,
"qg",
"Only include the q g -> W q process",
2);
static SwitchOption interfaceProcessqbarg
(interfaceProcess,
"qbarg",
"Only include the qbar g -> W qbar process",
3);
static Switch<MEPP2WJet,unsigned int> interfacePlusMinus
("Wcharge",
"Which intermediate W bosons to include",
&MEPP2WJet::_plusminus, 0, false, false);
static SwitchOption interfacePlusMinusAll
(interfacePlusMinus,
"Both",
"Include W+ and W-",
0);
static SwitchOption interfacePlusMinusPlus
(interfacePlusMinus,
"Plus",
"Only include W+",
1);
static SwitchOption interfacePlusMinusMinus
(interfacePlusMinus,
"Minus",
"Only include W-",
2);
static Switch<MEPP2WJet,unsigned int> interfaceWDecay
("WDecay",
"Which processes to include",
&MEPP2WJet::_wdec, 0, false, false);
static SwitchOption interfaceWDecayAll
(interfaceWDecay,
"All",
"Include all SM fermions as outgoing particles",
0);
static SwitchOption interfaceWDecayQuarks
(interfaceWDecay,
"Quarks",
"Only include outgoing quarks",
1);
static SwitchOption interfaceWDecayLeptons
(interfaceWDecay,
"Leptons",
"All include outgoing leptons",
2);
static SwitchOption interfaceWDecayElectron
(interfaceWDecay,
"Electron",
"Only include outgoing e nu_e",
3);
static SwitchOption interfaceWDecayMuon
(interfaceWDecay,
"Muon",
"Only include outgoing mu nu_mu",
4);
static SwitchOption interfaceWDecayTau
(interfaceWDecay,
"Tau",
"Only include outgoing tauu nu_tau",
5);
static SwitchOption interfaceWDecayUpDown
(interfaceWDecay,
"UpDown",
"Only include outgoing u dbar/ d ubar",
6);
static SwitchOption interfaceWDecayUpStrange
(interfaceWDecay,
"UpStrange",
"Only include outgoing u sbar/ s ubar",
7);
static SwitchOption interfaceWDecayUpBottom
(interfaceWDecay,
"UpBottom",
"Only include outgoing u bbar/ b ubar",
8);
static SwitchOption interfaceWDecayCharmDown
(interfaceWDecay,
"CharmDown",
"Only include outgoing c dbar/ d cbar",
9);
static SwitchOption interfaceWDecayCharmStrange
(interfaceWDecay,
"CharmStrange",
"Only include outgoing c sbar/ s cbar",
10);
static SwitchOption interfaceWDecayCharmBottom
(interfaceWDecay,
"CharmBottom",
"Only include outgoing c bbar/ b cbar",
11);
static Switch<MEPP2WJet,unsigned int> interfaceWidthOption
("WidthOption",
"The option for handling the width of the off-shell W boson",
&MEPP2WJet::_widthopt, 1, false, false);
static SwitchOption interfaceWidthOptionFixedDenominator
(interfaceWidthOption,
"FixedDenominator",
"Use a fixed with in the W propagator but the full matrix element"
" in the numerator",
1);
static SwitchOption interfaceWidthOptionAllRunning
(interfaceWidthOption,
"AllRunning",
"Use a running width in the W propagator and the full matrix "
"element in the numerator",
2);
}
void MEPP2WJet::getDiagrams() const {
// which intgermediates to include
bool wplus = _plusminus==0 || _plusminus==1;
bool wminus = _plusminus==0 || _plusminus==2;
// possible incoming and outgoing particles
typedef std::vector<pair<long,long> > Pairvector;
// possible parents
Pairvector parentpair;
parentpair.reserve(6);
// don't even think of putting 'break' in here!
switch(_maxflavour) {
case 5:
parentpair.push_back(make_pair(ParticleID::b, ParticleID::cbar));
parentpair.push_back(make_pair(ParticleID::b, ParticleID::ubar));
case 4:
parentpair.push_back(make_pair(ParticleID::s, ParticleID::cbar));
parentpair.push_back(make_pair(ParticleID::d, ParticleID::cbar));
case 3:
parentpair.push_back(make_pair(ParticleID::s, ParticleID::ubar));
case 2:
parentpair.push_back(make_pair(ParticleID::d, ParticleID::ubar));
default:
;
}
// possible children
Pairvector childpair;
childpair.reserve(9);
childpair.push_back(make_pair(ParticleID::eminus, ParticleID::nu_ebar));
childpair.push_back(make_pair(ParticleID::muminus, ParticleID::nu_mubar));
childpair.push_back(make_pair(ParticleID::tauminus, ParticleID::nu_taubar));
childpair.push_back(make_pair(ParticleID::d, ParticleID::ubar));
childpair.push_back(make_pair(ParticleID::s, ParticleID::ubar));
childpair.push_back(make_pair(ParticleID::b, ParticleID::ubar));
childpair.push_back(make_pair(ParticleID::d, ParticleID::cbar));
childpair.push_back(make_pair(ParticleID::s, ParticleID::cbar));
childpair.push_back(make_pair(ParticleID::b, ParticleID::cbar));
// gluon for diagrams
tcPDPtr g = getParticleData(ParticleID::g);
// loop over the children
bool lepton,quark;
Pairvector::const_iterator child = childpair.begin();
for (; child != childpair.end(); ++child) {
// allowed leptonic decay
lepton=child->first>10&&
(_wdec==0||_wdec==2||
(abs(child->first)-5)/2==int(_wdec));
// allowed quark decay
quark =abs(child->second)<10&&
(_wdec==0||_wdec==1||
(abs(child->second)==2&&(abs(child->first)+11)/2==int(_wdec))||
(abs(child->second)==4&&(abs(child->first)+17)/2==int(_wdec)));
// if decay not allowed skip
if(!(quark||lepton)) continue;
// decay products
tcPDPtr lNeg1 = getParticleData(child->first);
tcPDPtr lNeg2 = getParticleData(child->second);
tcPDPtr lPos1 = lNeg2->CC();
tcPDPtr lPos2 = lNeg1->CC();
Pairvector::const_iterator parent = parentpair.begin();
for (; parent != parentpair.end(); ++parent) {
// parents
tcPDPtr qNeg1 = getParticleData(parent->first);
tcPDPtr qNeg2 = getParticleData(parent->second);
tcPDPtr qPos1 = qNeg2->CC();
tcPDPtr qPos2 = qNeg1->CC();
// diagrams
// q qbar annhilation processes
if(_process==0||_process==1) {
// q qbar -> W- g
if(wminus) {
add(new_ptr((Tree2toNDiagram(3), qNeg1, qNeg2, qNeg2, 1, _wminus,
3, g, 4, lNeg1, 4, lNeg2, -1)));
add(new_ptr((Tree2toNDiagram(3), qNeg1, qNeg1, qNeg2, 3, _wminus,
1, g, 4, lNeg1, 4, lNeg2, -2)));
}
// q qbar -> W+ g
if(wplus) {
add(new_ptr((Tree2toNDiagram(3), qPos1, qPos2, qPos2, 1, _wplus,
3, g, 4, lPos1, 4, lPos2, -3)));
add(new_ptr((Tree2toNDiagram(3), qPos1, qPos1, qPos2, 3, _wplus,
1, g, 4, lPos1, 4, lPos2, -4)));
}
}
// q g compton
if(_process==0||_process==2) {
if(wminus) {
add(new_ptr((Tree2toNDiagram(3), qNeg1, qPos1, g , 1, _wminus,
3, qPos1, 4, lNeg1, 4, lNeg2, -5)));
add(new_ptr((Tree2toNDiagram(2), qNeg1, g, 1, qNeg1, 3, _wminus,
3, qPos1, 4, lNeg1, 4, lNeg2, -6)));
}
if(wplus) {
add(new_ptr((Tree2toNDiagram(3), qPos1, qNeg1, g, 1, _wplus,
3, qNeg1, 4, lPos1, 4, lPos2, -7)));
add(new_ptr((Tree2toNDiagram(2), qPos1, g, 1, qNeg1, 3, _wplus,
3, qNeg1, 4, lPos1, 4, lPos2, -8)));
}
}
// qbar g compton
if(_process==0||_process==3) {
if(wminus) {
add(new_ptr((Tree2toNDiagram(3), qNeg2, qPos2, g, 1, _wminus,
3, qPos2, 4, lNeg1, 4, lNeg2, -9 )));
add(new_ptr((Tree2toNDiagram(2), qNeg2, g, 1, qNeg2, 3, _wminus,
3, qPos2, 4, lNeg1, 4, lNeg2, -10)));
}
if(wplus) {
add(new_ptr((Tree2toNDiagram(3), qPos2, qNeg2, g, 1, _wplus,
3, qNeg2, 4, lPos1, 4, lPos2, -11)));
add(new_ptr((Tree2toNDiagram(2), qPos2, g, 1, qPos2, 3, _wplus,
3, qNeg2, 4, lPos1, 4, lPos2, -12)));
}
}
}
}
}
unsigned int MEPP2WJet::orderInAlphaS() const {
return 1;
}
unsigned int MEPP2WJet::orderInAlphaEW() const {
return 2;
}
void MEPP2WJet::persistentOutput(PersistentOStream & os) const {
os << _theFFWVertex << _theQQGVertex << _wplus << _widthopt
<< _wminus << _process << _maxflavour << _plusminus << _wdec;
}
void MEPP2WJet::persistentInput(PersistentIStream & is, int) {
is >> _theFFWVertex >> _theQQGVertex >> _wplus >> _widthopt
>> _wminus >> _process >> _maxflavour >> _plusminus >> _wdec;
}
int MEPP2WJet::nDim() const {
return 5;
}
Selector<const ColourLines *>
MEPP2WJet::colourGeometries(tcDiagPtr diag) const {
// colour lines for q qbar -> W g
static const ColourLines cqqbar[4]={ColourLines("1 -2 5,-3 -5"),
ColourLines("1 5, -5 2 -3"),
ColourLines("1 -2 5,-3 -5,6 -7"),
ColourLines("1 5, -5 2 -3,6 -7")};
// colour lines for q g -> W q
static const ColourLines cqg [4]={ColourLines("1 2 -3,3 5"),
ColourLines("1 -2,2 3 5"),
ColourLines("1 2 -3,3 5,6 -7"),
ColourLines("1 -2,2 3 5,6 -7")};
// colour lines for qbar q -> W qbar
static const ColourLines cqbarg[4]={ColourLines("-1 -2 3,-3 -5"),
ColourLines("-1 2,-2 -3 -5"),
ColourLines("-1 -2 3,-3 -5,6 -7"),
ColourLines("-1 2,-2 -3 -5,6 -7")};
// select the correct line
unsigned int icol = mePartonData()[3]->coloured() ? 2 : 0;
Selector<const ColourLines *> sel;
switch(abs(diag->id())) {
case 1 : case 3:
sel.insert(1.0, &cqqbar[icol]);
break;
case 2 : case 4:
sel.insert(1.0, &cqqbar[icol+1]);
break;
case 5 : case 7:
sel.insert(1.0, &cqg[icol]);
break;
case 6 : case 8:
sel.insert(1.0, &cqg[icol+1]);
break;
case 9 : case 11:
sel.insert(1.0, &cqbarg[icol]);
break;
case 10 : case 12:
sel.insert(1.0, &cqbarg[icol+1]);
break;
}
return sel;
}
Selector<MEBase::DiagramIndex>
MEPP2WJet::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
int id=abs(diags[i]->id());
if (id <= 2 ) sel.insert(meInfo()[id- 1],i);
if (id <= 4 ) sel.insert(meInfo()[id- 3],i);
else if(id <= 6 ) sel.insert(meInfo()[id- 5],i);
else if(id <= 8 ) sel.insert(meInfo()[id- 7],i);
else if(id <= 10) sel.insert(meInfo()[id- 9],i);
else if(id <= 12) sel.insert(meInfo()[id-11],i);
}
return sel;
}
Energy2 MEPP2WJet::scale() const {
return _scale;
}
CrossSection MEPP2WJet::dSigHatDR() const {
return me2()*jacobian()/(16.0*sqr(Constants::pi)*sHat())*sqr(hbarc);
}
bool MEPP2WJet::generateKinematics(const double * r) {
// initialize jacobian
jacobian(1.);
// cms energy
Energy ecm=sqrt(sHat());
// find the right W pointer
tcPDPtr wdata = mePartonData()[3]->iCharge()+mePartonData()[4]->iCharge() > 0 ?
_wplus :_wminus;
// first generate the mass of the off-shell gauge boson
// minimum mass of the
tcPDVector ptemp;
ptemp.push_back(mePartonData()[3]);
ptemp.push_back(mePartonData()[4]);
Energy2 minMass2 = max(lastCuts().minSij(mePartonData()[3],mePartonData()[4]),
lastCuts().minS(ptemp));
// minimum pt of the jet
Energy ptmin = max(lastCuts().minKT(mePartonData()[2]),
lastCuts().minKT(wdata));
// maximum mass of the gauge boson so pt is possible
Energy2 maxMass2 = min(ecm*(ecm-2.*ptmin),lastCuts().maxS(ptemp));
if(maxMass2<=0.*GeV2||minMass2<0.*GeV2) return false;
// also impose the limits from the ParticleData object
minMass2 = max(minMass2,sqr(wdata->massMin()));
maxMass2 = min(maxMass2,sqr(wdata->massMax()));
// return if not kinematically possible
if(minMass2>maxMass2) return false;
// generation of the mass
Energy M(wdata->mass()),Gamma(wdata->width());
Energy2 M2(sqr(M)),MG(M*Gamma);
double rhomin = atan((minMass2-M2)/MG);
double rhomax = atan((maxMass2-M2)/MG);
_mw2=M2+MG*tan(rhomin+r[1]*(rhomax-rhomin));
Energy mw=sqrt(_mw2);
// jacobian
jacobian(jacobian()*(sqr(_mw2-M2)+sqr(MG))/MG*(rhomax-rhomin)/sHat());
// set the masses of the outgoing particles in the 2-2 scattering
meMomenta()[2].setMass(0.*MeV);
Lorentz5Momentum pw(mw);
// generate the polar angle of the hard scattering
double ctmin(-1.0), ctmax(1.0);
Energy q(0.0*GeV);
try {
q = SimplePhaseSpace::getMagnitude(sHat(), meMomenta()[2].mass(),mw);
}
catch ( ImpossibleKinematics ) {
return false;
}
Energy2 pq = sqrt(sHat())*q;
if ( ptmin > 0.0*GeV ) {
double ctm = 1.0 - sqr(ptmin/q);
if ( ctm <= 0.0 ) return false;
ctmin = max(ctmin, -sqrt(ctm));
ctmax = min(ctmax, sqrt(ctm));
}
if ( ctmin >= ctmax ) return false;
double cth = getCosTheta(ctmin, ctmax, r[0]);
// momenta of particle in hard scattering
Energy pt = q*sqrt(1.0-sqr(cth));
double phi=2.0*Constants::pi*r[2];
meMomenta()[2].setVect(Momentum3( pt*sin(phi), pt*cos(phi), q*cth));
pw.setVect( Momentum3(-pt*sin(phi),-pt*cos(phi),-q*cth));
meMomenta()[2].rescaleEnergy();
pw.rescaleEnergy();
// set the scale
_scale = _mw2+sqr(pt);
// generate the momenta of the W decay products
meMomenta()[3].setMass(mePartonData()[3]->mass());
meMomenta()[4].setMass(mePartonData()[4]->mass());
Energy q2 = 0.0*GeV;
try {
q2 = SimplePhaseSpace::getMagnitude(_mw2, meMomenta()[3].mass(),
meMomenta()[4].mass());
} catch ( ImpossibleKinematics ) {
return false;
}
double cth2 =-1.+2.*r[3];
double phi2=Constants::twopi*r[4];
Energy pt2 =q2*sqrt(1.-sqr(cth2));
Lorentz5Momentum pl[2]={Lorentz5Momentum( pt2*cos(phi2), pt2*sin(phi2), q2*cth2,0.*MeV,
meMomenta()[3].mass()),
Lorentz5Momentum(-pt2*cos(phi2),-pt2*sin(phi2),-q2*cth2,0.*MeV,
meMomenta()[4].mass())};
pl[0].rescaleEnergy();
pl[1].rescaleEnergy();
Boost boostv(pw.boostVector());
pl[0].boost(boostv);
pl[1].boost(boostv);
meMomenta()[3] = pl[0];
meMomenta()[4] = pl[1];
// check passes all the cuts
vector<LorentzMomentum> out(3);
out[0] = meMomenta()[2];
out[1] = meMomenta()[3];
out[2] = meMomenta()[4];
tcPDVector tout(3);
tout[0] = mePartonData()[2];
tout[1] = mePartonData()[3];
tout[2] = mePartonData()[4];
if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) )
return false;
// jacobian
jacobian((pq/sHat())*Constants::pi*jacobian()/8./sqr(Constants::pi)*q2/mw);
return true;
}
double MEPP2WJet::getCosTheta(double ctmin, double ctmax, const double r) {
double cth = 0.0;
double zmin = 0.5*(1.0 - ctmax);
double zmax = 0.5*(1.0 - ctmin);
if ( zmin <= 0.0 || zmax >= 1.0 ) {
jacobian((ctmax - ctmin)*jacobian());
cth = ctmin + r*(ctmax-ctmin);
} else {
double A1 = (2.0*zmax - 1.0)/(zmax*(1.0-zmax));
double A0 = (2.0*zmin - 1.0)/(zmin*(1.0-zmin));
double A = r*(A1 - A0) + A0;
double z = A < 2.0? 2.0/(sqrt(sqr(A) + 4.0) + 2 - A):
0.5*(A - 2.0 + sqrt(sqr(A) + 4.0))/A;
cth = 1.0 - 2.0*z;
jacobian((2.0*(A1 - A0)*sqr(z)*sqr(1.0 - z)/(sqr(z) + sqr(1.0 - z)))*jacobian());
}
return cth;
}
double MEPP2WJet::me2() const {
useMe();
InvEnergy2 output(0./MeV2);
// construct spinors for the leptons (always the same)
vector<SpinorBarWaveFunction> lm;
vector<SpinorWaveFunction> lp;
SpinorBarWaveFunction lmout(meMomenta()[3],mePartonData()[3],outgoing);
SpinorWaveFunction lpout(meMomenta()[4],mePartonData()[4],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
lmout.reset(ix);lm.push_back(lmout);
lpout.reset(ix);lp.push_back(lpout);
}
// q g to q W
if(mePartonData()[0]->id()<=6&&mePartonData()[0]->id()>0&&
mePartonData()[1]->id()==ParticleID::g) {
// polarization states for the particles
vector<SpinorWaveFunction> fin;
vector<VectorWaveFunction> gin;
vector<SpinorBarWaveFunction> fout;
SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction glin(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction qout(meMomenta()[2],mePartonData()[2],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ; fin.push_back(qin);
glin.reset(2*ix); gin.push_back(glin);
qout.reset(ix);fout.push_back(qout);
}
output=qgME(fin,gin,fout,lm,lp);
}
// qbar g to qbar W
else if(mePartonData()[0]->id()>=-6&&mePartonData()[0]->id()<0&&
mePartonData()[1]->id()==ParticleID::g) {
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gin;
vector<SpinorWaveFunction> aout;
SpinorBarWaveFunction qbin (meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction glin (meMomenta()[1],mePartonData()[1],incoming);
SpinorWaveFunction qbout(meMomenta()[2],mePartonData()[2],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qbin.reset(ix) ; ain.push_back(qbin);
glin.reset(2*ix) ; gin.push_back(glin);
qbout.reset(ix);aout.push_back(qbout);
}
output=qbargME(ain,gin,aout,lm,lp);
}
// q qbar to g W
else {
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gout;
SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction qbin(meMomenta()[1],mePartonData()[1],incoming);
VectorWaveFunction glout(meMomenta()[2],mePartonData()[2],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ; fin.push_back(qin);
qbin.reset(ix) ; ain.push_back(qbin);
glout.reset(2*ix); gout.push_back(glout);
}
output=qqbarME(fin,ain,gout,lm,lp);
}
return output*sHat();
}
InvEnergy2 MEPP2WJet::qqbarME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & gout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool calc) const {
// if calculation spin corrections construct the me
if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1Half,
PDT::Spin1Half));
// some integers
unsigned int ihel1,ihel2,ohel1,ohel2,ohel3;
// find the right W pointer
tcPDPtr wdata = mePartonData()[3]->iCharge()+mePartonData()[4]->iCharge() > 0
? _wplus :_wminus;
// compute the W current for speed
VectorWaveFunction bcurr[2][2];
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
bcurr[ohel2][ohel3] = _theFFWVertex->evaluate(_mw2,_widthopt,wdata,
lp[ohel3],lm[ohel2]);
}
}
double me[3]={0.,0.,0.};
Complex diag[2];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
for(ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[0],
fin[ihel1],gout[ohel1]);
interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[1],
ain[ihel2],gout[ohel1]);
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
diag[0] = _theFFWVertex->evaluate(_mw2,fin[ihel1],interb,
bcurr[ohel2][ohel3]);
diag[1] = _theFFWVertex->evaluate(_mw2,inters,ain[ihel2],
bcurr[ohel2][ohel3]);
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
// total
diag[0] += diag[1];
me[0] += norm(diag[0]);
if(calc) _me(ihel1,ihel2,2*ohel1,ohel2,ohel3) = diag[0];
}
}
}
}
}
// results
// initial state spin and colour average
double colspin=1./9./4.;
// and C_F N_c from matrix element
colspin *= 4.;
// colour factor for the W decay
if(mePartonData()[3]->coloured()) colspin*=3.;
DVector save;
for(unsigned int ix=0;ix<3;++ix) {
me[ix]*=colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
return me[0] * UnitRemoval::InvE2;
}
InvEnergy2 MEPP2WJet::qgME(vector<SpinorWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool calc) const {
// if calculation spin corrections construct the me
if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half));
// find the right W pointer
tcPDPtr wdata = mePartonData()[3]->iCharge()+mePartonData()[4]->iCharge() > 0 ?
_wplus :_wminus;
// some integers
unsigned int ihel1,ihel2,ohel1,ohel2,ohel3;
// compute the leptonic W current for speed
VectorWaveFunction bcurr[2][2];
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
bcurr[ohel2][ohel3] = _theFFWVertex->evaluate(_mw2,_widthopt,wdata,
lp[ohel3],lm[ohel2]);
}
}
// compute the matrix elements
double me[3]={0.,0.,0.};
Complex diag[2];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
for(ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[2],
fout[ohel1],gin[ihel2]);
inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[0],
fin[ihel1],gin[ihel2]);
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
diag[0]=_theFFWVertex->evaluate(_mw2,fin[ihel1],interb,
bcurr[ohel2][ohel3]);
diag[1]=_theFFWVertex->evaluate(_mw2,inters,fout[ohel1],
bcurr[ohel2][ohel3]);
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
// total
diag[0] += diag[1];
me[0] += norm(diag[0]);
if(calc) _me(ihel1,2*ihel2,ohel1,ohel2,ohel3) = diag[0];
}
}
}
}
}
// results
// initial state spin and colour average
double colspin=1./24./4.;
// and C_F N_c from matrix element
colspin *=4.;
// colour factor for the W decay
if(mePartonData()[3]->coloured()) colspin*=3.;
DVector save;
for(unsigned int ix=0;ix<3;++ix) {
me[ix]*=colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
return me[0] * UnitRemoval::InvE2;
}
InvEnergy2 MEPP2WJet::qbargME(vector<SpinorBarWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
vector<SpinorWaveFunction> & fout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool calc) const {
// if calculation spin corrections construct the me
if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half));
// find the right W pointer
tcPDPtr wdata = mePartonData()[3]->iCharge()+mePartonData()[4]->iCharge() > 0 ?
_wplus :_wminus;
// some integers
unsigned int ihel1,ihel2,ohel1,ohel2,ohel3;
// compute the leptonic W current for speed
VectorWaveFunction bcurr[2][2];
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
bcurr[ohel2][ohel3] = _theFFWVertex->evaluate(_mw2,_widthopt,wdata,
lp[ohel3],lm[ohel2]);
}
}
// compute the matrix elements
double me[3]={0.,0.,0.};
Complex diag[2];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
for(ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[2],
fout[ohel1],gin[ihel2]);
interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[0],
fin[ihel1],gin[ihel2]);
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
diag[0]= _theFFWVertex->evaluate(_mw2,inters,fin[ihel1],
bcurr[ohel2][ohel3]);
diag[1]= _theFFWVertex->evaluate(_mw2,fout[ohel1],interb,
bcurr[ohel2][ohel3]);
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
// total
diag[0] += diag[1];
me[0] += norm(diag[0]);
if(calc) _me(ihel1,2*ihel2,ohel1,ohel2,ohel3) = diag[0];
}
}
}
}
}
// results
// initial state spin and colour average
double colspin=1./24./4.;
// and C_F N_c from matrix element
colspin *= 4.;
// colour factor for the W decay
if(mePartonData()[3]->coloured()) colspin*=3.;
DVector save;
for(unsigned int ix=0;ix<3;++ix) {
me[ix]*=colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
return me[0] * UnitRemoval::InvE2;
}
void MEPP2WJet::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard(5);
// incoming
hard[0]=sub->incoming().first;
hard[1]=sub->incoming().second;
if((hard[0]->id()<0&&hard[1]->id()<=6)||
hard[0]->id()==ParticleID::g) swap(hard[0],hard[1]);
// outgoing
for(unsigned int ix=0;ix<3;++ix) {
unsigned int iloc;
PPtr mother=sub->outgoing()[ix]->parents()[0];
if(mother&&abs(mother->id())==ParticleID::Wplus) {
if(sub->outgoing()[ix]->id()>0) iloc=3;
else iloc=4;
}
else iloc=2;
hard[iloc]=sub->outgoing()[ix];
}
// wavefunctions for the W decay products
vector<SpinorBarWaveFunction> lm;
vector<SpinorWaveFunction> lp;
SpinorBarWaveFunction(lm,hard[3],outgoing,true,true);
SpinorWaveFunction (lp,hard[4],outgoing,true,true);
// identify hard process and calculate matrix element
// q g to q W
if(hard[0]->id()<=6&&hard[0]->id()>0&&hard[1]->id()==ParticleID::g) {
vector<SpinorWaveFunction> fin;
vector<VectorWaveFunction> gin;
vector<SpinorBarWaveFunction> fout;
SpinorWaveFunction (fin ,hard[0],incoming,false,true);
VectorWaveFunction (gin ,hard[1],incoming,false,true,true);
SpinorBarWaveFunction (fout,hard[2],outgoing,true ,true);
gin[1]=gin[2];
qgME(fin,gin,fout,lm,lp,true);
}
// qbar g to qbar W
else if(hard[0]->id()>=-6&&hard[0]->id()<0&&hard[1]->id()==ParticleID::g) {
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gin;
vector<SpinorWaveFunction> aout;
SpinorBarWaveFunction(ain ,hard[0],incoming,false,true);
VectorWaveFunction (gin ,hard[1],incoming,false,true,true);
SpinorWaveFunction (aout,hard[2],outgoing,true ,true);
gin[1]=gin[2];
qbargME(ain,gin,aout,lm,lp,true);
}
// q qbar to g W
else {
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gout;
SpinorWaveFunction (fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
VectorWaveFunction (gout,hard[2],outgoing,true ,true,true);
gout[1]=gout[2];
qqbarME(fin,ain,gout,lm,lp,true);
}
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<5;++ix)
dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo())->setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/Hadron/MEPP2WJet.h b/MatrixElement/Hadron/MEPP2WJet.h
--- a/MatrixElement/Hadron/MEPP2WJet.h
+++ b/MatrixElement/Hadron/MEPP2WJet.h
@@ -1,363 +1,363 @@
// -*- C++ -*-
#ifndef HERWIG_MEPP2WJet_H
#define HERWIG_MEPP2WJet_H
//
// This is the declaration of the MEPP2WJet class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEPP2WJet class implements the matrix element for the production of
* a W boson and a jet including the decay of the W.
*
* @see \ref MEPP2WJetInterfaces "The interfaces"
* defined for MEPP2WJet.
*/
class MEPP2WJet: public MEBase {
public:
/**
* The default constructor.
*/
MEPP2WJet();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Used internally by generateKinematics, after calculating the
* limits on cos(theta).
*/
double getCosTheta(double cthmin, double cthmax, const double r);
/**
* Matrix elements for the different subprocesses
*/
//@{
/**
* Matrix element for \f$q\bar{q}\to W^\pm g\f$.
* @param fin Spinors for incoming quark
* @param ain Spinors for incoming antiquark
* @param gout Polarization vectors for the outgoing gluon
* @param lm Spinors for outgoing lepton
* @param lp Spinors for outgoing antilepton
* @param me Whether or not to calculate the matrix element for spin correlations
**/
InvEnergy2 qqbarME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & gout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool me=false) const;
/**
* Matrix element for \f$qg\to W^\pm q\f$.
* @param fin Spinors for incoming quark
* @param gin Polarization vectors for the incoming gluon
* @param fout Spinors for outgoing quark
* @param lm Spinors for outgoing lepton
* @param lp Spinors for outgoing antilepton
* @param me Whether or not to calculate the matrix element for spin correlations
**/
InvEnergy2 qgME(vector<SpinorWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool me=false) const;
/**
* Matrix element for \f$\bar{q}g\to W^\pm\bar{q}\f$.
* @param fin Spinors for incoming antiquark
* @param gin Polarization vectors for the incoming gluon
* @param fout Spinors for outgoing antiquark
* @param lm Spinors for outgoing lepton
* @param lp Spinors for outgoing antilepton
* @param me Whether or not to calculate the matrix element for spin correlations
**/
InvEnergy2 qbargME(vector<SpinorBarWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
vector<SpinorWaveFunction> & fout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool me=false) const;
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2WJet> initMEPP2WJet;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2WJet & operator=(const MEPP2WJet &);
private:
/**
* Vertices for the helicity amplitude calculation
*/
//@{
/**
* Pointer to the W vertex
*/
AbstractFFVVertexPtr _theFFWVertex;
/**
* Pointer to the \f$qqg\f$ vertex
*/
AbstractFFVVertexPtr _theQQGVertex;
//@}
/**
* @name Pointers to the W ParticleData objects
*/
//@{
/**
* The \f$W^+\f$ data pointer
*/
tcPDPtr _wplus;
/**
* The \f$W^-\f$ data pointer
*/
tcPDPtr _wminus;
//@}
/**
* @name Switches to control the particles in the hard process
*/
//@{
/**
* Subprocesses to include
*/
unsigned int _process;
/**
* Allowed flavours for the incoming quarks
*/
unsigned int _maxflavour;
/**
* Which charge states to include
*/
unsigned int _plusminus;
/**
* W decay modes
*/
unsigned int _wdec;
/**
* Option for the treatment of the W off-shell effects
*/
unsigned int _widthopt;
//@}
/**
* Matrix element for spin correlations
*/
mutable ProductionMatrixElement _me;
/**
* Storage of the scale to avoid the need to recalculate
*/
Energy2 _scale;
/**
* Storage of the off-shell W mass to avoid the need to recalculate
*/
Energy2 _mw2;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEPP2WJet. */
template <>
struct BaseClassTrait<Herwig::MEPP2WJet,1> {
/** Typedef of the first base class of MEPP2WJet. */
typedef MEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2WJet class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2WJet>
: public ClassTraitsBase<Herwig::MEPP2WJet> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2WJet"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2WJet is implemented. It may also include several, space-separated,
* libraries if the class MEPP2WJet depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEPP2WJet_H */
diff --git a/MatrixElement/Hadron/MEPP2ZJet.cc b/MatrixElement/Hadron/MEPP2ZJet.cc
--- a/MatrixElement/Hadron/MEPP2ZJet.cc
+++ b/MatrixElement/Hadron/MEPP2ZJet.cc
@@ -1,878 +1,878 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEPP2ZJet class.
//
#include "MEPP2ZJet.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Cuts/Cuts.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
MEPP2ZJet::MEPP2ZJet() : _process(0), _maxflavour(5), _zdec(0),
_gammaZ(0), _widthopt(1), _pprob(0.5)
{}
void MEPP2ZJet::doinit() throw(InitException) {
MEBase::doinit();
_z0 = getParticleData(ThePEG::ParticleID::Z0 );
_gamma = getParticleData(ThePEG::ParticleID::gamma);
// cast the SM pointer to the Herwig SM pointer
ThePEG::Ptr<Herwig::StandardModel>::transient_const_pointer
hwsm=ThePEG::dynamic_ptr_cast< ThePEG::Ptr<Herwig::StandardModel>
::transient_const_pointer>(standardModel());
// do the initialisation
if(!hwsm)
throw InitException() << "Must be Herwig::StandardModel in MEPP2ZJet::doinit()"
<< Exception::runerror;
// set the vertex pointers
_theFFZVertex = hwsm->vertexFFZ();
_theFFPVertex = hwsm->vertexFFP();
_theQQGVertex = hwsm->vertexFFG();
}
ClassDescription<MEPP2ZJet> MEPP2ZJet::initMEPP2ZJet;
// Definition of the static class description member.
void MEPP2ZJet::Init() {
static ClassDocumentation<MEPP2ZJet> documentation
("The MEPP2ZJet class implements the matrix element for Z/gamma+ jet production");
static Parameter<MEPP2ZJet,unsigned int> interfaceMaxFlavour
( "MaxFlavour",
"The heaviest incoming quark flavour this matrix element is allowed to handle "
"(if applicable).",
&MEPP2ZJet::_maxflavour, 5, 0, 8, false, false, true);
static Switch<MEPP2ZJet,unsigned int> interfaceZDecay
("ZDecay",
"Which process to included",
&MEPP2ZJet::_zdec, 0, false, false);
static SwitchOption interfaceZDecayAll
(interfaceZDecay,
"All",
"Include all SM fermions as outgoing particles",
0);
static SwitchOption interfaceZDecayQuarks
(interfaceZDecay,
"Quarks",
"All include the quarks as outgoing particles",
1);
static SwitchOption interfaceZDecayLeptons
(interfaceZDecay,
"Leptons",
"Only include the leptons as outgoing particles",
2);
static SwitchOption interfaceZDecayChargedLeptons
(interfaceZDecay,
"ChargedLeptons",
"Only include the charged leptons as outgoing particles",
3);
static SwitchOption interfaceZDecayNeutrinos
(interfaceZDecay,
"Neutrinos",
"Only include the neutrinos as outgoing particles",
4);
static SwitchOption interfaceZDecayElectron
(interfaceZDecay,
"Electron",
"Only include e+e- as outgoing particles",
5);
static SwitchOption interfaceZDecayMuon
(interfaceZDecay,
"Muon",
"Only include mu+mu- as outgoing particles",
6);
static SwitchOption interfaceZDecayTau
(interfaceZDecay,
"Tau",
"Only include tau+tau- as outgoing particles",
7);
static SwitchOption interfaceZDecayNu_e
(interfaceZDecay,
"Nu_e",
"Only include nu_e ne_ebar as outgoing particles",
8);
static SwitchOption interfaceZDecaynu_mu
(interfaceZDecay,
"Nu_mu",
"Only include nu_mu nu_mubar as outgoing particles",
9);
static SwitchOption interfaceZDecaynu_tau
(interfaceZDecay,
"Nu_tau",
"Only include nu_tau nu_taubar as outgoing particles",
10);
static SwitchOption interfaceZDecayDown
(interfaceZDecay,
"Down",
"Only include d dbar as outgoing particles",
11);
static SwitchOption interfaceZDecayUp
(interfaceZDecay,
"Up",
"Only include u ubar as outgoing particles",
12);
static SwitchOption interfaceZDecayStrange
(interfaceZDecay,
"Strange",
"Only include s sbar as outgoing particles",
13);
static SwitchOption interfaceZDecayCharm
(interfaceZDecay,
"Charm",
"Only include c cbar as outgoing particles",
14);
static SwitchOption interfaceZDecayBottom
(interfaceZDecay,
"Bottom",
"Only include b bbar as outgoing particles",
15);
static SwitchOption interfaceZDecayTop
(interfaceZDecay,
"Top",
"Only include t tbar as outgoing particles",
16);
static Switch<MEPP2ZJet,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEPP2ZJet::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
0);
static SwitchOption interfaceProcessqqbar
(interfaceProcess,
"qqbar",
"Only include q qbar -> Z/gamma g process",
1);
static SwitchOption interfaceProcessqg
(interfaceProcess,
"qg",
"Only include the q g -> Z/gamma q process",
2);
static SwitchOption interfaceProcessqbarg
(interfaceProcess,
"qbarg",
"Only include the qbar g -> Z/gamma qbar process",
3);
static Parameter<MEPP2ZJet,double> interfacePhotonProbablity
("PhotonProbablity",
"Probability for using the \\f$1/s^2\\f$ piece for the"
" generation of the gauge boson mass",
&MEPP2ZJet::_pprob, 0.5, 0.0, 1.0,
false, false, Interface::limited);
static Switch<MEPP2ZJet,unsigned int> interfaceGammaZ
("GammaZ",
"Which terms to include",
&MEPP2ZJet::_gammaZ, 0, false, false);
static SwitchOption interfaceGammaZAll
(interfaceGammaZ,
"All",
"Include both gamma and Z terms",
0);
static SwitchOption interfaceGammaZGamma
(interfaceGammaZ,
"Gamma",
"Only include the photon",
1);
static SwitchOption interfaceGammaZZ
(interfaceGammaZ,
"Z",
"Only include the Z",
2);
static Switch<MEPP2ZJet,unsigned int> interfaceWidthOption
("WidthOption",
"The option for handling the width of the off-shell W boson",
&MEPP2ZJet::_widthopt, 1, false, false);
static SwitchOption interfaceWidthOptionFixedDenominator
(interfaceWidthOption,
"FixedDenominator",
"Use a fxied with in the W propagator but the full matrix element"
" in the numerator",
1);
static SwitchOption interfaceWidthOptionAllRunning
(interfaceWidthOption,
"AllRunning",
"Use a running width in the W propagator and the full matrix "
"element in the numerator",
2);
}
void MEPP2ZJet::getDiagrams() const {
// which intermediates to include
bool gamma = _gammaZ==0 || _gammaZ==1;
bool Z0 = _gammaZ==0 || _gammaZ==2;
// pointer for gluon
tcPDPtr g = getParticleData(ParticleID::g);
bool quark,lepton;
for(unsigned int ix=1;ix<17;++ix) {
// increment counter to switch between quarks and leptons
if(ix==7) ix+=4;
// is it a valid quark process
quark=ix<=6&&(_zdec==0||_zdec==1||_zdec-10==ix);
// is it a valid lepton process
lepton=ix>=11&&ix<=16&&
(_zdec==0||_zdec==2||(_zdec==3&&ix%2==1)||
(_zdec==4&&ix%2==0)||(ix%2==0&&(ix-10)/2==_zdec-7)||
(ix%2==1&&(ix-9)/2==_zdec-4));
// if not a validf process continue
if(!(quark||lepton)) continue;
// pointer for Z decay products
tcPDPtr lm = getParticleData(ix);
tcPDPtr lp = lm->CC();
for (unsigned int i = 1; i <= _maxflavour; ++i ) {
tcPDPtr q = getParticleData(i);
tcPDPtr qb = q->CC();
// q qbar -> Z g -> l+l- g
if(_process==0||_process==1) {
if(gamma) add(new_ptr((Tree2toNDiagram(3), q, q, qb, 1, _gamma,
3, g, 4, lm, 4, lp, -1)));
if(Z0) add(new_ptr((Tree2toNDiagram(3), q, q, qb, 1, _z0,
3, g, 4, lm, 4, lp, -2)));
if(gamma) add(new_ptr((Tree2toNDiagram(3), q, q, qb, 3, _gamma,
1, g, 4, lm, 4, lp, -3)));
if(Z0) add(new_ptr((Tree2toNDiagram(3), q, q, qb, 3, _z0,
1, g, 4, lm, 4, lp, -4)));
}
// q g -> Z q -> l+l- qbar
if(_process==0||_process==2) {
if(gamma) add(new_ptr((Tree2toNDiagram(3), q, q, g, 1, _gamma,
3, q, 4, lm, 4, lp, -5)));
if(Z0) add(new_ptr((Tree2toNDiagram(3), q, q, g, 1, _z0,
3, q, 4, lm, 4, lp, -6)));
if(gamma) add(new_ptr((Tree2toNDiagram(2), q, g, 1, q, 3, _gamma,
3, q, 4, lm, 4, lp, -7)));
if(Z0) add(new_ptr((Tree2toNDiagram(2), q, g, 1, q, 3, _z0,
3, q, 4, lm, 4, lp, -8)));
}
// qbar g -> Z qbar -> l+l- qbar
if(_process==0||_process==3) {
if(gamma) add(new_ptr((Tree2toNDiagram(3), qb, qb, g, 1, _gamma,
3, qb, 4, lm, 4, lp, -9 )));
if(Z0) add(new_ptr((Tree2toNDiagram(3), qb, qb, g, 1, _z0,
3, qb, 4, lm, 4, lp, -10)));
if(gamma) add(new_ptr((Tree2toNDiagram(2), qb, g, 1, qb, 3, _gamma,
3, qb, 4, lm, 4, lp, -11)));
if(Z0) add(new_ptr((Tree2toNDiagram(2), qb, g, 1, qb, 3, _z0,
3, qb, 4, lm, 4, lp, -12)));
}
}
}
}
unsigned int MEPP2ZJet::orderInAlphaS() const {
return 1;
}
unsigned int MEPP2ZJet::orderInAlphaEW() const {
return 2;
}
void MEPP2ZJet::persistentOutput(PersistentOStream & os) const {
os << _theFFZVertex << _theFFPVertex << _theQQGVertex << _z0 << _widthopt
<< _gamma << _process << _maxflavour << _zdec << _pprob << _gammaZ;
}
void MEPP2ZJet::persistentInput(PersistentIStream & is, int) {
is >> _theFFZVertex >> _theFFPVertex >> _theQQGVertex >> _z0 >> _widthopt
>> _gamma >> _process >> _maxflavour >> _zdec >> _pprob >> _gammaZ;
}
int MEPP2ZJet::nDim() const {
return 5;
}
Selector<const ColourLines *>
MEPP2ZJet::colourGeometries(tcDiagPtr diag) const {
// colour lines for q qbar -> Z g
static const ColourLines cqqbar[4]={ColourLines("1 2 5,-3 -5"),
ColourLines("1 5,-5 2 -3"),
ColourLines("1 2 5,-3 -5, 6 -7"),
ColourLines("1 5,-5 2 -3, 6 -7")};
// colour lines for q g -> Z q
static const ColourLines cqg [4]={ColourLines("1 2 -3,3 5"),
ColourLines("1 -2,2 3 5"),
ColourLines("1 2 -3,3 5, 6 -7"),
ColourLines("1 -2,2 3 5, 6 -7")};
// colour lines for qbar q -> Z qbar
static const ColourLines cqbarg[4]={ColourLines("-1 -2 3,-3 -5"),
ColourLines("-1 2,-2 -3 -5"),
ColourLines("-1 -2 3,-3 -5, 6 -7"),
ColourLines("-1 2,-2 -3 -5, 6 -7")};
// select the correct line
unsigned int icol = mePartonData()[3]->coloured() ? 2 : 0;
Selector<const ColourLines *> sel;
switch(abs(diag->id())) {
case 1 : case 2:
sel.insert(1.0, &cqqbar[icol]);
break;
case 3 : case 4:
sel.insert(1.0, &cqqbar[icol+1]);
break;
case 5 : case 6:
sel.insert(1.0, &cqg[icol]);
break;
case 7 : case 8:
sel.insert(1.0, &cqg[icol+1]);
break;
case 9 : case 10:
sel.insert(1.0, &cqbarg[icol]);
break;
case 11 : case 12:
sel.insert(1.0, &cqbarg[icol+1]);
break;
}
return sel;
}
Selector<MEBase::DiagramIndex>
MEPP2ZJet::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
int id=abs(diags[i]->id());
if (id <= 4 ) sel.insert(meInfo()[id-1],i);
else if(id <= 8 ) sel.insert(meInfo()[id-5],i);
else if(id <= 12) sel.insert(meInfo()[id-9],i);
}
return sel;
}
Energy2 MEPP2ZJet::scale() const {
return _scale;
}
CrossSection MEPP2ZJet::dSigHatDR() const {
return me2()*jacobian()/(16.0*sqr(Constants::pi)*sHat())*sqr(hbarc);
}
bool MEPP2ZJet::generateKinematics(const double * r) {
// initialize jacobian
jacobian(1.);
// cms energy
Energy ecm=sqrt(sHat());
// first generate the mass of the off-shell gauge boson
// minimum mass of the
tcPDVector ptemp;
ptemp.push_back(mePartonData()[3]);
ptemp.push_back(mePartonData()[4]);
Energy2 minMass2 = max(lastCuts().minSij(mePartonData()[3],mePartonData()[4]),
lastCuts().minS(ptemp));
// minimum pt of the jet
Energy ptmin = max(lastCuts().minKT(mePartonData()[2]),
lastCuts().minKT(_z0));
// maximum mass of the gauge boson so pt is possible
Energy2 maxMass2 = min(ecm*(ecm-2.*ptmin),lastCuts().maxS(ptemp));
if(maxMass2<=0.*GeV2||minMass2<0.*GeV2) return false;
// also impose the limits from the ParticleData object
minMass2 = max(minMass2,sqr(_z0->massMin()));
maxMass2 = min(maxMass2,sqr(_z0->massMax()));
// also impose the limits from the ParticleData object
if(maxMass2<minMass2) return false;
// generation of the mass
Energy M(_z0->mass()),Gamma(_z0->width());
Energy2 M2(sqr(M)),MG(M*Gamma);
double rhomin = atan((minMass2-M2)/MG);
double rhomax = atan((maxMass2-M2)/MG);
if(r[1]<_pprob) {
double rand=r[1]/_pprob;
_mz2=minMass2*maxMass2/(minMass2+rand*(maxMass2-minMass2));
}
else {
double rand=(r[1]-_pprob)/(1.-_pprob);
_mz2=M2+MG*tan(rhomin+rand*(rhomax-rhomin));
}
Energy mz=sqrt(_mz2);
InvEnergy2 emjac1 = _pprob*minMass2*maxMass2/(maxMass2-minMass2)/sqr(_mz2);
InvEnergy2 emjac2 = (1.-_pprob)*MG/(rhomax-rhomin)/(sqr(_mz2-M2)+sqr(MG));
// jacobian
jacobian(jacobian()/sHat()/(emjac1+emjac2));
// set the masses of the outgoing particles to 2-2 scattering
meMomenta()[2].setMass(0.*MeV);
Lorentz5Momentum pz(mz);
// generate the polar angle of the hard scattering
double ctmin(-1.0), ctmax(1.0);
Energy q(0.0*GeV);
try {
q = SimplePhaseSpace::getMagnitude(sHat(), meMomenta()[2].mass(),mz);
}
catch ( ImpossibleKinematics ) {
return false;
}
Energy2 pq = sqrt(sHat())*q;
if ( ptmin > 0.0*GeV ) {
double ctm = 1.0 - sqr(ptmin/q);
if ( ctm <= 0.0 ) return false;
ctmin = max(ctmin, -sqrt(ctm));
ctmax = min(ctmax, sqrt(ctm));
}
if ( ctmin >= ctmax ) return false;
double cth = getCosTheta(ctmin, ctmax, r[0]);
Energy pt = q*sqrt(1.0-sqr(cth));
double phi = 2.0*Constants::pi*r[2];
meMomenta()[2].setVect(Momentum3( pt*sin(phi), pt*cos(phi), q*cth));
pz.setVect( Momentum3(-pt*sin(phi),-pt*cos(phi),-q*cth));
meMomenta()[2].rescaleEnergy();
pz.rescaleEnergy();
// set the scale
_scale = _mz2+sqr(pt);
// generate the momenta of the Z decay products
meMomenta()[3].setMass(mePartonData()[3]->mass());
meMomenta()[4].setMass(mePartonData()[4]->mass());
Energy q2 = 0.0*GeV;
try {
q2 = SimplePhaseSpace::getMagnitude(_mz2, meMomenta()[3].mass(),
meMomenta()[4].mass());
} catch ( ImpossibleKinematics ) {
return false;
}
double cth2 =-1.+2.*r[3];
double phi2=Constants::twopi*r[4];
Energy pt2 =q2*sqrt(1.-sqr(cth2));
Lorentz5Momentum pl[2]={Lorentz5Momentum( pt2*cos(phi2), pt2*sin(phi2), q2*cth2,0.*MeV,
meMomenta()[3].mass()),
Lorentz5Momentum(-pt2*cos(phi2),-pt2*sin(phi2),-q2*cth2,0.*MeV,
meMomenta()[4].mass())};
pl[0].rescaleEnergy();
pl[1].rescaleEnergy();
Boost boostv(pz.boostVector());
pl[0].boost(boostv);
pl[1].boost(boostv);
meMomenta()[3] = pl[0];
meMomenta()[4] = pl[1];
// check passes all the cuts
vector<LorentzMomentum> out(3);
tcPDVector tout(3);
for(unsigned int ix=0;ix<3;++ix) {
out[ ix] = meMomenta()[ix+2];
tout[ix] = mePartonData()[ix+2];
}
if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) )
return false;
// jacobian
jacobian((pq/sHat())*Constants::pi*jacobian()/8./sqr(Constants::pi)*q2/mz);
return true;
}
double MEPP2ZJet::getCosTheta(double ctmin, double ctmax, const double r) {
double cth = 0.0;
double zmin = 0.5*(1.0 - ctmax);
double zmax = 0.5*(1.0 - ctmin);
if ( zmin <= 0.0 || zmax >= 1.0 ) {
jacobian((ctmax - ctmin)*jacobian());
cth = ctmin + r*(ctmax-ctmin);
} else {
double A1 = (2.0*zmax - 1.0)/(zmax*(1.0-zmax));
double A0 = (2.0*zmin - 1.0)/(zmin*(1.0-zmin));
double A = r*(A1 - A0) + A0;
double z = A < 2.0? 2.0/(sqrt(sqr(A) + 4.0) + 2 - A):
0.5*(A - 2.0 + sqrt(sqr(A) + 4.0))/A;
cth = 1.0 - 2.0*z;
jacobian((2.0*(A1 - A0)*sqr(z)*sqr(1.0 - z)/(sqr(z) + sqr(1.0 - z)))*jacobian());
}
return cth;
}
double MEPP2ZJet::me2() const {
useMe();
InvEnergy2 output(0./GeV2);
// construct spinors for the leptons (always the same)
vector<SpinorBarWaveFunction> lm;
vector<SpinorWaveFunction> lp;
SpinorBarWaveFunction lmout(meMomenta()[3],mePartonData()[3],outgoing);
SpinorWaveFunction lpout(meMomenta()[4],mePartonData()[4],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
lmout.reset(ix);lm.push_back(lmout);
lpout.reset(ix);lp.push_back(lpout);
}
// q g to q Z
if(mePartonData()[0]->id()<=6&&mePartonData()[0]->id()>0&&
mePartonData()[1]->id()==ParticleID::g) {
// polarization states for the particles
vector<SpinorWaveFunction> fin;
vector<VectorWaveFunction> gin;
vector<SpinorBarWaveFunction> fout;
SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction glin(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction qout(meMomenta()[2],mePartonData()[2],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ; fin.push_back(qin);
glin.reset(2*ix); gin.push_back(glin);
qout.reset(ix);fout.push_back(qout);
}
output=qgME(fin,gin,fout,lm,lp);
}
// qbar g to qbar Z
else if(mePartonData()[0]->id()>=-6&&mePartonData()[0]->id()<0&&
mePartonData()[1]->id()==ParticleID::g) {
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gin;
vector<SpinorWaveFunction> aout;
SpinorBarWaveFunction qbin (meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction glin (meMomenta()[1],mePartonData()[1],incoming);
SpinorWaveFunction qbout(meMomenta()[2],mePartonData()[2],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qbin .reset(ix ); ain .push_back(qbin );
glin .reset(2*ix); gin .push_back(glin );
qbout.reset(ix ); aout.push_back(qbout);
}
output=qbargME(ain,gin,aout,lm,lp);
}
// q qbar to g Z
else {
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gout;
SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction qbin(meMomenta()[1],mePartonData()[1],incoming);
VectorWaveFunction glout(meMomenta()[2],mePartonData()[2],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ; fin.push_back(qin);
qbin.reset(ix) ; ain.push_back(qbin);
glout.reset(2*ix); gout.push_back(glout);
}
output=qqbarME(fin,ain,gout,lm,lp);
}
return output*sHat();
}
InvEnergy2 MEPP2ZJet::qqbarME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & gout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool calc) const {
// if calculation spin corrections construct the me
if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1Half,
PDT::Spin1Half));
// diagrams to include
bool gamma = _gammaZ==0 || _gammaZ==1;
bool Z0 = _gammaZ==0 || _gammaZ==2;
// some integers
unsigned int ihel1,ihel2,ohel1,ohel2,ohel3;
// compute the leptonic photon and Z currents for speed
VectorWaveFunction bcurr[2][2][2];
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
// photon current
if(gamma) bcurr[0][ohel2][ohel3]=
_theFFPVertex->evaluate(_mz2,1,_gamma,lp[ohel3],lm[ohel2]);
// Z current
if(Z0) bcurr[1][ohel2][ohel3]=
_theFFZVertex->evaluate(_mz2,_widthopt,_z0,lp[ohel3],lm[ohel2]);
}
}
// compute the matrix elements
double me[5]={0.,0.,0.,0.,0.};
Complex diag[4];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
for(ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[0],
fin[ihel1],gout[ohel1]);
interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[1],
ain[ihel2],gout[ohel1]);
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
diag[0] = gamma ?
_theFFPVertex->evaluate(_mz2,fin[ihel1],interb,
bcurr[0][ohel2][ohel3]) : 0.;
diag[1]= Z0 ?
_theFFZVertex->evaluate(_mz2,fin[ihel1],interb,
bcurr[1][ohel2][ohel3]) : 0.;
diag[2]= gamma ?
_theFFPVertex->evaluate(_mz2,inters,ain[ihel2],
bcurr[0][ohel2][ohel3]) : 0.;
diag[3]= Z0 ?
_theFFZVertex->evaluate(_mz2,inters,ain[ihel2],
bcurr[1][ohel2][ohel3]) : 0.;
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
me[3] += norm(diag[2]);
me[4] += norm(diag[3]);
// total
diag[0] += diag[1] + diag[2] + diag[3];
me[0] += norm(diag[0]);
if(calc) _me(ihel1,ihel2,2*ohel1,ohel2,ohel3) = diag[0];
}
}
}
}
}
// results
// initial state spin and colour average
double colspin = 1./9./4.;
// and C_F N_c from matrix element
colspin *= 4.;
// and for Z decay products
if(mePartonData()[3]->coloured()) colspin *= 3.;
DVector save;
for(unsigned int ix=0;ix<5;++ix) {
me[ix] *= colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
return me[0]*UnitRemoval::InvE2;
}
InvEnergy2 MEPP2ZJet::qgME(vector<SpinorWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool calc) const {
// diagrams to include
bool gamma = _gammaZ==0 || _gammaZ==1;
bool Z0 = _gammaZ==0 || _gammaZ==2;
// if calculation spin corrections construct the me
if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half));
// some integers
unsigned int ihel1,ihel2,ohel1,ohel2,ohel3;
// compute the leptonic photon and Z currents for speed
VectorWaveFunction bcurr[2][2][2];
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
// photon current
if(gamma) bcurr[0][ohel2][ohel3]=
_theFFPVertex->evaluate(_mz2,1,_gamma,lp[ohel3],lm[ohel2]);
// Z current
if(Z0) bcurr[1][ohel2][ohel3]=
_theFFZVertex->evaluate(_mz2,_widthopt,_z0,lp[ohel3],lm[ohel2]);
}
}
// compute the matrix elements
double me[5]={0.,0.,0.,0.,0.};
Complex diag[4];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
Energy2 _scale=scale();
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
for(ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[2],
fout[ohel1],gin[ihel2]);
inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[0],
fin[ihel1],gin[ihel2]);
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
diag[0]=gamma ?
_theFFPVertex->evaluate(_mz2,fin[ihel1],interb,
bcurr[0][ohel2][ohel3]) : 0.;
diag[1]=Z0 ?
_theFFZVertex->evaluate(_mz2,fin[ihel1],interb,
bcurr[1][ohel2][ohel3]) : 0.;
diag[2]=gamma ?
_theFFPVertex->evaluate(_mz2,inters,fout[ohel1],
bcurr[0][ohel2][ohel3]) : 0.;
diag[3]=Z0 ?
_theFFZVertex->evaluate(_mz2,inters,fout[ohel1],
bcurr[1][ohel2][ohel3]) : 0.;
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
me[3] += norm(diag[2]);
me[4] += norm(diag[3]);
// total
diag[0] += diag[1] + diag[2] + diag[3];
me[0] += norm(diag[0]);
if(calc) _me(ihel1,2*ihel2,ohel1,ohel2,ohel3) = diag[0];
}
}
}
}
}
// results
// initial state spin and colour average
double colspin = 1./24./4.;
// and C_F N_c from matrix element
colspin *= 4.;
// and for Z decay products
if(mePartonData()[3]->coloured()) colspin *= 3.;
DVector save;
for(unsigned int ix=0;ix<5;++ix) {
me[ix] *= colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
return me[0]*UnitRemoval::InvE2;
}
InvEnergy2 MEPP2ZJet::qbargME(vector<SpinorBarWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
vector<SpinorWaveFunction> & fout,
vector<SpinorBarWaveFunction> & lm,
vector<SpinorWaveFunction> & lp,
bool calc) const {
// diagrams to include
bool gamma = _gammaZ==0 || _gammaZ==1;
bool Z0 = _gammaZ==0 || _gammaZ==2;
// if calculation spin corrections construct the me
if(calc) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half));
// some integers
unsigned int ihel1,ihel2,ohel1,ohel2,ohel3;
// compute the leptonic photon and Z currents for speed
VectorWaveFunction bcurr[2][2][2];
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
// photon current
if(gamma) bcurr[0][ohel2][ohel3]=
_theFFPVertex->evaluate(_mz2,1,_gamma,lp[ohel3],lm[ohel2]);
// Z current
if(Z0) bcurr[1][ohel2][ohel3]=
_theFFZVertex->evaluate(_mz2,_widthopt,_z0,lp[ohel3],lm[ohel2]);
}
}
// compute the matrix elements
double me[5]={0.,0.,0.,0.,0.};
Complex diag[4];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
Energy2 _scale=scale();
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
for(ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
inters=_theQQGVertex->evaluate(_scale,5,mePartonData()[2],
fout[ohel1],gin[ihel2]);
interb=_theQQGVertex->evaluate(_scale,5,mePartonData()[0],
fin[ihel1],gin[ihel2]);
for(ohel2=0;ohel2<2;++ohel2) {
for(ohel3=0;ohel3<2;++ohel3) {
diag[0]= gamma ?
_theFFPVertex->evaluate(_mz2,inters,fin[ihel1],
bcurr[0][ohel2][ohel3]) : 0.;
diag[1]= Z0 ?
_theFFZVertex->evaluate(_mz2,inters,fin[ihel1],
bcurr[1][ohel2][ohel3]) : 0.;
diag[2]= gamma ?
_theFFPVertex->evaluate(_mz2,fout[ohel1],interb,
bcurr[0][ohel2][ohel3]) : 0.;
diag[3]= Z0 ?
_theFFZVertex->evaluate(_mz2,fout[ohel1],interb,
bcurr[1][ohel2][ohel3]) : 0.;
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
me[3] += norm(diag[2]);
me[4] += norm(diag[3]);
// total
diag[0] += diag[1] + diag[2] + diag[3];
me[0] += norm(diag[0]);
if(calc) _me(ihel1,2*ihel2,ohel1,ohel2,ohel3) = diag[0];
}
}
}
}
}
// results
// initial state spin and colour average
double colspin = 1./24./4.;
// and C_F N_c from matrix element
colspin *= 4.;
// and for Z decay products
if(mePartonData()[3]->coloured()) colspin*=3.;
DVector save;
for(unsigned int ix=0;ix<5;++ix) {
me[ix] *= colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
return me[0]*UnitRemoval::InvE2;
}
void MEPP2ZJet::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard(5);
// incoming
hard[0]=sub->incoming().first;
hard[1]=sub->incoming().second;
if((hard[0]->id()<0&&hard[1]->id()<=6)||
hard[0]->id()==ParticleID::g) swap(hard[0],hard[1]);
// outgoing
for(unsigned int ix=0;ix<3;++ix) {
unsigned int iloc;
PPtr mother=sub->outgoing()[ix]->parents()[0];
if(mother&&(mother->id()==ParticleID::gamma||mother->id()==ParticleID::Z0)) {
if(sub->outgoing()[ix]->id()>0) iloc=3;
else iloc=4;
}
else iloc=2;
hard[iloc]=sub->outgoing()[ix];
}
// wavefunctions for the Z decay products
vector<SpinorBarWaveFunction> lm;
vector<SpinorWaveFunction> lp;
SpinorBarWaveFunction(lm,hard[3],outgoing,true,true);
SpinorWaveFunction (lp,hard[4],outgoing,true,true);
// identify hard process and calculate matrix element
// q g to q Z
if(hard[0]->id()<=6&&hard[0]->id()>0&&hard[1]->id()==ParticleID::g) {
vector<SpinorWaveFunction> fin;
vector<VectorWaveFunction> gin;
vector<SpinorBarWaveFunction> fout;
SpinorWaveFunction (fin ,hard[0],incoming,false,true);
VectorWaveFunction (gin ,hard[1],incoming,false,true,true);
SpinorBarWaveFunction (fout,hard[2],outgoing,true ,true);
gin[1]=gin[2];
qgME(fin,gin,fout,lm,lp,true);
}
// qbar g to qbar Z
else if(hard[0]->id()>=-6&&hard[0]->id()<0&&hard[1]->id()==ParticleID::g) {
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gin;
vector<SpinorWaveFunction> aout;
SpinorBarWaveFunction(ain ,hard[0],incoming,false,true);
VectorWaveFunction (gin ,hard[1],incoming,false,true,true);
SpinorWaveFunction (aout,hard[2],outgoing,true ,true);
gin[1]=gin[2];
qbargME(ain,gin,aout,lm,lp,true);
}
// q qbar to g Z
else {
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gout;
SpinorWaveFunction (fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
VectorWaveFunction (gout,hard[2],outgoing,true ,true,true);
gout[1]=gout[2];
qqbarME(fin,ain,gout,lm,lp,true);
}
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<5;++ix)
dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo())->setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/Hadron/MEPP2ZJet.h b/MatrixElement/Hadron/MEPP2ZJet.h
--- a/MatrixElement/Hadron/MEPP2ZJet.h
+++ b/MatrixElement/Hadron/MEPP2ZJet.h
@@ -1,370 +1,370 @@
// -*- C++ -*-
#ifndef HERWIG_MEPP2ZJet_H
#define HERWIG_MEPP2ZJet_H
//
// This is the declaration of the MEPP2ZJet class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEPP2ZJet class implements the matrix element for the production
* of a Z boson + a jet including the decay of the Z including \f$Z/\gamma\f$
* interference
*
* @see \ref MEPP2ZJetInterfaces "The interfaces"
* defined for MEPP2ZJet.
*/
class MEPP2ZJet: public MEBase {
public:
/**
* The default constructor.
*/
MEPP2ZJet();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Used internally by generateKinematics, after calculating the
* limits on cos(theta).
*/
double getCosTheta(double cthmin, double cthmax, const double r);
/**
* Matrix elements for the different subprocesses
*/
//@{
/**
* Matrix element for \f$q\bar{q}\to Z/\gamma g\f$.
* @param fin Spinors for incoming quark
* @param ain Spinors for incoming antiquark
* @param gout Polarization vectors for the outgoing gluon
* @param lm Spinors for outgoing lepton
* @param lp Spinors for outgoing antilepton
* @param me Whether or not to calculate the matrix element for spin correlations
**/
InvEnergy2 qqbarME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<VectorWaveFunction> & gout,
vector<SpinorBarWaveFunction> & lm, vector<SpinorWaveFunction> & lp,
bool me=false) const;
/**
* Matrix element for \f$qg\to Z/\gamma q\f$.
* @param fin Spinors for incoming quark
* @param gin Polarization vectors for the incoming gluon
* @param fout Spinors for outgoing quark
* @param lm Spinors for outgoing lepton
* @param lp Spinors for outgoing antilepton
* @param me Whether or not to calculate the matrix element for spin correlations
**/
InvEnergy2 qgME(vector<SpinorWaveFunction> & fin,vector<VectorWaveFunction> & gin,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorBarWaveFunction> & lm, vector<SpinorWaveFunction> & lp,
bool me=false) const;
/**
* Matrix element for \f$\bar{q}g\to Z/\gamma\bar{q}\f$.
* @param fin Spinors for incoming antiquark
* @param gin Polarization vectors for the incoming gluon
* @param fout Spinors for outgoing antiquark
* @param lm Spinors for outgoing lepton
* @param lp Spinors for outgoing antilepton
* @param me Whether or not to calculate the matrix element for spin correlations
**/
InvEnergy2 qbargME(vector<SpinorBarWaveFunction> & fin,
vector<VectorWaveFunction> & gin,
vector<SpinorWaveFunction> & fout,
vector<SpinorBarWaveFunction> & lm, vector<SpinorWaveFunction> & lp,
bool me=false) const;
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2ZJet> initMEPP2ZJet;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2ZJet & operator=(const MEPP2ZJet &);
private:
/**
* Vertices for the helicity amplitude calculation
*/
//@{
/**
* Pointer to the Z vertex
*/
AbstractFFVVertexPtr _theFFZVertex;
/**
* Pointer to the photon vertex
*/
AbstractFFVVertexPtr _theFFPVertex;
/**
* Pointer to the \f$qqg\f$ vertex
*/
AbstractFFVVertexPtr _theQQGVertex;
//@}
/**
* @name Pointers to the \f$Z^0\f$ and \f$\gamma\f$ ParticleData objects
*/
//@{
/**
* Pointer to the Z ParticleData object
*/
tcPDPtr _z0;
/**
* Pointer to the photon ParticleData object
*/
tcPDPtr _gamma;
//@}
/**
* @name Switches to control the particles in the hard process
*/
//@{
/**
* Subprocesses to include
*/
unsigned int _process;
/**
* Allowed flavours for the incoming quarks
*/
unsigned int _maxflavour;
/**
* Control over which Z decay modes to include
*/
unsigned int _zdec;
/**
* Which terms to include
*/
unsigned int _gammaZ;
/**
* Option for the treatment of the W off-shell effects
*/
unsigned int _widthopt;
//@}
/**
* Probability of selecting \f$1/s^2\f$ for the jacobian
* transformation of the boson mass
*/
double _pprob;
/**
* Matrix element for spin correlations
*/
mutable ProductionMatrixElement _me;
/**
* Storage of the scale to avoid the need to recalculate
*/
Energy2 _scale;
/**
* Storage of the off-shell Z mass to avoid the need to recalculate
*/
Energy2 _mz2;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEPP2ZJet. */
template <>
struct BaseClassTrait<Herwig::MEPP2ZJet,1> {
/** Typedef of the first base class of MEPP2ZJet. */
typedef MEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2ZJet class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2ZJet>
: public ClassTraitsBase<Herwig::MEPP2ZJet> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2ZJet"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2ZJet is implemented. It may also include several, space-separated,
* libraries if the class MEPP2ZJet depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEPP2ZJet_H */
diff --git a/MatrixElement/Hadron/MEQCD2to2.cc b/MatrixElement/Hadron/MEQCD2to2.cc
--- a/MatrixElement/Hadron/MEQCD2to2.cc
+++ b/MatrixElement/Hadron/MEQCD2to2.cc
@@ -1,1180 +1,1180 @@
// -*- C++ -*-
//
// MEQCD2to2.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 MEQCD2to2 class.
//
#include "MEQCD2to2.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;MEQCD2to2::MEQCD2to2():_maxflavour(5),_process(0) {
massOption(true ,0);
massOption(false,0);
}
void MEQCD2to2::rebind(const TranslationMap & trans)
throw(RebindException) {
_ggggvertex = trans.translate(_ggggvertex);
_gggvertex = trans.translate( _gggvertex);
_qqgvertex = trans.translate( _qqgvertex);
_gluon = trans.translate( _gluon);
for(unsigned int ix=0;ix<_quark.size();++ix)
{_quark[ix]=trans.translate(_quark[ix]);}
for(unsigned int ix=0;ix<_antiquark.size();++ix)
{_antiquark[ix]=trans.translate(_quark[ix]);}
HwME2to2Base::rebind(trans);
}
IVector MEQCD2to2::getReferences() {
IVector ret = HwME2to2Base::getReferences();
ret.push_back(_ggggvertex);
ret.push_back(_gggvertex);
ret.push_back(_qqgvertex);
ret.push_back(_gluon);
for(unsigned int ix=0;ix<_quark.size();++ix)
{ret.push_back(_quark[ix]);}
for(unsigned int ix=0;ix<_antiquark.size();++ix)
{ret.push_back(_antiquark[ix]);}
return ret;
}
void MEQCD2to2::doinit() throw(InitException) {
// call the base class
HwME2to2Base::doinit();
// get the vedrtex pointers from the SM object
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm) {
_qqgvertex = hwsm->vertexFFG();
_gggvertex = hwsm->vertexGGG();
_ggggvertex = hwsm->vertexGGGG();
}
else throw InitException() << "Wrong type of StandardModel object in "
<< "MEQCD2to2::doinit() the Herwig++ version must be used"
<< Exception::runerror;
// get the particle data objects
_gluon=getParticleData(ParticleID::g);
for(int ix=1;ix<=int(_maxflavour);++ix) {
_quark.push_back( getParticleData( ix));
_antiquark.push_back(getParticleData(-ix));
}
}
Energy2 MEQCD2to2::scale() const {
Energy2 s(sHat()),u(uHat()),t(tHat());
return 2.*s*t*u/(s*s+t*t+u*u);
}
void MEQCD2to2::persistentOutput(PersistentOStream & os) const {
os << _ggggvertex << _gggvertex << _qqgvertex << _maxflavour
<< _process << _gluon << _quark << _antiquark;
}
void MEQCD2to2::persistentInput(PersistentIStream & is, int) {
is >> _ggggvertex >> _gggvertex >> _qqgvertex >> _maxflavour
>> _process >> _gluon >> _quark >> _antiquark;
}
unsigned int MEQCD2to2::orderInAlphaS() const {
return 2;
}
unsigned int MEQCD2to2::orderInAlphaEW() const {
return 0;
}
ClassDescription<MEQCD2to2> MEQCD2to2::initMEQCD2to2;
// Definition of the static class description member.
void MEQCD2to2::Init() {
static ClassDocumentation<MEQCD2to2> documentation
("The MEQCD2to2 class implements the QCD 2->2 processes in hadron-hadron"
" collisions");
static Parameter<MEQCD2to2,unsigned int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour of the quarks in the process",
&MEQCD2to2::_maxflavour, 5, 1, 5,
false, false, Interface::limited);
static Switch<MEQCD2to2,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEQCD2to2::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
0);
static SwitchOption interfaceProcess1
(interfaceProcess,
"gg2gg",
"Include only gg->gg subprocesses",
1);
static SwitchOption interfaceProcess2
(interfaceProcess,
"gg2qqbar",
"Include only gg -> q qbar processes",
2);
static SwitchOption interfaceProcessqqbargg
(interfaceProcess,
"qqbar2gg",
"Include only q qbar -> gg processes",
3);
static SwitchOption interfaceProcessqgqg
(interfaceProcess,
"qg2qg",
"Include only q g -> q g processes",
4);
static SwitchOption interfaceProcessqbargqbarg
(interfaceProcess,
"qbarg2qbarg",
"Include only qbar g -> qbar g processes",
5);
static SwitchOption interfaceProcessqqqq
(interfaceProcess,
"qq2qq",
"Include only q q -> q q processes",
6);
static SwitchOption interfaceProcessqbarqbarqbarqbar
(interfaceProcess,
"qbarqbar2qbarqbar",
"Include only qbar qbar -> qbar qbar processes",
7);
static SwitchOption interfaceProcessqqbarqqbar
(interfaceProcess,
"qqbar2qqbar",
"Include only q qbar -> q qbar processes",
8);
}
Selector<MEBase::DiagramIndex>
MEQCD2to2::diagrams(const DiagramVector & diags) const {
// select the diagram, this is easy for us as we have already done it
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if(diags[i]->id()==-int(_diagram)) sel.insert(1.0, i);
else sel.insert(0., i);
}
return sel;
}
double MEQCD2to2::gg2qqbarME(vector<VectorWaveFunction> &g1,
vector<VectorWaveFunction> &g2,
vector<SpinorBarWaveFunction> & q,
vector<SpinorWaveFunction> & qbar,
unsigned int iflow) const {
// scale
Energy2 mt(scale());
// matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1,
PDT::Spin1Half,PDT::Spin1Half));
// calculate the matrix element
double output(0.),sumdiag[3]={0.,0.,0.},sumflow[2]={0.,0.};
Complex diag[3],flow[2];
VectorWaveFunction interv;
SpinorWaveFunction inters;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
interv=_gggvertex->evaluate(mt,5,_gluon,g1[ihel1],g2[ihel2]);
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
//first t-channel diagram
inters =_qqgvertex->evaluate(mt,5,qbar[ohel2].getParticle(),
qbar[ohel2],g2[ihel2]);
diag[0]=_qqgvertex->evaluate(mt,inters,q[ohel1],g1[ihel1]);
//second t-channel diagram
inters =_qqgvertex->evaluate(mt,5,qbar[ohel2].getParticle(),
qbar[ohel2],g1[ihel1]);
diag[1]=_qqgvertex->evaluate(mt,inters,q[ohel1],g2[ihel2]);
// s-channel diagram
diag[2]=_qqgvertex->evaluate(mt,qbar[ohel2],q[ohel1],interv);
// colour flows
flow[0]=diag[0]+diag[2];
flow[1]=diag[1]-diag[2];
// sums
for(unsigned int ix=0;ix<3;++ix) sumdiag[ix] += norm(diag[ix]);
for(unsigned int ix=0;ix<2;++ix) sumflow[ix] += norm(flow[ix]);
// total
output +=real(flow[0]*conj(flow[0])+flow[1]*conj(flow[1])
-0.25*flow[0]*conj(flow[1]));
// store the me if needed
if(iflow!=0) _me(2*ihel1,2*ihel2,ohel1,ohel2)=flow[iflow-1];
}
}
}
}
// test code vs me from ESW
//Energy2 u(uHat()),t(tHat()),s(sHat());
//double alphas(4.*pi*SM().alphaS(mt));
//cerr << "testing matrix element "
// << 48.*(1./6./u/t-3./8./s/s)*(t*t+u*u)*sqr(alphas)/output << endl;
// select a colour flow
_flow=1+UseRandom::rnd2(sumflow[0],sumflow[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=4+UseRandom::rnd3(sumdiag[0],sumdiag[1],sumdiag[2]);
// final part of colour and spin factors
return output/48.;
}
double MEQCD2to2::qqbar2ggME(vector<SpinorWaveFunction> & q,
vector<SpinorBarWaveFunction> & qbar,
vector<VectorWaveFunction> &g1,
vector<VectorWaveFunction> &g2,
unsigned int iflow) const {
// scale
Energy2 mt(scale());
// matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1));
// calculate the matrix element
double output(0.),sumdiag[3]={0.,0.,0.},sumflow[2]={0.,0.};
Complex diag[3],flow[2];
VectorWaveFunction interv;
SpinorWaveFunction inters;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
interv=_qqgvertex->evaluate(mt,5,_gluon,q[ihel1],qbar[ihel2]);
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
// first t-channel diagram
inters=_qqgvertex->evaluate(mt,5,q[ihel1].getParticle(),
q[ihel1],g1[ohel1]);
diag[0]=_qqgvertex->evaluate(mt,inters,qbar[ihel2],g2[ohel2]);
// second t-channel diagram
inters=_qqgvertex->evaluate(mt,5,q[ihel1].getParticle(),
q[ihel1],g2[ohel2]);
diag[1]=_qqgvertex->evaluate(mt,inters,qbar[ihel2],g1[ohel1]);
// s-channel diagram
diag[2]=_gggvertex->evaluate(mt,g1[ohel1],g2[ohel2],interv);
// colour flows
flow[0]=diag[0]-diag[2];
flow[1]=diag[1]+diag[2];
// sums
for(unsigned int ix=0;ix<3;++ix) sumdiag[ix] += norm(diag[ix]);
for(unsigned int ix=0;ix<2;++ix) sumflow[ix] += norm(flow[ix]);
// total
output +=real(flow[0]*conj(flow[0])+flow[1]*conj(flow[1])
-0.25*flow[0]*conj(flow[1]));
// store the me if needed
if(iflow!=0) _me(ihel1,ihel2,2*ohel1,2*ohel2)=flow[iflow-1];
}
}
}
}
// test code vs me from ESW
//Energy2 u(uHat()),t(tHat()),s(sHat());
//double alphas(4.*pi*SM().alphaS(mt));
//cerr << "testing matrix element "
// << 27./2.*0.5*(32./27./u/t-8./3./s/s)*(t*t+u*u)*sqr(alphas)/output << endl;
//select a colour flow
_flow=1+UseRandom::rnd2(sumflow[0],sumflow[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=7+UseRandom::rnd3(sumdiag[0],sumdiag[1],sumdiag[2]);
// final part of colour and spin factors
return 2.*output/27.;
}
double MEQCD2to2::qg2qgME(vector<SpinorWaveFunction> & qin,
vector<VectorWaveFunction> &g2,
vector<SpinorBarWaveFunction> & qout,
vector<VectorWaveFunction> &g4,
unsigned int iflow) const {
// scale
Energy2 mt(scale());
// matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1Half,PDT::Spin1));
// calculate the matrix element
double output(0.),sumdiag[3]={0.,0.,0.},sumflow[2]={0.,0.};
Complex diag[3],flow[2];
VectorWaveFunction interv;
SpinorWaveFunction inters,inters2;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
inters=_qqgvertex->evaluate(mt,5,qin[ihel1].getParticle(),
qin[ihel1],g2[ihel2]);
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
// s-channel diagram
diag[0]=_qqgvertex->evaluate(mt,inters,qout[ohel1],g4[ohel2]);
// first t-channel
inters2=_qqgvertex->evaluate(mt,5,qin[ihel1].getParticle(),
qin[ihel1],g4[ohel2]);
diag[1]=_qqgvertex->evaluate(mt,inters2,qout[ohel1],g2[ihel2]);
// second t-channel
interv=_qqgvertex->evaluate(mt,5,_gluon,qin[ihel1],qout[ohel1]);
diag[2]=_gggvertex->evaluate(mt,g2[ihel2],g4[ohel2],interv);
// colour flows
flow[0]=diag[0]-diag[2];
flow[1]=diag[1]+diag[2];
// sums
for(unsigned int ix=0;ix<3;++ix) sumdiag[ix] += norm(diag[ix]);
for(unsigned int ix=0;ix<2;++ix) sumflow[ix] += norm(flow[ix]);
// total
output +=real(flow[0]*conj(flow[0])+flow[1]*conj(flow[1])
-0.25*flow[0]*conj(flow[1]));
// store the me if needed
if(iflow!=0) _me(ihel1,2*ihel2,ohel1,2*ohel2)=flow[iflow-1];
}
}
}
}
// test code vs me from ESW
//Energy2 u(uHat()),t(tHat()),s(sHat());
//double alphas(4.*pi*SM().alphaS(mt));
//cerr << "testing matrix element "
// << 18./output*(-4./9./s/u+1./t/t)*(s*s+u*u)*sqr(alphas) << endl;
//select a colour flow
_flow=1+UseRandom::rnd2(sumflow[0],sumflow[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=10+UseRandom::rnd3(sumdiag[0],sumdiag[1],sumdiag[2]);
// final part of colour and spin factors
return output/18.;
}
double MEQCD2to2::gg2ggME(vector<VectorWaveFunction> &g1,vector<VectorWaveFunction> &g2,
vector<VectorWaveFunction> &g3,vector<VectorWaveFunction> &g4,
unsigned int iflow) const {
// colour factors for different flows
static const double c1 = 4.*( sqr(9.)/8.-3.*9./8.+1.-0.75/9.);
static const double c2 = 4.*(-0.25*9. +1.-0.75/9.);
// scale
Energy2 mt(scale());
// // matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1,
PDT::Spin1,PDT::Spin1));
// calculate the matrix element
double output(0.),sumdiag[3]={0.,0.,0.},sumflow[3]={0.,0.,0.};
Complex diag[3],flow[3];
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
// s-channel diagram
diag[0]=_ggggvertex->evaluate(mt,1,g3[ohel1],g1[ihel1],
g4[ohel2],g2[ihel2]);
// t-channel
diag[1]=_ggggvertex->evaluate(mt,1,g1[ihel1],g2[ihel2],
g3[ohel1],g4[ohel2]);
// u-channel
diag[2]=_ggggvertex->evaluate(mt,1,g2[ihel2],g1[ihel1],
g3[ohel1],g4[ohel2]);
// colour flows
flow[0] = diag[0]-diag[2];
flow[1] = -diag[0]-diag[1];
flow[2] = diag[1]+diag[2];
// sums
for(unsigned int ix=0;ix<3;++ix) {
sumdiag[ix] += norm(diag[ix]);
sumflow[ix] += norm(flow[ix]);
}
// total
output += c1*(norm(flow[0])+norm(flow[1])+norm(flow[2]))
+2.*c2*real(flow[0]*conj(flow[1])+flow[0]*conj(flow[2])+
flow[1]*conj(flow[2]));
// store the me if needed
if(iflow!=0) _me(2*ihel1,2*ihel2,2*ohel1,2*ohel2)=flow[iflow-1];
}
}
}
}
// spin, colour and identical particle factorsxs
output /= 4.*64.*2.;
// test code vs me from ESW
// Energy2 u(uHat()),t(tHat()),s(sHat());
// using Constants::pi;
// double alphas(4.*pi*SM().alphaS(mt));
// cerr << "testing matrix element "
// << 1./output*9./4.*(3.-t*u/s/s-s*u/t/t-s*t/u/u)*sqr(alphas) << endl;
// select a colour flow
_flow=1+UseRandom::rnd3(sumflow[0],sumflow[1],sumflow[2]);
// and diagram
if(_flow==1) _diagram = 1+2*UseRandom::rnd2(sumdiag[0],sumdiag[2]);
else if(_flow==2) _diagram = 1+ UseRandom::rnd2(sumdiag[0],sumdiag[1]);
else if(_flow==3) _diagram = 2+ UseRandom::rnd2(sumdiag[1],sumdiag[2]);
// final part of colour and spin factors
return output;
}
double MEQCD2to2::qbarg2qbargME(vector<SpinorBarWaveFunction> & qin,
vector<VectorWaveFunction> &g2,
vector<SpinorWaveFunction> & qout,
vector<VectorWaveFunction> &g4,
unsigned int iflow) const {
// scale
Energy2 mt(scale());
// matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1Half,PDT::Spin1));
// calculate the matrix element
double output(0.),sumdiag[3]={0.,0.,0.},sumflow[2]={0.,0.};
Complex diag[3],flow[2];
VectorWaveFunction interv;
SpinorBarWaveFunction inters,inters2;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
inters=_qqgvertex->evaluate(mt,5,qin[ihel1].getParticle(),
qin[ihel1],g2[ihel2]);
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
// s-channel diagram
diag[0]=_qqgvertex->evaluate(mt,qout[ohel1],inters,g4[ohel2]);
// first t-channel
inters2=_qqgvertex->evaluate(mt,5,qin[ihel1].getParticle(),
qin[ihel1],g4[ohel2]);
diag[1]=_qqgvertex->evaluate(mt,qout[ohel1],inters2,g2[ihel2]);
// second t-channel
interv=_qqgvertex->evaluate(mt,5,_gluon,qout[ohel1],qin[ihel1]);
diag[2]=_gggvertex->evaluate(mt,g2[ihel2],g4[ohel2],interv);
// colour flows
flow[0]=diag[0]+diag[2];
flow[1]=diag[1]-diag[2];
// sums
for(unsigned int ix=0;ix<3;++ix) sumdiag[ix] += norm(diag[ix]);
for(unsigned int ix=0;ix<2;++ix) sumflow[ix] += norm(flow[ix]);
// total
output +=real(flow[0]*conj(flow[0])+flow[1]*conj(flow[1])
-0.25*flow[0]*conj(flow[1]));
// store the me if needed
if(iflow!=0) _me(ihel1,2*ihel2,ohel1,2*ohel2)=flow[iflow-1];
}
}
}
}
// test code vs me from ESW
//Energy2 u(uHat()),t(tHat()),s(sHat());
//double alphas(4.*pi*SM().alphaS(mt));
//cerr << "testing matrix element "
// << 18./output*(-4./9./s/u+1./t/t)*(s*s+u*u)*sqr(alphas) << endl;
//select a colour flow
_flow=1+UseRandom::rnd2(sumflow[0],sumflow[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=13+UseRandom::rnd3(sumdiag[0],sumdiag[1],sumdiag[2]);
// final part of colour and spin factors
return output/18.;
}
double MEQCD2to2::qq2qqME(vector<SpinorWaveFunction> & q1,
vector<SpinorWaveFunction> & q2,
vector<SpinorBarWaveFunction> & q3,
vector<SpinorBarWaveFunction> & q4,
unsigned int iflow) const {
// identify special case of identical quarks
bool identical(q1[0].id()==q2[0].id());
// scale
Energy2 mt(scale());
// matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half));
// calculate the matrix element
double output(0.),sumdiag[2]={0.,0.};
Complex diag[2];
VectorWaveFunction interv;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
// first diagram
interv = _qqgvertex->evaluate(mt,5,_gluon,q1[ihel1],q3[ohel1]);
diag[0] = _qqgvertex->evaluate(mt,q2[ihel2],q4[ohel2],interv);
// second diagram if identical
if(identical) {
interv = _qqgvertex->evaluate(mt,5,_gluon,q1[ihel1],q4[ohel2]);
diag[1]=_qqgvertex->evaluate(mt,q2[ihel2],q3[ohel1],interv);
}
else diag[1]=0.;
// sum of diagrams
for(unsigned int ix=0;ix<2;++ix) sumdiag[ix] += norm(diag[ix]);
// total
output +=real(diag[0]*conj(diag[0])+diag[1]*conj(diag[1])
+2./3.*diag[0]*conj(diag[1]));
// store the me if needed
if(iflow!=0) _me(ihel1,ihel2,ohel1,ohel2)=diag[iflow-1];
}
}
}
}
// identical particle symmetry factor if needed
if(identical) output*=0.5;
// test code vs me from ESW
//Energy2 u(uHat()),t(tHat()),s(sHat());
//double alphas(4.*pi*SM().alphaS(mt));
//if(identical)
// {cerr << "testing matrix element A "
// << 18./output*0.5*(4./9.*((s*s+u*u)/t/t+(s*s+t*t)/u/u)
// -8./27.*s*s/u/t)*sqr(alphas) << endl;}
//else
// {cerr << "testing matrix element B "
// << 18./output*(4./9.*(s*s+u*u)/t/t)*sqr(alphas) << endl;}
//select a colour flow
_flow=1+UseRandom::rnd2(sumdiag[0],sumdiag[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=16+UseRandom::rnd2(sumdiag[0],sumdiag[1]);
// final part of colour and spin factors
return output/18.;
}
double MEQCD2to2::qbarqbar2qbarqbarME(vector<SpinorBarWaveFunction> & q1,
vector<SpinorBarWaveFunction> & q2,
vector<SpinorWaveFunction> & q3,
vector<SpinorWaveFunction> & q4,
unsigned int iflow) const {
// identify special case of identical quarks
bool identical(q1[0].id()==q2[0].id());
// scale
Energy2 mt(scale());
// matrix element to be stored
if(iflow!=0)
{_me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half));}
// calculate the matrix element
double output(0.),sumdiag[2]={0.,0.};
Complex diag[2];
VectorWaveFunction interv;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
// first diagram
interv = _qqgvertex->evaluate(mt,5,_gluon,q3[ohel1],q1[ihel1]);
diag[0] = _qqgvertex->evaluate(mt,q4[ohel2],q2[ihel2],interv);
// second diagram if identical
if(identical) {
interv = _qqgvertex->evaluate(mt,5,_gluon,q4[ohel2],q1[ihel1]);
diag[1]=_qqgvertex->evaluate(mt,q3[ohel1],q2[ihel2],interv);
}
else diag[1]=0.;
// sum of diagrams
for(unsigned int ix=0;ix<2;++ix) sumdiag[ix] += norm(diag[ix]);
// total
output +=real(diag[0]*conj(diag[0])+diag[1]*conj(diag[1])
+2./3.*diag[0]*conj(diag[1]));
// store the me if needed
if(iflow!=0) _me(ihel1,ihel2,ohel1,ohel2)=diag[iflow-1];
}
}
}
}
// identical particle symmetry factor if needed
if(identical){output*=0.5;}
// test code vs me from ESW
// Energy2 u(uHat()),t(tHat()),s(sHat());
// double alphas(4.*pi*SM().alphaS(mt));
// if(identical)
// {cerr << "testing matrix element A "
// << 18./output*0.5*(4./9.*((s*s+u*u)/t/t+(s*s+t*t)/u/u)
// -8./27.*s*s/u/t)*sqr(alphas) << endl;}
// else
// {cerr << "testing matrix element B "
// << 18./output*(4./9.*(s*s+u*u)/t/t)*sqr(alphas) << endl;}
//select a colour flow
_flow=1+UseRandom::rnd2(sumdiag[0],sumdiag[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=18+UseRandom::rnd2(sumdiag[0],sumdiag[1]);
// final part of colour and spin factors
return output/18.;
}
double MEQCD2to2::qqbar2qqbarME(vector<SpinorWaveFunction> & q1,
vector<SpinorBarWaveFunction> & q2,
vector<SpinorBarWaveFunction> & q3,
vector<SpinorWaveFunction> & q4,
unsigned int iflow) const {
// type of process
bool diagon[2]={q1[0].id()== -q2[0].id(),q1[0].id()== q3[0].id()};
// scale
Energy2 mt(scale());
// matrix element to be stored
if(iflow!=0) _me.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half));
// calculate the matrix element
double output(0.),sumdiag[2]={0.,0.};
Complex diag[2];
VectorWaveFunction interv;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
// first diagram
if(diagon[0]) {
interv = _qqgvertex->evaluate(mt,5,_gluon,q1[ihel1],q2[ihel2]);
diag[0] = _qqgvertex->evaluate(mt,q4[ohel2],q3[ohel1],interv);
}
else diag[0]=0.;
// second diagram
if(diagon[1]) {
interv = _qqgvertex->evaluate(mt,5,_gluon,q1[ihel1],q3[ohel1]);
diag[1]=_qqgvertex->evaluate(mt,q4[ohel2],q2[ihel2],interv);
}
else diag[1]=0.;
// sum of diagrams
for(unsigned int ix=0;ix<2;++ix) sumdiag[ix] += norm(diag[ix]);
// total
output +=real(diag[0]*conj(diag[0])+diag[1]*conj(diag[1])
+2./3.*diag[0]*conj(diag[1]));
// store the me if needed
if(iflow!=0){_me(ihel1,ihel2,ohel1,ohel2)=diag[iflow-1];}
}
}
}
}
// test code vs me from ESW
// Energy2 u(uHat()),t(tHat()),s(sHat());
// double alphas(4.*pi*SM().alphaS(mt));
// if(diagon[0]&&diagon[1]) {
// cerr << "testing matrix element A "
// << q1[0].id() << " " << q2[0].id() << " -> "
// << q3[0].id() << " " << q4[0].id() << " "
// << 18./output*0.5*(4./9.*((s*s+u*u)/t/t+(u*u+t*t)/s/s)
// -8./27.*u*u/s/t)*sqr(alphas) << endl;
// }
// else if(diagon[0]) {
// cerr << "testing matrix element B "
// << q1[0].id() << " " << q2[0].id() << " -> "
// << q3[0].id() << " " << q4[0].id() << " "
// << 18./output*(4./9.*(t*t+u*u)/s/s)*sqr(alphas) << endl;
// }
// else if(diagon[1]) {
// cerr << "testing matrix element C "
// << q1[0].id() << " " << q2[0].id() << " -> "
// << q3[0].id() << " " << q4[0].id() << " "
// << 18./output*(4./9.*(s*s+u*u)/t/t)*sqr(alphas) << endl;
// }
//select a colour flow
_flow=1+UseRandom::rnd2(sumdiag[0],sumdiag[1]);
// select a diagram ensuring it is one of those in the selected colour flow
sumdiag[_flow%2]=0.;
_diagram=20+UseRandom::rnd2(sumdiag[0],sumdiag[1]);
// final part of colour and spin factors
return output/18.;
}
void MEQCD2to2::getDiagrams() const {
// gg-> gg subprocess
if(_process==0||_process==1) {
// s-channel
add(new_ptr((Tree2toNDiagram(2),_gluon,_gluon, 1, _gluon,
3,_gluon, 3, _gluon, -1)));
// first t-channel
add(new_ptr((Tree2toNDiagram(3),_gluon,_gluon,_gluon,
1,_gluon, 2,_gluon,-2)));
// second t-channel
add(new_ptr((Tree2toNDiagram(3),_gluon,_gluon,_gluon,
2,_gluon, 1,_gluon,-3)));
}
// processes involving one quark line
for(unsigned int ix=0;ix<_maxflavour;++ix) {
// gg -> q qbar subprocesses
if(_process==0||_process==2) {
// first t-channel
add(new_ptr((Tree2toNDiagram(3),_gluon,_antiquark[ix],_gluon,
1,_quark[ix], 2,_antiquark[ix],-4)));
// interchange
add(new_ptr((Tree2toNDiagram(3),_gluon,_antiquark[ix],_gluon,
2,_quark[ix], 1,_antiquark[ix],-5)));
// s-channel
add(new_ptr((Tree2toNDiagram(2),_gluon,_gluon, 1, _gluon,
3,_quark[ix], 3, _antiquark[ix], -6)));
}
// q qbar -> g g subprocesses
if(_process==0||_process==3) {
// first t-channel
add(new_ptr((Tree2toNDiagram(3),_quark[ix],_antiquark[ix],_antiquark[ix],
1,_gluon, 2,_gluon,-7)));
// second t-channel
add(new_ptr((Tree2toNDiagram(3),_quark[ix],_antiquark[ix],_antiquark[ix],
2,_gluon, 1,_gluon,-8)));
// s-channel
add(new_ptr((Tree2toNDiagram(2),_quark[ix], _antiquark[ix],
1, _gluon, 3, _gluon, 3, _gluon,-9)));
}
// q g -> q g subprocesses
if(_process==0||_process==4) {
// s-channel
add(new_ptr((Tree2toNDiagram(2),_quark[ix], _gluon,
1, _quark[ix], 3, _quark[ix], 3, _gluon,-10)));
// quark t-channel
add(new_ptr((Tree2toNDiagram(3),_quark[ix],_quark[ix],_gluon,
2,_quark[ix],1,_gluon,-11)));
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),_quark[ix],_gluon,_gluon,
1,_quark[ix],2,_gluon,-12)));
}
// qbar g -> qbar g subprocesses
if(_process==0||_process==5) {
// s-channel
add(new_ptr((Tree2toNDiagram(2),_antiquark[ix], _gluon,
1, _antiquark[ix], 3, _antiquark[ix], 3, _gluon,-13)));
// quark t-channel
add(new_ptr((Tree2toNDiagram(3),_antiquark[ix],_antiquark[ix],_gluon,
2,_antiquark[ix],1,_gluon,-14)));
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),_antiquark[ix],_gluon,_gluon,
1,_antiquark[ix],2,_gluon,-15)));
}
// processes involving two quark lines
for(unsigned int iy=0;iy<_maxflavour;++iy) {
// q q -> q q subprocesses
if(_process==0||_process==6) {
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),_quark[ix],_gluon,_quark[iy],
1,_quark[ix],2,_quark[iy],-16)));
// exchange for identical quarks
if(ix==iy)
add(new_ptr((Tree2toNDiagram(3),_quark[ix],_gluon,_quark[iy],
2,_quark[ix],1,_quark[iy],-17)));
}
// qbar qbar -> qbar qbar subprocesses
if(_process==0||_process==7) {
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),_antiquark[ix],_gluon,_antiquark[iy],
1,_antiquark[ix],2,_antiquark[iy],-18)));
// exchange for identical quarks
if(ix==iy)
add(new_ptr((Tree2toNDiagram(3),_antiquark[ix],_gluon,_antiquark[iy],
2,_antiquark[ix],1,_antiquark[iy],-19)));
}
// q qbar -> q qbar
if(_process==0||_process==8) {
// gluon s-channel
add(new_ptr((Tree2toNDiagram(2),_quark[ix], _antiquark[ix],
1, _gluon, 3, _quark[iy], 3, _antiquark[iy],-20)));
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),_quark[ix],_gluon,_antiquark[iy],
1,_quark[ix],2,_antiquark[iy],-21)));
}
}
}
}
Selector<const ColourLines *>
MEQCD2to2::colourGeometries(tcDiagPtr diag) const {
// colour lines for gg to gg
static const ColourLines cgggg[12]={ColourLines("1 -2, -1 -3 -5, 5 -4, 2 3 4"),// A_2 s
ColourLines("-1 2, 1 3 5, -5 4, -2 -3 -4"),// A_1 s
ColourLines("1 5, -1 -2 3, -3 -4, -5 2 4"),// A_1 u
ColourLines("-1 -5, 1 2 -3, 3 4, 5 -2 -4"),// A_2 u
ColourLines("1 -2, -1 -3 -4, 4 -5, 2 3 5"),// B_2 s
ColourLines("-1 2, 1 3 4, -4 5, -2 -3 -5"),// B_1 s
ColourLines("1 4, -1 -2 3, -3 -5, -4 2 5"),// B_1 t
ColourLines("-1 -4, 1 2 -3, 3 5, 4 -2 -5"),// B_2 t
ColourLines("1 4, -1 -2 -5, 3 5, -3 2 -4"),// C_1 t
ColourLines("-1 -4, 1 2 5, -3 -5, 3 -2 4"),// C_2 t
ColourLines("1 5, -1 -2 -4, 3 4, -3 2 -5"),// C_1 u
ColourLines("-1 -5, 1 2 4, -3 -4, 3 -2 5") // C_2 u
};
// colour lines for gg to q qbar
static const ColourLines cggqq[4]={ColourLines("1 4, -1 -2 3, -3 -5"),
ColourLines("3 4, -3 -2 1, -1 -5"),
ColourLines("2 -1, 1 3 4, -2 -3 -5"),
ColourLines("1 -2, -1 -3 -5, 2 3 4")};
// colour lines for q qbar to gg
static const ColourLines cqqgg[4]={ColourLines("1 4, -4 -2 5, -3 -5"),
ColourLines("1 5, -3 -4, 4 -2 -5"),
ColourLines("1 3 4, -4 5, -2 -3 -5"),
ColourLines("1 3 5, -5 4, -2 -3 -4")};
// colour lines for q g to q g
static const ColourLines cqgqg[4]={ColourLines("1 -2, 2 3 5, 4 -5"),
ColourLines("1 5, 3 4,-3 2 -5 "),
ColourLines("1 2 -3, 3 5, -5 -2 4"),
ColourLines("1 -2 5,3 2 4,-3 -5")};
// colour lines for qbar g -> qbar g
static const ColourLines cqbgqbg[4]={ColourLines("-1 2, -2 -3 -5, -4 5"),
ColourLines("-1 -5, -3 -4, 3 -2 5"),
ColourLines("-1 -2 3, -3 -5, 5 2 -4"),
ColourLines("-1 2 -5,-3 -2 -4, 3 5")};
// colour lines for q q -> q q
static const ColourLines cqqqq[2]={ColourLines("1 2 5,3 -2 4"),
ColourLines("1 2 4,3 -2 5")};
// colour lines for qbar qbar -> qbar qbar
static const ColourLines cqbqbqbqb[2]={ColourLines("-1 -2 -5,-3 2 -4"),
ColourLines("-1 -2 -4,-3 2 -5")};
// colour lines for q qbar -> q qbar
static const ColourLines cqqbqqb[2]={ColourLines("1 3 4,-2 -3 -5"),
ColourLines("1 2 -3,4 -2 -5")};
// select the colour flow (as all ready picked just insert answer)
Selector<const ColourLines *> sel;
switch(abs(diag->id())) {
// gg -> gg subprocess
case 1:
if(_flow==1) {
sel.insert(0.5, &cgggg[0]);
sel.insert(0.5, &cgggg[1]);
}
else {
sel.insert(0.5, &cgggg[4]);
sel.insert(0.5, &cgggg[5]);
}
break;
case 2:
if(_flow==2) {
sel.insert(0.5, &cgggg[6]);
sel.insert(0.5, &cgggg[7]);
}
else {
sel.insert(0.5, &cgggg[8]);
sel.insert(0.5, &cgggg[9]);
}
break;
case 3:
if(_flow==1) {
sel.insert(0.5, &cgggg[2]);
sel.insert(0.5, &cgggg[3]);
}
else {
sel.insert(0.5, &cgggg[10]);
sel.insert(0.5, &cgggg[11]);
}
break;
// gg -> q qbar subprocess
case 4: case 5:
sel.insert(1.0, &cggqq[abs(diag->id())-4]);
break;
case 6:
sel.insert(1.0, &cggqq[1+_flow]);
break;
// q qbar -> gg subprocess
case 7: case 8:
sel.insert(1.0, &cqqgg[abs(diag->id())-7]);
break;
case 9:
sel.insert(1.0, &cqqgg[1+_flow]);
break;
// q g -> q g subprocess
case 10: case 11:
sel.insert(1.0, &cqgqg[abs(diag->id())-10]);
break;
case 12:
sel.insert(1.0, &cqgqg[1+_flow]);
break;
// q g -> q g subprocess
case 13: case 14:
sel.insert(1.0, &cqbgqbg[abs(diag->id())-13]);
break;
case 15:
sel.insert(1.0, &cqbgqbg[1+_flow]);
break;
// q q -> q q subprocess
case 16: case 17:
sel.insert(1.0, &cqqqq[abs(diag->id())-16]);
break;
// qbar qbar -> qbar qbar subprocess
case 18: case 19:
sel.insert(1.0, &cqbqbqbqb[abs(diag->id())-18]);
break;
// q qbar -> q qbar subprocess
case 20: case 21:
sel.insert(1.0, &cqqbqqb[abs(diag->id())-20]);
break;
}
return sel;
}
double MEQCD2to2::me2() const {
// total matrix element
double me(0.);
// gg initiated processes
if(mePartonData()[0]->id()==ParticleID::g&&mePartonData()[1]->id()==ParticleID::g) {
// gg -> gg
if(mePartonData()[2]->id()==ParticleID::g) {
VectorWaveFunction g1w(meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction g2w(meMomenta()[1],mePartonData()[1],incoming);
VectorWaveFunction g3w(meMomenta()[2],mePartonData()[2],outgoing);
VectorWaveFunction g4w(meMomenta()[3],mePartonData()[3],outgoing);
vector<VectorWaveFunction> g1,g2,g3,g4;
for(unsigned int ix=0;ix<2;++ix) {
g1w.reset(2*ix);g1.push_back(g1w);
g2w.reset(2*ix);g2.push_back(g2w);
g3w.reset(2*ix);g3.push_back(g3w);
g4w.reset(2*ix);g4.push_back(g4w);
}
// calculate the matrix element
me = gg2ggME(g1,g2,g3,g4,0);
}
// gg -> q qbar
else {
VectorWaveFunction g1w(meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction g2w(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction qw(meMomenta()[2],mePartonData()[2],outgoing);
SpinorWaveFunction qbarw(meMomenta()[3],mePartonData()[3],outgoing);
vector<VectorWaveFunction> g1,g2;
vector<SpinorBarWaveFunction> q;
vector<SpinorWaveFunction> qbar;
for(unsigned int ix=0;ix<2;++ix) {
g1w.reset(2*ix);g1.push_back(g1w);
g2w.reset(2*ix);g2.push_back(g2w);
qw.reset(ix);q.push_back(qw);
qbarw.reset(ix);qbar.push_back(qbarw);
}
// calculate the matrix element
me=gg2qqbarME(g1,g2,q,qbar,0);
}
}
// quark first processes
else if(mePartonData()[0]->id()>0) {
// q g -> q g
if(mePartonData()[1]->id()==ParticleID::g) {
SpinorWaveFunction qinw(meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction g2w(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction qoutw(meMomenta()[2],mePartonData()[2],outgoing);
VectorWaveFunction g4w(meMomenta()[3],mePartonData()[3],outgoing);
vector<VectorWaveFunction> g2,g4;
vector<SpinorWaveFunction> qin;
vector<SpinorBarWaveFunction> qout;
for(unsigned int ix=0;ix<2;++ix) {
qinw.reset(ix);qin.push_back(qinw);
g2w.reset(2*ix);g2.push_back(g2w);
qoutw.reset(ix);qout.push_back(qoutw);
g4w.reset(2*ix);g4.push_back(g4w);
}
// calculate the matrix element
me = qg2qgME(qin,g2,qout,g4,0);
}
else if(mePartonData()[1]->id()<0) {
// q qbar initiated processes( q qbar -> gg)
if(mePartonData()[2]->id()==ParticleID::g) {
SpinorWaveFunction qw(meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction qbarw(meMomenta()[1],mePartonData()[1],incoming);
VectorWaveFunction g1w(meMomenta()[2],mePartonData()[2],outgoing);
VectorWaveFunction g2w(meMomenta()[3],mePartonData()[3],outgoing);
vector<VectorWaveFunction> g1,g2;
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qbar;
for(unsigned int ix=0;ix<2;++ix) {
qw.reset(ix);q.push_back(qw);
qbarw.reset(ix);qbar.push_back(qbarw);
g1w.reset(2*ix);g1.push_back(g1w);
g2w.reset(2*ix);g2.push_back(g2w);
}
// calculate the matrix element
me = qqbar2ggME(q,qbar,g1,g2,0);
}
// q qbar to q qbar
else {
SpinorWaveFunction q1w(meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction q2w(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction q3w(meMomenta()[2],mePartonData()[2],outgoing);
SpinorWaveFunction q4w(meMomenta()[3],mePartonData()[3],outgoing);
vector<SpinorWaveFunction> q1,q4;
vector<SpinorBarWaveFunction> q2,q3;
for(unsigned int ix=0;ix<2;++ix) {
q1w.reset(ix);q1.push_back(q1w);
q2w.reset(ix);q2.push_back(q2w);
q3w.reset(ix);q3.push_back(q3w);
q4w.reset(ix);q4.push_back(q4w);
}
// calculate the matrix element
me = qqbar2qqbarME(q1,q2,q3,q4,0);
}
}
// q q -> q q
else if(mePartonData()[1]->id()>0) {
SpinorWaveFunction q1w(meMomenta()[0],mePartonData()[0],incoming);
SpinorWaveFunction q2w(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction q3w(meMomenta()[2],mePartonData()[2],outgoing);
SpinorBarWaveFunction q4w(meMomenta()[3],mePartonData()[3],outgoing);
vector<SpinorWaveFunction> q1,q2;
vector<SpinorBarWaveFunction> q3,q4;
for(unsigned int ix=0;ix<2;++ix) {
q1w.reset(ix);q1.push_back(q1w);
q2w.reset(ix);q2.push_back(q2w);
q3w.reset(ix);q3.push_back(q3w);
q4w.reset(ix);q4.push_back(q4w);
}
// calculate the matrix element
me = qq2qqME(q1,q2,q3,q4,0);
}
}
// antiquark first processes
else if(mePartonData()[0]->id()<0) {
// qbar g -> qbar g
if(mePartonData()[1]->id()==ParticleID::g) {
SpinorBarWaveFunction qinw(meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction g2w(meMomenta()[1],mePartonData()[1],incoming);
SpinorWaveFunction qoutw(meMomenta()[2],mePartonData()[2],outgoing);
VectorWaveFunction g4w(meMomenta()[3],mePartonData()[3],outgoing);
vector<VectorWaveFunction> g2,g4;
vector<SpinorBarWaveFunction> qin;
vector<SpinorWaveFunction> qout;
for(unsigned int ix=0;ix<2;++ix) {
qinw.reset(ix);qin.push_back(qinw);
g2w.reset(2*ix);g2.push_back(g2w);
qoutw.reset(ix);qout.push_back(qoutw);
g4w.reset(2*ix);g4.push_back(g4w);
}
// calculate the matrix element
me = qbarg2qbargME(qin,g2,qout,g4,0);
}
// qbar qbar -> qbar qbar
else if(mePartonData()[1]->id()<0) {
SpinorBarWaveFunction q1w(meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction q2w(meMomenta()[1],mePartonData()[1],incoming);
SpinorWaveFunction q3w(meMomenta()[2],mePartonData()[2],outgoing);
SpinorWaveFunction q4w(meMomenta()[3],mePartonData()[3],outgoing);
vector<SpinorBarWaveFunction> q1,q2;
vector<SpinorWaveFunction> q3,q4;
for(unsigned int ix=0;ix<2;++ix) {
q1w.reset(ix);q1.push_back(q1w);
q2w.reset(ix);q2.push_back(q2w);
q3w.reset(ix);q3.push_back(q3w);
q4w.reset(ix);q4.push_back(q4w);
}
// calculate the matrix element
me = qbarqbar2qbarqbarME(q1,q2,q3,q4,0);
}
}
else throw Exception() << "Unknown process in MEQCD2to2::me2()"
<< Exception::abortnow;
// return the answer
return me;
}
void MEQCD2to2::constructVertex(tSubProPtr sub) {
SpinfoPtr spin[4];
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
// order of particles
unsigned int order[4]={0,1,2,3};
// identify the process and calculate the matrix element
if(hard[0]->id()==ParticleID::g&&hard[1]->id()==ParticleID::g) {
// gg -> gg
if(hard[2]->id()==ParticleID::g) {
vector<VectorWaveFunction> g1,g2,g3,g4;
VectorWaveFunction(g1,hard[0],incoming,false,true,true);
VectorWaveFunction(g2,hard[1],incoming,false,true,true);
VectorWaveFunction(g3,hard[2],outgoing,true ,true,true);
VectorWaveFunction(g4,hard[3],outgoing,true ,true,true);
g1[1]=g1[2];g2[1]=g2[2];g3[1]=g3[2];g4[1]=g4[2];
gg2ggME(g1,g2,g3,g4,_flow);
}
// gg -> q qbar
else {
if(hard[2]->id()<0) swap(order[2],order[3]);
vector<VectorWaveFunction> g1,g2;
vector<SpinorBarWaveFunction> q;
vector<SpinorWaveFunction> qbar;
VectorWaveFunction( g1,hard[ 0 ],incoming,false,true,true);
VectorWaveFunction( g2,hard[ 1 ],incoming,false,true,true);
SpinorBarWaveFunction(q ,hard[order[2]],outgoing,true ,true);
SpinorWaveFunction( qbar,hard[order[3]],outgoing,true ,true);
g1[1]=g1[2];g2[1]=g2[2];
gg2qqbarME(g1,g2,q,qbar,_flow);
}
}
else if(hard[0]->id()==ParticleID::g||hard[1]->id()==ParticleID::g) {
if(hard[0]->id()==ParticleID::g) swap(order[0],order[1]);
if(hard[2]->id()==ParticleID::g) swap(order[2],order[3]);
// q g -> q g
if(hard[order[0]]->id()>0) {
vector<VectorWaveFunction> g2,g4;
vector<SpinorWaveFunction> qin;
vector<SpinorBarWaveFunction> qout;
SpinorWaveFunction( qin,hard[order[0]],incoming,false,true);
VectorWaveFunction( g2,hard[order[1]],incoming,false,true,true);
SpinorBarWaveFunction(qout,hard[order[2]],outgoing,true ,true);
VectorWaveFunction( g4,hard[order[3]],outgoing,true ,true,true);
g2[1]=g2[2];g4[1]=g4[2];
qg2qgME(qin,g2,qout,g4,_flow);
}
// qbar g -> qbar g
else {
vector<VectorWaveFunction> g2,g4;
vector<SpinorBarWaveFunction> qin;
vector<SpinorWaveFunction> qout;
SpinorBarWaveFunction( qin,hard[order[0]],incoming,false,true);
VectorWaveFunction( g2,hard[order[1]],incoming,false,true,true);
SpinorWaveFunction( qout,hard[order[2]],outgoing,true ,true);
VectorWaveFunction( g4,hard[order[3]],outgoing,true ,true,true);
g2[1]=g2[2];g4[1]=g4[2];
qbarg2qbargME(qin,g2,qout,g4,_flow);
}
}
else if(hard[0]->id()>0||hard[1]->id()>0) {
if(hard[2]->id()==ParticleID::g) {
if(hard[0]->id()<0) swap(order[0],order[1]);
vector<SpinorBarWaveFunction> qbar;
vector<SpinorWaveFunction> q;
vector<VectorWaveFunction> g3,g4;
SpinorWaveFunction( q ,hard[order[0]],incoming,false,true);
SpinorBarWaveFunction(qbar,hard[order[1]],incoming,false,true);
VectorWaveFunction( g3,hard[ 2 ],outgoing,true ,true,true);
VectorWaveFunction( g4,hard[ 3 ],outgoing,true ,true,true);
g3[1]=g3[2];g4[1]=g4[2];
qqbar2ggME(q,qbar,g3,g4,_flow);
}
// q q -> q q
else if(hard[0]->id()>0&&hard[1]->id()>0) {
if(hard[2]->id()!=hard[0]->id()) swap(order[2],order[3]);
vector<SpinorWaveFunction> q1,q2;
vector<SpinorBarWaveFunction> q3,q4;
SpinorWaveFunction( q1,hard[order[0]],incoming,false,true);
SpinorWaveFunction( q2,hard[order[1]],incoming,false,true);
SpinorBarWaveFunction(q3,hard[order[2]],outgoing,true ,true);
SpinorBarWaveFunction(q4,hard[order[3]],outgoing,true ,true);
qq2qqME(q1,q2,q3,q4,_flow);
}
// q qbar -> q qbar
else {
if(hard[0]->id()<0) swap(order[0],order[1]);
if(hard[2]->id()<0) swap(order[2],order[3]);
vector<SpinorWaveFunction> q1,q4;
vector<SpinorBarWaveFunction> q2,q3;
SpinorWaveFunction( q1,hard[order[0]],incoming,false,true);
SpinorBarWaveFunction(q2,hard[order[1]],incoming,false,true);
SpinorBarWaveFunction(q3,hard[order[2]],outgoing,true ,true);
SpinorWaveFunction( q4,hard[order[3]],outgoing,true ,true);
qqbar2qqbarME(q1,q2,q3,q4,_flow);
}
}
else if (hard[0]->id()<0&&hard[1]->id()<0) {
if(hard[2]->id()!=hard[0]->id()) swap(order[2],order[3]);
vector<SpinorBarWaveFunction> q1,q2;
vector<SpinorWaveFunction> q3,q4;
SpinorBarWaveFunction(q1,hard[order[0]],incoming,false,true);
SpinorBarWaveFunction(q2,hard[order[1]],incoming,false,true);
SpinorWaveFunction( q3,hard[order[2]],outgoing,true ,true);
SpinorWaveFunction( q4,hard[order[3]],outgoing,true ,true);
qbarqbar2qbarqbarME(q1,q2,q3,q4,_flow);
}
else throw Exception() << "Unknown process in MEQCD2to2::constructVertex()"
<< Exception::runerror;
// get the spin info objects
for(unsigned int ix=0;ix<4;++ix)
spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[order[ix]]->spinInfo());
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) spin[ix]->setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/Hadron/MEQCD2to2.h b/MatrixElement/Hadron/MEQCD2to2.h
--- a/MatrixElement/Hadron/MEQCD2to2.h
+++ b/MatrixElement/Hadron/MEQCD2to2.h
@@ -1,404 +1,404 @@
// -*- C++ -*-
//
// MEQCD2to2.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_MEQCD2to2_H
#define HERWIG_MEQCD2to2_H
//
// This is the declaration of the MEQCD2to2 class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVVertex.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* Here is the documentation of the MEQCD2to2 class.
*
* @see \ref MEQCD2to2Interfaces "The interfaces"
* defined for MEQCD2to2.
*/
class MEQCD2to2: public HwME2to2Base {
public:
/**
* The default constructor.
*/
MEQCD2to2();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Members to calculate the matrix elements
*/
//@{
/**
* Matrix element for \f$gg\to gg\f$.
* @param g1 The wavefunctions for the first incoming gluon
* @param g2 The wavefunctions for the second incoming gluon
* @param g3 The wavefunctions for the first outgoing gluon
* @param g4 The wavefunctions for the second outgoing gluon
* @param flow The colour flow
*/
double gg2ggME(vector<VectorWaveFunction> &g1,vector<VectorWaveFunction> &g2,
vector<VectorWaveFunction> &g3,vector<VectorWaveFunction> &g4,
unsigned int flow) const;
/**
* Matrix element for \f$gg\to q\bar{q}\f$
* @param g1 The wavefunctions for the first incoming gluon
* @param g2 The wavefunctions for the second incoming gluon
* @param q The wavefunction for the outgoing quark
* @param qbar The wavefunction for the outgoing antiquark
* @param flow The colour flow
*/
double gg2qqbarME(vector<VectorWaveFunction> &g1,vector<VectorWaveFunction> &g2,
vector<SpinorBarWaveFunction> & q,vector<SpinorWaveFunction> & qbar,
unsigned int flow) const;
/**
* Matrix element for \f$q\bar{q}\to gg\f$
* @param q The wavefunction for the incoming quark
* @param qbar The wavefunction for the incoming antiquark
* @param g1 The wavefunctions for the first outgoing gluon
* @param g2 The wavefunctions for the second outgoing gluon
* @param flow The colour flow
*/
double qqbar2ggME(vector<SpinorWaveFunction> & q,vector<SpinorBarWaveFunction> & qbar,
vector<VectorWaveFunction> &g1,vector<VectorWaveFunction> &g2,
unsigned int flow) const;
/**
* Matrix element for \f$qg\to qg\f$
* @param qin The wavefunction for the incoming quark
* @param g2 The wavefunction for the incoming gluon
* @param qout The wavefunction for the outgoing quark
* @param g4 The wavefunction for the outgoing gluon
* @param flow The colour flow
*/
double qg2qgME(vector<SpinorWaveFunction> & qin,vector<VectorWaveFunction> &g2,
vector<SpinorBarWaveFunction> & qout,vector<VectorWaveFunction> &g4,
unsigned int flow) const;
/**
* Matrix elements for \f$\bar{q}g\to \bar{q}g\f$.
* @param qin The wavefunction for the incoming antiquark
* @param g2 The wavefunction for the incoming gluon
* @param qout The wavefunction for the outgoing antiquark
* @param g4 The wavefunction for the outgoing gluon
* @param flow The colour flow
*/
double qbarg2qbargME(vector<SpinorBarWaveFunction> & qin,
vector<VectorWaveFunction> &g2,
vector<SpinorWaveFunction> & qout,vector<VectorWaveFunction> &g4,
unsigned int flow) const;
/**
* Matrix element for \f$qq\to qq\f$
* @param q1 The wavefunction for the first incoming quark
* @param q2 The wavefunction for the second incoming quark
* @param q3 The wavefunction for the first outgoing quark
* @param q4 The wavefunction for the second outgoing quark
* @param flow The colour flow
*/
double qq2qqME(vector<SpinorWaveFunction> & q1, vector<SpinorWaveFunction> & q2,
vector<SpinorBarWaveFunction> & q3, vector<SpinorBarWaveFunction> & q4,
unsigned int flow) const;
/**
* Matrix element for \f$\bar{q}\bar{q}\to \bar{q}\bar{q}\f$
* @param q1 The wavefunction for the first incoming antiquark
* @param q2 The wavefunction for the second incoming antiquark
* @param q3 The wavefunction for the first outgoing antiquark
* @param q4 The wavefunction for the second outgoing antiquark
* @param flow The colour flow
*/
double qbarqbar2qbarqbarME(vector<SpinorBarWaveFunction> & q1,
vector<SpinorBarWaveFunction> & q2,
vector<SpinorWaveFunction> & q3,
vector<SpinorWaveFunction> & q4,
unsigned int flow) const;
/**
* Matrix element for \f$q\bar{q}\to q\bar{q}\f$
* @param q1 The wavefunction for the incoming quark
* @param q2 The wavefunction for the incoming antiquark
* @param q3 The wavefunction for the outgoing quark
* @param q4 The wavefunction for the outgoing antiquark
* @param flow The colour flow
*/
double qqbar2qqbarME(vector<SpinorWaveFunction> & q1,
vector<SpinorBarWaveFunction> & q2,
vector<SpinorBarWaveFunction> & q3,
vector<SpinorWaveFunction> & q4,
unsigned int flow) const;
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
throw(RebindException);
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEQCD2to2> initMEQCD2to2;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEQCD2to2 & operator=(const MEQCD2to2 &);
private:
/**
* Vertices needed to compute the diagrams
*/
//@{
/**
* \f$gggg\f$ vertex
*/
AbstractVVVVVertexPtr _ggggvertex;
/**
* \f$ggg\f$ vertex
*/
AbstractVVVVertexPtr _gggvertex;
/**
* \f$q\bar{q}g\f$ vertex
*/
AbstractFFVVertexPtr _qqgvertex;
//@}
/**
* Maximum numbere of quark flavours to include
*/
unsigned int _maxflavour;
/**
* Processes to include
*/
unsigned int _process;
/**
* Colour flow
*/
mutable unsigned int _flow;
/**
* Diagram
*/
mutable unsigned int _diagram;
/**
* Matrix element
*/
mutable ProductionMatrixElement _me;
/**
* ParticleData objects of the partons
*/
//@{
/**
* The gluon
*/
PDPtr _gluon;
/**
* the quarks
*/
vector<PDPtr> _quark;
/**
* the antiquarks
*/
vector<PDPtr> _antiquark;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEQCD2to2. */
template <>
struct BaseClassTrait<Herwig::MEQCD2to2,1> {
/** Typedef of the first base class of MEQCD2to2. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEQCD2to2 class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEQCD2to2>
: public ClassTraitsBase<Herwig::MEQCD2to2> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEQCD2to2"; }
/**
* The name of a file containing the dynamic library where the class
* MEQCD2to2 is implemented. It may also include several, space-separated,
* libraries if the class MEQCD2to2 depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEQCD2to2_H */
diff --git a/MatrixElement/Hadron/MEQCD2to2Fast.cc b/MatrixElement/Hadron/MEQCD2to2Fast.cc
--- a/MatrixElement/Hadron/MEQCD2to2Fast.cc
+++ b/MatrixElement/Hadron/MEQCD2to2Fast.cc
@@ -1,394 +1,393 @@
// -*- C++ -*-
//
// MEQCD2to2Fast.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 MEQCD2to2Fast class.
//
#include "MEQCD2to2Fast.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
using namespace Herwig;
Energy2 MEQCD2to2Fast::scale() const {
Energy2 s(sHat()),u(uHat()),t(tHat());
return 2.*s*t*u/(s*s+t*t+u*u);
}
void MEQCD2to2Fast::persistentOutput(PersistentOStream & os) const {
os << _maxflavour << _process;
}
void MEQCD2to2Fast::persistentInput(PersistentIStream & is, int) {
is >> _maxflavour >> _process;
}
unsigned int MEQCD2to2Fast::orderInAlphaS() const {
return 2;
}
unsigned int MEQCD2to2Fast::orderInAlphaEW() const {
return 0;
}
ClassDescription<MEQCD2to2Fast> MEQCD2to2Fast::initMEQCD2to2Fast;
// Definition of the static class description member.
void MEQCD2to2Fast::Init() {
static ClassDocumentation<MEQCD2to2Fast> documentation
("The MEQCD2to2Fast class implements the QCD 2->2 processes in hadron-hadron"
" collisions");
static Parameter<MEQCD2to2Fast,unsigned int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour of the quarks in the process",
&MEQCD2to2Fast::_maxflavour, 5, 1, 5,
false, false, Interface::limited);
static Switch<MEQCD2to2Fast,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEQCD2to2Fast::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
0);
static SwitchOption interfaceProcess1
(interfaceProcess,
"gg2gg",
"Include only gg->gg subprocesses",
1);
static SwitchOption interfaceProcess2
(interfaceProcess,
"gg2qqbar",
"Include only gg -> q qbar processes",
2);
static SwitchOption interfaceProcessqqbargg
(interfaceProcess,
"qqbar2gg",
"Include only q qbar -> gg processes",
3);
static SwitchOption interfaceProcessqgqg
(interfaceProcess,
"qg2qg",
"Include only q g -> q g processes",
4);
static SwitchOption interfaceProcessqbargqbarg
(interfaceProcess,
"qbarg2qbarg",
"Include only qbar g -> qbar g processes",
5);
static SwitchOption interfaceProcessqqqq
(interfaceProcess,
"qq2qq",
"Include only q q -> q q processes",
6);
static SwitchOption interfaceProcessqbarqbarqbarqbar
(interfaceProcess,
"qbarqbar2qbarqbar",
"Include only qbar qbar -> qbar qbar processes",
7);
static SwitchOption interfaceProcessqqbarqqbar
(interfaceProcess,
"qqbar2qqbar",
"Include only q qbar -> q qbar processes",
8);
}
Selector<MEBase::DiagramIndex>
MEQCD2to2Fast::diagrams(const DiagramVector & diags) const {
// select the diagram, this is easy for us as we have already done it
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if(diags[i]->id()==-int(_diagram)) sel.insert(1.0, i);
else sel.insert(0., i);
}
return sel;
}
void MEQCD2to2Fast::getDiagrams() const {
// get the particle data objects
PDPtr gluon=getParticleData(ParticleID::g);
vector<PDPtr> quark,antiquark;
for(int ix=1;ix<=int(_maxflavour);++ix) {
quark.push_back( getParticleData( ix));
antiquark.push_back(getParticleData(-ix));
}
// gg-> gg subprocess
if(_process==0||_process==1) {
// s-channel
add(new_ptr((Tree2toNDiagram(2),gluon,gluon, 1, gluon,
3,gluon, 3, gluon, -1)));
// first t-channel
add(new_ptr((Tree2toNDiagram(3),gluon,gluon,gluon,
1,gluon, 2,gluon,-2)));
// second t-channel
add(new_ptr((Tree2toNDiagram(3),gluon,gluon,gluon,
2,gluon, 1,gluon,-3)));
}
// processes involving one quark line
for(unsigned int ix=0;ix<_maxflavour;++ix) {
// gg -> q qbar subprocesses
if(_process==0||_process==2) {
// first t-channel
add(new_ptr((Tree2toNDiagram(3),gluon,antiquark[ix],gluon,
1,quark[ix], 2,antiquark[ix],-4)));
// interchange
add(new_ptr((Tree2toNDiagram(3),gluon,antiquark[ix],gluon,
2,quark[ix], 1,antiquark[ix],-5)));
// s-channel
add(new_ptr((Tree2toNDiagram(2),gluon,gluon, 1, gluon,
3,quark[ix], 3, antiquark[ix], -6)));
}
// q qbar -> g g subprocesses
if(_process==0||_process==3) {
// first t-channel
add(new_ptr((Tree2toNDiagram(3),quark[ix],antiquark[ix],antiquark[ix],
1,gluon, 2,gluon,-7)));
// second t-channel
add(new_ptr((Tree2toNDiagram(3),quark[ix],antiquark[ix],antiquark[ix],
2,gluon, 1,gluon,-8)));
// s-channel
add(new_ptr((Tree2toNDiagram(2),quark[ix], antiquark[ix],
1, gluon, 3, gluon, 3, gluon,-9)));
}
// q g -> q g subprocesses
if(_process==0||_process==4) {
// s-channel
add(new_ptr((Tree2toNDiagram(2),quark[ix], gluon,
1, quark[ix], 3, quark[ix], 3, gluon,-10)));
// quark t-channel
add(new_ptr((Tree2toNDiagram(3),quark[ix],quark[ix],gluon,
2,quark[ix],1,gluon,-11)));
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),quark[ix],gluon,gluon,
1,quark[ix],2,gluon,-12)));
}
// qbar g -> qbar g subprocesses
if(_process==0||_process==5) {
// s-channel
add(new_ptr((Tree2toNDiagram(2),antiquark[ix], gluon,
1, antiquark[ix], 3, antiquark[ix], 3, gluon,-13)));
// quark t-channel
add(new_ptr((Tree2toNDiagram(3),antiquark[ix],antiquark[ix],gluon,
2,antiquark[ix],1,gluon,-14)));
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),antiquark[ix],gluon,gluon,
1,antiquark[ix],2,gluon,-15)));
}
// processes involving two quark lines
for(unsigned int iy=0;iy<_maxflavour;++iy) {
// q q -> q q subprocesses
if(_process==0||_process==6) {
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),quark[ix],gluon,quark[iy],
1,quark[ix],2,quark[iy],-16)));
// exchange for identical quarks
if(ix==iy)
add(new_ptr((Tree2toNDiagram(3),quark[ix],gluon,quark[iy],
2,quark[ix],1,quark[iy],-17)));
}
// qbar qbar -> qbar qbar subprocesses
if(_process==0||_process==7) {
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),antiquark[ix],gluon,antiquark[iy],
1,antiquark[ix],2,antiquark[iy],-18)));
// exchange for identical quarks
if(ix==iy)
add(new_ptr((Tree2toNDiagram(3),antiquark[ix],gluon,antiquark[iy],
2,antiquark[ix],1,antiquark[iy],-19)));
}
// q qbar -> q qbar
if(_process==0||_process==8) {
// gluon s-channel
add(new_ptr((Tree2toNDiagram(2),quark[ix], antiquark[ix],
1, gluon, 3, quark[iy], 3, antiquark[iy],-20)));
// gluon t-channel
add(new_ptr((Tree2toNDiagram(3),quark[ix],gluon,antiquark[iy],
1,quark[ix],2,antiquark[iy],-21)));
}
}
}
}
Selector<const ColourLines *>
MEQCD2to2Fast::colourGeometries(tcDiagPtr diag) const {
// colour lines for gg to gg
static const ColourLines cgggg[12]={ColourLines("1 -2, -1 -3 -5, 5 -4, 2 3 4"),// A_2 s
ColourLines("-1 2, 1 3 5, -5 4, -2 -3 -4"),// A_1 s
ColourLines("1 5, -1 -2 3, -3 -4, -5 2 4"),// A_1 u
ColourLines("-1 -5, 1 2 -3, 3 4, 5 -2 -4"),// A_2 u
ColourLines("1 -2, -1 -3 -4, 4 -5, 2 3 5"),// B_2 s
ColourLines("-1 2, 1 3 4, -4 5, -2 -3 -5"),// B_1 s
ColourLines("1 4, -1 -2 3, -3 -5, -4 2 5"),// B_1 t
ColourLines("-1 -4, 1 2 -3, 3 5, 4 -2 -5"),// B_2 t
ColourLines("1 4, -1 -2 -5, 3 5, -3 2 -4"),// C_1 t
ColourLines("-1 -4, 1 2 5, -3 -5, 3 -2 4"),// C_2 t
ColourLines("1 5, -1 -2 -4, 3 4, -3 2 -5"),// C_1 u
ColourLines("-1 -5, 1 2 4, -3 -4, 3 -2 5") // C_2 u
};
// colour lines for gg to q qbar
static const ColourLines cggqq[4]={ColourLines("1 4, -1 -2 3, -3 -5"),
ColourLines("3 4, -3 -2 1, -1 -5"),
ColourLines("2 -1, 1 3 4, -2 -3 -5"),
ColourLines("1 -2, -1 -3 -5, 2 3 4")};
// colour lines for q qbar to gg
static const ColourLines cqqgg[4]={ColourLines("1 4, -4 -2 5, -3 -5"),
ColourLines("1 5, -3 -4, 4 -2 -5"),
ColourLines("1 3 4, -4 5, -2 -3 -5"),
ColourLines("1 3 5, -5 4, -2 -3 -4")};
// colour lines for q g to q g
static const ColourLines cqgqg[4]={ColourLines("1 -2, 2 3 5, 4 -5"),
ColourLines("1 5, 3 4,-3 2 -5 "),
ColourLines("1 2 -3, 3 5, -5 -2 4"),
ColourLines("1 -2 5,3 2 4,-3 -5")};
// colour lines for qbar g -> qbar g
static const ColourLines cqbgqbg[4]={ColourLines("-1 2, -2 -3 -5, -4 5"),
ColourLines("-1 -5, -3 -4, 3 -2 5"),
ColourLines("-1 -2 3, -3 -5, 5 2 -4"),
ColourLines("-1 2 -5,-3 -2 -4, 3 5")};
// colour lines for q q -> q q
static const ColourLines cqqqq[2]={ColourLines("1 2 5,3 -2 4"),
ColourLines("1 2 4,3 -2 5")};
// colour lines for qbar qbar -> qbar qbar
static const ColourLines cqbqbqbqb[2]={ColourLines("-1 -2 -5,-3 2 -4"),
ColourLines("-1 -2 -4,-3 2 -5")};
// colour lines for q qbar -> q qbar
static const ColourLines cqqbqqb[2]={ColourLines("1 3 4,-2 -3 -5"),
ColourLines("1 2 -3,4 -2 -5")};
// select the colour flow (as all ready picked just insert answer)
Selector<const ColourLines *> sel;
switch(abs(diag->id())) {
// gg -> gg subprocess
case 1:
if(_flow==1) {
sel.insert(0.5, &cgggg[0]);
sel.insert(0.5, &cgggg[1]);
}
else {
sel.insert(0.5, &cgggg[4]);
sel.insert(0.5, &cgggg[5]);
}
break;
case 2:
if(_flow==2) {
sel.insert(0.5, &cgggg[6]);
sel.insert(0.5, &cgggg[7]);
}
else {
sel.insert(0.5, &cgggg[8]);
sel.insert(0.5, &cgggg[9]);
}
break;
case 3:
if(_flow==1) {
sel.insert(0.5, &cgggg[2]);
sel.insert(0.5, &cgggg[3]);
}
else {
sel.insert(0.5, &cgggg[10]);
sel.insert(0.5, &cgggg[11]);
}
break;
// gg -> q qbar subprocess
case 4: case 5:
sel.insert(1.0, &cggqq[abs(diag->id())-4]);
break;
case 6:
sel.insert(1.0, &cggqq[1+_flow]);
break;
// q qbar -> gg subprocess
case 7: case 8:
sel.insert(1.0, &cqqgg[abs(diag->id())-7]);
break;
case 9:
sel.insert(1.0, &cqqgg[1+_flow]);
break;
// q g -> q g subprocess
case 10: case 11:
sel.insert(1.0, &cqgqg[abs(diag->id())-10]);
break;
case 12:
sel.insert(1.0, &cqgqg[1+_flow]);
break;
// q g -> q g subprocess
case 13: case 14:
sel.insert(1.0, &cqbgqbg[abs(diag->id())-13]);
break;
case 15:
sel.insert(1.0, &cqbgqbg[1+_flow]);
break;
// q q -> q q subprocess
case 16: case 17:
sel.insert(1.0, &cqqqq[abs(diag->id())-16]);
break;
// qbar qbar -> qbar qbar subprocess
case 18: case 19:
sel.insert(1.0, &cqbqbqbqb[abs(diag->id())-18]);
break;
// q qbar -> q qbar subprocess
case 20: case 21:
sel.insert(1.0, &cqqbqqb[abs(diag->id())-20]);
break;
}
return sel;
}
double MEQCD2to2Fast::me2() const {
// total matrix element
double me(0.);
// gg initiated processes
if(mePartonData()[0]->id()==ParticleID::g&&mePartonData()[1]->id()==ParticleID::g) {
// gg -> gg
if(mePartonData()[2]->id()==ParticleID::g) me = gg2ggME();
// gg -> q qbar
else me=gg2qqbarME();
}
// quark first processes
else if(mePartonData()[0]->id()>0) {
// q g -> q g
if(mePartonData()[1]->id()==ParticleID::g) me = qg2qgME();
else if(mePartonData()[1]->id()<0) {
// q qbar initiated processes( q qbar -> gg)
if(mePartonData()[2]->id()==ParticleID::g) me = qqbar2ggME();
// q qbar to q qbar
else me = qqbar2qqbarME();
}
// q q -> q q
else if(mePartonData()[1]->id()>0) me = qq2qqME();
}
// antiquark first processes
else if(mePartonData()[0]->id()<0) {
// qbar g -> qbar g
if(mePartonData()[1]->id()==ParticleID::g) me = qbarg2qbargME();
// qbar qbar -> qbar qbar
else if(mePartonData()[1]->id()<0) me = qbarqbar2qbarqbarME();
}
else {
throw Exception() << "Unknown process in MEQCD2to2Fast::me2()"
<< Exception::abortnow;
}
// multpliy by alpha_S^2 and return answer
double alphas(4.*Constants::pi*SM().alphaS(scale()));
return me*sqr(alphas);
}
diff --git a/MatrixElement/Hadron/MEQCD2to2Fast.h b/MatrixElement/Hadron/MEQCD2to2Fast.h
--- a/MatrixElement/Hadron/MEQCD2to2Fast.h
+++ b/MatrixElement/Hadron/MEQCD2to2Fast.h
@@ -1,267 +1,266 @@
// -*- C++ -*-
//
// MEQCD2to2Fast.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_MEQCD2to2Fast_H
#define HERWIG_MEQCD2to2Fast_H
//
// This is the declaration of the MEQCD2to2Fast class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
#include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h"
#include "ThePEG/Helicity/Vertex/Vector/VVVVVertex.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEQCD2to2Fast class implements the matrix elements for
* QCD \f$2\to2\f$ scattering processes using hard coded formulae and
* as such can not include spin correlations. It is designed to be a faster
* replacement for MEQCD2to2 for use in the underlying event.
*
* @see \ref MEQCD2to2FastInterfaces "The interfaces"
* defined for MEQCD2to2Fast.
*/
class MEQCD2to2Fast: public HwME2to2Base {
public:
/**
* The default constructor.
*/
inline MEQCD2to2Fast();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Members to calculate the matrix elements
*/
//@{
/**
* Matrix element for \f$gg\to gg\f$.
*/
inline double gg2ggME() const;
/**
* Matrix element for \f$gg\to q\bar{q}\f$
*/
inline double gg2qqbarME() const;
/**
* Matrix element for \f$q\bar{q}\to gg\f$
*/
inline double qqbar2ggME() const;
/**
* Matrix element for \f$qg\to qg\f$
*/
inline double qg2qgME() const;
/**
* Matrix elements for \f$\bar{q}g\to \bar{q}g\f$.
*/
inline double qbarg2qbargME() const;
/**
* Matrix element for \f$qq\to qq\f$
*/
inline double qq2qqME() const;
/**
* Matrix element for \f$\bar{q}\bar{q}\to \bar{q}\bar{q}\f$
*/
inline double qbarqbar2qbarqbarME() const;
/**
* Matrix element for \f$q\bar{q}\to q\bar{q}\f$
*/
inline double qqbar2qqbarME() const;
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEQCD2to2Fast> initMEQCD2to2Fast;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEQCD2to2Fast & operator=(const MEQCD2to2Fast &);
private:
/**
* Maximum numbere of quark flavours to include
*/
unsigned int _maxflavour;
/**
* Processes to include
*/
unsigned int _process;
/**
* Colour flow
*/
mutable unsigned int _flow;
/**
* Diagram
*/
mutable unsigned int _diagram;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEQCD2to2Fast. */
template <>
struct BaseClassTrait<Herwig::MEQCD2to2Fast,1> {
/** Typedef of the first base class of MEQCD2to2Fast. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEQCD2to2Fast class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEQCD2to2Fast>
: public ClassTraitsBase<Herwig::MEQCD2to2Fast> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEQCD2to2Fast"; }
/**
* The name of a file containing the dynamic library where the class
* MEQCD2to2Fast is implemented. It may also include several, space-separated,
* libraries if the class MEQCD2to2Fast depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadronFast.so"; }
};
/** @endcond */
}
#include "MEQCD2to2Fast.icc"
#endif /* HERWIG_MEQCD2to2Fast_H */
diff --git a/MatrixElement/Hadron/MEqq2W2ff.cc b/MatrixElement/Hadron/MEqq2W2ff.cc
--- a/MatrixElement/Hadron/MEqq2W2ff.cc
+++ b/MatrixElement/Hadron/MEqq2W2ff.cc
@@ -1,358 +1,358 @@
// -*- C++ -*-
//
// MEqq2W2ff.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 MEqq2W2ff class.
//
#include "MEqq2W2ff.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include <cassert>
using namespace Herwig;
MEqq2W2ff::MEqq2W2ff() : _maxflavour(5), _plusminus(0), _process(0) {
massOption(true ,1);
massOption(false,1);
}
void MEqq2W2ff::doinit() throw(InitException) {
HwME2to2Base::doinit();
_wp=getParticleData(ThePEG::ParticleID::Wplus);
_wm=getParticleData(ThePEG::ParticleID::Wminus);
// cast the SM pointer to the Herwig SM pointer
tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm)
_theFFWVertex = hwsm->vertexFFW();
else
throw InitException() << "Must be the Herwig++ StandardModel class in "
<< "MEqq2W2ff::doinit" << Exception::abortnow;
}
void MEqq2W2ff::getDiagrams() const {
// which intgermediates to include
bool wplus =_plusminus==0||_plusminus==1;
bool wminus=_plusminus==0||_plusminus==2;
// possible incoming and outgoing particles
typedef std::vector<pair<long,long> > Pairvector;
// possible parents
Pairvector parentpair;
parentpair.reserve(6);
// don't even think of putting 'break' in here!
switch(_maxflavour) {
case 5:
parentpair.push_back(make_pair(ParticleID::b, ParticleID::cbar));
parentpair.push_back(make_pair(ParticleID::b, ParticleID::ubar));
case 4:
parentpair.push_back(make_pair(ParticleID::s, ParticleID::cbar));
parentpair.push_back(make_pair(ParticleID::d, ParticleID::cbar));
case 3:
parentpair.push_back(make_pair(ParticleID::s, ParticleID::ubar));
case 2:
parentpair.push_back(make_pair(ParticleID::d, ParticleID::ubar));
default:
;
}
// possible children
Pairvector childpair;
childpair.reserve(9);
childpair.push_back(make_pair(ParticleID::eminus, ParticleID::nu_ebar));
childpair.push_back(make_pair(ParticleID::muminus, ParticleID::nu_mubar));
childpair.push_back(make_pair(ParticleID::tauminus, ParticleID::nu_taubar));
childpair.push_back(make_pair(ParticleID::d, ParticleID::ubar));
childpair.push_back(make_pair(ParticleID::s, ParticleID::ubar));
childpair.push_back(make_pair(ParticleID::b, ParticleID::ubar));
childpair.push_back(make_pair(ParticleID::d, ParticleID::cbar));
childpair.push_back(make_pair(ParticleID::s, ParticleID::cbar));
childpair.push_back(make_pair(ParticleID::b, ParticleID::cbar));
// loop over the children
bool lepton,quark;
Pairvector::const_iterator child = childpair.begin();
for (; child != childpair.end(); ++child) {
assert(child->first > 0 && child->second < 0);
// allowed leptonic decay
lepton = child->first > 10 && (_process==0
|| _process==2
|| (child->first - 5)/2 == int(_process));
// allowed quark decay
quark = child->first < 10 && (_process==0
|| _process==1
|| (child->second == -2 && (child->first + 11)/2 == int(_process))
|| (child->second == -4 && (child->first + 17)/2 == int(_process))
);
// if decay not allowed skip
if(!(quark || lepton)) continue;
// decay products
tcPDPtr lNeg1 = getParticleData(child->first);
tcPDPtr lNeg2 = getParticleData(child->second);
tcPDPtr lPos1 = lNeg2->CC();
tcPDPtr lPos2 = lNeg1->CC();
Pairvector::const_iterator parent = parentpair.begin();
for (; parent != parentpair.end(); ++parent) {
// parents
tcPDPtr qNeg1 = getParticleData(parent->first);
tcPDPtr qNeg2 = getParticleData(parent->second);
tcPDPtr qPos1 = qNeg2->CC();
tcPDPtr qPos2 = qNeg1->CC();
// diagrams
if(wminus) add(new_ptr((Tree2toNDiagram(2),
qNeg1, qNeg2,
1, _wm,
3, lNeg1, 3, lNeg2, -1)));
if(wplus) add(new_ptr((Tree2toNDiagram(2),
qPos1, qPos2,
1, _wp,
3, lPos1, 3, lPos2, -2)));
}
}
}
Energy2 MEqq2W2ff::scale() const {
return sHat();
}
double MEqq2W2ff::me2() const {
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction q (meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction qbar(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction f (meMomenta()[2],mePartonData()[2],outgoing);
SpinorWaveFunction fbar(meMomenta()[3],mePartonData()[3],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
q.reset(ix) ; fin.push_back(q);
qbar.reset(ix); ain.push_back(qbar);
f.reset(ix) ;fout.push_back(f);
fbar.reset(ix);aout.push_back(fbar);
}
return qqbarME(fin,ain,fout,aout,false);
}
unsigned int MEqq2W2ff::orderInAlphaS() const {
return 0;
}
unsigned int MEqq2W2ff::orderInAlphaEW() const {
return 2;
}
Selector<MEBase::DiagramIndex>
MEqq2W2ff::diagrams(const DiagramVector &) const {
Selector<DiagramIndex> sel;
sel.insert(1.0, 0);
return sel;
}
Selector<const ColourLines *>
MEqq2W2ff::colourGeometries(tcDiagPtr) const {
static const ColourLines c1("1 -2");
static const ColourLines c2("1 -2,4 -5");
Selector<const ColourLines *> sel;
if(abs(mePartonData()[2]->id())<=6) sel.insert(1.0, &c2);
else sel.insert(1.0, &c1);
return sel;
}
void MEqq2W2ff::persistentOutput(PersistentOStream & os) const {
os << _maxflavour << _plusminus << _process << _theFFWVertex << _wp << _wm;
}
void MEqq2W2ff::persistentInput(PersistentIStream & is, int) {
is >> _maxflavour >> _plusminus >> _process >> _theFFWVertex >> _wp >> _wm;
}
ClassDescription<MEqq2W2ff> MEqq2W2ff::initMEqq2W2ff;
// Definition of the static class description member.
void MEqq2W2ff::Init() {
static ClassDocumentation<MEqq2W2ff> documentation
("The MEqq2W2ff class implements the matrix element for"
"q qbar to Standard Model fermions via W exchange using helicity amplitude"
"techniques");
static Parameter<MEqq2W2ff,unsigned int> interfaceMaxFlavour
( "MaxFlavour",
"The heaviest incoming quark flavour this matrix element is allowed to handle "
"(if applicable).",
&MEqq2W2ff::_maxflavour, 5, 0, 5, false, false, true);
static Switch<MEqq2W2ff,unsigned int> interfacePlusMinus
("Wcharge",
"Which intermediate W bosons to include",
&MEqq2W2ff::_plusminus, 0, false, false);
static SwitchOption interfacePlusMinusAll
(interfacePlusMinus,
"Both",
"Include W+ and W-",
0);
static SwitchOption interfacePlusMinusPlus
(interfacePlusMinus,
"Plus",
"Only include W+",
1);
static SwitchOption interfacePlusMinusMinus
(interfacePlusMinus,
"Minus",
"Only include W-",
2);
static Switch<MEqq2W2ff,unsigned int> interfaceProcess
("Process",
"Which processes to include",
&MEqq2W2ff::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all SM fermions as outgoing particles",
0);
static SwitchOption interfaceProcessQuarks
(interfaceProcess,
"Quarks",
"Only include outgoing quarks",
1);
static SwitchOption interfaceProcessLeptons
(interfaceProcess,
"Leptons",
"All include outgoing leptons",
2);
static SwitchOption interfaceProcessElectron
(interfaceProcess,
"Electron",
"Only include outgoing e nu_e",
3);
static SwitchOption interfaceProcessMuon
(interfaceProcess,
"Muon",
"Only include outgoing mu nu_mu",
4);
static SwitchOption interfaceProcessTau
(interfaceProcess,
"Tau",
"Only include outgoing tauu nu_tau",
5);
static SwitchOption interfaceProcessUpDown
(interfaceProcess,
"UpDown",
"Only include outgoing u dbar/ d ubar",
6);
static SwitchOption interfaceProcessUpStrange
(interfaceProcess,
"UpStrange",
"Only include outgoing u sbar/ s ubar",
7);
static SwitchOption interfaceProcessUpBottom
(interfaceProcess,
"UpBottom",
"Only include outgoing u bbar/ b ubar",
8);
static SwitchOption interfaceProcessCharmDown
(interfaceProcess,
"CharmDown",
"Only include outgoing c dbar/ d cbar",
9);
static SwitchOption interfaceProcessCharmStrange
(interfaceProcess,
"CharmStrange",
"Only include outgoing c sbar/ s cbar",
10);
static SwitchOption interfaceProcessCharmBottom
(interfaceProcess,
"CharmBottom",
"Only include outgoing c bbar/ b cbar",
11);
}
double MEqq2W2ff::qqbarME(vector<SpinorWaveFunction> & fin ,
vector<SpinorBarWaveFunction> & ain ,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
bool calc) const {
// matrix element to be stored
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// positive or negative W boson
bool positive = mePartonData()[0]->iCharge()
+ mePartonData()[1]->iCharge() > 0;
unsigned int ihel1,ihel2,ohel1,ohel2;
// sum over helicities to get the matrix element
double me = 0.;
VectorWaveFunction inter;
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
for(ohel1=0;ohel1<2;++ohel1) {
for(ohel2=0;ohel2<2;++ohel2) {
Complex diag = 0.0;
if (positive) {
// the Wp exchange
inter = _theFFWVertex->evaluate(scale(),1,_wp,fin[ihel1],ain[ihel2]);
diag = _theFFWVertex->evaluate(scale(),aout[ohel2],fout[ohel1],inter);
}
else {
// the Wm exchange
inter = _theFFWVertex->evaluate(scale(),1,_wm,fin[ihel1],ain[ihel2]);
diag = _theFFWVertex->evaluate(scale(),aout[ohel2],fout[ohel1],inter);
}
// sum over helicities
me += real(diag*conj(diag));
if(calc) newme(ihel1,ihel2,ohel1,ohel2) = diag;
}
}
}
}
// results
// spin and colour factor
double colspin=1./12.;
if(abs(fout[0].id())<=6) colspin*=3.;
if(calc) _me.reset(newme);
return me*colspin;
}
void MEqq2W2ff::constructVertex(tSubProPtr sub) {
SpinfoPtr spin[4];
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
// order of particles
unsigned int order[4]={0,1,2,3};
if(hard[0]->id()<0){order[0]=1;order[1]=0;}
if(hard[2]->id()<0){order[2]=3;order[3]=2;}
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction( fin ,hard[order[0]],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[order[1]],incoming,false,true);
SpinorBarWaveFunction(fout,hard[order[2]],outgoing,true ,true);
SpinorWaveFunction( aout,hard[order[3]],outgoing,true ,true);
qqbarME(fin,ain,fout,aout,true);
// get the spin info objects
for(unsigned int ix=0;ix<4;++ix)
{spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[order[ix]]->spinInfo());}
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix){spin[ix]->setProductionVertex(hardvertex);}
}
diff --git a/MatrixElement/Hadron/MEqq2W2ff.h b/MatrixElement/Hadron/MEqq2W2ff.h
--- a/MatrixElement/Hadron/MEqq2W2ff.h
+++ b/MatrixElement/Hadron/MEqq2W2ff.h
@@ -1,268 +1,268 @@
// -*- C++ -*-
//
// MEqq2W2ff.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_MEqq2W2ff_H
#define HERWIG_MEqq2W2ff_H
//
// This is the declaration of the MEqq2W2ff class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEqq2W2ff class implements the matrix element for \f$q\bar{q'}\to W^\pm\f$
* including the decay of the \f$W^\pm\f$ to Standard Model fermions.
*
* @see \ref MEqq2W2ffInterfaces "The interfaces"
* defined for MEqq2W2ff.
*/
class MEqq2W2ff: public HwME2to2Base {
public:
/**
* The default constructor.
*/
MEqq2W2ff();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Matrix element for \f$q\bar{q}\to \gamma/Z \to f\bar{f}\f$.
* @param fin Spinors for incoming quark
* @param ain Spinors for incoming antiquark
* @param fout Spinors for incoming quark
* @param aout Spinors for incoming antiquark
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double qqbarME(vector<SpinorWaveFunction> & fin ,
vector<SpinorBarWaveFunction> & ain ,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
bool me) const;
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEqq2W2ff> initMEqq2W2ff;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEqq2W2ff & operator=(const MEqq2W2ff &);
private:
/**
* Pointer to the W vertex
*/
AbstractFFVVertexPtr _theFFWVertex;
/**
* Pointers to the intermediates resonances
*/
//@{
/**
* Pointer to the \f$W^+\f$
*/
tcPDPtr _wp;
/**
* Pointer to the \f$W^-\f$
*/
tcPDPtr _wm;
//@}
/**
* Switches to control the particles in the hard process
*/
//@{
/**
* The allowed flavours of the incoming quarks
*/
unsigned int _maxflavour;
/**
* Which intermediate \f$W^\pm\f$ bosons to include
*/
unsigned int _plusminus;
/**
* Which decay products of the \f$W^\pm\f$ to include
*/
unsigned int _process;
//@}
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEqq2W2ff. */
template <>
struct BaseClassTrait<Herwig::MEqq2W2ff,1> {
/** Typedef of the first base class of MEqq2W2ff. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEqq2W2ff class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEqq2W2ff>
: public ClassTraitsBase<Herwig::MEqq2W2ff> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEqq2W2ff"; }
/** Return the name(s) of the shared library (or libraries) be loaded to get
* access to the MEqq2W2ff class and any other class on which it depends
* (except the base class). */
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEqq2W2ff_H */
diff --git a/MatrixElement/Hadron/MEqq2gZ2ff.cc b/MatrixElement/Hadron/MEqq2gZ2ff.cc
--- a/MatrixElement/Hadron/MEqq2gZ2ff.cc
+++ b/MatrixElement/Hadron/MEqq2gZ2ff.cc
@@ -1,357 +1,357 @@
// -*- C++ -*-
//
// MEqq2gZ2ff.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 MEqq2gZ2ff class.
//
#include "MEqq2gZ2ff.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Repository/EventGenerator.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
MEqq2gZ2ff::MEqq2gZ2ff() : _maxflavour(5), _gammaZ(0), _process(0) {
massOption(true ,1);
massOption(false,1);
}
void MEqq2gZ2ff::doinit() throw(InitException) {
HwME2to2Base::doinit();
_z0=getParticleData(ThePEG::ParticleID::Z0);
_gamma=getParticleData(ThePEG::ParticleID::gamma);
// cast the SM pointer to the Herwig SM pointer
tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm) {
_theFFZVertex = hwsm->vertexFFZ();
_theFFPVertex = hwsm->vertexFFP();
}
else
throw InitException() << "Must be the Herwig++ StandardModel class in "
<< "MEqq2gZ2ff::doinit" << Exception::abortnow;
}
void MEqq2gZ2ff::getDiagrams() const {
// which intermediates to include
bool gamma = _gammaZ==0 || _gammaZ==1;
bool Z0 = _gammaZ==0 || _gammaZ==2;
// loop over the processes we need
for(unsigned int ix=1;ix<17;++ix) {
// increment counter to switch between quarks and leptons
if(ix==7) ix+=4;
// is it a valid quark process
bool quark = ix<=6 && (_process==0 || _process==1 || _process-10==ix);
// is it a valid lepton process
bool lepton= ix>=11 && ix<=16
&& (_process==0
|| _process==2
|| (_process==3 && ix%2==1)
|| (_process==4 && ix%2==0)
|| (ix%2==0 && (ix-10)/2==_process-7)
|| (ix%2==1 && (ix-9)/2 ==_process-4)
);
// if not a valid process continue
if(!(quark||lepton)) continue;
tcPDPtr lm = getParticleData(ix);
tcPDPtr lp = lm->CC();
for(unsigned int i = 1; i <= _maxflavour; ++i) {
tcPDPtr q = getParticleData(i);
tcPDPtr qb = q->CC();
if(Z0) add(new_ptr((Tree2toNDiagram(2), q, qb, 1, _z0 , 3, lm, 3, lp, -1)));
if(gamma) add(new_ptr((Tree2toNDiagram(2), q, qb, 1, _gamma, 3, lm, 3, lp, -2)));
}
}
}
Energy2 MEqq2gZ2ff::scale() const {
return sHat();
}
double MEqq2gZ2ff::me2() const {
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction q(meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction qbar(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction f(meMomenta()[2],mePartonData()[2],outgoing);
SpinorWaveFunction fbar(meMomenta()[3],mePartonData()[3],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
q.reset(ix) ; fin.push_back(q);
qbar.reset(ix); ain.push_back(qbar);
f.reset(ix) ;fout.push_back(f);
fbar.reset(ix);aout.push_back(fbar);
}
return qqbarME(fin,ain,fout,aout,false);
}
unsigned int MEqq2gZ2ff::orderInAlphaS() const {
return 0;
}
unsigned int MEqq2gZ2ff::orderInAlphaEW() const {
return 2;
}
Selector<MEBase::DiagramIndex>
MEqq2gZ2ff::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if ( diags[i]->id() == -1 ) sel.insert(meInfo()[0], i);
else if ( diags[i]->id() == -2 ) sel.insert(meInfo()[1], i);
}
return sel;
}
Selector<const ColourLines *>
MEqq2gZ2ff::colourGeometries(tcDiagPtr) const {
static const ColourLines c1("1 -2");
static const ColourLines c2("1 -2,4 -5");
Selector<const ColourLines *> sel;
if(abs(mePartonData()[2]->id())<=6) sel.insert(1.0, &c2);
else sel.insert(1.0, &c1);
return sel;
}
void MEqq2gZ2ff::persistentOutput(PersistentOStream & os) const {
os << _maxflavour << _gammaZ << _process
<< _theFFZVertex << _theFFPVertex
<< _gamma << _z0;
}
void MEqq2gZ2ff::persistentInput(PersistentIStream & is, int) {
is >> _maxflavour >> _gammaZ >> _process
>> _theFFZVertex >> _theFFPVertex
>> _gamma >> _z0;
}
ClassDescription<MEqq2gZ2ff> MEqq2gZ2ff::initMEqq2gZ2ff;
// Definition of the static class description member.
void MEqq2gZ2ff::Init() {
static ClassDocumentation<MEqq2gZ2ff> documentation
("The MEqq2gZ2ff class implements the matrix element for"
"q qbar to Standard Model fermions via Z and photon exchange using"
" helicity amplitude techniques");
static Parameter<MEqq2gZ2ff,unsigned int> interfaceMaxFlavour
("MaxFlavour",
"The heaviest incoming quark flavour this matrix element is allowed to handle",
&MEqq2gZ2ff::_maxflavour, 5, 1, 6,
false, false, Interface::limited);
static Switch<MEqq2gZ2ff,unsigned int> interfaceGammaZ
("GammaZ",
"Which terms to include",
&MEqq2gZ2ff::_gammaZ, 0, false, false);
static SwitchOption interfaceGammaZAll
(interfaceGammaZ,
"All",
"Include both gamma and Z terms",
0);
static SwitchOption interfaceGammaZGamma
(interfaceGammaZ,
"Gamma",
"Only include the photon",
1);
static SwitchOption interfaceGammaZZ
(interfaceGammaZ,
"Z",
"Only include the Z",
2);
static Switch<MEqq2gZ2ff,unsigned int> interfaceProcess
("Process",
"Which process to included",
&MEqq2gZ2ff::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all SM fermions as outgoing particles",
0);
static SwitchOption interfaceProcessQuarks
(interfaceProcess,
"Quarks",
"All include the quarks as outgoing particles",
1);
static SwitchOption interfaceProcessLeptons
(interfaceProcess,
"Leptons",
"Only include the leptons as outgoing particles",
2);
static SwitchOption interfaceProcessChargedLeptons
(interfaceProcess,
"ChargedLeptons",
"Only include the charged leptons as outgoing particles",
3);
static SwitchOption interfaceProcessNeutrinos
(interfaceProcess,
"Neutrinos",
"Only include the neutrinos as outgoing particles",
4);
static SwitchOption interfaceProcessElectron
(interfaceProcess,
"Electron",
"Only include e+e- as outgoing particles",
5);
static SwitchOption interfaceProcessMuon
(interfaceProcess,
"Muon",
"Only include mu+mu- as outgoing particles",
6);
static SwitchOption interfaceProcessTau
(interfaceProcess,
"Tau",
"Only include tau+tau- as outgoing particles",
7);
static SwitchOption interfaceProcessNu_e
(interfaceProcess,
"Nu_e",
"Only include nu_e ne_ebar as outgoing particles",
8);
static SwitchOption interfaceProcessnu_mu
(interfaceProcess,
"Nu_mu",
"Only include nu_mu nu_mubar as outgoing particles",
9);
static SwitchOption interfaceProcessnu_tau
(interfaceProcess,
"Nu_tau",
"Only include nu_tau nu_taubar as outgoing particles",
10);
static SwitchOption interfaceProcessDown
(interfaceProcess,
"Down",
"Only include d dbar as outgoing particles",
11);
static SwitchOption interfaceProcessUp
(interfaceProcess,
"Up",
"Only include u ubar as outgoing particles",
12);
static SwitchOption interfaceProcessStrange
(interfaceProcess,
"Strange",
"Only include s sbar as outgoing particles",
13);
static SwitchOption interfaceProcessCharm
(interfaceProcess,
"Charm",
"Only include c cbar as outgoing particles",
14);
static SwitchOption interfaceProcessBottom
(interfaceProcess,
"Bottom",
"Only include b bbar as outgoing particles",
15);
static SwitchOption interfaceProcessTop
(interfaceProcess,
"Top",
"Only include t tbar as outgoing particles",
16);
}
double MEqq2gZ2ff::qqbarME(vector<SpinorWaveFunction> & fin ,
vector<SpinorBarWaveFunction> & ain ,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
bool calc) const {
// scale
Energy2 mb2(scale());
// matrix element to be stored
ProductionMatrixElement menew(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// which intermediates to include
bool gamma=_gammaZ==0||_gammaZ==1;
bool Z0 =_gammaZ==0||_gammaZ==2;
// declare the variables we need
unsigned int ihel1,ihel2,ohel1,ohel2;
VectorWaveFunction inter[2],test;
double me[3]={0.,0.,0.};
Complex diag1,diag2;
// sum over helicities to get the matrix element
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
// intermediate for Z
if(Z0) inter[0]=_theFFZVertex->evaluate(mb2,1,_z0 ,fin[ihel1],ain[ihel2]);
// intermediate for photon
if(gamma) inter[1]=_theFFPVertex->evaluate(mb2,1,_gamma,fin[ihel1],ain[ihel2]);
for(ohel1=0;ohel1<2;++ohel1) {
for(ohel2=0;ohel2<2;++ohel2) {
// first the Z exchange diagram
diag1 = Z0 ?
_theFFZVertex->evaluate(mb2,aout[ohel2],fout[ohel1],inter[0]) : 0.;
// first the photon exchange diagram
diag2 = gamma ?
_theFFPVertex->evaluate(mb2,aout[ohel2],fout[ohel1],inter[1]) : 0.;
// add up squares of individual terms
me[1] += real(diag1*conj(diag1));
me[2] += real(diag2*conj(diag2));
// the full thing including interference
diag1 +=diag2;
me[0] += real(diag1*conj(diag1));
if(calc) menew(ihel1,ihel2,ohel1,ohel2) = diag1;
}
}
}
}
// spin and colour factor
double colspin=1./12.;
if(abs(fout[0].id())<=6) colspin*=3.;
// results
// factor 12 from 4 helicity and 3 colour
for(int ix=0;ix<3;++ix){me[ix]*=colspin;}
DVector save;
save.push_back(me[1]);
save.push_back(me[2]);
meInfo(save);
if(calc) _me.reset(menew);
return me[0];
}
void MEqq2gZ2ff::constructVertex(tSubProPtr sub) {
SpinfoPtr spin[4];
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
// order of particles
unsigned int order[4]={0,1,2,3};
if(hard[0]->id()<0){order[0]=1;order[1]=0;}
if(hard[2]->id()<0){order[2]=3;order[3]=2;}
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction( fin ,hard[order[0]],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[order[1]],incoming,false,true);
SpinorBarWaveFunction(fout,hard[order[2]],outgoing,true ,true);
SpinorWaveFunction( aout,hard[order[3]],outgoing,true ,true);
qqbarME(fin,ain,fout,aout,true);
// get the spin info objects
for(unsigned int ix=0;ix<4;++ix)
spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[order[ix]]->spinInfo());
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) spin[ix]->setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/Hadron/MEqq2gZ2ff.h b/MatrixElement/Hadron/MEqq2gZ2ff.h
--- a/MatrixElement/Hadron/MEqq2gZ2ff.h
+++ b/MatrixElement/Hadron/MEqq2gZ2ff.h
@@ -1,279 +1,279 @@
// -*- C++ -*-
//
// MEqq2gZ2ff.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_MEqq2gZ2ff_H
#define HERWIG_MEqq2gZ2ff_H
//
// This is the declaration of the MEqq2gZ2ff class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEqq2gZ2ff class implements the products of Standard Model
* fermion antifermion pairs via the \f$Z^0\f$ resonance including
* photon interference terms.
*
* @see \ref MEqq2gZ2ffInterfaces "The interfaces"
* defined for MEqq2gZ2ff.
*/
class MEqq2gZ2ff: public HwME2to2Base {
public:
/**
* The default constructor.
*/
MEqq2gZ2ff();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Matrix element for \f$q\bar{q}\to \gamma/Z \to f\bar{f}\f$.
* @param fin Spinors for incoming quark
* @param ain Spinors for incoming antiquark
* @param fout Spinors for incoming quark
* @param aout Spinors for incoming antiquark
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double qqbarME(vector<SpinorWaveFunction> & fin ,
vector<SpinorBarWaveFunction> & ain ,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
bool me) const;
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEqq2gZ2ff> initMEqq2gZ2ff;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEqq2gZ2ff & operator=(const MEqq2gZ2ff &);
private:
/**
* Pointer to the vertices for the helicity calculations
*/
//@{
/**
* Pointer to the Z vertex
*/
AbstractFFVVertexPtr _theFFZVertex;
/**
* Pointer to the photon vertex
*/
AbstractFFVVertexPtr _theFFPVertex;
//@}
/**
* Pointers to the intermediate resonances
*/
//@{
/**
* Pointer to the Z ParticleData object
*/
tcPDPtr _z0;
/**
* Pointer to the photon ParticleData object
*/
tcPDPtr _gamma;
//@}
/**
* Switches to control the particles in the hard process
*/
//@{
/**
* Allowed flavours for the incoming quarks
*/
unsigned int _maxflavour;
/**
* Whether to include both \f$Z^0\f$ and \f$\gamma\f$ or only one
*/
unsigned int _gammaZ;
/**
* Which processes to include
*/
unsigned int _process;
//@}
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEqq2gZ2ff. */
template <>
struct BaseClassTrait<Herwig::MEqq2gZ2ff,1> {
/** Typedef of the first base class of MEqq2gZ2ff. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEqq2gZ2ff class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEqq2gZ2ff>
: public ClassTraitsBase<Herwig::MEqq2gZ2ff> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEqq2gZ2ff"; }
/** Return the name(s) of the shared library (or libraries) be loaded to get
* access to the MEqq2gZ2ff class and any other class on which it depends
* (except the base class). */
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEqq2gZ2ff_H */
diff --git a/MatrixElement/HardVertex.cc b/MatrixElement/HardVertex.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/HardVertex.cc
@@ -0,0 +1,69 @@
+// -*- C++ -*-
+//
+// HardVertex.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 HardVertex class.
+//
+// Author: Peter Richardson
+//
+
+#include "HardVertex.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Helicity/SpinInfo.h"
+#ifdef ThePEG_TEMPLATES_IN_CC_FILE
+// #include "HardVertex.tcc"
+#endif
+
+namespace Herwig {
+
+using ThePEG::Helicity::SpinInfo;
+using ThePEG::Helicity::tcSpinfoPtr;
+
+using namespace ThePEG;
+
+NoPIOClassDescription<HardVertex> HardVertex::initHardVertex;
+ // Definition of the static class description member.
+
+void HardVertex::Init() {
+
+ static ClassDocumentation<HardVertex> documentation
+ ("The HardVertex class implements the vertex for a hard "
+ "interaction for the Herwig++ spin correlation algorithm");
+
+}
+
+// method to get the rho matrix for a given outgoing particle
+RhoDMatrix HardVertex::getRhoMatrix(int i)
+{
+ // get the rho matrices for the outgoing particles
+ vector<RhoDMatrix> rhoout;
+ for(unsigned int ix=0,N=outgoing().size();ix<N;++ix)
+ {
+ if(int(ix)!=i)
+ {rhoout.push_back(dynamic_ptr_cast<tcSpinfoPtr>(outgoing()[ix])->DMatrix());}
+ }
+ // calculate the spin density matrix
+ RhoDMatrix temp=_matrixelement.calculateRhoMatrix(i,dynamic_ptr_cast<tcSpinfoPtr>(incoming()[0])->DMatrix(),dynamic_ptr_cast<tcSpinfoPtr>(incoming()[1])->DMatrix(),rhoout);
+ return temp;
+}
+
+// method to get the D matrix for an incoming particle
+RhoDMatrix HardVertex::getDMatrix(int i)
+{
+ // get rho rho matrices for the outgoing particles
+ vector<RhoDMatrix> rhoout;
+ for(unsigned int ix=0,N=outgoing().size();ix<N;++ix)
+ {rhoout.push_back(dynamic_ptr_cast<tcSpinfoPtr>(outgoing()[ix])->DMatrix());}
+ // calculate the decay matrix
+ int j=0;if(i==0){j=1;}
+ RhoDMatrix temp=_matrixelement.calculateDMatrix(i,dynamic_ptr_cast<tcSpinfoPtr>(incoming()[1])->DMatrix(),rhoout);
+ return temp;
+}
+}
+
diff --git a/MatrixElement/HardVertex.fh b/MatrixElement/HardVertex.fh
new file mode 100644
--- /dev/null
+++ b/MatrixElement/HardVertex.fh
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+//
+// This is the forward declaration of the HardVertex class.
+//
+#ifndef HERWIG_HardVertex_FH
+#define HERWIG_HardVertex_FH
+
+#include "ThePEG/Config/Pointers.h"
+
+namespace Herwig {
+using namespace ThePEG;
+
+class HardVertex;
+ThePEG_DECLARE_POINTERS(HardVertex,HardVertexPtr);
+
+}
+
+#endif
diff --git a/MatrixElement/HardVertex.h b/MatrixElement/HardVertex.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/HardVertex.h
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+//
+// HardVertex.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_HardVertex_H
+#define HERWIG_HardVertex_H
+//
+// This is the declaration of the HardVertex class.
+
+#include "ThePEG/Helicity/HelicityVertex.h"
+#include "ProductionMatrixElement.h"
+#include "HardVertex.fh"
+// #include "HardVertex.xh"
+
+namespace Herwig {
+using ThePEG::Helicity::HelicityVertex;
+
+using namespace ThePEG;
+
+/** \ingroup Helicity
+ * \author Peter Richardson
+ *
+ * The HardVertex class is designed to implement the vertex for a
+ * hard interaction for the Herwig++ spin correlation algorithm.
+ * It inherits from the HelicityVertex class of ThePEG and implements
+ * the methods to calculate the \f$\rho\f$ and \f$D\f$ matrices.
+ *
+ * The ProductionMatrixElement class is used to store the matrix element
+ * and this class performs the calculations of the matrices.
+ *
+ * @see HelicityVertex
+ * @see ProductionMatrixElement
+ */
+
+class HardVertex: public HelicityVertex {
+
+public:
+
+ /**
+ * Access to the matrix element
+ */
+ //@{
+ /**
+ * Get the matrix element
+ */
+ inline const ProductionMatrixElement & ME() const
+ {return _matrixelement;}
+
+ /**
+ * Set the matrix element
+ */
+ inline void ME(const ProductionMatrixElement & in) const
+ {_matrixelement.reset(in);}
+ //@}
+
+public:
+
+ /**
+ * Standard Init function used to initialize the interfaces.
+ */
+ static void Init();
+
+public:
+
+ /**
+ * Method to calculate the \f$\rho\f$ matrix for one of the outgoing particles
+ * @param iout The outgoing particle we are calculating the \f$\rho\f$ matrix for.
+ */
+ virtual RhoDMatrix getRhoMatrix(int iout);
+
+ /**
+ * Method to calculate the \f$D\f$ matrix for an incoming particle.
+ * @param in The incoming particle we are calculating the \f$D\f$ matrix for.
+ */
+ virtual RhoDMatrix getDMatrix(int in);
+
+private:
+
+ /**
+ * Describe a concrete class without persistent data.
+ */
+ static NoPIOClassDescription<HardVertex> initHardVertex;
+
+ /**
+ * Private and non-existent assignment operator.
+ */
+ HardVertex & operator=(const HardVertex &);
+
+private:
+
+ /**
+ * Storage of the matrix element.
+ */
+ ProductionMatrixElement _matrixelement;
+
+};
+}
+
+
+
+namespace ThePEG {
+
+/** @cond TRAITSPECIALIZATIONS */
+
+/**
+ * The following template specialization informs ThePEG about the
+ * base class of HardVertex.
+ */
+template <>
+struct BaseClassTrait<Herwig::HardVertex,1> {
+ /** Typedef of the base class of HardVertex. */
+ typedef ThePEG::Helicity::HelicityVertex NthBase;
+};
+
+/**
+ * The following template specialization informs ThePEG about the
+ * name of this class and the shared object where it is defined.
+ */
+template <>
+struct ClassTraits<Herwig::HardVertex>
+ : public ClassTraitsBase<Herwig::HardVertex> {
+
+ /**
+ * Return the class name.
+ */
+ static string className() { return "Herwig::HardVertex"; }
+};
+
+/** @endcond */
+
+}
+
+#endif /* HERWIG_HardVertex_H */
diff --git a/MatrixElement/Lepton/MEee2Higgs2SM.cc b/MatrixElement/Lepton/MEee2Higgs2SM.cc
--- a/MatrixElement/Lepton/MEee2Higgs2SM.cc
+++ b/MatrixElement/Lepton/MEee2Higgs2SM.cc
@@ -1,262 +1,262 @@
// -*- C++ -*-
//
// MEee2Higgs2SM.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 MEee2Higgs2SM class.
//
#include "MEee2Higgs2SM.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/PDT/EnumParticles.h"
using namespace Herwig;
void MEee2Higgs2SM::doinit() throw(InitException) {
ME2to2Base::doinit();
_h0 = getParticleData(ThePEG::ParticleID::h0);
tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm) {
_theFFHVertex = hwsm->vertexFFH();
}
else {
throw InitException() << "Must have Herwig++ StandardModel object in "
<< "MEee2Higgs2SM::doinit()" << Exception::runerror;
}
}
Energy2 MEee2Higgs2SM::scale() const {
return sHat();
}
unsigned int MEee2Higgs2SM::orderInAlphaS() const {
return 0;
}
unsigned int MEee2Higgs2SM::orderInAlphaEW() const {
return 2;
}
void MEee2Higgs2SM::getDiagrams() const {
// specific the diagrams
tcPDPtr ep = getParticleData(ParticleID::eplus );
tcPDPtr em = getParticleData(ParticleID::eminus);
// outgoing quarks
for(int i=1;i<=5;++i) {
if(_allowed==0 || _allowed==1 || _allowed==i+2) {
tcPDPtr lm = getParticleData(i);
tcPDPtr lp = lm->CC();
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, _h0, 3, lm, 3, lp, -1)));
}
}
// outgoing leptons
for( int i =11;i<=16;i+=2) {
if(_allowed==0 || _allowed==2 || _allowed==(i+7)/2) {
tcPDPtr lm = getParticleData(i);
tcPDPtr lp = lm->CC();
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, _h0, 3, lm, 3, lp, -1)));
}
}
}
double MEee2Higgs2SM::me2() const {
double aver=0.;
// get the order right
int ielectron(0),ipositron(1),ilp(2),ilm(3);
if(mePartonData()[0]->id()!=11) swap(ielectron,ipositron);
if(mePartonData()[2]->id()>mePartonData()[3]->id()) swap(ilp,ilm);
// the arrays for the wavefunction to be passed to the matrix element
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
for(unsigned int ihel=0;ihel<2;++ihel) {
fin .push_back(SpinorWaveFunction(meMomenta()[ielectron],
mePartonData()[ielectron],ihel,incoming));
ain .push_back(SpinorBarWaveFunction(meMomenta()[ipositron],
mePartonData()[ipositron],ihel,incoming));
fout.push_back(SpinorBarWaveFunction(meMomenta()[ilm],
mePartonData()[ilm],ihel,outgoing));
aout.push_back(SpinorWaveFunction(meMomenta()[ilp],
mePartonData()[ilp],ihel,outgoing));
}
HelicityME(fin,ain,fout,aout,aver);
if(mePartonData()[ilm]->id()<=6) aver*=3.;
return aver;
}
// the helicity amplitude matrix element
ProductionMatrixElement MEee2Higgs2SM::HelicityME(vector<SpinorWaveFunction> fin,
vector<SpinorBarWaveFunction> ain,
vector<SpinorBarWaveFunction> fout,
vector<SpinorWaveFunction> aout,
double & aver) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming antifermion (vbar spinor)
// for the outgoing
// 0 outgoing fermion (ubar spinor)
// 1 outgoing antifermion (v spinor)
// me to be returned
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// wavefunctions for the intermediate particles
ScalarWaveFunction interh;
// temporary storage of the different diagrams
Complex diag;
aver=0.;
// sum over helicities to get the matrix element
unsigned int inhel1,inhel2,outhel1,outhel2;
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
interh = _theFFHVertex->evaluate(sHat(),1,_h0,fin[inhel1],ain[inhel2]);
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
diag = _theFFHVertex->evaluate(sHat(),aout[outhel2],
fout[outhel1],interh);
output(inhel1,inhel2,outhel1,outhel2)=diag;
aver +=real(diag*conj(diag));
}
}
}
}
return output;
}
Selector<MEBase::DiagramIndex>
MEee2Higgs2SM::diagrams(const DiagramVector &) const {
Selector<DiagramIndex> sel;sel.insert(1.0, 0);
return sel;
}
Selector<const ColourLines *>
MEee2Higgs2SM::colourGeometries(tcDiagPtr diag) const {
static ColourLines neutral ( " " );
static ColourLines quarks ( "-5 4");
Selector<const ColourLines *> sel;
int id = abs((diag->partons()[2])->id());
if (id<=6 )
sel.insert(1.0, &quarks);
else
sel.insert(1.0, &neutral);
return sel;
}
void MEee2Higgs2SM::persistentOutput(PersistentOStream & os) const {
os << _theFFHVertex << _h0 << _allowed;
}
void MEee2Higgs2SM::persistentInput(PersistentIStream & is, int) {
is >> _theFFHVertex >> _h0 >>_allowed;
}
ClassDescription<MEee2Higgs2SM> MEee2Higgs2SM::initMEee2Higgs2SM;
// Definition of the static class description member.
void MEee2Higgs2SM::Init() {
static ClassDocumentation<MEee2Higgs2SM> documentation
("The MEee2Higgs2SM class implements the matrix element for e+e- to"
" SM particle via Higgs exchnage and is designed to be a process to test"
" things involving scalar particles. ");
static Switch<MEee2Higgs2SM,int> interfaceallowed
("Allowed",
"Allowed outgoing particles",
&MEee2Higgs2SM::_allowed, 0, false, false);
static SwitchOption interfaceallowedAll
(interfaceallowed,
"All",
"All SM particles allowed",
0);
static SwitchOption interfaceallowed1
(interfaceallowed,
"Quarks",
"Only the quarks allowed",
1);
static SwitchOption interfaceallowed2
(interfaceallowed,
"Leptons",
"Only the leptons allowed",
2);
static SwitchOption interfacealloweddown
(interfaceallowed,
"Down",
"Only d dbar allowed",
3);
static SwitchOption interfaceallowedup
(interfaceallowed,
"Up",
"Only u ubar allowed",
4);
static SwitchOption interfaceallowedstrange
(interfaceallowed,
"Strange",
"Only s sbar allowed",
5);
static SwitchOption interfaceallowedcharm
(interfaceallowed,
"Charm",
"Only c cbar allowed",
6);
static SwitchOption interfaceallowedbottom
(interfaceallowed,
"Bottom",
"Only b bbar allowed",
7);
static SwitchOption interfaceallowedtop
(interfaceallowed,
"Top",
"Only t tbar allowed",
8);
static SwitchOption interfaceallowedelectron
(interfaceallowed,
"Electron",
"Only e+e- allowed",
9);
static SwitchOption interfaceallowedMuon
(interfaceallowed,
"Muon",
"Only mu+mu- allowed",
10);
static SwitchOption interfaceallowedTau
(interfaceallowed,
"Tau",
"Only tau+tau- allowed",
11);
}
void MEee2Higgs2SM::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
if(hard[0]->id()<hard[1]->id()) swap(hard[0],hard[1]);
if(hard[2]->id()<hard[3]->id()) swap(hard[2],hard[3]);
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction( fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true);
SpinorWaveFunction( aout,hard[3],outgoing,true ,true);
// calculate the matrix element
double me;
ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me);
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(prodme);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) {
dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo())->setProductionVertex(hardvertex);
}
}
diff --git a/MatrixElement/Lepton/MEee2Higgs2SM.fh b/MatrixElement/Lepton/MEee2Higgs2SM.fh
deleted file mode 100644
--- a/MatrixElement/Lepton/MEee2Higgs2SM.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEee2Higgs2SM class.
-//
-#ifndef HERWIG_MEee2Higgs2SM_FH
-#define HERWIG_MEee2Higgs2SM_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEee2Higgs2SM;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEee2Higgs2SM,MEee2Higgs2SMPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/Lepton/MEee2Higgs2SM.h b/MatrixElement/Lepton/MEee2Higgs2SM.h
--- a/MatrixElement/Lepton/MEee2Higgs2SM.h
+++ b/MatrixElement/Lepton/MEee2Higgs2SM.h
@@ -1,262 +1,261 @@
// -*- C++ -*-
//
// MEee2Higgs2SM.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_MEee2Higgs2SM_H
#define HERWIG_MEee2Higgs2SM_H
//
// This is the declaration of the MEee2Higgs2SM class.
//
#include "ThePEG/MatrixElement/ME2to2Base.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "MEee2Higgs2SM.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MEee2Higgs2SM class implements the production of an \f$s\f$-channel
* Higgs in \f$e^+e^-\f$ collisions in order to allow easy tests of Higgs
* decays. It should not be used for physics studies.
*
* @see \ref MEee2Higgs2SMInterfaces "The interfaces"
* defined for MEee2Higgs2SM.
*/
class MEee2Higgs2SM: public ME2to2Base {
public:
/**
* The default constructor.
*/
inline MEee2Higgs2SM();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
inline virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* set up the spin correlations
*/
virtual void constructVertex(tSubProPtr sub);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
inline virtual void rebind(const TranslationMap & trans)
throw(RebindException);
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
inline virtual IVector getReferences();
//@}
private:
/**
* The matrix element
* @param fin The incoming spinor wavefunction
* @param ain The incoming spinorbar wavefunction
* @param fout The outgoing spinor bar wavefunction
* @param aout The outgoing spinor wavefunction
* @param me The spin averaged matrix element
*/
ProductionMatrixElement HelicityME(vector<SpinorWaveFunction> fin,
vector<SpinorBarWaveFunction> ain,
vector<SpinorBarWaveFunction> fout,
vector<SpinorWaveFunction> aout,double& me) const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEee2Higgs2SM> initMEee2Higgs2SM;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2Higgs2SM & operator=(const MEee2Higgs2SM &);
private:
/**
* Pointer to the Higgs vertex
*/
AbstractFFSVertexPtr _theFFHVertex;
/**
* Allowed outgoing particles
*/
int _allowed;
/**
* Pointer to the Higgs ParticleData object
*/
PDPtr _h0;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2Higgs2SM. */
template <>
struct BaseClassTrait<Herwig::MEee2Higgs2SM,1> {
/** Typedef of the first base class of MEee2Higgs2SM. */
typedef ME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2Higgs2SM class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2Higgs2SM>
: public ClassTraitsBase<Herwig::MEee2Higgs2SM> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2Higgs2SM"; }
/**
* The name of a file containing the dynamic library where the class
* MEee2Higgs2SM is implemented. It may also include several, space-separated,
* libraries if the class MEee2Higgs2SM depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#include "MEee2Higgs2SM.icc"
#endif /* HERWIG_MEee2Higgs2SM_H */
diff --git a/MatrixElement/Lepton/MEee2HiggsVBF.fh b/MatrixElement/Lepton/MEee2HiggsVBF.fh
deleted file mode 100644
--- a/MatrixElement/Lepton/MEee2HiggsVBF.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEee2HiggsVBF class.
-//
-#ifndef HERWIG_MEee2HiggsVBF_FH
-#define HERWIG_MEee2HiggsVBF_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEee2HiggsVBF;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEee2HiggsVBF,MEee2HiggsVBFPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/Lepton/MEee2HiggsVBF.h b/MatrixElement/Lepton/MEee2HiggsVBF.h
--- a/MatrixElement/Lepton/MEee2HiggsVBF.h
+++ b/MatrixElement/Lepton/MEee2HiggsVBF.h
@@ -1,119 +1,118 @@
// -*- C++ -*-
#ifndef HERWIG_MEee2HiggsVBF_H
#define HERWIG_MEee2HiggsVBF_H
//
// This is the declaration of the MEee2HiggsVBF class.
//
#include "Herwig++/MatrixElement/MEfftoffH.h"
-#include "MEee2HiggsVBF.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MEee2HiggsVBF class
*
* @see \ref MEee2HiggsVBFInterfaces "The interfaces"
* defined for MEee2HiggsVBF.
*/
class MEee2HiggsVBF: public MEfftoffH {
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
//@}
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an concrete class without persistent data.
*/
static NoPIOClassDescription<MEee2HiggsVBF> initMEee2HiggsVBF;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2HiggsVBF & operator=(const MEee2HiggsVBF &);
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2HiggsVBF. */
template <>
struct BaseClassTrait<Herwig::MEee2HiggsVBF,1> {
/** Typedef of the first base class of MEee2HiggsVBF. */
typedef Herwig::MEfftoffH NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2HiggsVBF class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2HiggsVBF>
: public ClassTraitsBase<Herwig::MEee2HiggsVBF> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2HiggsVBF"; }
/**
* The name of a file containing the dynamic library where the class
* MEee2HiggsVBF is implemented. It may also include several, space-separated,
* libraries if the class MEee2HiggsVBF depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#include "MEee2HiggsVBF.icc"
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
// #include "MEee2HiggsVBF.tcc"
#endif
#endif /* HERWIG_MEee2HiggsVBF_H */
diff --git a/MatrixElement/Lepton/MEee2VectorMeson.cc b/MatrixElement/Lepton/MEee2VectorMeson.cc
--- a/MatrixElement/Lepton/MEee2VectorMeson.cc
+++ b/MatrixElement/Lepton/MEee2VectorMeson.cc
@@ -1,227 +1,227 @@
// -*- C++ -*-
//
// MEee2VectorMeson.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 MEee2VectorMeson class.
//
#include "MEee2VectorMeson.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Cuts/Cuts.h"
#include "Herwig++/PDT/GenericMassGenerator.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
using ThePEG::Helicity::SpinfoPtr;
void MEee2VectorMeson::getDiagrams() const {
tcPDPtr em = getParticleData(ParticleID::eminus);
tcPDPtr ep = getParticleData(ParticleID::eplus);
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, _vector,-1)));
}
Energy2 MEee2VectorMeson::scale() const {
return sHat();
}
int MEee2VectorMeson::nDim() const {
return 0;
}
void MEee2VectorMeson::setKinematics() {
MEBase::setKinematics(); // Always call the base class method first.
}
bool MEee2VectorMeson::generateKinematics(const double *) {
Lorentz5Momentum pout=meMomenta()[0]+meMomenta()[1];
pout.rescaleMass();
meMomenta()[2] = pout;
jacobian(1.0);
// check passes all the cuts
vector<LorentzMomentum> out(1,meMomenta()[2]);
tcPDVector tout(1,mePartonData()[2]);
// return true if passes the cuts
return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]);
}
unsigned int MEee2VectorMeson::orderInAlphaS() const {
return 0;
}
unsigned int MEee2VectorMeson::orderInAlphaEW() const {
return 0;
}
Selector<const ColourLines *>
MEee2VectorMeson::colourGeometries(tcDiagPtr) const {
static ColourLines neutral ( " " );
Selector<const ColourLines *> sel;sel.insert(1.,&neutral);
return sel;
}
void MEee2VectorMeson::persistentOutput(PersistentOStream & os) const {
os << _coupling << _vector << _massgen << _lineshape;
}
void MEee2VectorMeson::persistentInput(PersistentIStream & is, int) {
is >> _coupling >> _vector >> _massgen >> _lineshape;
}
ClassDescription<MEee2VectorMeson> MEee2VectorMeson::initMEee2VectorMeson;
// Definition of the static class description member.
void MEee2VectorMeson::Init() {
static ClassDocumentation<MEee2VectorMeson> documentation
("The MEee2VectorMeson class implements the production of a vector meson"
" in e+e- collisions and is primilarly intended to test the hadron decay package");
static Switch<MEee2VectorMeson,bool> interfaceLineShape
("LineShape",
"Option for the vector meson lineshape",
&MEee2VectorMeson::_lineshape, false, false, false);
static SwitchOption interfaceLineShapeMassGenerator
(interfaceLineShape,
"MassGenerator",
"Use the mass generator if available",
true);
static SwitchOption interfaceLineShapeBreitWigner
(interfaceLineShape,
"BreitWigner",
"Use a Breit-Wigner with the naive running width",
false);
static Reference<MEee2VectorMeson,ParticleData> interfaceVectorMeson
("VectorMeson",
"The vector meson produced",
&MEee2VectorMeson::_vector, false, false, true, false, false);
static Parameter<MEee2VectorMeson,double> interfaceCoupling
("Coupling",
"The leptonic coupling of the vector meson",
&MEee2VectorMeson::_coupling, 0.0012, 0.0, 10.0,
false, false, Interface::limited);
}
Selector<MEBase::DiagramIndex>
MEee2VectorMeson::diagrams(const DiagramVector &) const {
Selector<DiagramIndex> sel;sel.insert(1.0, 0);
return sel;
}
CrossSection MEee2VectorMeson::dSigHatDR() const {
InvEnergy2 wgt;
Energy M(_vector->mass()),G(_vector->width());
Energy2 M2(sqr(M)),GM(G*M);
if(_massgen&&_lineshape) {
wgt =Constants::pi*_massgen->weight(sqrt(sHat()))/(sqr(sHat()-M2)+sqr(GM))*UnitRemoval::E2;
}
else {
wgt = sHat()*G/M/(sqr(sHat()-M2)+sqr(sHat()*G/M));
}
return me2()*jacobian()*wgt*sqr(hbarc);
}
void MEee2VectorMeson::doinit() throw(InitException) {
MEBase::doinit();
// mass generator
tMassGenPtr mass=_vector->massGenerator();
if(mass) {
_massgen=dynamic_ptr_cast<GenericMassGeneratorPtr>(mass);
}
}
double MEee2VectorMeson::me2() const {
double aver=0.;
// get the order right
int ielectron(0),ipositron(1);
if(mePartonData()[0]->id()!=11) swap(ielectron,ipositron);
// the vectors for the wavefunction to be passed to the matrix element
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> vout;
for(unsigned int ihel=0;ihel<2;++ihel) {
fin.push_back(SpinorWaveFunction(meMomenta()[ielectron],
mePartonData()[ielectron],ihel,incoming));
ain.push_back(SpinorBarWaveFunction(meMomenta()[ipositron],
mePartonData()[ipositron],ihel,incoming));
}
for(unsigned int ihel=0;ihel<3;++ihel) {
vout.push_back(VectorWaveFunction(meMomenta()[2],mePartonData()[2],ihel,outgoing));
}
ProductionMatrixElement temp=HelicityME(fin,ain,vout,aver);
return aver;
}
// the helicity amplitude matrix element
ProductionMatrixElement MEee2VectorMeson::HelicityME(vector<SpinorWaveFunction> fin,
vector<SpinorBarWaveFunction> ain,
vector<VectorWaveFunction> vout,
double & aver) const {
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1);
Complex product;
// sum over helicities to get the matrix element
unsigned int inhel1,inhel2,outhel1;
double me(0.);
LorentzPolarizationVector vec;
Complex ii(0.,1.);
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
vec = fin[inhel1].wave().vectorCurrent(ain[inhel2].wave());
vec*=_coupling;
for(outhel1=0;outhel1<3;++outhel1) {
product = vec.dot(vout[outhel1].wave());
output(inhel1,inhel2,outhel1)=product;
me+=real(product*conj(product));
}
}
}
aver=(me*UnitRemoval::E2)/sHat();
return output;
}
void MEee2VectorMeson::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
if(hard[0]->id()<hard[1]->id()) swap(hard[0],hard[1]);
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> vout;
SpinorWaveFunction( fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
VectorWaveFunction(vout ,hard[2],outgoing,true,false,true);
double dummy;
ProductionMatrixElement prodme=HelicityME(fin,ain,vout,dummy);
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(prodme);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<3;++ix) {
dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo())->setProductionVertex(hardvertex);
}
}
diff --git a/MatrixElement/Lepton/MEee2VectorMeson.fh b/MatrixElement/Lepton/MEee2VectorMeson.fh
deleted file mode 100644
--- a/MatrixElement/Lepton/MEee2VectorMeson.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEee2VectorMeson class.
-//
-#ifndef THEPEG_MEee2VectorMeson_FH
-#define THEPEG_MEee2VectorMeson_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEee2VectorMeson;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEee2VectorMeson,MEee2VectorMesonPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/Lepton/MEee2VectorMeson.h b/MatrixElement/Lepton/MEee2VectorMeson.h
--- a/MatrixElement/Lepton/MEee2VectorMeson.h
+++ b/MatrixElement/Lepton/MEee2VectorMeson.h
@@ -1,278 +1,277 @@
// -*- C++ -*-
//
// MEee2VectorMeson.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 THEPEG_MEee2VectorMeson_H
#define THEPEG_MEee2VectorMeson_H
//
// This is the declaration of the MEee2VectorMeson class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "Herwig++/PDT/GenericMassGenerator.fh"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
-#include "MEee2VectorMeson.fh"
namespace Herwig {
using namespace ThePEG;
using Helicity::SpinorWaveFunction;
using Helicity::SpinorBarWaveFunction;
using Helicity::VectorWaveFunction;
/**
* The MEee2VectorMeson class is designed to produce neutral vector mesons
* in \f$e^+e^-\f$ collisions and is primarily intended to test the hadronic
* decay package.
*
* @see \ref MEee2VectorMesonInterfaces "The interfaces"
* defined for MEee2VectorMeson.
*/
class MEee2VectorMeson: public MEBase {
public:
/**
* The default constructor.
*/
inline MEee2VectorMeson();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Set the typed and momenta of the incoming and outgoing partons to
* be used in subsequent calls to me() and colourGeometries()
* according to the associated XComb object. If the function is
* overridden in a sub class the new function must call the base
* class one first.
*/
virtual void setKinematics();
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
inline virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Set up the spin correlations
*/
virtual void constructVertex(tSubProPtr sub);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
inline virtual void doinit() throw(InitException);
//@}
private:
/**
* Member to return the helicity amplitudes
*/
ProductionMatrixElement HelicityME(vector<SpinorWaveFunction> fin,
vector<SpinorBarWaveFunction> ain,
vector<VectorWaveFunction> vout,double& me) const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEee2VectorMeson> initMEee2VectorMeson;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2VectorMeson & operator=(const MEee2VectorMeson &);
private:
/**
* The vector meson being produced
*/
PDPtr _vector;
/**
* The coupling
*/
double _coupling;
/**
* Use the mass generator for the line shape
*/
bool _lineshape;
/**
* Pointer to the mass generator for the Higgs
*/
GenericMassGeneratorPtr _massgen;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2VectorMeson. */
template <>
struct BaseClassTrait<Herwig::MEee2VectorMeson,1> {
/** Typedef of the first base class of MEee2VectorMeson. */
typedef MEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2VectorMeson class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2VectorMeson>
: public ClassTraitsBase<Herwig::MEee2VectorMeson> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2VectorMeson"; }
/**
* The name of a file containing the dynamic library where the class
* MEee2VectorMeson is implemented. It may also include several, space-separated,
* libraries if the class MEee2VectorMeson depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#include "MEee2VectorMeson.icc"
#endif /* THEPEG_MEee2VectorMeson_H */
diff --git a/MatrixElement/Lepton/MEee2Z.cc b/MatrixElement/Lepton/MEee2Z.cc
--- a/MatrixElement/Lepton/MEee2Z.cc
+++ b/MatrixElement/Lepton/MEee2Z.cc
@@ -1,194 +1,194 @@
// -*- C++ -*-
//
// MEee2Z.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 MEee2Z class.
//
#include "MEee2Z.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Helicity/FermionSpinInfo.h"
#include "ThePEG/Helicity/VectorSpinInfo.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Cuts/Cuts.h"
namespace Herwig {
using namespace ThePEG;
using ThePEG::Helicity::FermionSpinPtr;
using ThePEG::Helicity::VectorSpinPtr;
using ThePEG::Helicity::VertexPtr;
using ThePEG::Helicity::FermionSpinInfo;
using ThePEG::Helicity::VectorSpinInfo;
using namespace ThePEG::Helicity;
using ThePEG::Helicity::DiracRep;
using ThePEG::Helicity::HaberDRep;
using ThePEG::Helicity::HELASDRep;
using ThePEG::Helicity::defaultDRep;
void MEee2Z::getDiagrams() const {
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
tcPDPtr em = getParticleData(ParticleID::eminus);
tcPDPtr ep = getParticleData(ParticleID::eplus);
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, Z0,-1)));
}
Energy2 MEee2Z::scale() const {
return sHat();
}
int MEee2Z::nDim() const {
return 1;
}
bool MEee2Z::generateKinematics(const double *) {
// Here you can use nDim() random numbers in the vector provided
// to generate the internal kinematics. Note that sHat() has
// already been given from the outside.
meMomenta()[2]=meMomenta()[0]+meMomenta()[1];
meMomenta()[2].rescaleMass();
jacobian(1.0);
// check passes all the cuts
vector<LorentzMomentum> out(1,meMomenta()[2]);
tcPDVector tout(1,mePartonData()[2]);
// return true if passes the cuts
return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]);
}
double MEee2Z::me2() const {
double aver=0.;
// the arrays for the wavefunction to be passed to the matrix element
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> vin;
SpinorWaveFunction fwave(meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction awave(meMomenta()[1],mePartonData()[1],incoming);
for(unsigned int ihel=0;ihel<2;++ihel) {
fwave.reset(ihel);fin.push_back(fwave);
awave.reset(ihel);ain.push_back(awave);
}
VectorWaveFunction vwave(meMomenta()[2],mePartonData()[2],outgoing);
for(unsigned int ihel=0;ihel<3;++ihel) {
vwave.reset(ihel); vin.push_back(vwave);
}
ProductionMatrixElement temp=HelicityME(fin,ain,vin,aver);
// add the Breit-Wigner factors
Energy width=mePartonData()[2]->width();
Energy mass =mePartonData()[2]->mass();
InvEnergy2 fact = width*mass/(sqr(sHat()-mass*mass)+sqr(mass*width));
return aver*fact*sHat();
}
CrossSection MEee2Z::dSigHatDR() const {
return (me2()*jacobian()/sHat())*sqr(hbarc);
}
unsigned int MEee2Z::orderInAlphaS() const {
return 0;
}
unsigned int MEee2Z::orderInAlphaEW() const {
return 1;
}
Selector<MEBase::DiagramIndex>
MEee2Z::diagrams(const DiagramVector &) const {
Selector<DiagramIndex> sel;
sel.insert(1.0, 0);
return sel;
}
Selector<const ColourLines *>
MEee2Z::colourGeometries(tcDiagPtr) const {
static const ColourLines neutral ( " " );
Selector<const ColourLines *> sel;
sel.insert(1.,&neutral);
return sel;
}
void MEee2Z::persistentOutput(PersistentOStream & os) const {
os << _theFFZVertex;
}
void MEee2Z::persistentInput(PersistentIStream & is, int) {
is >> _theFFZVertex;
}
ClassDescription<MEee2Z> MEee2Z::initMEee2Z;
// Definition of the static class description member.
void MEee2Z::Init() {
static ClassDocumentation<MEee2Z> documentation
("The MEee2Z class implements the e+e- -> Z as a 1->2 process for testing"
" of spin correlations etc..");
}
void MEee2Z::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
if(hard[0]->id()<hard[1]->id()) swap(hard[0],hard[1]);
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> vin;
SpinorWaveFunction( fin,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain,hard[1],incoming,false,true);
VectorWaveFunction (vin,hard[2],outgoing,true,false,true);
double dummy;
ProductionMatrixElement prodme=HelicityME(fin,ain,vin,dummy);
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(prodme);
// set the pointers to and from the vertex
for(unsigned int ix=0;ix<3;++ix) {
dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo())->
setProductionVertex(hardvertex);
}
}
// the helicity amplitude matrix element
ProductionMatrixElement MEee2Z::HelicityME(vector<SpinorWaveFunction> fin,
vector<SpinorBarWaveFunction> ain,
vector<VectorWaveFunction> vout,
double & aver) const
{
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1);
Complex product;
// sum over helicities to get the matrix element
unsigned int inhel1,inhel2,outhel1;
double me(0.);
LorentzPolarizationVector vec;
Complex ii(0.,1.);
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
for(outhel1=0;outhel1<3;++outhel1) {
product=_theFFZVertex->evaluate(sHat(),fin[inhel1],ain[inhel2],
vout[outhel1]);
output(inhel1,inhel2,outhel1)=product;
me+=real(product*conj(product));
}
}
}
aver=me/4.;
return output;
}
}
diff --git a/MatrixElement/Lepton/MEee2Z.h b/MatrixElement/Lepton/MEee2Z.h
--- a/MatrixElement/Lepton/MEee2Z.h
+++ b/MatrixElement/Lepton/MEee2Z.h
@@ -1,247 +1,247 @@
// -*- C++ -*-
//
// MEee2Z.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_MEee2Z_H
#define HERWIG_MEee2Z_H
//
// This is the declaration of the <!id>MEee2Z<!!id> class.
//
#include "ThePEG/MatrixElement/ME2to2Base.h"
#include "ThePEG/MatrixElement/MEBase.h"
#include "Herwig++/Models/RSModel/RSModel.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Utilities/Rebinder.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::SpinorWaveFunction;
using Helicity::SpinorBarWaveFunction;
using Helicity::VectorWaveFunction;
/**
* The MEee2Z class implements the matrix element for \f$e^+e^-\to Z\f$ for
* the testing of spin correlations
*/
class MEee2Z: public MEBase {
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
inline virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
/**
* The number of internal degreed of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given 'nDim()' uniform
* random numbers in the interval ]0,1[. To help the phase space
* generator, the 'dSigHatDR()' should be a smooth function of these
* numbers, although this is not strictly necessary. Return
* false if the chosen points failed the kinematical cuts.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(). Uses
* me().
*/
virtual CrossSection dSigHatDR() const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
inline virtual void doinit() throw(InitException);
//@}
private:
/**
* The matrix element
* @param fin The spinors for the incoming fermion
* @param ain The spinors for the incoming antifermion
* @param vout The polarization vectors for the outgoing Z
* @param me The spin averaged matrix element
*/
ProductionMatrixElement HelicityME(vector<SpinorWaveFunction> fin,
vector<SpinorBarWaveFunction> ain,
vector<VectorWaveFunction> vout,double& me) const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEee2Z> initMEee2Z;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2Z & operator=(const MEee2Z &);
private:
/**
* Pointer to the Z vertex
*/
AbstractFFVVertexPtr _theFFZVertex;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2Z. */
template <>
struct BaseClassTrait<Herwig::MEee2Z,1> {
/** Typedef of the first base class of MEee2Z. */
typedef MEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2Z class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2Z>
: public ClassTraitsBase<Herwig::MEee2Z> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2Z"; }
/** Return the name(s) of the shared library (or libraries) be loaded to get
* access to the MEee2Z class and any other class on which it depends
* (except the base class). */
static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#include "MEee2Z.icc"
#endif /* HERWIG_MEee2Z_H */
diff --git a/MatrixElement/Lepton/MEee2ZH.fh b/MatrixElement/Lepton/MEee2ZH.fh
deleted file mode 100644
--- a/MatrixElement/Lepton/MEee2ZH.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEee2ZH class.
-//
-#ifndef HERWIG_MEee2ZH_FH
-#define HERWIG_MEee2ZH_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEee2ZH;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEee2ZH,MEee2ZHPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/Lepton/MEee2ZH.h b/MatrixElement/Lepton/MEee2ZH.h
--- a/MatrixElement/Lepton/MEee2ZH.h
+++ b/MatrixElement/Lepton/MEee2ZH.h
@@ -1,120 +1,119 @@
// -*- C++ -*-
#ifndef HERWIG_MEee2ZH_H
#define HERWIG_MEee2ZH_H
//
// This is the declaration of the MEee2ZH class.
//
#include "Herwig++/MatrixElement/MEfftoVH.h"
-#include "MEee2ZH.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MEee2ZH class implements the matrix element
* for \f$e^+e^-\to Z^0h^0\f$.
*
* @see \ref MEee2ZHInterfaces "The interfaces"
* defined for MEee2ZH.
*/
class MEee2ZH: public MEfftoVH {
public:
/**
* The default constructor.
*/
inline MEee2ZH();
/** @name Virtual functions required by the MEfftoVH class. */
//@{
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static NoPIOClassDescription<MEee2ZH> initMEee2ZH;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2ZH & operator=(const MEee2ZH &);
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2ZH. */
template <>
struct BaseClassTrait<Herwig::MEee2ZH,1> {
/** Typedef of the first base class of MEee2ZH. */
typedef Herwig::MEfftoVH NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2ZH class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2ZH>
: public ClassTraitsBase<Herwig::MEee2ZH> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2ZH"; }
/**
* The name of a file containing the dynamic library where the class
* MEee2ZH is implemented. It may also include several, space-separated,
* libraries if the class MEee2ZH depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#include "MEee2ZH.icc"
#endif /* HERWIG_MEee2ZH_H */
diff --git a/MatrixElement/Lepton/MEee2gZ2ll.cc b/MatrixElement/Lepton/MEee2gZ2ll.cc
--- a/MatrixElement/Lepton/MEee2gZ2ll.cc
+++ b/MatrixElement/Lepton/MEee2gZ2ll.cc
@@ -1,237 +1,237 @@
// -*- C++ -*-
//
// MEee2gZ2ll.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 MEee2gZ2ll class.
//
#include "MEee2gZ2ll.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
void MEee2gZ2ll::getDiagrams() const {
// specific the diagrams
tcPDPtr ep = getParticleData(ParticleID::eplus);
tcPDPtr em = getParticleData(ParticleID::eminus);
// setup the processes
for( int i =11;i<=16;++i) {
if(_allowed==0 || (_allowed==1 && i%2==1) || (_allowed==2&&i==11)
|| (_allowed==3&&i==13) || (_allowed==4&&i==15)) {
tcPDPtr lm = getParticleData(i);
tcPDPtr lp = lm->CC();
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, _gamma, 3, lm, 3, lp, -1)));
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, _Z0, 3, lm, 3, lp, -2)));
}
}
}
Energy2 MEee2gZ2ll::scale() const {
return sHat();
}
unsigned int MEee2gZ2ll::orderInAlphaS() const {
return 0;
}
unsigned int MEee2gZ2ll::orderInAlphaEW() const {
return 2;
}
Selector<MEBase::DiagramIndex>
MEee2gZ2ll::diagrams(const DiagramVector & diags) const {
double lastCont(0.5),lastBW(0.5);
if ( lastXCombPtr() ) {
lastCont = meInfo()[0];
lastBW = meInfo()[1];
}
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if ( diags[i]->id() == -1 ) sel.insert(lastCont, i);
else if ( diags[i]->id() == -2 ) sel.insert(lastBW, i);
}
return sel;
}
Selector<const ColourLines *>
MEee2gZ2ll::colourGeometries(tcDiagPtr) const {
static ColourLines ctST(" ");
Selector<const ColourLines *> sel;
sel.insert(1.0, &ctST);
return sel;
}
void MEee2gZ2ll::persistentOutput(PersistentOStream & os) const {
os << _allowed << _theFFZVertex << _theFFPVertex << _gamma << _Z0;
}
void MEee2gZ2ll::persistentInput(PersistentIStream & is, int) {
is >> _allowed >> _theFFZVertex >> _theFFPVertex >> _gamma >> _Z0;
}
ClassDescription<MEee2gZ2ll> MEee2gZ2ll::initMEee2gZ2ll;
// Definition of the static class description member.
void MEee2gZ2ll::Init() {
static Switch<MEee2gZ2ll,int> interfaceallowed
("Allowed",
"Allowed outgoing leptons",
&MEee2gZ2ll::_allowed, 0, false, false);
static SwitchOption interfaceallowedAll
(interfaceallowed,
"All",
"Allow all leptons as outgoing particles",
0);
static SwitchOption interfaceallowedCharged
(interfaceallowed,
"Charged",
"Only charged leptons as outgoing particles",
1);
static SwitchOption interfaceallowedElectron
(interfaceallowed,
"Electron",
"Only the electron and positron as outgoing leptons",
2);
static SwitchOption interfaceallowedMuon
(interfaceallowed,
"Muon",
"Only muons as outgoing particles",
3);
static SwitchOption interfaceallowedTau
(interfaceallowed,
"Tau",
"Only taus as outgoing particles",
4);
static ClassDocumentation<MEee2gZ2ll> documentation
("The MEee2gZ2ll class implements the matrix element for"
"e+e- to leptons via Z and photon exchange using helicity amplitude"
"techniques");
}
double MEee2gZ2ll::me2() const {
int ie(0),ip(1),ilp(2),ilm(3);
// get the order right
if(mePartonData()[0]->id()!=11) swap(ie,ip);
if(mePartonData()[2]->id()<0) swap(ilm,ilp);
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction ein (meMomenta()[ie ],mePartonData()[ie ],incoming);
SpinorBarWaveFunction pin (meMomenta()[ip ],mePartonData()[ip ],incoming);
SpinorBarWaveFunction ilmout(meMomenta()[ilm],mePartonData()[ilm],outgoing);
SpinorWaveFunction ilpout(meMomenta()[ilp],mePartonData()[ilp],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
ein.reset(ix) ;fin.push_back( ein );
pin.reset(ix) ;ain.push_back( pin );
ilmout.reset(ix);fout.push_back(ilmout);
ilpout.reset(ix);aout.push_back(ilpout);
}
// compute the matrix element
double me,lastCont,lastBW;
HelicityME(fin,ain,fout,aout,me,lastCont,lastBW);
// save the components
DVector save;
save.push_back(lastCont);
save.push_back(lastBW);
meInfo(save);
// return the answer
return me;
}
ProductionMatrixElement MEee2gZ2ll::HelicityME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
double & me,double & cont,
double & BW ) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming antifermion (vbar spinor)
// for the outgoing
// 0 outgoing fermion (ubar spinor)
// 1 outgoing antifermion (v spinor)
// me to be returned
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// // wavefunctions for the intermediate particles
VectorWaveFunction interZ,interG;
// temporary storage of the different diagrams
Complex diag1,diag2;
// sum over helicities to get the matrix element
unsigned int inhel1,inhel2,outhel1,outhel2;
double total[3]={0.,0.};
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
// intermediate Z
interZ = _theFFZVertex->evaluate(sHat(),1,_Z0,fin[inhel1],ain[inhel2]);
// intermediate photon
interG = _theFFPVertex->evaluate(sHat(),1,_gamma,fin[inhel1],ain[inhel2]);
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
// first the Z exchange diagram
diag1 = _theFFZVertex->evaluate(sHat(),aout[outhel2],fout[outhel1],
interZ);
// then the photon exchange diagram
diag2 = _theFFPVertex->evaluate(sHat(),aout[outhel2],fout[outhel1],
interG);
// add up squares of individual terms
total[1] += real(diag1*conj(diag1));
total[2] += real(diag2*conj(diag2));
diag1+=diag2;
// the full thing including interference
diag1 +=diag2;
total[0] += real(diag1*conj(diag1));
output(inhel1,inhel2,outhel1,outhel2)=diag1;
}
}
}
}
// results
for(int ix=0;ix<3;++ix){total[ix]*=0.25;}
cont = total[2];
BW = total[1];
me = total[0];
return output;
}
void MEee2gZ2ll::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
if(hard[0]->id()<hard[1]->id()) swap(hard[0],hard[1]);
if(hard[2]->id()<hard[3]->id()) swap(hard[2],hard[3]);
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction( fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true);
SpinorWaveFunction( aout,hard[3],outgoing,true ,true);
// calculate the matrix element
double me,cont,BW;
ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me,cont,BW);
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(prodme);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) {
dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo())->setProductionVertex(hardvertex);
}
}
diff --git a/MatrixElement/Lepton/MEee2gZ2ll.fh b/MatrixElement/Lepton/MEee2gZ2ll.fh
deleted file mode 100644
--- a/MatrixElement/Lepton/MEee2gZ2ll.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEee2gZ2ll class.
-//
-#ifndef HERWIG_MEee2gZ2ll_FH
-#define HERWIG_MEee2gZ2ll_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEee2gZ2ll;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEee2gZ2ll,MEee2gZ2llPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/Lepton/MEee2gZ2ll.h b/MatrixElement/Lepton/MEee2gZ2ll.h
--- a/MatrixElement/Lepton/MEee2gZ2ll.h
+++ b/MatrixElement/Lepton/MEee2gZ2ll.h
@@ -1,284 +1,283 @@
// -*- C++ -*-
//
// MEee2gZ2ll.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_MEee2gZ2ll_H
#define HERWIG_MEee2gZ2ll_H
//
// This is the declaration of the MEee2gZ2ll class.
//
#include "ThePEG/MatrixElement/ME2to2Base.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/PDT/EnumParticles.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "MEee2gZ2ll.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MEee2gZ2ll class provides the matrix element for
* \f$e^+e^-\to\ell^+\ell^-\f$. N.B. for the production of \f$e^+e^-\f$
* only the \f$s\f$-channel Z and photon diagrams are included.
*
* @see \ref MEee2gZ2llInterfaces "The interfaces"
* defined for MEee2gZ2ll.
*/
class MEee2gZ2ll: public ME2to2Base {
public:
/**
* The default constructor.
*/
inline MEee2gZ2ll();
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
inline virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
inline virtual void doinit() throw(InitException);
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
inline virtual void rebind(const TranslationMap & trans)
throw(RebindException);
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
inline virtual IVector getReferences();
//@}
private:
/**
* Member to calculate the matrix element
* @param fin Spinors for incoming fermion
* @param ain Spinors for incoming antifermion
* @param fout Spinors for outgoing fermion
* @param aout Spinors for outgong antifermion
* @param me Spin summed Matrix element
* @param cont The continuum piece of the matrix element
* @param BW The Z piece of the matrix element
*/
ProductionMatrixElement HelicityME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
double & me,
double & cont,
double & BW ) const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEee2gZ2ll> initMEee2gZ2ll;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2gZ2ll & operator=(const MEee2gZ2ll &);
private:
/**
* Pointer to the fermion-antifermion Z vertex
*/
AbstractFFVVertexPtr _theFFZVertex;
/**
* Pointer to the fermion-antifermion photon vertex
*/
AbstractFFVVertexPtr _theFFPVertex;
/**
* Pointer to the particle data object for the Z
*/
PDPtr _Z0;
/**
* Pointer to the particle data object for the photon
*/
PDPtr _gamma;
/**
* The allowed outgoing
*/
int _allowed;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2gZ2ll. */
template <>
struct BaseClassTrait<Herwig::MEee2gZ2ll,1> {
/** Typedef of the first base class of MEee2gZ2ll. */
typedef ME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2gZ2ll class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2gZ2ll>
: public ClassTraitsBase<Herwig::MEee2gZ2ll> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2gZ2ll"; }
/**
* The name of a file containing the dynamic library where the class
* MEee2gZ2ll is implemented. It may also include several, space-separated,
* libraries if the class MEee2gZ2ll depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#include "MEee2gZ2ll.icc"
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
// #include "MEee2gZ2ll.tcc"
#endif
#endif /* HERWIG_MEee2gZ2ll_H */
diff --git a/MatrixElement/Lepton/MEee2gZ2qq.cc b/MatrixElement/Lepton/MEee2gZ2qq.cc
--- a/MatrixElement/Lepton/MEee2gZ2qq.cc
+++ b/MatrixElement/Lepton/MEee2gZ2qq.cc
@@ -1,284 +1,284 @@
// -*- C++ -*-
//
// MEee2gZ2qq.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 MEee2gZ2qq class.
//
#include "MEee2gZ2qq.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
void MEee2gZ2qq::doinit() throw(InitException) {
HwME2to2Base::doinit();
massOption(true ,_massopt);
massOption(false,_massopt);
rescalingOption(3);
if(_minflav>_maxflav)
throw InitException() << "The minimum flavour " << _minflav
<< "must be lower the than maximum flavour " << _maxflav
<< " in MEee2gZ2qq::doinit() "
<< Exception::runerror;
// set the particle data objects
_Z0=getParticleData(ThePEG::ParticleID::Z0);
_gamma=getParticleData(ThePEG::ParticleID::gamma);
// cast the SM pointer to the Herwig SM pointer
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm) {
_theFFZVertex = hwsm->vertexFFZ();
_theFFPVertex = hwsm->vertexFFP();
}
else throw InitException() << "Wrong type of StandardModel object in "
<< "MEee2gZ2qq::doinit() the Herwig++ version must be used"
<< Exception::runerror;
}
void MEee2gZ2qq::getDiagrams() const {
// specific the diagrams
tcPDPtr ep = getParticleData(ParticleID::eplus);
tcPDPtr em = getParticleData(ParticleID::eminus);
tcPDPtr gamma = getParticleData(ParticleID::gamma);
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
// setup the processes
for(unsigned int i =_minflav;i<=_maxflav;++i) {
tcPDPtr qk = getParticleData(i);
tcPDPtr qb = qk->CC();
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, gamma, 3, qk, 3, qb, -1)));
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, Z0 , 3, qk, 3, qb, -2)));
}
}
Energy2 MEee2gZ2qq::scale() const {
return sHat();
}
unsigned int MEee2gZ2qq::orderInAlphaS() const {
return 0;
}
unsigned int MEee2gZ2qq::orderInAlphaEW() const {
return 2;
}
Selector<MEBase::DiagramIndex>
MEee2gZ2qq::diagrams(const DiagramVector & diags) const {
double lastCont(0.5),lastBW(0.5);
if ( lastXCombPtr() ) {
lastCont = meInfo()[0];
lastBW = meInfo()[1];
}
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if ( diags[i]->id() == -1 ) sel.insert(lastCont, i);
else if ( diags[i]->id() == -2 ) sel.insert(lastBW, i);
}
return sel;
}
Selector<const ColourLines *>
MEee2gZ2qq::colourGeometries(tcDiagPtr ) const {
static const ColourLines c("-5 4");
Selector<const ColourLines *> sel;
sel.insert(1.0, &c);
return sel;
}
void MEee2gZ2qq::persistentOutput(PersistentOStream & os) const {
os << _theFFZVertex << _theFFPVertex << _Z0 << _gamma << _minflav
<< _maxflav << _massopt;
}
void MEee2gZ2qq::persistentInput(PersistentIStream & is, int) {
is >> _theFFZVertex >> _theFFPVertex >> _Z0 >> _gamma >> _minflav
>> _maxflav >> _massopt;
}
ClassDescription<MEee2gZ2qq> MEee2gZ2qq::initMEee2gZ2qq;
// Definition of the static class description member.
void MEee2gZ2qq::Init() {
static ClassDocumentation<MEee2gZ2qq> documentation
("The MEee2gZ2qq class implements the matrix element for e+e- -> q qbar");
static Parameter<MEee2gZ2qq,unsigned int> interfaceMinimumFlavour
("MinimumFlavour",
"The PDG code of the quark with the lowest PDG code to produce.",
&MEee2gZ2qq::_minflav, 1, 1, 6,
false, false, Interface::limited);
static Parameter<MEee2gZ2qq,unsigned int> interfaceMaximumFlavour
("MaximumFlavour",
"The PDG code of the quark with the highest PDG code to produce",
&MEee2gZ2qq::_maxflav, 5, 1, 6,
false, false, Interface::limited);
static Switch<MEee2gZ2qq,unsigned int> interfaceTopMassOption
("TopMassOption",
"Option for the treatment of the top quark mass",
&MEee2gZ2qq::_massopt, 1, false, false);
static SwitchOption interfaceTopMassOptionOnMassShell
(interfaceTopMassOption,
"OnMassShell",
"The top is produced on its mass shell",
1);
static SwitchOption interfaceTopMassOption2
(interfaceTopMassOption,
"OffShell",
"The top is generated off-shell using the mass and width generator.",
2);
}
double MEee2gZ2qq::me2() const {
int ie(0),ip(1),iqk(2),iqb(3);
// get the order right
if(mePartonData()[0]->id()!=11) swap(ie,ip);
if(mePartonData()[2]->id()<0) swap(iqk,iqb);
// compute the spinors
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction ein (rescaledMomenta()[ie ],mePartonData()[ie ],incoming);
SpinorBarWaveFunction pin (rescaledMomenta()[ip ],mePartonData()[ip ],incoming);
SpinorBarWaveFunction qkout(rescaledMomenta()[iqk],mePartonData()[iqk],outgoing);
SpinorWaveFunction qbout(rescaledMomenta()[iqb],mePartonData()[iqb],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
ein.reset(ix) ;fin.push_back( ein );
pin.reset(ix) ;ain.push_back( pin );
qkout.reset(ix);fout.push_back(qkout);
qbout.reset(ix);aout.push_back(qbout);
}
// compute the matrix element
double me,lastCont,lastBW;
HelicityME(fin,ain,fout,aout,me,lastCont,lastBW);
// save the components
DVector save;
save.push_back(lastCont);
save.push_back(lastBW);
meInfo(save);
// add the QCD K-factor
int Nf = SM().Nf(scale());
me *= (1.0 + alphaS()/Constants::pi
+ (1.986-0.115*Nf)*sqr(alphaS()/Constants::pi));
// return the answer
return me;
}
ProductionMatrixElement MEee2gZ2qq::HelicityME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
double & me,
double & cont,
double & BW ) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming antifermion (vbar spinor)
// for the outgoing
// 0 outgoing fermion (ubar spinor)
// 1 outgoing antifermion (v spinor)
// me to be returned
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// wavefunctions for the intermediate particles
VectorWaveFunction interZ,interG;
// temporary storage of the different diagrams
Complex diag1,diag2;
// sum over helicities to get the matrix element
unsigned int inhel1,inhel2,outhel1,outhel2;
double total[3]={0.,0.};
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
// intermediate Z
interZ = _theFFZVertex->evaluate(sHat(),1,_Z0,fin[inhel1],ain[inhel2]);
// intermediate photon
interG = _theFFPVertex->evaluate(sHat(),1,_gamma,fin[inhel1],ain[inhel2]);
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
// first the Z exchange diagram
diag1 = _theFFZVertex->evaluate(sHat(),aout[outhel2],fout[outhel1],
interZ);
// then the photon exchange diagram
diag2 = _theFFPVertex->evaluate(sHat(),aout[outhel2],fout[outhel1],
interG);
// add up squares of individual terms
total[1] += real(diag1*conj(diag1));
total[2] += real(diag2*conj(diag2));
// the full thing including interference
diag1+=diag2;
total[0] += real(diag1*conj(diag1));
output(inhel1,inhel2,outhel1,outhel2)=diag1;
}
}
}
}
// results
for(int ix=0;ix<3;++ix){total[ix]*=0.75;}
cont = total[2];
BW = total[1];
me = total[0];
return output;
}
void MEee2gZ2qq::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
hard.push_back(sub->outgoing()[1]);
if(hard[0]->id()<hard[1]->id()) swap(hard[0],hard[1]);
if(hard[2]->id()<hard[3]->id()) swap(hard[2],hard[3]);
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
// get wave functions for off-shell momenta for later on
SpinorWaveFunction( fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true);
SpinorWaveFunction( aout,hard[3],outgoing,true ,true);
// now rescale the momenta and compute the matrix element with the
// rescaled momenta for correlations
vector<Lorentz5Momentum> momenta;
cPDVector data;
for(unsigned int ix=0;ix<4;++ix) {
momenta.push_back(hard[ix]->momentum());
data .push_back(hard[ix]->dataPtr());
}
rescaleMomenta(momenta,data);
SpinorWaveFunction ein (rescaledMomenta()[0],data[0],incoming);
SpinorBarWaveFunction pin (rescaledMomenta()[1],data[1],incoming);
SpinorBarWaveFunction qkout(rescaledMomenta()[2],data[2],outgoing);
SpinorWaveFunction qbout(rescaledMomenta()[3],data[3],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
ein.reset(ix) ; fin [ix] = ein ;
pin.reset(ix) ; ain [ix] = pin ;
qkout.reset(ix); fout[ix] = qkout;
qbout.reset(ix); aout[ix] = qbout;
}
// calculate the matrix element
double me,cont,BW;
ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me,cont,BW);
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(prodme);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix)
dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo())->setProductionVertex(hardvertex);
}
diff --git a/MatrixElement/Lepton/MEee2gZ2qq.fh b/MatrixElement/Lepton/MEee2gZ2qq.fh
deleted file mode 100644
--- a/MatrixElement/Lepton/MEee2gZ2qq.fh
+++ /dev/null
@@ -1,18 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEee2gZ2qq class.
-//
-#ifndef HERWIG_MEee2gZ2qq_FH
-#define HERWIG_MEee2gZ2qq_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-using namespace ThePEG;
-
-class MEee2gZ2qq;
-ThePEG_DECLARE_POINTERS(MEee2gZ2qq,MEee2gZ2qqPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/Lepton/MEee2gZ2qq.h b/MatrixElement/Lepton/MEee2gZ2qq.h
--- a/MatrixElement/Lepton/MEee2gZ2qq.h
+++ b/MatrixElement/Lepton/MEee2gZ2qq.h
@@ -1,289 +1,288 @@
// -*- C++ -*-
//
// MEee2gZ2qq.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_MEee2gZ2qq_H
#define HERWIG_MEee2gZ2qq_H
//
// This is the declaration of the MEee2gZ2qq class.
//
#include "Herwig++/MatrixElement/HwME2to2Base.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/Rebinder.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "MEee2gZ2qq.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MEee2gZ2qq class implements the matrix element
* for \f$e^+e^-\to Z/\gamma \to q\bar{q}\f$ including spin correlations.
* The class includes greater control over the type of quark produced than is available
* in the corresponding matrix element from ThePEG, in addition to spin correlations.
*
* @see \ref MEee2gZ2qqInterfaces "The interfaces"
* defined for MEee2gZ2qq.
*/
class MEee2gZ2qq: public HwME2to2Base {
public:
/**
* The default constructor.
*/
inline MEee2gZ2qq();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
inline virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
inline virtual void rebind(const TranslationMap & trans)
throw(RebindException);
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
inline virtual IVector getReferences();
//@}
private:
/**
* Member to calculate the matrix element
* @param fin Spinors for incoming fermion
* @param ain Spinors for incoming antifermion
* @param fout Spinors for outgoing fermion
* @param aout Spinors for outgong antifermion
* @param me Spin summed Matrix element
* @param cont The continuum piece of the matrix element
* @param BW The Z piece of the matrix element
*/
ProductionMatrixElement HelicityME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
double & me,
double & cont,
double & BW ) const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEee2gZ2qq> initMEee2gZ2qq;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2gZ2qq & operator=(const MEee2gZ2qq &);
private:
/**
* Pointer to the fermion-antifermion Z vertex
*/
AbstractFFVVertexPtr _theFFZVertex;
/**
* Pointer to the fermion-antifermion photon vertex
*/
AbstractFFVVertexPtr _theFFPVertex;
/**
* Pointer to the particle data object for the Z
*/
PDPtr _Z0;
/**
* Pointer to the particle data object for the photon
*/
PDPtr _gamma;
/**
* The minimum PDG of the quarks to be produced
*/
unsigned int _minflav;
/**
* The maximum PDG of the quarks to be produced
*/
unsigned int _maxflav;
/**
* Option for the treatment of the top quark mass
*/
unsigned int _massopt;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2gZ2qq. */
template <>
struct BaseClassTrait<Herwig::MEee2gZ2qq,1> {
/** Typedef of the first base class of MEee2gZ2qq. */
typedef Herwig::HwME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2gZ2qq class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2gZ2qq>
: public ClassTraitsBase<Herwig::MEee2gZ2qq> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2gZ2qq"; }
/** Return the name(s) of the shared library (or libraries) be loaded to get
* access to the MEee2gZ2qq class and any other class on which it depends
* (except the base class). */
static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#include "MEee2gZ2qq.icc"
#endif /* HERWIG_MEee2gZ2qq_H */
diff --git a/MatrixElement/Lepton/Makefile.am b/MatrixElement/Lepton/Makefile.am
--- a/MatrixElement/Lepton/Makefile.am
+++ b/MatrixElement/Lepton/Makefile.am
@@ -1,10 +1,10 @@
pkglib_LTLIBRARIES = HwMELepton.la
HwMELepton_la_SOURCES = \
-MEee2gZ2qq.h MEee2gZ2qq.icc MEee2gZ2qq.cc MEee2gZ2qq.fh \
-MEee2gZ2ll.h MEee2gZ2ll.icc MEee2gZ2ll.cc MEee2gZ2ll.fh \
-MEee2VectorMeson.h MEee2VectorMeson.icc MEee2VectorMeson.cc MEee2VectorMeson.fh \
-MEee2Higgs2SM.h MEee2Higgs2SM.icc MEee2Higgs2SM.cc MEee2Higgs2SM.fh \
+MEee2gZ2qq.h MEee2gZ2qq.icc MEee2gZ2qq.cc\
+MEee2gZ2ll.h MEee2gZ2ll.icc MEee2gZ2ll.cc\
+MEee2VectorMeson.h MEee2VectorMeson.icc MEee2VectorMeson.cc\
+MEee2Higgs2SM.h MEee2Higgs2SM.icc MEee2Higgs2SM.cc\
MEee2Z.h MEee2Z.icc MEee2Z.cc \
-MEee2ZH.h MEee2ZH.icc MEee2ZH.cc MEee2ZH.fh \
-MEee2HiggsVBF.h MEee2HiggsVBF.icc MEee2HiggsVBF.cc MEee2HiggsVBF.fh
+MEee2ZH.h MEee2ZH.icc MEee2ZH.cc\
+MEee2HiggsVBF.h MEee2HiggsVBF.icc MEee2HiggsVBF.cc
HwMELepton_la_LDFLAGS = -module -version-info 3:0:0
diff --git a/MatrixElement/MEfftoVH.cc b/MatrixElement/MEfftoVH.cc
--- a/MatrixElement/MEfftoVH.cc
+++ b/MatrixElement/MEfftoVH.cc
@@ -1,416 +1,416 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEfftoVH class.
//
#include "MEfftoVH.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
#include "Herwig++/Utilities/Kinematics.h"
using namespace Herwig;
void MEfftoVH::persistentOutput(PersistentOStream & os) const {
os << _shapeopt << _wplus << _wminus << _z0
<< _vertexFFW << _vertexFFZ << _vertexWWH
<< ounit(_mh,GeV) << ounit(_wh,GeV) << _hmass;
}
void MEfftoVH::persistentInput(PersistentIStream & is, int) {
is >> _shapeopt >> _wplus >> _wminus >> _z0
>> _vertexFFW >> _vertexFFZ >> _vertexWWH
>> iunit(_mh,GeV) >> iunit(_wh,GeV) >> _hmass;
}
AbstractClassDescription<MEfftoVH> MEfftoVH::initMEfftoVH;
// Definition of the static class description member.
void MEfftoVH::Init() {
static ClassDocumentation<MEfftoVH> documentation
("The MEfftoVH class is the base class for the Bjirken process f fbar -> V H");
static Switch<MEfftoVH,unsigned int> interfaceShapeOption
("ShapeScheme",
"Option for the treatment of the Higgs resonance shape",
&MEfftoVH::_shapeopt, 2, false, false);
static SwitchOption interfaceStandardShapeFixed
(interfaceShapeOption,
"FixedBreitWigner",
"Breit-Wigner s-channel resonanse",
1);
static SwitchOption interfaceStandardShapeRunning
(interfaceShapeOption,
"MassGenerator",
"Use the mass generator to give the shape",
2);
}
unsigned int MEfftoVH::orderInAlphaS() const {
return 0;
}
unsigned int MEfftoVH::orderInAlphaEW() const {
return 3;
}
Energy2 MEfftoVH::scale() const {
return sHat();
}
int MEfftoVH::nDim() const {
return 5;
}
void MEfftoVH::setKinematics() {
MEBase::setKinematics();
}
Selector<MEBase::DiagramIndex>
MEfftoVH::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i )
sel.insert(1.0, i);
return sel;
}
Selector<const ColourLines *>
MEfftoVH::colourGeometries(tcDiagPtr ) const {
static ColourLines c1("");
static ColourLines c2("6 -7");
static ColourLines c3("1 -2");
static ColourLines c4("1 -2, 6 -7");
Selector<const ColourLines *> sel;
if(mePartonData()[0]->coloured()) {
if(mePartonData()[4]->coloured()) sel.insert(1.0, &c4);
else sel.insert(1.0, &c3);
}
else {
if(mePartonData()[4]->coloured()) sel.insert(1.0, &c2);
else sel.insert(1.0, &c1);
}
return sel;
}
void MEfftoVH::doinit() throw(InitException) {
MEBase::doinit();
// get the vedrtex pointers from the SM object
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm) {
_vertexFFW = hwsm->vertexFFW();
_vertexFFZ = hwsm->vertexFFZ();
_vertexWWH = hwsm->vertexWWH();
}
else throw InitException() << "Wrong type of StandardModel object in "
<< "MEfftoVH::doinit() the Herwig++"
<< " version must be used"
<< Exception::runerror;
// get the particle data objects for the intermediates
_wplus = getParticleData(ParticleID::Wplus );
_wminus = getParticleData(ParticleID::Wminus);
_z0 = getParticleData(ParticleID::Z0);
tcPDPtr h0=getParticleData(ParticleID::h0);
_mh = h0->mass();
_wh = h0->width();
if(h0->massGenerator()) {
_hmass=dynamic_ptr_cast<SMHiggsMassGeneratorPtr>(h0->massGenerator());
}
if(_shapeopt==2&&!_hmass) throw InitException()
<< "If using the mass generator for the line shape in MEfftoVH::doinit()"
<< "the mass generator must be an instance of the SMHiggsMassGenerator class"
<< Exception::runerror;
}
double MEfftoVH::me2() const {
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction q(meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction qbar(meMomenta()[1],mePartonData()[1],incoming);
SpinorBarWaveFunction f(meMomenta()[3],mePartonData()[3],outgoing);
SpinorWaveFunction fbar(meMomenta()[4],mePartonData()[4],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
q.reset(ix) ; fin.push_back(q);
qbar.reset(ix); ain.push_back(qbar);
f.reset(ix) ;fout.push_back(f);
fbar.reset(ix);aout.push_back(fbar);
}
return helicityME(fin,ain,fout,aout,false)*sHat()*UnitRemoval::InvE2;
}
double MEfftoVH::helicityME(vector<SpinorWaveFunction> & fin ,
vector<SpinorBarWaveFunction> & ain ,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
bool calc) const {
// scale
Energy2 mb2(scale());
// matrix element to be stored
ProductionMatrixElement menew(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0,
PDT::Spin1Half,PDT::Spin1Half);
// work out the id of the vector boson
int incharge = mePartonData()[0]->iCharge()+mePartonData()[1]->iCharge();
tcPDPtr vec;
if(incharge==0) vec = _z0;
else if(incharge>0) vec = _wplus;
else vec = _wminus;
// vertex for vector boson
AbstractFFVVertexPtr vertex = vec==_z0 ? _vertexFFZ : _vertexFFW;
// wavefunction for the scalar
ScalarWaveFunction higgs(meMomenta()[2],mePartonData()[2],1.,outgoing);
// calculate the matrix element
VectorWaveFunction inter[2];
unsigned int ihel1,ihel2,ohel1,ohel2;
Complex diag;
double me(0.);
for(ihel1=0;ihel1<2;++ihel1) {
for(ihel2=0;ihel2<2;++ihel2) {
// wavefunction for the intermediate 1st vector
inter[0] = vertex->evaluate(mb2,1,vec,fin[ihel1],ain[ihel2]);
// after the emission of the higgs
inter[1] = _vertexWWH->evaluate(mb2,1,vec,inter[0],higgs);
// boson decay piece
for(ohel1=0;ohel1<2;++ohel1) {
for(ohel2=0;ohel2<2;++ohel2) {
diag = vertex->evaluate(sqr(inter[1].getParticle()->mass()),
aout[ohel2],fout[ohel1],inter[1]);
me += norm(diag);
if(calc) menew(ihel1,ihel2,0,ohel1,ohel2) = diag;
}
}
}
}
// spin factor
me *=0.25;
// incoming colour factor
if(mePartonData()[0]->coloured()) me /= 3.;
// outgoing colour factor
if(mePartonData()[3]->coloured()) me *= 3.;
if(calc) _me.reset(menew);
return me;
}
void MEfftoVH::constructVertex(tSubProPtr sub) {
SpinfoPtr spin[5];
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
hard.push_back(sub->outgoing()[1]);
hard.push_back(sub->outgoing()[2]);
// ensure right order
if(hard[0]->id()<0) swap(hard[0],hard[1]);
if(hard[3]->id()==ParticleID::h0) swap(hard[2],hard[3]);
if(hard[4]->id()==ParticleID::h0) swap(hard[2],hard[4]);
if(hard[3]->id()<0) swap(hard[3],hard[4]);
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction( fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
ScalarWaveFunction( hard[2],outgoing,true,true);
SpinorBarWaveFunction(fout,hard[3],outgoing,true ,true);
SpinorWaveFunction( aout,hard[4],outgoing,true ,true);
helicityME(fin,ain,fout,aout,true);
// get the spin info objects
for(unsigned int ix=0;ix<5;++ix) {
spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo());
}
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(_me);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<5;++ix) {
spin[ix]->setProductionVertex(hardvertex);
}
}
bool MEfftoVH::generateKinematics(const double * r) {
using Constants::pi;
// workout the ID of the vector boson
tcPDPtr vec = mePartonData()[0]->iCharge()+mePartonData()[1]->iCharge()!=0
? _wplus : _z0;
// order determined randomly
Energy e = sqrt(sHat())/2.0;
Energy mh,mv;
double jac(1.);
if(UseRandom::rndbool()) {
// generate the mass of the Higgs
Energy mhmax = min(2.*e-vec->massMin(),mePartonData()[2]->massMax());
Energy mhmin = max(0.*GeV ,mePartonData()[2]->massMin());
if(mhmax<=mhmin) return false;
double rhomin = atan((sqr(mhmin)-sqr(_mh))/_mh/_wh);
double rhomax = atan((sqr(mhmax)-sqr(_mh))/_mh/_wh);
mh = sqrt(_mh*_wh*tan(rhomin+r[1]*(rhomax-rhomin))+sqr(_mh));
jac *= rhomax-rhomin;
// generate the mass of the vector boson
Energy2 mvmax2 = sqr(min(2.*e-mh,vec->massMax()));
Energy2 mvmin2 = sqr(vec->massMin());
if(mvmax2<=mvmin2) return false;
rhomin = atan((mvmin2-sqr(vec->mass()))/vec->mass()/vec->width());
rhomax = atan((mvmax2-sqr(vec->mass()))/vec->mass()/vec->width());
mv = sqrt(vec->mass()*vec->width()*tan(rhomin+r[2]*(rhomax-rhomin))
+sqr(vec->mass()));
jac *= rhomax-rhomin;
}
else {
// generate the mass of the vector boson
Energy2 mvmax2 = sqr(min(2.*e,vec->massMax()));
Energy2 mvmin2 = sqr(vec->massMin());
if(mvmax2<=mvmin2) return false;
double rhomin = atan((mvmin2-sqr(vec->mass()))/vec->mass()/vec->width());
double rhomax = atan((mvmax2-sqr(vec->mass()))/vec->mass()/vec->width());
mv = sqrt(vec->mass()*vec->width()*tan(rhomin+r[2]*(rhomax-rhomin))
+sqr(vec->mass()));
jac *= rhomax-rhomin;
// generate the mass of the Higgs
Energy mhmax = min(2.*e-mv,mePartonData()[2]->massMax());
Energy mhmin = max(0.*GeV ,mePartonData()[2]->massMin());
if(mhmax<=mhmin) return false;
rhomin = atan((sqr(mhmin)-sqr(_mh))/_mh/_wh);
rhomax = atan((sqr(mhmax)-sqr(_mh))/_mh/_wh);
mh = sqrt(_mh*_wh*tan(rhomin+r[1]*(rhomax-rhomin))+sqr(_mh));
jac *= rhomax-rhomin;
}
// assign masses
meMomenta()[2].setMass(mh);
for(unsigned int ix=3;ix<5;++ix)
meMomenta()[ix] = Lorentz5Momentum(mePartonData()[ix]->generateMass());
Energy q = 0.0*GeV;
Lorentz5Momentum pvec(mv);
try {
q = SimplePhaseSpace::
getMagnitude(sHat(), meMomenta()[2].mass(), mv);
}
catch ( ImpossibleKinematics ) {
return false;
}
Energy ptmin = max(lastCuts().minKT(mePartonData()[2]),
lastCuts().minKT(vec));
Energy2 m22 = meMomenta()[2].mass2();
Energy2 m32 = pvec .mass2();
Energy2 e0e2 = 2.0*e*sqrt(sqr(q) + m22);
Energy2 e1e2 = 2.0*e*sqrt(sqr(q) + m22);
Energy2 e0e3 = 2.0*e*sqrt(sqr(q) + m32);
Energy2 e1e3 = 2.0*e*sqrt(sqr(q) + m32);
Energy2 pq = 2.0*e*q;
double ctmin = -1.0,ctmax = 1.0;
Energy2 thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[2]);
if ( thmin > 0.0*GeV2 ) ctmax = min(ctmax, (e0e2 - m22 - thmin)/pq);
thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[2]);
if ( thmin > 0.0*GeV2 ) ctmin = max(ctmin, (thmin + m22 - e1e2)/pq);
thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[3]);
if ( thmin > 0.0*GeV2 ) ctmax = min(ctmax, (e1e3 - m32 - thmin)/pq);
thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[3]);
if ( thmin > 0.0*GeV2 ) ctmin = max(ctmin, (thmin + m32 - e0e3)/pq);
if ( ptmin > 0.0*GeV ) {
double ctm = 1.0 - sqr(ptmin/q);
if ( ctm <= 0.0 ) return false;
ctmin = max(ctmin, -sqrt(ctm));
ctmax = min(ctmax, sqrt(ctm));
}
if ( ctmin >= ctmax ) return false;
double cth = getCosTheta(ctmin, ctmax, r[0]);
Energy pt = q*sqrt(1.0-sqr(cth));
double phi = UseRandom::rnd()*2.0*pi;
meMomenta()[2].setX(pt*sin(phi));
meMomenta()[2].setY(pt*cos(phi));
meMomenta()[2].setZ(q*cth);
pvec .setX(-pt*sin(phi));
pvec .setY(-pt*cos(phi));
pvec .setZ(-q*cth);
meMomenta()[2].rescaleEnergy();
pvec .rescaleEnergy();
// decay of the vector boson
bool test=Kinematics::twoBodyDecay(pvec,meMomenta()[3].mass(),
meMomenta()[4].mass(),
-1.+2*r[3],r[4]*2.*pi,
meMomenta()[3],meMomenta()[4]);
if(!test) return false;
// check cuts
vector<LorentzMomentum> out;
tcPDVector tout;
for(unsigned int ix=2;ix<5;++ix) {
out .push_back(meMomenta()[ix]);
tout.push_back(mePartonData()[ix]);
}
if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) )
return false;
// jacobian factors
// main piece
jacobian((pq/sHat())*pi*jacobian());
// mass piece
jacobian(jac*jacobian());
// decay piece
Energy p2 = Kinematics::pstarTwoBodyDecay(mv,meMomenta()[3].mass(),
meMomenta()[4].mass());
jacobian(p2/mv/8./sqr(pi)*jacobian());
// jacobian factor for the gauge boson
jacobian((sqr(sqr(mv)-sqr(vec->mass()))+sqr(vec->mass()*vec->width()))/
(vec->mass()*vec->width())*jacobian()/sHat());
return true;
}
CrossSection MEfftoVH::dSigHatDR() const {
using Constants::pi;
// jacobian factor for the higgs
InvEnergy2 bwfact;
Energy moff =meMomenta()[2].mass();if(_shapeopt==1) {
tcPDPtr h0 = mePartonData()[2]->id()==ParticleID::h0 ?
mePartonData()[2] : mePartonData()[3];
bwfact = h0->generateWidth(moff)*moff/pi/
(sqr(sqr(moff)-sqr(_mh))+sqr(_mh*_wh));
}
else {
bwfact = _hmass->BreitWignerWeight(moff,0);
}
double jac1 = bwfact*(sqr(sqr(moff)-sqr(_mh))+sqr(_mh*_wh))/(_mh*_wh);
// answer
return jac1*me2()*jacobian()/(16.0*sqr(pi)*sHat())*sqr(hbarc);
}
double MEfftoVH::getCosTheta(double ctmin, double ctmax, double r) {
double cth = 0.0;
if ( ctmin <= -1.0 && ctmax >= 1.0 ) {
jacobian((ctmax - ctmin));
cth = ctmin + r*jacobian();
} else if ( ctmin <= -1.0 ) {
cth = 1.0 - (1.0 - ctmax)*pow((1.0 - ctmin)/(1.0 - ctmax), r);
jacobian(log((1.0 - ctmin)/(1.0 - ctmax))*(1.0 - cth));
} else if ( ctmax >= 1.0 ) {
cth = -1.0 + (1.0 + ctmin)*pow((1.0 + ctmax)/(1.0 + ctmin), r);
jacobian(log((1.0 + ctmax)/(1.0 + ctmin))*(1.0 + cth));
} else {
double zmin = 0.5*(1.0 - ctmax);
double zmax = 0.5*(1.0 - ctmin);
double A1 = (2.0*zmax - 1.0)/(zmax*(1.0-zmax));
double A0 = (2.0*zmin - 1.0)/(zmin*(1.0-zmin));
double A = r*(A1 - A0) + A0;
double z = A < 2.0? 2.0/(sqrt(sqr(A) + 4.0) + 2 - A):
0.5*(A - 2.0 + sqrt(sqr(A) + 4.0))/A;
cth = 1.0 - 2.0*z;
jacobian(2.0*(A1 - A0)*sqr(z)*sqr(1.0 - z)/(sqr(z) + sqr(1.0 - z)));
}
return cth;
}
diff --git a/MatrixElement/MEfftoVH.fh b/MatrixElement/MEfftoVH.fh
deleted file mode 100644
--- a/MatrixElement/MEfftoVH.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEfftoVH class.
-//
-#ifndef HERWIG_MEfftoVH_FH
-#define HERWIG_MEfftoVH_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEfftoVH;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEfftoVH,MEfftoVHPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/MEfftoVH.h b/MatrixElement/MEfftoVH.h
--- a/MatrixElement/MEfftoVH.h
+++ b/MatrixElement/MEfftoVH.h
@@ -1,313 +1,312 @@
// -*- C++ -*-
#ifndef HERWIG_MEfftoVH_H
#define HERWIG_MEfftoVH_H
//
// This is the declaration of the MEfftoVH class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "Herwig++/PDT/SMHiggsMassGenerator.h"
-#include "MEfftoVH.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MEfftoVH class is the base class for \f$f\bar{f}\to VH\f$ processes.
* This base class handles the phase-space integration while
* the inheriting classes implement the matrix element
*
* @see \ref MEfftoVHInterfaces "The interfaces"
* defined for MEfftoVH.
*/
class MEfftoVH: public MEBase {
public:
/**
* The default constructor.
*/
MEfftoVH() : _shapeopt(2), _mh(), _wh() {}
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Set the typed and momenta of the incoming and outgoing partons to
* be used in subsequent calls to me() and colourGeometries()
* according to the associated XComb object. If the function is
* overridden in a sub class the new function must call the base
* class one first.
*/
virtual void setKinematics();
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Matrix element for \f$f\bar{f}\to V h^0\to f'\bar{f'} h^0\f$.
* @param fin Spinors for incoming fermion
* @param ain Spinors for incoming antifermion
* @param fout Spinors for incoming fermion
* @param aout Spinors for incoming antifermion
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double helicityME(vector<SpinorWaveFunction> & fin ,
vector<SpinorBarWaveFunction> & ain ,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
bool me) const;
/**
* Used internally by generateKinematics, after calculating the
* limits on cos(theta).
*/
virtual double getCosTheta(double cthmin, double cthmax, double r);
/**
* Access to the vector ParticleData objects
*/
//@{
/**
* Access to the \f$W^+\f$ data
*/
PDPtr WPlus() const { return _wplus; }
/**
* Access to the \f$W^-\f$ data
*/
PDPtr WMinus() const { return _wminus; }
/**
* Access to the \f$Z^0\f$ data
*/
PDPtr Z0() const { return _z0; }
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<MEfftoVH> initMEfftoVH;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEfftoVH & operator=(const MEfftoVH &);
private:
/**
* Defines the Higgs resonance shape
*/
unsigned int _shapeopt;
/**
* The intermediate vector bosons
*/
//@{
/**
* \f$W^+\f$
*/
PDPtr _wplus;
/**
* \f$W^-\f$
*/
PDPtr _wminus;
/**
* \f$Z^0\f$
*/
PDPtr _z0;
//@}
/**
* The vertices for the calculation of the matrix element
*/
//@{
/**
* Vertex for fermion-fermion-W
*/
AbstractFFVVertexPtr _vertexFFW;
/**
* Vertex for fermion-fermion-Z
*/
AbstractFFVVertexPtr _vertexFFZ;
/**
* Vertex for vector-vector-Higgs
*/
AbstractVVSVertexPtr _vertexWWH;
//@}
/**
* On-shell mass for the higgs
*/
Energy _mh;
/**
* On-shell width for the higgs
*/
Energy _wh;
/**
* The mass generator for the Higgs
*/
SMHiggsMassGeneratorPtr _hmass;
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEfftoVH. */
template <>
struct BaseClassTrait<Herwig::MEfftoVH,1> {
/** Typedef of the first base class of MEfftoVH. */
typedef MEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEfftoVH class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEfftoVH>
: public ClassTraitsBase<Herwig::MEfftoVH> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEfftoVH"; }
};
/** @endcond */
}
#endif /* HERWIG_MEfftoVH_H */
diff --git a/MatrixElement/MEfftoffH.cc b/MatrixElement/MEfftoffH.cc
--- a/MatrixElement/MEfftoffH.cc
+++ b/MatrixElement/MEfftoffH.cc
@@ -1,386 +1,386 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEfftoffH class.
//
#include "MEfftoffH.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
-#include "Herwig++/MatrixElement/General/HardVertex.h"
+#include "Herwig++/MatrixElement/HardVertex.h"
using namespace Herwig;
void MEfftoffH::persistentOutput(PersistentOStream & os) const {
os << _shapeopt << _process << _wplus << _wminus << _z0
<< _vertexFFW << _vertexFFZ << _vertexWWH
<< ounit(_mh,GeV) << ounit(_wh,GeV) << _hmass;
}
void MEfftoffH::persistentInput(PersistentIStream & is, int) {
is >> _shapeopt >> _process >> _wplus >> _wminus >> _z0
>> _vertexFFW >> _vertexFFZ >> _vertexWWH
>> iunit(_mh,GeV) >> iunit(_wh,GeV) >> _hmass;
}
AbstractClassDescription<MEfftoffH> MEfftoffH::initMEfftoffH;
// Definition of the static class description member.
void MEfftoffH::Init() {
static ClassDocumentation<MEfftoffH> documentation
("The MEfftoffH class is the base class for VBF processes in Herwig++");
static Switch<MEfftoffH,unsigned int> interfaceShapeOption
("ShapeScheme",
"Option for the treatment of the Higgs resonance shape",
&MEfftoffH::_shapeopt, 2, false, false);
static SwitchOption interfaceStandardShapeFixed
(interfaceShapeOption,
"FixedBreitWigner",
"Breit-Wigner s-channel resonance",
1);
static SwitchOption interfaceStandardShapeRunning
(interfaceShapeOption,
"MassGenerator",
"Use the mass generator to give the shape",
2);
static SwitchOption interfaceStandardShapeOnShell
(interfaceShapeOption,
"OnShell",
"Produce an on-shell Higgs boson",
0);
static Switch<MEfftoffH,unsigned int> interfaceProcess
("Process",
"Which processes to include",
&MEfftoffH::_process, 0, false, false);
static SwitchOption interfaceProcessBoth
(interfaceProcess,
"Both",
"Include both WW and ZZ processes",
0);
static SwitchOption interfaceProcessWW
(interfaceProcess,
"WW",
"Only include WW processes",
1);
static SwitchOption interfaceProcessZZ
(interfaceProcess,
"ZZ",
"Only include ZZ processes",
2);
}
unsigned int MEfftoffH::orderInAlphaS() const {
return 0;
}
unsigned int MEfftoffH::orderInAlphaEW() const {
return 3;
}
int MEfftoffH::nDim() const {
return 4 + int(_shapeopt>0);
}
Energy2 MEfftoffH::scale() const {
return sqr(_mh);
}
void MEfftoffH::setKinematics() {
MEBase::setKinematics();
}
Selector<MEBase::DiagramIndex>
MEfftoffH::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i )
sel.insert(1.0, i);
return sel;
}
Selector<const ColourLines *>
MEfftoffH::colourGeometries(tcDiagPtr ) const {
static ColourLines c0("");
static ColourLines c1("1 5, 4 6");
static ColourLines c2("1 5, -4 -6");
static ColourLines c3("-1 -5, 4 6");
static ColourLines c4("-1 -5, -4 -6");
Selector<const ColourLines *> sel;
if(mePartonData()[0]->coloured()) {
if(mePartonData()[0]->id()>0) {
if(mePartonData()[1]->id()>0) sel.insert(1.0, &c1);
else sel.insert(1.0, &c2);
}
else {
if(mePartonData()[1]->id()>0) sel.insert(1.0, &c3);
else sel.insert(1.0, &c4);
}
}
else
sel.insert(1.0, &c0);
return sel;
}
void MEfftoffH::doinit() throw(InitException) {
MEBase::doinit();
// get the vertex pointers from the SM object
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(hwsm) {
_vertexFFW = hwsm->vertexFFW();
_vertexFFZ = hwsm->vertexFFZ();
_vertexWWH = hwsm->vertexWWH();
}
else throw InitException() << "Wrong type of StandardModel object in "
<< "MEfftoffH::doinit() the Herwig++"
<< " version must be used"
<< Exception::runerror;
// get the particle data objects for the intermediates
_wplus = getParticleData(ParticleID::Wplus );
_wminus = getParticleData(ParticleID::Wminus);
_z0 = getParticleData(ParticleID::Z0);
tcPDPtr h0=getParticleData(ParticleID::h0);
_mh = h0->mass();
_wh = h0->width();
if(h0->massGenerator()) {
_hmass=dynamic_ptr_cast<SMHiggsMassGeneratorPtr>(h0->massGenerator());
}
if(_shapeopt==2&&!_hmass) throw InitException()
<< "If using the mass generator for the line shape in MEfftoffH::doinit()"
<< "the mass generator must be an instance of the SMHiggsMassGenerator class"
<< Exception::runerror;
}
double MEfftoffH::me2() const {
vector<SpinorWaveFunction> f1,f2;
vector<SpinorBarWaveFunction> a1,a2;
SpinorWaveFunction fin1,fin2;
SpinorBarWaveFunction ain1,ain2;
if(mePartonData()[0]->id()>0) {
fin1 = SpinorWaveFunction(meMomenta()[0],mePartonData()[0],incoming);
ain1 = SpinorBarWaveFunction(meMomenta()[2],mePartonData()[2],outgoing);
}
else {
fin1 = SpinorWaveFunction(meMomenta()[2],mePartonData()[2],outgoing);
ain1 = SpinorBarWaveFunction(meMomenta()[0],mePartonData()[0],incoming);
}
if(mePartonData()[1]->id()>0) {
fin2 = SpinorWaveFunction(meMomenta()[1],mePartonData()[1],incoming);
ain2 = SpinorBarWaveFunction(meMomenta()[3],mePartonData()[3],outgoing);
}
else {
fin2 = SpinorWaveFunction(meMomenta()[3],mePartonData()[3],outgoing);
ain2 = SpinorBarWaveFunction(meMomenta()[1],mePartonData()[1],incoming);
}
for(unsigned int ix=0;ix<2;++ix) {
fin1.reset(ix); f1.push_back(fin1);
fin2.reset(ix); f2.push_back(fin2);
ain1.reset(ix); a1.push_back(ain1);
ain2.reset(ix); a2.push_back(ain2);
}
return helicityME(f1,f2,a1,a2,false)*sHat()*UnitRemoval::InvE2;
}
double MEfftoffH::helicityME(vector<SpinorWaveFunction> & f1 ,
vector<SpinorWaveFunction> & f2 ,
vector<SpinorBarWaveFunction> & a1,
vector<SpinorBarWaveFunction> & a2,
bool calc) const {
// scale
Energy2 mb2(scale());
// matrix element to be stored
ProductionMatrixElement menew(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0);
// identify the bosons and which vertices to use
tcPDPtr vec[2];
AbstractFFVVertexPtr vertex[2];
for(unsigned int ix=0;ix<2;++ix) {
int icharge = mePartonData()[ix]->iCharge()-mePartonData()[ix+2]->iCharge();
if(icharge==0) vec[ix] = _z0;
else if(icharge>0) vec[ix] = _wplus;
else vec[ix] = _wminus;
vertex[ix] = vec[ix]==_z0 ? _vertexFFZ : _vertexFFW;
}
// wavefunction for the scalar
ScalarWaveFunction higgs(meMomenta()[4],mePartonData()[4],1.,outgoing);
// calculate the matrix element
VectorWaveFunction inter[2];
Complex diag;
double me(0.);
for(unsigned int i1=0;i1<2;++i1) {
for(unsigned int i2=0;i2<2;++i2) {
// wavefunction for the 1st intermediate vector
inter[0] = vertex[0]->evaluate(mb2,1,vec[0],f1[i1],a1[i2]);
for(unsigned int i3=0;i3<2;++i3) {
for(unsigned int i4=0;i4<2;++i4) {
// wavefunction for the 2nd intermediate vector
inter[1] = vertex[1]->evaluate(mb2,1,vec[1],f2[i3],a2[i4]);
// matrix element
diag = _vertexWWH->evaluate(mb2,inter[0],inter[1],higgs);
me += norm(diag);
// store matrix element if needed
if(calc) {
unsigned int ihel[5]={i1,i3,i2,i4,0};
if(f1[i1].id()<0) swap(ihel[0],ihel[2]);
if(f2[i2].id()<0) swap(ihel[1],ihel[3]);
menew(ihel[0],ihel[1],ihel[2],ihel[3],ihel[4]) = diag;
}
}
}
}
}
// spin factor
me *=0.25;
// test of the matrix element for e+e- > nu nubar H
// Energy2 mw2 = sqr(WPlus()->mass());
// Energy2 t1 = (meMomenta()[0]-meMomenta()[2]).m2()-mw2;
// Energy2 t2 = (meMomenta()[1]-meMomenta()[3]).m2()-mw2;
// InvEnergy2 metest = 64.*pow(Constants::pi*standardModel()->alphaEM(mb2)/
// standardModel()->sin2ThetaW(),3)*mw2/sqr(t1)/sqr(t2)*
// (meMomenta()[0]*meMomenta()[3])*(meMomenta()[1]*meMomenta()[2]);
// cerr << "testing matrix element " << me/metest*UnitRemoval::InvE2 << "\n";
if(calc) _me.reset(menew);
return me;
}
bool MEfftoffH::generateKinematics(const double * r) {
// set the jacobian to 1
jacobian(1.);
// roots
Energy roots(sqrt(sHat()));
// generate the Higgs mass if needed
Energy mh(_mh);
if(_shapeopt!=0) {
Energy mhmax = min(roots ,mePartonData()[4]->massMax());
Energy mhmin = max(0.*GeV,mePartonData()[4]->massMin());
if(mhmax<=mhmin) return false;
double rhomin = atan((sqr(mhmin)-sqr(_mh))/_mh/_wh);
double rhomax = atan((sqr(mhmax)-sqr(_mh))/_mh/_wh);
mh = sqrt(_mh*_wh*tan(rhomin+r[4]*(rhomax-rhomin))+sqr(_mh));
jacobian(jacobian()*(rhomax-rhomin));
}
if(mh>roots) return false;
// generate p1 by transform to eta = 1-2p1/sqrt s
// and generate according to deta/eta
double eta = pow(mh/roots,2.*r[0]);
jacobian(-jacobian()*eta*2.*log(mh/roots));
Energy p1 = 0.5*roots*(1.-eta);
// generate the value of cos theta2 first as no cut
double ctheta[2];
double ctmin = -1.0,ctmax = 1.0;
// cos theta 1
ctheta[0] = ctmin+r[1]*(ctmax-ctmin);
// cos theta 2
ctheta[1] = ctmin+r[2]*(ctmax-ctmin);
jacobian(sqr(ctmax-ctmin)*jacobian());
// generate azimuthal angle between 1 and 2
double phi12 = r[3]*Constants::twopi;
// sins
double stheta[2] = {sqrt(1.-sqr(ctheta[0])),sqrt(1.-sqr(ctheta[1]))};
// and angle between them
double cost12 = stheta[0]*stheta[1]*cos(phi12)+ctheta[0]*ctheta[1];
// momentum of 2
Energy p2 = 0.5*(sHat()-2.*roots*p1-sqr(mh))/(roots-p1*(1.-cost12));
if(p2<0.*GeV) return false;
// construct the momenta
// first outgoing particle
meMomenta()[2].setX(stheta[0]*p1);
meMomenta()[2].setY(0.*GeV);
meMomenta()[2].setZ(ctheta[0]*p1);
meMomenta()[2].setT(p1);
meMomenta()[2].setMass(0.*GeV);
// second outgoing particle
meMomenta()[3].setX(stheta[1]*cos(phi12)*p2);
meMomenta()[3].setY(stheta[1]*sin(phi12)*p2);
meMomenta()[3].setZ(ctheta[1]*p2);
meMomenta()[3].setT(p2);
meMomenta()[3].setMass(0.*GeV);
// finally the higgs
meMomenta()[4].setX(-meMomenta()[2].x()-meMomenta()[3].x());
meMomenta()[4].setY(-meMomenta()[2].y()-meMomenta()[3].y());
meMomenta()[4].setZ(-meMomenta()[2].z()-meMomenta()[3].z());
meMomenta()[4].setMass(mh);
meMomenta()[4].rescaleEnergy();
// azimuth of the whole system
double phi = UseRandom::rnd()*Constants::twopi;
// and apply rotation
for(unsigned int ix=2;ix<5;++ix) meMomenta()[ix].rotateZ(phi);
// check cuts
vector<LorentzMomentum> out;
tcPDVector tout;
for(unsigned int ix=2;ix<5;++ix) {
out .push_back(meMomenta()[ix]);
tout.push_back(mePartonData()[ix]);
}
if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) )
return false;
// final bits of the jacobian
Energy2 dot = meMomenta()[3]*meMomenta()[4];
jacobian(jacobian()*p1*sqr(p2)/roots/dot);
return true;
}
CrossSection MEfftoffH::dSigHatDR() const {
using Constants::pi;
// jacobian factor for the higgs
InvEnergy2 bwfact;
Energy moff =meMomenta()[4].mass();
if(_shapeopt==1) {
tPDPtr h0 = getParticleData(ParticleID::h0);
bwfact = h0->generateWidth(moff)*moff/pi/
(sqr(sqr(moff)-sqr(_mh))+sqr(_mh*_wh));
}
else if(_shapeopt==2) {
bwfact = _hmass->BreitWignerWeight(moff,0);
}
double jac1 = _shapeopt!=0 ?
double( bwfact*(sqr(sqr(moff)-sqr(_mh))+sqr(_mh*_wh))/(_mh*_wh)) : 1.;
// cross section
return jac1*me2()*jacobian()/pow(Constants::twopi,3)/32.*sqr(hbarc)/sHat();
}
void MEfftoffH::constructVertex(tSubProPtr sub) {
// SpinfoPtr spin[5];
// // extract the particles in the hard process
// ParticleVector hard;
// hard.push_back(sub->incoming().first);
// hard.push_back(sub->incoming().second);
// hard.push_back(sub->outgoing()[0]);
// hard.push_back(sub->outgoing()[1]);
// hard.push_back(sub->outgoing()[2]);
// // ensure right order
// if(hard[0]->id()<0) swap(hard[0],hard[1]);
// if(hard[3]->id()==ParticleID::h0) swap(hard[2],hard[3]);
// if(hard[4]->id()==ParticleID::h0) swap(hard[2],hard[4]);
// if(hard[3]->id()<0) swap(hard[3],hard[4]);
// vector<SpinorWaveFunction> fin,aout;
// vector<SpinorBarWaveFunction> ain,fout;
// SpinorWaveFunction( fin ,hard[0],incoming,false,true);
// SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
// ScalarWaveFunction( hard[2],outgoing,true,true);
// SpinorBarWaveFunction(fout,hard[3],outgoing,true ,true);
// SpinorWaveFunction( aout,hard[4],outgoing,true ,true);
// helicityME(fin,ain,fout,aout,true);
// // get the spin info objects
// for(unsigned int ix=0;ix<5;++ix) {
// spin[ix]=dynamic_ptr_cast<SpinfoPtr>(hard[ix]->spinInfo());
// }
// // construct the vertex
// HardVertexPtr hardvertex=new_ptr(HardVertex());
// // set the matrix element for the vertex
// hardvertex->ME(_me);
// // set the pointers and to and from the vertex
// for(unsigned int ix=0;ix<5;++ix) {
// spin[ix]->setProductionVertex(hardvertex);
// }
}
diff --git a/MatrixElement/MEfftoffH.fh b/MatrixElement/MEfftoffH.fh
deleted file mode 100644
--- a/MatrixElement/MEfftoffH.fh
+++ /dev/null
@@ -1,22 +0,0 @@
-// -*- C++ -*-
-//
-// This is the forward declaration of the MEfftoffH class.
-//
-#ifndef HERWIG_MEfftoffH_FH
-#define HERWIG_MEfftoffH_FH
-
-#include "ThePEG/Config/Pointers.h"
-
-namespace Herwig {
-
-class MEfftoffH;
-
-}
-
-namespace ThePEG {
-
-ThePEG_DECLARE_POINTERS(Herwig::MEfftoffH,MEfftoffHPtr);
-
-}
-
-#endif
diff --git a/MatrixElement/MEfftoffH.h b/MatrixElement/MEfftoffH.h
--- a/MatrixElement/MEfftoffH.h
+++ b/MatrixElement/MEfftoffH.h
@@ -1,320 +1,319 @@
// -*- C++ -*-
#ifndef HERWIG_MEfftoffH_H
#define HERWIG_MEfftoffH_H
//
// This is the declaration of the MEfftoffH class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
-#include "Herwig++/MatrixElement/General/ProductionMatrixElement.h"
+#include "Herwig++/MatrixElement/ProductionMatrixElement.h"
#include "Herwig++/PDT/SMHiggsMassGenerator.h"
-#include "MEfftoffH.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The MEfftoffH class is the base class for vector boson fusion type
* processes in Herwig++.
*
* @see \ref MEfftoffHInterfaces "The interfaces"
* defined for MEfftoffH.
*/
class MEfftoffH: public MEBase {
public:
/**
* The default constructor.
*/
inline MEfftoffH();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Set the typed and momenta of the incoming and outgoing partons to
* be used in subsequent calls to me() and colourGeometries()
* according to the associated XComb object. If the function is
* overridden in a sub class the new function must call the base
* class one first.
*/
virtual void setKinematics();
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Matrix element for \f$ff\to h^0\to ff h^0\f$.
* @param f1 Spinors for first incoming fermion
* @param f2 Spinors for second incoming fermion
* @param a1 Spinors for first outgoing fermion
* @param a2 Spinors for second outgoing fermion
* @param me Whether or not to calculate the matrix element for spin correlations
*/
double helicityME(vector<SpinorWaveFunction> & f1 ,
vector<SpinorWaveFunction> & f2 ,
vector<SpinorBarWaveFunction> & a1,
vector<SpinorBarWaveFunction> & a2,
bool me) const;
/**
* Access to the vector ParticleData objects
*/
//@{
/**
* Access to the \f$W^+\f$ data
*/
inline PDPtr WPlus() const;
/**
* Access to the \f$W^-\f$ data
*/
inline PDPtr WMinus() const;
/**
* Access to the \f$Z^0\f$ data
*/
inline PDPtr Z0() const;
//@}
/**
* Which process to generate
*/
inline unsigned int process() const;
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<MEfftoffH> initMEfftoffH;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEfftoffH & operator=(const MEfftoffH &);
private:
/**
* Defines the Higgs resonance shape
*/
unsigned int _shapeopt;
/**
* Whether to include $WW$ and $ZZ$ processes or both
*/
unsigned int _process;
/**
* The intermediate vector bosons
*/
//@{
/**
* \f$W^+\f$
*/
PDPtr _wplus;
/**
* \f$W^-\f$
*/
PDPtr _wminus;
/**
* \f$Z^0\f$
*/
PDPtr _z0;
//@}
/**
* The vertices for the calculation of the matrix element
*/
//@{
/**
* Vertex for fermion-fermion-W
*/
AbstractFFVVertexPtr _vertexFFW;
/**
* Vertex for fermion-fermion-Z
*/
AbstractFFVVertexPtr _vertexFFZ;
/**
* Vertex for vector-vector-Higgs
*/
AbstractVVSVertexPtr _vertexWWH;
//@}
/**
* On-shell mass for the higgs
*/
Energy _mh;
/**
* On-shell width for the higgs
*/
Energy _wh;
/**
* The mass generator for the Higgs
*/
SMHiggsMassGeneratorPtr _hmass;
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement _me;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEfftoffH. */
template <>
struct BaseClassTrait<Herwig::MEfftoffH,1> {
/** Typedef of the first base class of MEfftoffH. */
typedef MEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEfftoffH class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEfftoffH>
: public ClassTraitsBase<Herwig::MEfftoffH> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEfftoffH"; }
};
/** @endcond */
}
#include "MEfftoffH.icc"
#endif /* HERWIG_MEfftoffH_H */
diff --git a/MatrixElement/Makefile.am b/MatrixElement/Makefile.am
--- a/MatrixElement/Makefile.am
+++ b/MatrixElement/Makefile.am
@@ -1,8 +1,10 @@
SUBDIRS = General Lepton Hadron DIS Powheg GammaGamma
noinst_LTLIBRARIES = libHwME.la
libHwME_la_SOURCES = \
HwME2to2Base.h HwME2to2Base.icc HwME2to2Base.cc \
-MEfftoVH.h MEfftoVH.fh MEfftoVH.cc \
-MEfftoffH.h MEfftoffH.fh MEfftoffH.icc MEfftoffH.cc
+MEfftoVH.h MEfftoVH.cc \
+MEfftoffH.h MEfftoffH.icc MEfftoffH.cc \
+HardVertex.fh HardVertex.h HardVertex.icc HardVertex.cc \
+ProductionMatrixElement.h ProductionMatrixElement.icc ProductionMatrixElement.cc
\ No newline at end of file
diff --git a/MatrixElement/ProductionMatrixElement.cc b/MatrixElement/ProductionMatrixElement.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/ProductionMatrixElement.cc
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+//
+// ProductionMatrixElement.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 ProductionMatrixElement class.
+//
+// Author: Peter Richardson
+//
+
+#include "ProductionMatrixElement.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+
+#ifdef ThePEG_TEMPLATES_IN_CC_FILE
+// #include "ProductionMatrixElement.tcc"
+#endif
+
+namespace Herwig {
+using namespace ThePEG;
+
+NoPIOClassDescription<ProductionMatrixElement> ProductionMatrixElement::initProductionMatrixElement;
+// Definition of the static class description member.
+
+void ProductionMatrixElement::Init() {
+
+ static ClassDocumentation<ProductionMatrixElement> documentation
+ ("The ProductionMatrixElement class is designed to store the "
+ "matrix element for a hard interaction.");
+
+}
+
+// calculate a decay matrix for one of the incoming particles
+RhoDMatrix ProductionMatrixElement::calculateDMatrix(int id, RhoDMatrix rhoin,
+ vector<RhoDMatrix> rhoout)
+{
+ // vectors for the helicities
+ vector<unsigned int> ihel1(_outspin.size()+2),ihel2(_outspin.size()+2);
+ // rhomatrix to be returned
+ RhoDMatrix output(_inspin[id]); output.zero();
+ // loop over all helicity components of the matrix element
+ // outer loop
+ Complex temp;
+ unsigned int ix,iy;
+ int ixa,iya;
+ for(ix=0;ix<_matrixelement.size();++ix)
+ {
+ // map the vector index to the helicities
+ for(ixa=_outspin.size()+1;ixa>=0;--ixa)
+ {ihel1[ixa]=(ix%_constants[ixa])/_constants[ixa+1];}
+ // inner loop
+ for(iy=0;iy<_matrixelement.size();++iy)
+ {
+ // map the vector index to the helicities
+ for(iya=_outspin.size()+1;iya>=0;--iya)
+ {ihel2[iya]=(iy%_constants[iya])/_constants[iya+1];}
+ // matrix element piece
+ temp=_matrixelement[ix]*conj(_matrixelement[iy]);
+ // spin density matrices for the outgoing particles
+ for(unsigned int iz=0;iz<_outspin.size();++iz)
+ {temp*=rhoout[iz](ihel1[iz+2],ihel2[iz+2]);}
+ // construct the spin density matrix
+ if(id==0)
+ {
+ temp*=rhoin(ihel1[1],ihel2[1]);
+ output(ihel1[0],ihel2[0])+=temp;
+ }
+ else
+ {
+ temp*=rhoin(ihel1[0],ihel2[0]);
+ output(ihel1[1],ihel2[1])+=temp;
+ }
+ }
+ }
+ // return the answer
+ return output;
+}
+
+// calculate the rho matrix for a given outgoing particle
+RhoDMatrix ProductionMatrixElement::calculateRhoMatrix(int id,
+ RhoDMatrix rhoin0,
+ RhoDMatrix rhoin1,
+ vector<RhoDMatrix>rhoout)
+{
+ unsigned int ix,iy;
+ int ixa,iya;
+ // vectors for the helicities
+ vector<unsigned int> ihel1(_outspin.size()+2),ihel2(_outspin.size()+2);
+ // rhomatrix to be returned
+ RhoDMatrix output(_outspin[id]); output.zero();
+ // loop over all helicity components of the matrix element
+ // outer loop
+ Complex temp;
+ for(ix=0;ix<_matrixelement.size();++ix)
+ {
+ // map the vector index to the helicities
+ for(ixa=_outspin.size()+1;ixa>=0;--ixa)
+ {ihel1[ixa]=(ix%_constants[ixa])/_constants[ixa+1];}
+ // inner loop
+ for(iy=0;iy<_matrixelement.size();++iy)
+ {
+ // map the vector index to the helicities
+ for(iya=_outspin.size()+1;iya>=0;--iya)
+ {ihel2[iya]=(iy%_constants[iya])/_constants[iya+1];}
+ // matrix element piece
+ temp=_matrixelement[ix]*conj(_matrixelement[iy]);
+ // spin denisty matrix for the incoming particles
+ temp*=rhoin0(ihel1[0],ihel2[0]);
+ temp*=rhoin1(ihel1[1],ihel2[1]);
+ // spin density matrix for the outgoing particles
+ for(unsigned int iz=0;iz<_outspin.size()-1;++iz)
+ {
+ if(int(iz)<id){temp*=rhoout[iz](ihel1[iz+2],ihel2[iz+2]);}
+ else{temp*=rhoout[iz](ihel1[iz+3],ihel2[iz+3]);}
+ }
+ output(ihel1[id+2],ihel2[id+2])+=temp;
+ }
+ }
+ // normalise the matrix so it has unit trace
+ output.normalize();
+ // return the answer
+ return output;
+}
+
+}
diff --git a/MatrixElement/ProductionMatrixElement.h b/MatrixElement/ProductionMatrixElement.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/ProductionMatrixElement.h
@@ -0,0 +1,454 @@
+// -*- C++ -*-
+//
+// ProductionMatrixElement.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_ProductionMatrixElement_H
+#define HERWIG_ProductionMatrixElement_H
+//
+// This is the declaration of the ProductionMatrixElement class.
+
+#include <ThePEG/Config/ThePEG.h>
+#include <ThePEG/Utilities/ClassDescription.h>
+#include <ThePEG/Helicity/RhoDMatrix.h>
+// #include "ProductionMatrixElement.fh"
+// #include "ProductionMatrixElement.xh"
+
+namespace Herwig {
+using ThePEG::Helicity::RhoDMatrix;
+
+using namespace ThePEG;
+
+/** \ingroup Helicity
+ *
+ * The storage of the helicity amplitude expression for the matrix element
+ * of a hard process. Two incoming particles and an arbitary number of
+ * external particles are supported.
+ *
+ * @see DecayMatrixElement
+ * @see RhoDMatrix
+ * @see HardVertex
+ *
+ * \author Peter Richardson
+ */
+
+class ProductionMatrixElement: public Base {
+
+public:
+
+ /** @name Standard constructors and destructors. */
+ //@{
+ /**
+ * Constructor for 2-1 scattering.
+ * @param in1 \f$2S+1\f$ for the first incoming particle.
+ * @param in2 \f$2S+1\f$ for the second incoming particle.
+ * @param out \f$2S+1\f$ for the outgoing particle.
+ */
+ inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out);
+
+ /**
+ * Constructor for 2-2 scattering.
+ * @param in1 \f$2S+1\f$ for the first incoming particle.
+ * @param in2 \f$2S+1\f$ for the second incoming particle.
+ * @param out1 \f$2S+1\f$ for the first outgoing particle.
+ * @param out2 \f$2S+1\f$ for the second outgoing particle.
+ */
+ inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
+ PDT::Spin out2);
+
+ /**
+ * Constructor for 2-3 scattering.
+ * @param in1 \f$2S+1\f$ for the first incoming particle.
+ * @param in2 \f$2S+1\f$ for the second incoming particle.
+ * @param out1 \f$2S+1\f$ for the first outgoing particle.
+ * @param out2 \f$2S+1\f$ for the second outgoing particle.
+ * @param out3 \f$2S+1\f$ for the third outgoing particle.
+ */
+ inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
+ PDT::Spin out2,PDT::Spin out3);
+
+ /**
+ * Constructor for 2-4 scattering.
+ * @param in1 \f$2S+1\f$ for the first incoming particle.
+ * @param in2 \f$2S+1\f$ for the second incoming particle.
+ * @param out1 \f$2S+1\f$ for the first outgoing particle.
+ * @param out2 \f$2S+1\f$ for the second outgoing particle.
+ * @param out3 \f$2S+1\f$ for the third outgoing particle.
+ * @param out4 \f$2S+1\f$ for the fourth outgoing particle.
+ */
+ inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
+ PDT::Spin out2,PDT::Spin out3, PDT::Spin out4);
+
+ /**
+ * Constructor for 2-5 scattering.
+ * @param in1 \f$2S+1\f$ for the first incoming particle.
+ * @param in2 \f$2S+1\f$ for the second incoming particle.
+ * @param out1 \f$2S+1\f$ for the first outgoing particle.
+ * @param out2 \f$2S+1\f$ for the second outgoing particle.
+ * @param out3 \f$2S+1\f$ for the third outgoing particle.
+ * @param out4 \f$2S+1\f$ for the fourth outgoing particle.
+ * @param out5 \f$2S+1\f$ for the fifth outgoing particle.
+ */
+ inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
+ PDT::Spin out2,PDT::Spin out3, PDT::Spin out4,
+ PDT::Spin out5);
+
+ /**
+ * Constructor for 2-6 scattering.
+ * @param in1 \f$2S+1\f$ for the first incoming particle.
+ * @param in2 \f$2S+1\f$ for the second incoming particle.
+ * @param out1 \f$2S+1\f$ for the first outgoing particle.
+ * @param out2 \f$2S+1\f$ for the second outgoing particle.
+ * @param out3 \f$2S+1\f$ for the third outgoing particle.
+ * @param out4 \f$2S+1\f$ for the fourth outgoing particle.
+ * @param out5 \f$2S+1\f$ for the fifth outgoing particle.
+ * @param out6 \f$2S+1\f$ for the sixth outgoing particle.
+ */
+ inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,PDT::Spin out1,
+ PDT::Spin out2,PDT::Spin out3, PDT::Spin out4,
+ PDT::Spin out5, PDT::Spin out6);
+
+ /**
+ * Constructor for 2-n scattering.
+ * @param in1 \f$2S+1\f$ for the first incoming particle.
+ * @param in2 \f$2S+1\f$ for the second incoming particle.
+ * @param out A vector containing \f$2S+1\f$ for the outgoing particles.
+ */
+ inline ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,vector<PDT::Spin> out);
+
+ /**
+ * Default constructor.
+ */
+ inline ProductionMatrixElement();
+ //@}
+
+public:
+
+ /** @name Access to the spins of the particles. */
+ //@{
+ /**
+ * Get the spins of the incoming particles particle
+ * @return A vector containing \f$2S+1\f$ for the two incoming particles.
+ */
+ inline vector<PDT::Spin> inspin();
+
+ /**
+ * Get the spins of the outgoing particles.
+ * @return A vector containing \f$2S+1\f$ for the outgoing particles.
+ */
+ inline vector<PDT::Spin> outspin();
+ //@}
+
+public:
+
+ /** @name Access to the individual helicity components. */
+ //@{
+
+ /**
+ * Access the helicity components for a 2-1 scattering. This method supplies
+ * the component but does not allow it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel The helicity of the outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel) const;
+
+ /**
+ * Access the helicity components for a 2-1 scattering. This method supplies
+ * the component and allows it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel The helicity of the outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel);
+
+ /**
+ * Access the helicity components for a 2-2 scattering. This method supplies
+ * the component but does not allow it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2) const;
+
+ /**
+ * Access the helicity components for a 2-2 scattering. This method supplies
+ * the component and allows it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2);
+
+ /**
+ * Access the helicity components for a 2-3 scattering. This method supplies
+ * the component but does not allow it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @param outhel3 The helicity of the third outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2,
+ unsigned int outhel3) const;
+
+ /**
+ * Access the helicity components for a 2-3 scattering. This method supplies
+ * the component and allows it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @param outhel3 The helicity of the third outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2,
+ unsigned int outhel3);
+
+ /**
+ * Access the helicity components for a 2-4 scattering. This method supplies
+ * the component but does not allow it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @param outhel3 The helicity of the third outgoing particle.
+ * @param outhel4 The helicity of the fourth outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2,
+ unsigned int outhel3,unsigned int outhel4) const;
+
+ /**
+ * Access the helicity components for a 2-4 scattering. This method supplies
+ * the component and allows it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @param outhel3 The helicity of the third outgoing particle.
+ * @param outhel4 The helicity of the fourth outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2,
+ unsigned int outhel3, unsigned int outhel4);
+
+ /**
+ * Access the helicity components for a 2-5 scattering. This method supplies
+ * the component but does not allow it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @param outhel3 The helicity of the third outgoing particle.
+ * @param outhel4 The helicity of the fourth outgoing particle.
+ * @param outhel5 The helicity of the fifth outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2,
+ unsigned int outhel3,unsigned int outhel4,
+ unsigned int outhel5) const;
+
+ /**
+ * Access the helicity components for a 2-5 scattering. This method supplies
+ * the component and allows it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @param outhel3 The helicity of the third outgoing particle.
+ * @param outhel4 The helicity of the fourth outgoing particle.
+ * @param outhel5 The helicity of the fifth outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2,
+ unsigned int outhel3, unsigned int outhel4,
+ unsigned int outhel5);
+
+ /**
+ * Access the helicity components for a 2-6 scattering. This method supplies
+ * the component but does not allow it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @param outhel3 The helicity of the third outgoing particle.
+ * @param outhel4 The helicity of the fourth outgoing particle.
+ * @param outhel5 The helicity of the fifth outgoing particle.
+ * @param outhel6 The helicity of the sixth outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2,
+ unsigned int outhel3,unsigned int outhel4,
+ unsigned int outhel5,unsigned int outhel6) const;
+
+ /**
+ * Access the helicity components for a 2-6 scattering. This method supplies
+ * the component and allows it to be changed.
+ * @param inhel1 The helicity of the first incoming particle.
+ * @param inhel2 The helicity of the second incoming particle.
+ * @param outhel1 The helicity of the first outgoing particle.
+ * @param outhel2 The helicity of the second outgoing particle.
+ * @param outhel3 The helicity of the third outgoing particle.
+ * @param outhel4 The helicity of the fourth outgoing particle.
+ * @param outhel5 The helicity of the fifth outgoing particle.
+ * @param outhel6 The helicity of the sixth outgoing particle.
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex & operator () (unsigned int inhel1,unsigned int inhel2,
+ unsigned int outhel1,unsigned int outhel2,
+ unsigned int outhel3, unsigned int outhel4,
+ unsigned int outhel5, unsigned int outhel6);
+
+
+ /**
+ * Access the helicity components for a 2-n scattering. This method supplies
+ * the component but does not allow it to be changed.
+ * @param hel The helicities of the incoming and outgoing particles
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex operator () (vector<unsigned int> hel) const;
+
+ /**
+ * Access the helicity components for a 2-n scattering. This method supplies
+ * the component and allows it to be changed.
+ * @param hel The helicities of the incoming and outgoing particles
+ * @return The matrix element for the given helicities.
+ */
+ inline Complex & operator () (vector<unsigned int> hel);
+ //@}
+
+public:
+
+ /**
+ * Calculate the decay matrix for an incoming particle.
+ */
+ RhoDMatrix calculateDMatrix(int,RhoDMatrix, vector<RhoDMatrix>);
+
+ /**
+ * Calculate the rho matrix for a given outgoing particle.
+ */
+ RhoDMatrix calculateRhoMatrix(int,RhoDMatrix,RhoDMatrix,
+ vector<RhoDMatrix>);
+
+public:
+
+ /**
+ * Reset the matrix element.
+ */
+ inline void reset(const ProductionMatrixElement &) const;
+
+public:
+
+ /**
+ * Standard Init function used to initialize the interfaces.
+ */
+ static void Init();
+
+private:
+
+ /**
+ * Describe a concrete class without persistent data.
+ */
+ static NoPIOClassDescription<ProductionMatrixElement> initProductionMatrixElement;
+
+ /**
+ * Private and non-existent assignment operator.
+ */
+ ProductionMatrixElement & operator=(const ProductionMatrixElement& );
+
+private:
+
+ /**
+ * Set the size of the vector containing the matrix element.
+ */
+ inline void setMESize();
+
+private:
+
+ /**
+ * Number of outgoing particles.
+ */
+ mutable unsigned int _nout;
+
+ /**
+ * Spin of the incoming particles as 2s+1.
+ */
+ mutable vector<PDT::Spin> _inspin;
+
+ /**
+ * Spins of the outgoing particles.
+ */
+ mutable vector<PDT::Spin> _outspin;
+
+ /**
+ * Storage of the matrix element, a vector is better for memory usage.
+ */
+ mutable vector<Complex> _matrixelement;
+
+ /**
+ * Constants needed to map the index of the vector to a helicity structure.
+ */
+ mutable vector<int> _constants;
+
+};
+
+}
+
+
+namespace ThePEG {
+
+/** @cond TRAITSPECIALIZATIONS */
+
+/**
+ * The following template specialization informs ThePEG about the
+ * base class of ProductionMatrixElement.
+ */
+template <>
+struct BaseClassTrait<Herwig::ProductionMatrixElement,1> {
+ /** Typedef of the base class of ProductionMatrixElement. */
+ typedef Base NthBase;
+};
+
+/**
+ * The following template specialization informs ThePEG about the
+ * name of this class and the shared object where it is defined.
+ */
+template <>
+struct ClassTraits<Herwig::ProductionMatrixElement>
+ : public ClassTraitsBase<Herwig::ProductionMatrixElement> {
+
+ /**
+ * Return the class name.
+ */
+ static string className() { return "Herwig::ProductionMatrixElement"; }
+};
+
+/** @endcond */
+
+}
+
+#include "ProductionMatrixElement.icc"
+
+#endif /* HERWIG_ProductionMatrixElement_H */
diff --git a/MatrixElement/ProductionMatrixElement.icc b/MatrixElement/ProductionMatrixElement.icc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/ProductionMatrixElement.icc
@@ -0,0 +1,402 @@
+// -*- C++ -*-
+//
+// ProductionMatrixElement.icc 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 inlined member functions of
+// the ProductionMatrixElement class.
+//
+// Author: Peter Richardson
+//
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+// default constructor
+inline ProductionMatrixElement::ProductionMatrixElement() {}
+
+// constructor for 2-1 scattering
+inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,
+ PDT::Spin out1)
+{
+ _nout=2;
+ _inspin.resize(2);
+ _inspin[0]=in1; _inspin[1]=in2;
+ _outspin.push_back(out1);
+ setMESize();
+}
+// constructor for 2-2 scattering
+inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1,PDT::Spin in2,
+ PDT::Spin out1,PDT::Spin out2)
+{
+ _nout=2;
+ _inspin.resize(2);
+ _inspin[0]=in1; _inspin[1]=in2;
+ _outspin.push_back(out1);_outspin.push_back(out2);
+ setMESize();
+}
+
+// constructor for 2-3 scattering
+inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
+ PDT::Spin out1,PDT::Spin out2,
+ PDT::Spin out3)
+{
+ _inspin.resize(2);
+ _nout=3; _inspin[0]=in1; _inspin[1]=in2;
+ _outspin.push_back(out1);_outspin.push_back(out2);_outspin.push_back(out3);
+ setMESize();
+}
+
+// constructor for 2-4 scattering
+ inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
+ PDT::Spin out1,PDT::Spin out2,
+ PDT::Spin out3,PDT::Spin out4)
+{
+ _nout=4;
+ _inspin.resize(2);
+ _inspin[0]=in1; _inspin[1]=in2;
+ _outspin.push_back(out1);_outspin.push_back(out2);
+ _outspin.push_back(out3);_outspin.push_back(out4);
+ setMESize();
+}
+
+// constructor for 2-5 scattering
+inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
+ PDT::Spin out1,PDT::Spin out2,
+ PDT::Spin out3,PDT::Spin out4,
+ PDT::Spin out5)
+{
+ _nout=5;
+ _inspin.resize(2);
+ _inspin[0]=in1; _inspin[1]=in2;
+ _outspin.push_back(out1);_outspin.push_back(out2);
+ _outspin.push_back(out3);_outspin.push_back(out4);_outspin.push_back(out5);
+ setMESize();
+}
+
+// constructor for 2-6 scattering
+inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
+ PDT::Spin out1,PDT::Spin out2,
+ PDT::Spin out3,PDT::Spin out4,
+ PDT::Spin out5,PDT::Spin out6)
+{
+ _nout=6;
+ _inspin.resize(2);
+ _inspin[0]=in1; _inspin[1]=in2;
+ _outspin.push_back(out1);_outspin.push_back(out2);
+ _outspin.push_back(out3);_outspin.push_back(out4);
+ _outspin.push_back(out5);_outspin.push_back(out6);
+ setMESize();
+}
+
+// constructor for 2-n scattering
+inline ProductionMatrixElement::ProductionMatrixElement(PDT::Spin in1, PDT::Spin in2,
+ vector<PDT::Spin> out)
+{
+ _inspin.resize(2);
+ _nout=out.size(); _inspin[0]=in1; _inspin[1]=in2;
+ _outspin=out;setMESize();
+}
+
+// set the size of the vector containing the matrix element
+inline void ProductionMatrixElement::setMESize()
+{
+ unsigned int ix;
+ int isize=_inspin[0]*_inspin[1];
+ for(ix=0;ix<_outspin.size();++ix){isize*=_outspin[ix];}
+ // zero the matrix element
+ _matrixelement.resize(isize,0.);
+ // set up the constants for the mapping of helicity to vectro index
+ _constants.resize(_outspin.size()+3);
+ unsigned int temp=1;
+ for(ix=_outspin.size()+1;ix>1;--ix){temp*=_outspin[ix-2];_constants[ix]=temp;}
+ temp*=_inspin[1];_constants[1]=temp;
+ temp*=_inspin[0];_constants[0]=temp;
+ _constants[_outspin.size()+2]=1;
+}
+
+// get the spins of the incoming particles particle
+inline vector<PDT::Spin> ProductionMatrixElement::inspin(){return _inspin;}
+
+// get the spins of the outgoing particles
+inline vector<PDT::Spin> ProductionMatrixElement::outspin(){return _outspin;}
+
+// access to the individual helicity components (2-2 scattering)
+inline Complex ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1) const
+{
+ // check this is really a 2-2 matrix element
+ if(_outspin.size()!=1)
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Requested component of 2-1 matrix element"
+ << " but matrix element is 2-"
+ << _outspin.size() << Exception::abortnow;
+ return 0.;
+ }
+ unsigned int iloc(0);
+ iloc+=in1*_constants[1];
+ iloc+=in2*_constants[2];
+ iloc+=out1*_constants[3];
+ if(iloc>=_matrixelement.size())
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Invalid component of 2-1 matrix element requested"
+ << Exception::abortnow;
+ return 0.;
+ }
+ return _matrixelement[iloc];
+}
+
+// access to the individual helicity components (2-2 scattering)
+inline Complex ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2) const
+{
+ // check this is really a 2-2 matrix element
+ if(_outspin.size()!=2)
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Requested component of 2-2 matrix element but matrix element is 2-"
+ << _outspin.size() << Exception::abortnow;
+ return 0.;
+ }
+ unsigned int iloc(0);
+ iloc+=in1*_constants[1];
+ iloc+=in2*_constants[2];
+ iloc+=out1*_constants[3];
+ iloc+=out2*_constants[4];
+ if(iloc>=_matrixelement.size())
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Invalid component of 2-2 matrix element requested"
+ << Exception::abortnow;
+ return 0.;
+ }
+ return _matrixelement[iloc];
+}
+
+// access to the individual helicity components (2-3 scattering)
+inline Complex ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,
+ unsigned int out1,unsigned int out2,unsigned int out3) const
+{
+ if(_outspin.size()!=3)
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Requested component of 2-3 matrix element but matrix element is 2-"
+ << _outspin.size() << Exception::abortnow;
+ return 0.;
+ }
+ // map the indices to the location in the vector
+ vector<unsigned int> ivec(5);
+ ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
+ return (*this)(ivec);
+}
+
+// access to the individual helicity components (2-4 scattering)
+inline Complex ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
+ unsigned int out3,unsigned int out4) const
+{
+ if(_outspin.size()!=4)
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Requested component of 2-4 matrix element but matrix element is 2-"
+ << _outspin.size() << Exception::abortnow;
+ return 0.;
+ }
+ vector<unsigned int> ivec(6);
+ ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
+ ivec[5]=out4;
+ return (*this)(ivec);
+}
+
+
+// access to the individual helicity components (2-5 scattering)
+inline Complex ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
+ unsigned int out3,unsigned int out4, unsigned int out5) const
+{
+ if(_outspin.size()!=5)
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Requested component of 2-4 matrix element but matrix element is 2-"
+ << _outspin.size() << Exception::abortnow;
+ return 0.;
+ }
+ vector<unsigned int> ivec(7);
+ ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
+ ivec[5]=out4;ivec[6]=out5;
+ return (*this)(ivec);
+}
+
+
+// access to the individual helicity components (2-6 scattering)
+inline Complex ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
+ unsigned int out3,unsigned int out4, unsigned int out5, unsigned int out6) const
+{
+ if(_outspin.size()!=6)
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Requested component of 2-6 matrix element but matrix element is 2-"
+ << _outspin.size() << Exception::abortnow;
+ return 0.;
+ }
+ vector<unsigned int> ivec(8);
+ ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
+ ivec[5]=out4;ivec[6]=out5;ivec[7]=out6;
+ return (*this)(ivec);
+}
+
+
+// access to the individual helicity components (2-n scattering)
+inline Complex ProductionMatrixElement::operator ()
+ (vector<unsigned int> in) const
+{
+ if(_outspin.size()!=in.size()-2)
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Requested component of 2-" << in.size()
+ << " matrix element but matrix element is 2-"
+ << _outspin.size() << Exception::abortnow;
+ return 0.;
+ }
+ unsigned int iloc(0),ix;
+ // incoming and outgoing particles
+ for(ix=0;ix<in.size();++ix){iloc+=in[ix]*_constants[ix+1];}
+ if(iloc>=_matrixelement.size())
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Invalid component of 2-n matrix element requested"
+ << Exception::abortnow;
+ return 0.;
+ }
+ return _matrixelement[iloc];
+}
+
+// set the individual helicity components (2-1 scattering)
+inline Complex & ProductionMatrixElement::operator () (unsigned int in1,unsigned int in2,
+ unsigned int out1)
+{
+ static Complex dummy=0.;
+ unsigned int iloc(0);
+ iloc+= in1*_constants[1];
+ iloc+= in2*_constants[2];
+ iloc+=out1*_constants[3];
+ if(iloc>=_matrixelement.size())
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Invalid component of 2-1 matrix element requested"
+ << Exception::abortnow;
+ return dummy;
+ }
+ return _matrixelement[iloc];
+}
+
+// set the individual helicity components (2-2 scattering)
+inline Complex & ProductionMatrixElement::operator () (unsigned int in1,
+ unsigned int in2,
+ unsigned int out1,
+ unsigned int out2)
+{
+ static Complex dummy=0.;
+ unsigned int iloc(0);
+ iloc+= in1*_constants[1];
+ iloc+= in2*_constants[2];
+ iloc+=out1*_constants[3];
+ iloc+=out2*_constants[4];
+ if(iloc>=_matrixelement.size())
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Invalid component of 2-2 matrix element requested"
+ << Exception::abortnow;
+ return dummy;
+ }
+ return _matrixelement[iloc];
+}
+
+// set the individual helicity components (2-3 scattering)
+inline Complex & ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
+ unsigned int out3)
+{
+ vector<unsigned int> ivec(5);
+ ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
+ return (*this)(ivec);
+}
+
+// set the individual helicity components (2-4 scattering)
+inline Complex & ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
+ unsigned int out3, unsigned int out4)
+{
+ vector<unsigned int> ivec(6);
+ ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
+ ivec[5]=out4;
+ return (*this)(ivec);
+}
+
+// set the individual helicity components (2-5 scattering)
+inline Complex & ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
+ unsigned int out3, unsigned int out4, unsigned int out5)
+{
+ vector<unsigned int> ivec(7);
+ ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
+ ivec[5]=out4; ivec[6]=out5;
+ return (*this)(ivec);
+}
+
+// set the individual helicity components (2-6 scattering)
+inline Complex & ProductionMatrixElement::operator ()
+ (unsigned int in1,unsigned int in2,unsigned int out1,unsigned int out2,
+ unsigned int out3, unsigned int out4, unsigned int out5, unsigned int out6)
+{
+ vector<unsigned int> ivec(8);
+ ivec[0]=in1;ivec[1]=in2;ivec[2]=out1;ivec[3]=out2;ivec[4]=out3;
+ ivec[5]=out4; ivec[6]=out5; ivec[7]=out6;
+ return (*this)(ivec);
+}
+
+inline Complex & ProductionMatrixElement::operator ()
+ (vector<unsigned int> in)
+{
+ static Complex dummy=0;
+ if(_outspin.size()!=in.size()-2)
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Requested component of 2-" << in.size()
+ << " matrix element but matrix element is 2-"
+ << _outspin.size() << Exception::abortnow;
+ return dummy;
+ }
+ unsigned int iloc=0;
+ // incoming particles
+ for(unsigned int ix=0;ix<in.size();++ix){iloc+=in[ix]*_constants[ix+1];}
+ if(iloc>=_matrixelement.size())
+ {
+ throw ThePEG::Helicity::HelicityConsistencyError()
+ << "Invalid component of 2-n matrix element requested"
+ << Exception::abortnow;
+ return dummy;
+ }
+ return _matrixelement[iloc];
+}
+
+// reset the matrix element
+inline void ProductionMatrixElement::reset(const ProductionMatrixElement & x) const
+{
+ _nout = x._nout;
+ _inspin = x._inspin;
+ _outspin =x._outspin;
+ _matrixelement=x._matrixelement;
+ _constants=x._constants;
+}
+
+}

File Metadata

Mime Type
text/x-diff
Expires
Wed, May 14, 10:51 AM (20 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5109191
Default Alt Text
(826 KB)

Event Timeline