Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7877333
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
117 KB
Subscribers
None
View Options
diff --git a/Decay/General/GeneralTwoBodyDecayer.h b/Decay/General/GeneralTwoBodyDecayer.h
--- a/Decay/General/GeneralTwoBodyDecayer.h
+++ b/Decay/General/GeneralTwoBodyDecayer.h
@@ -1,306 +1,271 @@
// -*- C++ -*-
//
// GeneralTwoBodyDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_GeneralTwoBodyDecayer_H
#define HERWIG_GeneralTwoBodyDecayer_H
//
// This is the declaration of the GeneralTwoBodyDecayer class.
//
#include "Herwig/Decay/PerturbativeDecayer.h"
#include "Herwig/Decay/DecayPhaseSpaceMode.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "GeneralTwoBodyDecayer.fh"
+#include "GeneralTwoBodyDecayer2.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
/** \ingroup Decay
* The GeneralTwoBodyDecayer class is designed to be the base class
* for 2 body decays for some general model. It inherits from
* PerturbativeDecayer and implements the modeNumber() virtual function
* that is the same for all of the decays. A decayer for
* a specific spin configuration should inherit from this and implement
* the me2() and partialWidth() member functions. The colourConnections()
* member should be called from inside me2() in the inheriting decayer
* to set up the colour lines.
*
* @see \ref GeneralTwoBodyDecayerInterfaces "The interfaces"
* defined for GeneralTwoBodyDecayer.
* @see PerturbativeDecayer
*/
class GeneralTwoBodyDecayer: public PerturbativeDecayer {
public:
/** A ParticleData ptr and (possible) mass pair.*/
typedef pair<tcPDPtr, Energy> PMPair;
public:
/**
* The default constructor.
*/
GeneralTwoBodyDecayer() : maxWeight_(1.), colour_(1,DVector(1,1.))
{}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* For a given decay mode and a given particle instance, perform the
* decay and return the decay products. As this is the base class this
* is not implemented.
* @return The vector of particles produced in the decay.
*/
virtual ParticleVector decay(const Particle & parent,
const tPDVector & children) const;
/**
* Which of the possible decays is required
* @param cc Is this mode the charge conjugate
* @param parent The decaying particle
* @param children The decay products
*/
virtual int modeNumber(bool & cc, tcPDPtr parent,const tPDVector & children) const;
/**
* Return the matrix element squared for a given mode and phase-space channel
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int , const Particle & part,
const ParticleVector & decay, MEOption meopt) const = 0;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
/**
* Specify the \f$1\to2\f$ matrix element to be used in the running width
* calculation.
* @param dm The DecayMode
* @param mecode The code for the matrix element as described
* in the GenericWidthGenerator class.
* @param coupling The coupling for the matrix element.
* @return True if the the order of the particles in the
* decayer is the same as the DecayMode tag.
*/
virtual bool twoBodyMEcode(const DecayMode & dm, int & mecode,
double & coupling) const;
/**
* An overidden member to calculate a branching ratio for a certain
* particle instance.
* @param dm The DecayMode of the particle
* @param p The particle object
* @param oldbrat The branching fraction given in the DecayMode object
*/
virtual double brat(const DecayMode & dm, const Particle & p,
double oldbrat) const;
//@}
/**
* Set the information on the decay
*/
virtual void setDecayInfo(PDPtr incoming, PDPair outgoing,
vector<VertexBasePtr>,
map<ShowerInteraction,VertexBasePtr> &,
const vector<map<ShowerInteraction,VertexBasePtr> > &,
map<ShowerInteraction,VertexBasePtr>) =0;
protected:
/** @name Functions used by inheriting decayers. */
//@{
/**
* Set integration weight
* @param wgt Maximum integration weight
*/
void setWeight(double wgt) { maxWeight_ = wgt; }
/**
* Set colour connections
* @param parent Parent particle
* @param out Particle vector containing particles to
* connect colour lines
*/
void colourConnections(const Particle & parent,
const ParticleVector & out) const;
/**
* Compute the spin and colour factor
*/
double colourFactor(tcPDPtr in, tcPDPtr out1, tcPDPtr out2) const;
/**
* Calculate matrix element ratio R/B
*/
double matrixElementRatio(const Particle & inpart, const ParticleVector & decay2,
const ParticleVector & decay3, MEOption meopt,
ShowerInteraction inter);
/**
* Set the information on the decay
*/
void decayInfo(PDPtr incoming, PDPair outgoing);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
protected:
/**
* Member for the generation of additional hard radiation
*/
//@{
/**
* Return the matrix of colour factors
*/
typedef vector<pair<int,double > > CFlowPairVec;
typedef vector<CFlowPairVec> CFlow;
const vector<DVector> & getColourFactors(const Particle & inpart,
const ParticleVector & decay,
unsigned int & nflow);
const CFlow & colourFlows(const Particle & inpart,
const ParticleVector & decay);
/**
* Three-body matrix element including additional QCD radiation
*/
virtual double threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay,
ShowerInteraction inter, MEOption meopt);
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GeneralTwoBodyDecayer & operator=(const GeneralTwoBodyDecayer &);
private:
/**
* Store the incoming particle
*/
PDPtr incoming_;
/**
* Outgoing particles
*/
vector<PDPtr> outgoing_;
/**
* Maximum weight for integration
*/
double maxWeight_;
/**
* Store colour factors for ME calc.
*/
vector<DVector> colour_;
};
-
-/**
- * Write a map with ShowerInteraction as the key
- */
-template<typename T, typename Cmp, typename A>
-inline PersistentOStream & operator<<(PersistentOStream & os,
- const map<ShowerInteraction,T,Cmp,A> & m) {
- os << m.size();
- if(m.find(ShowerInteraction::QCD)!=m.end()) {
- os << 0 << m.at(ShowerInteraction::QCD);
- }
- if(m.find(ShowerInteraction::QED)!=m.end()) {
- os << 1 << m.at(ShowerInteraction::QED);
- }
- return os;
}
-/**
- * Read a map with ShowerInteraction as the key
- */
-template <typename T, typename Cmp, typename A>
-inline PersistentIStream & operator>>(PersistentIStream & is, map<ShowerInteraction,T,Cmp,A> & m) {
- m.clear();
- long size;
- int k;
- is >> size;
- while ( size-- && is ) {
- is >> k;
- if(k==0)
- is >> m[ShowerInteraction::QCD];
- else if(k==1)
- is >> m[ShowerInteraction::QED];
- else
- assert(false);
- }
- return is;
-}
-}
#endif /* HERWIG_GeneralTwoBodyDecayer_H */
diff --git a/Decay/General/GeneralTwoBodyDecayer2.cc b/Decay/General/GeneralTwoBodyDecayer2.cc
--- a/Decay/General/GeneralTwoBodyDecayer2.cc
+++ b/Decay/General/GeneralTwoBodyDecayer2.cc
@@ -1,819 +1,823 @@
// -*- C++ -*-
//
// GeneralTwoBodyDecayer2.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GeneralTwoBodyDecayer2 class.
//
#include "GeneralTwoBodyDecayer2.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Utilities/Exception.h"
#include "Herwig/Shower/RealEmissionProcess.h"
using namespace Herwig;
ParticleVector GeneralTwoBodyDecayer2::decay(const Particle & parent,
const tPDVector & children) const {
// return empty vector if products heavier than parent
Energy mout(ZERO);
for(tPDVector::const_iterator it=children.begin();
it!=children.end();++it) mout+=(**it).massMin();
if(mout>parent.mass()) return ParticleVector();
// generate the decay
bool cc;
int imode=modeNumber(cc,parent.dataPtr(),children);
// generate the kinematics
ParticleVector decay=generate(generateIntermediates(),cc,imode,parent);
// make the colour connections
colourConnections(parent, decay);
// return the answer
return decay;
}
void GeneralTwoBodyDecayer2::doinit() {
PerturbativeDecayer2::doinit();
assert( incoming_ && outgoing_.size()==2);
//create phase space mode
addMode(new_ptr(PhaseSpaceMode(incoming_,{outgoing_[0],outgoing_[1]},
maxWeight_)));
}
int GeneralTwoBodyDecayer2::modeNumber(bool & cc, tcPDPtr parent,
const tPDVector & children) const {
long parentID = parent->id();
long id1 = children[0]->id();
long id2 = children[1]->id();
cc = false;
long out1 = outgoing_[0]->id();
long out2 = outgoing_[1]->id();
if( parentID == incoming_->id() &&
((id1 == out1 && id2 == out2) ||
(id1 == out2 && id2 == out1)) ) {
return 0;
}
else if(incoming_->CC() && parentID == incoming_->CC()->id()) {
cc = true;
if( outgoing_[0]->CC()) out1 = outgoing_[0]->CC()->id();
if( outgoing_[1]->CC()) out2 = outgoing_[1]->CC()->id();
if((id1 == out1 && id2 == out2) ||
(id1 == out2 && id2 == out1)) return 0;
}
return -1;
}
void GeneralTwoBodyDecayer2::
colourConnections(const Particle & parent,
const ParticleVector & out) const {
PDT::Colour incColour(parent.data().iColour());
PDT::Colour outaColour(out[0]->data().iColour());
PDT::Colour outbColour(out[1]->data().iColour());
//incoming colour singlet
if(incColour == PDT::Colour0) {
// colour triplet-colourantitriplet
if((outaColour == PDT::Colour3 && outbColour == PDT::Colour3bar) ||
(outaColour == PDT::Colour3bar && outbColour == PDT::Colour3)) {
bool ac(out[0]->id() < 0);
out[0]->colourNeighbour(out[1],!ac);
}
//colour octet
else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour8) {
out[0]->colourNeighbour(out[1]);
out[0]->antiColourNeighbour(out[1]);
}
// colour singlets
else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour0) {
}
// unknown
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour singlet in "
<< "GeneralTwoBodyDecayer2::colourConnections "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
//incoming colour triplet
else if(incColour == PDT::Colour3) {
// colour triplet + singlet
if(outaColour == PDT::Colour3 && outbColour == PDT::Colour0) {
out[0]->incomingColour(const_ptr_cast<tPPtr>(&parent));
}
//opposite order
else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour3) {
out[1]->incomingColour(const_ptr_cast<tPPtr>(&parent));
}
// octet + triplet
else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour3) {
out[0]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[1]->antiColourNeighbour(out[0]);
}
//opposite order
else if(outaColour == PDT::Colour3 && outbColour == PDT::Colour8) {
out[1]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[0]->antiColourNeighbour(out[1]);
}
else if(outaColour == PDT::Colour3bar && outaColour == PDT::Colour3bar) {
tColinePtr col[2] = {ColourLine::create(out[0],true),
ColourLine::create(out[1],true)};
parent.colourLine()->setSinkNeighbours(col[0],col[1]);
}
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour triplet in "
<< "GeneralTwoBodyDecayer2::colourConnections() "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
// incoming colour anti triplet
else if(incColour == PDT::Colour3bar) {
// colour antitriplet +singlet
if(outaColour == PDT::Colour3bar && outbColour == PDT::Colour0) {
out[0]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
//opposite order
else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour3bar) {
out[1]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
//octet + antitriplet
else if(outaColour == PDT::Colour3bar && outbColour == PDT::Colour8) {
out[1]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
out[0]->colourNeighbour(out[1]);
}
//opposite order
else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour3bar) {
out[0]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
out[1]->colourNeighbour(out[0]);
}
else if(outaColour == PDT::Colour3 && outbColour == PDT::Colour3) {
tColinePtr col[2] = {ColourLine::create(out[0]),
ColourLine::create(out[1])};
parent.antiColourLine()->setSourceNeighbours(col[0],col[1]);
}
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour antitriplet "
<< "in GeneralTwoBodyDecayer2::colourConnections() "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
//incoming colour octet
else if(incColour == PDT::Colour8) {
// triplet-antitriplet
if(outaColour == PDT::Colour3&&outbColour == PDT::Colour3bar) {
out[0]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[1]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
// opposite order
else if(outbColour == PDT::Colour3&&outaColour == PDT::Colour3bar) {
out[0]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
out[1]->incomingColour(const_ptr_cast<tPPtr>(&parent));
}
// neutral octet
else if(outaColour == PDT::Colour0&&outbColour == PDT::Colour8) {
out[1]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[1]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
else if(outbColour == PDT::Colour0&&outaColour == PDT::Colour8) {
out[0]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[0]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour octet "
<< "in GeneralTwoBodyDecayer2::colourConnections() "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
else if(incColour == PDT::Colour6) {
if(outaColour == PDT::Colour3 && outbColour == PDT::Colour3) {
tPPtr tempParent = const_ptr_cast<tPPtr>(&parent);
Ptr<MultiColour>::pointer parentColour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
(tempParent->colourInfo());
tColinePtr line1 = const_ptr_cast<tColinePtr>(parentColour->colourLines()[0]);
line1->addColoured(dynamic_ptr_cast<tPPtr>(out[0]));
tColinePtr line2 = const_ptr_cast<tColinePtr>(parentColour->colourLines()[1]);
line2->addColoured(dynamic_ptr_cast<tPPtr>(out[1]));
}
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour sextet "
<< "in GeneralTwoBodyDecayer2::colourConnections() "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
else if(incColour == PDT::Colour6bar) {
if(outaColour == PDT::Colour3bar && outbColour == PDT::Colour3bar) {
tPPtr tempParent = const_ptr_cast<tPPtr>(&parent);
Ptr<MultiColour>::pointer parentColour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
(tempParent->colourInfo());
tColinePtr line1 = const_ptr_cast<tColinePtr>(parentColour->antiColourLines()[0]);
line1->addAntiColoured(dynamic_ptr_cast<tPPtr>(out[0]));
tColinePtr line2 = const_ptr_cast<tColinePtr>(parentColour->antiColourLines()[1]);
line2->addAntiColoured(dynamic_ptr_cast<tPPtr>(out[1]));
}
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour anti-sextet "
<< "in GeneralTwoBodyDecayer2::colourConnections() "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
else
throw Exception() << "Unknown incoming colour in "
<< "GeneralTwoBodyDecayer2::colourConnections() "
<< incColour
<< Exception::runerror;
}
bool GeneralTwoBodyDecayer2::twoBodyMEcode(const DecayMode & dm, int & mecode,
double & coupling) const {
assert(dm.parent()->id() == incoming_->id());
ParticleMSet::const_iterator pit = dm.products().begin();
long id1 = (*pit)->id();
++pit;
long id2 = (*pit)->id();
long id1t(outgoing_[0]->id()), id2t(outgoing_[1]->id());
mecode = -1;
coupling = 1.;
if( id1 == id1t && id2 == id2t ) {
return true;
}
else if( id1 == id2t && id2 == id1t ) {
return false;
}
else
assert(false);
return false;
}
void GeneralTwoBodyDecayer2::persistentOutput(PersistentOStream & os) const {
os << incoming_ << outgoing_ << maxWeight_;
}
void GeneralTwoBodyDecayer2::persistentInput(PersistentIStream & is, int) {
is >> incoming_ >> outgoing_ >> maxWeight_;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeAbstractClass<GeneralTwoBodyDecayer2,PerturbativeDecayer2>
describeHerwigGeneralTwoBodyDecayer2("Herwig::GeneralTwoBodyDecayer2", "Herwig.so");
void GeneralTwoBodyDecayer2::Init() {
static ClassDocumentation<GeneralTwoBodyDecayer2> documentation
("This class is designed to be a base class for all 2 body decays"
"in a general model");
}
double GeneralTwoBodyDecayer2::brat(const DecayMode &, const Particle & p,
double oldbrat) const {
ParticleVector children = p.children();
if( children.size() != 2 || !p.data().widthGenerator() )
return oldbrat;
// partial width for this mode
Energy scale = p.mass();
Energy pwidth =
partialWidth( make_pair(p.dataPtr(), scale),
make_pair(children[0]->dataPtr(), children[0]->mass()),
make_pair(children[1]->dataPtr(), children[1]->mass()) );
Energy width = p.data().widthGenerator()->width(p.data(), scale);
return pwidth/width;
}
void GeneralTwoBodyDecayer2::doinitrun() {
PerturbativeDecayer2::doinitrun();
for(unsigned int ix=0;ix<numberModes();++ix) {
double fact = pow(1.5,int(mode(ix)->incoming().first->iSpin())-1);
mode(ix)->maxWeight(fact*mode(ix)->maxWeight());
}
}
double GeneralTwoBodyDecayer2::colourFactor(tcPDPtr in, tcPDPtr out1,
tcPDPtr out2) const {
// identical particle symmetry factor
double output = out1->id()==out2->id() ? 0.5 : 1.;
// colour neutral incoming particle
if(in->iColour()==PDT::Colour0) {
// both colour neutral
if(out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour0)
output *= 1.;
// colour triplet/ antitriplet
else if((out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3bar) ||
(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3 ) ) {
output *= 3.;
}
// colour octet colour octet
else if(out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour8 ) {
output *= 8.;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour neutral particle in "
<< "GeneralTwoBodyDecayer2::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
// triplet
else if(in->iColour()==PDT::Colour3) {
// colour triplet + neutral
if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour3) ||
(out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour0) ) {
output *= 1.;
}
// colour triplet + octet
else if((out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour3) ||
(out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour8) ) {
output *= 4./3.;
}
// colour anti triplet anti triplet
else if(out1->iColour()==PDT::Colour3bar &&
out2->iColour()==PDT::Colour3bar) {
output *= 2.;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour triplet particle in "
<< "GeneralTwoBodyDecayer2::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
// anti triplet
else if(in->iColour()==PDT::Colour3bar) {
// colour anti triplet + neutral
if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour3bar ) ||
(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour0 ) ) {
output *= 1.;
}
// colour anti triplet + octet
else if((out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour3bar ) ||
(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour8 ) ) {
output *= 4./3.;
}
// colour triplet triplet
else if(out1->iColour()==PDT::Colour3 &&
out2->iColour()==PDT::Colour3) {
output *= 2.;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour anti triplet particle in "
<< "GeneralTwoBodyDecayer2::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
else if(in->iColour()==PDT::Colour8) {
// colour octet + neutral
if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour8 ) ||
(out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour0 ) ) {
output *= 1.;
}
// colour triplet/antitriplet
else if((out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3bar) ||
(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3 ) ) {
output *= 0.5;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour octet particle in "
<< "GeneralTwoBodyDecayer2::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
else if(in->iColour()==PDT::Colour6) {
// colour sextet -> triplet triplet
if( out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3 ) {
output *= 1.;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour sextet particle in "
<< "GeneralTwoBodyDecayer2::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
else if(in->iColour()==PDT::Colour6bar) {
// colour sextet -> triplet triplet
if( out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3bar ) {
output *= 1.;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour anti-sextet particle in "
<< "GeneralTwoBodyDecayer2::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
else
throw Exception() << "Unknown colour "
<< in->iColour() << " for the decaying particle in "
<< "GeneralTwoBodyDecayer2::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
return output;
}
Energy GeneralTwoBodyDecayer2::partialWidth(PMPair inpart, PMPair outa,
- PMPair outb) const {
+ PMPair outb) const {
// select the number of the mode
tPDVector children;
children.push_back(const_ptr_cast<PDPtr>(outa.first));
children.push_back(const_ptr_cast<PDPtr>(outb.first));
bool cc;
int nmode=modeNumber(cc,inpart.first,children);
tcPDPtr newchild[2] = {mode(nmode)->outgoing()[0],
mode(nmode)->outgoing()[1]};
// make the particles
Lorentz5Momentum pparent = Lorentz5Momentum(inpart.second);
PPtr parent = inpart.first->produceParticle(pparent);
- Lorentz5Momentum pout[2];
+ vector<Lorentz5Momentum> pout(2);
double ctheta,phi;
Kinematics::generateAngles(ctheta,phi);
Kinematics::twoBodyDecay(pparent, outa.second, outb.second,
ctheta, phi,pout[0],pout[1]);
if( ( !cc && outa.first!=newchild[0]) ||
( cc && !(( outa.first->CC() && outa.first->CC() == newchild[0])||
( !outa.first->CC() && outa.first == newchild[0]) )))
swap(pout[0],pout[1]);
- ParticleVector decay;
- decay.push_back(newchild[0]->produceParticle(pout[0]));
- decay.push_back(newchild[1]->produceParticle(pout[1]));
- double me = me2(-1,*parent,decay,Initialize);
+ tPDVector out = {const_ptr_cast<tPDPtr>(outa.first),
+ const_ptr_cast<tPDPtr>(outb.first)};
+ double me = me2(-1,*parent,out,pout,Initialize);
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,
outa.second, outb.second);
return me/(8.*Constants::pi)*pcm;
}
void GeneralTwoBodyDecayer2::decayInfo(PDPtr incoming, PDPair outgoing) {
incoming_=incoming;
outgoing_.clear();
outgoing_.push_back(outgoing.first );
outgoing_.push_back(outgoing.second);
}
double GeneralTwoBodyDecayer2::matrixElementRatio(const Particle & inpart,
- const ParticleVector & decay2,
- const ParticleVector & decay3,
- MEOption meopt,
- ShowerInteraction inter) {
+ const ParticleVector & decay2,
+ const ParticleVector & decay3,
+ MEOption meopt,
+ ShowerInteraction inter) {
// calculate R/B
- double B = me2 (0, inpart, decay2, meopt);
+ tPDVector outgoing = {const_ptr_cast<tPDPtr>(decay2[0]->dataPtr()),
+ const_ptr_cast<tPDPtr>(decay2[1]->dataPtr())};
+ const vector<Lorentz5Momentum> mom = {decay2[0]->momentum(),
+ decay2[1]->momentum()};
+
+ double B = me2 (0, inpart, outgoing,mom, meopt);
double R = threeBodyME(0, inpart, decay3, inter, meopt);
return R/B;
}
const vector<DVector> & GeneralTwoBodyDecayer2::getColourFactors(const Particle & inpart,
const ParticleVector & decay,
unsigned int & nflow) {
// calculate the colour factors for the three-body decay
vector<int> sing,trip,atrip,oct,sex,asex;
for(unsigned int it=0;it<decay.size();++it) {
if (decay[it]->dataPtr()->iColour() == PDT::Colour0 ) sing. push_back(it);
else if(decay[it]->dataPtr()->iColour() == PDT::Colour3 ) trip. push_back(it);
else if(decay[it]->dataPtr()->iColour() == PDT::Colour3bar ) atrip.push_back(it);
else if(decay[it]->dataPtr()->iColour() == PDT::Colour8 ) oct. push_back(it);
else if(decay[it]->dataPtr()->iColour() == PDT::Colour6 ) sex. push_back(it);
else if(decay[it]->dataPtr()->iColour() == PDT::Colour6bar ) asex. push_back(it);
}
// identical particle symmetry factor
double symFactor=1.;
if (( sing.size()==2 && decay[ sing[0]]->id()==decay[ sing[1]]->id()) ||
( trip.size()==2 && decay[ trip[0]]->id()==decay[ trip[1]]->id()) ||
(atrip.size()==2 && decay[atrip[0]]->id()==decay[atrip[1]]->id()) ||
( oct.size()==2 && decay[ oct[0]]->id()==decay[ oct[1]]->id()) ||
( sex.size()==2 && decay[ sex[0]]->id()==decay[ sex[1]]->id()) ||
( asex.size()==2 && decay[ asex[0]]->id()==decay[ asex[1]]->id()))
symFactor /= 2.;
else if (oct.size()==3 &&
decay[oct[0]]->id()==decay[oct[1]]->id() &&
decay[oct[0]]->id()==decay[oct[2]]->id())
symFactor /= 6.;
colour_ = vector<DVector>(1,DVector(1,symFactor*1.));
// decaying colour singlet
if(inpart.dataPtr()->iColour() == PDT::Colour0) {
if(trip.size()==1 && atrip.size()==1 && oct.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*4.));
}
else if(trip.size()==1 && atrip.size()==1 && sing.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*3.));
}
else if (oct.size()==3){
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*24.));
}
else if(sing.size()==3) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor));
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour scalar particle in "
<< "GeneralTwoBodyDecayer2::getColourFactors() for "
<< inpart. dataPtr()->PDGName() << " -> "
<< decay[0]->dataPtr()->PDGName() << " "
<< decay[1]->dataPtr()->PDGName() << " "
<< decay[2]->dataPtr()->PDGName()
<< Exception::runerror;
}
// decaying colour triplet
else if(inpart.dataPtr()->iColour() == PDT::Colour3) {
if(trip.size()==1 && sing.size()==1 && oct.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*4./3.));
}
else if(trip.size()==1 && sing.size()==2) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor));
}
else if(trip.size()==1 && oct.size()==2) {
nflow = 2;
colour_.clear();
colour_.resize(2,DVector(2,0.));
colour_[0][0] = symFactor*16./9.; colour_[0][1] = -symFactor*2./9.;
colour_[1][0] = -symFactor*2./9.; colour_[1][1] = symFactor*16./9.;
}
else if(atrip.size()==2 && sing.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*2.));
}
else if(atrip.size()==2 && oct.size()==1) {
nflow = 2;
colour_.clear();
colour_.resize(2,DVector(2,0.));
colour_[0][0] = 8./3.*symFactor; colour_[0][1] =-4./3.*symFactor;
colour_[1][0] = -4./3.*symFactor; colour_[1][1] = 8./3.*symFactor;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour triplet particle in "
<< "GeneralTwoBodyDecayer2::getColourFactors() for "
<< inpart. dataPtr()->PDGName() << " -> "
<< decay[0]->dataPtr()->PDGName() << " "
<< decay[1]->dataPtr()->PDGName() << " "
<< decay[2]->dataPtr()->PDGName()
<< Exception::runerror;
}
// decaying colour anti-triplet
else if(inpart.dataPtr()->iColour() == PDT::Colour3bar) {
if(atrip.size()==1 && sing.size()==1 && oct.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*4./3.));
}
else if(atrip.size()==1 && sing.size()==2) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor));
}
else if(atrip.size()==1 && oct.size()==2){
nflow = 2;
colour_.clear();
colour_ .resize(2,DVector(2,0.));
colour_[0][0] = symFactor*16./9.; colour_[0][1] = -symFactor*2./9.;
colour_[1][0] = -symFactor*2./9.; colour_[1][1] = symFactor*16./9.;
}
else if(trip.size()==2 && sing.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*2.));
}
else if(trip.size()==2 && oct.size()==1) {
nflow = 2;
colour_.clear();
colour_.resize(2,DVector(2,0.));
colour_[0][0] = 8./3.*symFactor; colour_[0][1] =-4./3.*symFactor;
colour_[1][0] = -4./3.*symFactor; colour_[1][1] = 8./3.*symFactor;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour anti-triplet particle in "
<< "GeneralTwoBodyDecayer2::getColourFactors() for "
<< inpart. dataPtr()->PDGName() << " -> "
<< decay[0]->dataPtr()->PDGName() << " "
<< decay[1]->dataPtr()->PDGName() << " "
<< decay[2]->dataPtr()->PDGName()
<< Exception::runerror;
}
// decaying colour octet
else if(inpart.dataPtr()->iColour() == PDT::Colour8) {
if(oct.size()==1 && trip.size()==1 && atrip.size()==1) {
nflow = 2;
colour_.clear();
colour_.resize(2,DVector(2,0.));
colour_[0][0] = symFactor*2./3. ; colour_[0][1] = -symFactor*1./12.;
colour_[1][0] = -symFactor*1./12.; colour_[1][1] = symFactor*2./3. ;
}
else if (sing.size()==1 && trip.size()==1 && atrip.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*0.5));
}
else if (oct.size()==2 && sing.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor*3.));
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for a decaying colour octet particle in "
<< "GeneralTwoBodyDecayer2::getColourFactors() for "
<< inpart. dataPtr()->PDGName() << " -> "
<< decay[0]->dataPtr()->PDGName() << " "
<< decay[1]->dataPtr()->PDGName() << " "
<< decay[2]->dataPtr()->PDGName()
<< Exception::runerror;
}
// Sextet
else if(inpart.dataPtr()->iColour() == PDT::Colour6) {
if(trip.size()==2 && sing.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor));
}
else if(trip.size()==2 && oct.size()==1) {
nflow = 2;
colour_.clear();
colour_.resize(2,DVector(2,0.));
colour_[0][0] = 4./3.*symFactor; colour_[0][1] = 1./3.*symFactor;
colour_[1][0] = 1./3.*symFactor; colour_[1][1] = 4./3.*symFactor;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for a decaying colour sextet particle in "
<< "GeneralTwoBodyDecayer2::getColourFactors() for "
<< inpart. dataPtr()->PDGName() << " -> "
<< decay[0]->dataPtr()->PDGName() << " "
<< decay[1]->dataPtr()->PDGName() << " "
<< decay[2]->dataPtr()->PDGName()
<< Exception::runerror;
}
// anti Sextet
else if(inpart.dataPtr()->iColour() == PDT::Colour6bar) {
if(atrip.size()==2 && sing.size()==1) {
nflow = 1;
colour_ = vector<DVector>(1,DVector(1,symFactor));
}
else if(atrip.size()==2 && oct.size()==1) {
nflow = 2;
colour_.clear();
colour_.resize(2,DVector(2,0.));
colour_[0][0] = 4./3.*symFactor; colour_[0][1] = 1./3.*symFactor;
colour_[1][0] = 1./3.*symFactor; colour_[1][1] = 4./3.*symFactor;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for a decaying colour anti-sextet particle in "
<< "GeneralTwoBodyDecayer2::getColourFactors() for "
<< inpart. dataPtr()->PDGName() << " -> "
<< decay[0]->dataPtr()->PDGName() << " "
<< decay[1]->dataPtr()->PDGName() << " "
<< decay[2]->dataPtr()->PDGName()
<< Exception::runerror;
}
else
throw Exception() << "Unknown colour for the decaying particle in "
<< "GeneralTwoBodyDecayer2::getColourFactors() for "
<< inpart. dataPtr()->PDGName() << " -> "
<< decay[0]->dataPtr()->PDGName() << " "
<< decay[1]->dataPtr()->PDGName() << " "
<< decay[2]->dataPtr()->PDGName()
<< Exception::runerror;
return colour_;
}
const GeneralTwoBodyDecayer2::CFlow &
GeneralTwoBodyDecayer2::colourFlows(const Particle & inpart,
const ParticleVector & decay) {
// static initialization of commonly used colour structures
static const CFlow init = CFlow(3, CFlowPairVec(1, make_pair(0, 1.)));
static CFlow tripflow = init;
static CFlow atripflow = init;
static CFlow octflow = init;
static CFlow sexflow = init;
static CFlow epsflow = init;
static const CFlow fpflow = CFlow(4, CFlowPairVec(1, make_pair(0, 1.)));
static bool initialized = false;
if (! initialized) {
tripflow[2].resize(2, make_pair(0,1.));
tripflow[2][0] = make_pair(0, 1.);
tripflow[2][1] = make_pair(1,-1.);
tripflow[1][0] = make_pair(1, 1.);
atripflow[1].resize(2, make_pair(0,1.));
atripflow[1][0] = make_pair(0, 1.);
atripflow[1][1] = make_pair(1,-1.);
atripflow[2][0] = make_pair(1, 1.);
octflow[0].resize(2, make_pair(0,1.));
octflow[0][0] = make_pair(0,-1.);
octflow[0][1] = make_pair(1, 1.);
octflow[2][0] = make_pair(1, 1.);
sexflow[0].resize(2, make_pair(0,1.));
sexflow[0][1] = make_pair(1,1.);
sexflow[2][0] = make_pair(1,1.);
epsflow[0].resize(2, make_pair(0,-1.));
epsflow[0][0] = make_pair(0,-1.);
epsflow[0][1] = make_pair(1,-1.);
epsflow[2][0] = make_pair(1,1.);
initialized = true;
}
// main function body
int sing=0,trip=0,atrip=0,oct=0,sex=0,asex=0;
for (size_t it=0; it<decay.size(); ++it) {
switch ( decay[it]->dataPtr()->iColour() ) {
case PDT::Colour0: ++sing; break;
case PDT::Colour3: ++trip; break;
case PDT::Colour3bar: ++atrip; break;
case PDT::Colour8: ++oct; break;
case PDT::Colour6: ++sex; break;
case PDT::Colour6bar: ++asex; break;
/// @todo: handle these better
case PDT::ColourUndefined: break;
case PDT::Coloured: break;
}
}
const CFlow * retval = 0;
// decaying colour triplet
if(inpart.dataPtr()->iColour() == PDT::Colour3 &&
trip==1 && oct==2) {
retval = &tripflow;
}
// decaying colour anti-triplet
else if(inpart.dataPtr()->iColour() == PDT::Colour3bar &&
atrip==1 && oct==2){
retval = &atripflow;
}
// decaying colour octet
else if(inpart.dataPtr()->iColour() == PDT::Colour8 &&
oct==1 && trip==1 && atrip==1) {
retval = &octflow;
}
// decaying colour sextet
else if(inpart.dataPtr()->iColour() ==PDT::Colour6 &&
oct==1 && trip==2) {
retval = &sexflow;
}
// decaying anti colour sextet
else if(inpart.dataPtr()->iColour() ==PDT::Colour6bar &&
oct==1 && atrip==2) {
retval = &sexflow;
}
// decaying colour triplet (eps)
else if(inpart.dataPtr()->iColour() == PDT::Colour3 &&
atrip==2 && oct==1) {
retval = &epsflow;
}
// decaying colour anti-triplet (eps)
else if(inpart.dataPtr()->iColour() == PDT::Colour3bar &&
trip==2 && oct==1){
retval = &epsflow;
}
else {
retval = &fpflow;
}
return *retval;
}
double GeneralTwoBodyDecayer2::threeBodyME(const int , const Particle &,
const ParticleVector &,
ShowerInteraction, MEOption) {
throw Exception() << "Base class GeneralTwoBodyDecayer2::threeBodyME() "
<< "called, should have an implementation in the inheriting class"
<< Exception::runerror;
return 0.;
}
diff --git a/Decay/General/GeneralTwoBodyDecayer2.h b/Decay/General/GeneralTwoBodyDecayer2.h
--- a/Decay/General/GeneralTwoBodyDecayer2.h
+++ b/Decay/General/GeneralTwoBodyDecayer2.h
@@ -1,306 +1,295 @@
// -*- C++ -*-
//
// GeneralTwoBodyDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_GeneralTwoBodyDecayer2_H
#define HERWIG_GeneralTwoBodyDecayer2_H
//
// This is the declaration of the GeneralTwoBodyDecayer2 class.
//
#include "Herwig/Decay/PerturbativeDecayer2.h"
#include "Herwig/Decay/PhaseSpaceMode.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "GeneralTwoBodyDecayer2.fh"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
/** \ingroup Decay
* The GeneralTwoBodyDecayer2 class is designed to be the base class
* for 2 body decays for some general model. It inherits from
* PerturbativeDecayer2 and implements the modeNumber() virtual function
* that is the same for all of the decays. A decayer for
* a specific spin configuration should inherit from this and implement
* the me2() and partialWidth() member functions. The colourConnections()
* member should be called from inside me2() in the inheriting decayer
* to set up the colour lines.
*
* @see \ref GeneralTwoBodyDecayer2Interfaces "The interfaces"
* defined for GeneralTwoBodyDecayer2.
* @see PerturbativeDecayer2
*/
class GeneralTwoBodyDecayer2: public PerturbativeDecayer2 {
public:
/** A ParticleData ptr and (possible) mass pair.*/
typedef pair<tcPDPtr, Energy> PMPair;
public:
/**
* The default constructor.
*/
GeneralTwoBodyDecayer2() : maxWeight_(1.), colour_(1,DVector(1,1.))
{}
/** @name Virtual functions required by the Decayer2 class. */
//@{
/**
* For a given decay mode and a given particle instance, perform the
* decay and return the decay products. As this is the base class this
* is not implemented.
* @return The vector of particles produced in the decay.
*/
virtual ParticleVector decay(const Particle & parent,
const tPDVector & children) const;
/**
* Which of the possible decays is required
* @param cc Is this mode the charge conjugate
* @param parent The decaying particle
* @param children The decay products
*/
virtual int modeNumber(bool & cc, tcPDPtr parent,const tPDVector & children) const;
-
- /**
- * Return the matrix element squared for a given mode and phase-space channel
- * @param ichan The channel we are calculating the matrix element for.
- * @param part The decaying Particle.
- * @param decay The particles produced in the decay.
- * @param meopt Option for the calculation of the matrix element
- * @return The matrix element squared for the phase-space configuration.
- */
- virtual double me2(const int , const Particle & part,
- const ParticleVector & decay, MEOption meopt) const = 0;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
/**
* Specify the \f$1\to2\f$ matrix element to be used in the running width
* calculation.
* @param dm The DecayMode
* @param mecode The code for the matrix element as described
* in the GenericWidthGenerator class.
* @param coupling The coupling for the matrix element.
* @return True if the the order of the particles in the
* decayer is the same as the DecayMode tag.
*/
virtual bool twoBodyMEcode(const DecayMode & dm, int & mecode,
double & coupling) const;
/**
* An overidden member to calculate a branching ratio for a certain
* particle instance.
* @param dm The DecayMode of the particle
* @param p The particle object
* @param oldbrat The branching fraction given in the DecayMode object
*/
virtual double brat(const DecayMode & dm, const Particle & p,
double oldbrat) const;
//@}
/**
* Set the information on the decay
*/
virtual void setDecayInfo(PDPtr incoming, PDPair outgoing,
vector<VertexBasePtr>,
map<ShowerInteraction,VertexBasePtr> &,
const vector<map<ShowerInteraction,VertexBasePtr> > &,
map<ShowerInteraction,VertexBasePtr>) =0;
protected:
/** @name Functions used by inheriting decayers. */
//@{
/**
* Set integration weight
* @param wgt Maximum integration weight
*/
void setWeight(double wgt) { maxWeight_ = wgt; }
/**
* Set colour connections
* @param parent Parent particle
* @param out Particle vector containing particles to
* connect colour lines
*/
void colourConnections(const Particle & parent,
const ParticleVector & out) const;
/**
* Compute the spin and colour factor
*/
double colourFactor(tcPDPtr in, tcPDPtr out1, tcPDPtr out2) const;
/**
* Calculate matrix element ratio R/B
*/
double matrixElementRatio(const Particle & inpart, const ParticleVector & decay2,
const ParticleVector & decay3, MEOption meopt,
ShowerInteraction inter);
/**
* Set the information on the decay
*/
void decayInfo(PDPtr incoming, PDPair outgoing);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
protected:
/**
* Member for the generation of additional hard radiation
*/
//@{
/**
* Return the matrix of colour factors
*/
typedef vector<pair<int,double > > CFlowPairVec;
typedef vector<CFlowPairVec> CFlow;
const vector<DVector> & getColourFactors(const Particle & inpart,
const ParticleVector & decay,
unsigned int & nflow);
const CFlow & colourFlows(const Particle & inpart,
const ParticleVector & decay);
/**
* Three-body matrix element including additional QCD radiation
*/
virtual double threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay,
ShowerInteraction inter, MEOption meopt);
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GeneralTwoBodyDecayer2 & operator=(const GeneralTwoBodyDecayer2 &);
private:
/**
* Store the incoming particle
*/
PDPtr incoming_;
/**
* Outgoing particles
*/
vector<PDPtr> outgoing_;
/**
* Maximum weight for integration
*/
double maxWeight_;
/**
* Store colour factors for ME calc.
*/
vector<DVector> colour_;
};
/**
* Write a map with ShowerInteraction as the key
*/
template<typename T, typename Cmp, typename A>
inline PersistentOStream & operator<<(PersistentOStream & os,
const map<ShowerInteraction,T,Cmp,A> & m) {
os << m.size();
if(m.find(ShowerInteraction::QCD)!=m.end()) {
os << 0 << m.at(ShowerInteraction::QCD);
}
if(m.find(ShowerInteraction::QED)!=m.end()) {
os << 1 << m.at(ShowerInteraction::QED);
}
return os;
}
/**
* Read a map with ShowerInteraction as the key
*/
template <typename T, typename Cmp, typename A>
inline PersistentIStream & operator>>(PersistentIStream & is, map<ShowerInteraction,T,Cmp,A> & m) {
m.clear();
long size;
int k;
is >> size;
while ( size-- && is ) {
is >> k;
if(k==0)
is >> m[ShowerInteraction::QCD];
else if(k==1)
is >> m[ShowerInteraction::QED];
else
assert(false);
}
return is;
}
}
#endif /* HERWIG_GeneralTwoBodyDecayer2_H */
diff --git a/Decay/General/SVVDecayer.cc b/Decay/General/SVVDecayer.cc
--- a/Decay/General/SVVDecayer.cc
+++ b/Decay/General/SVVDecayer.cc
@@ -1,434 +1,440 @@
// -*- C++ -*-
//
// SVVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SVVDecayer class.
//
#include "SVVDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "Herwig/Utilities/Kinematics.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
IBPtr SVVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr SVVDecayer::fullclone() const {
return new_ptr(*this);
}
void SVVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing,
vector<VertexBasePtr> vertex,
map<ShowerInteraction,VertexBasePtr> & inV,
const vector<map<ShowerInteraction,VertexBasePtr> > & outV,
map<ShowerInteraction,VertexBasePtr> ) {
decayInfo(incoming,outgoing);
for(auto vert : vertex) {
vertex_ .push_back(dynamic_ptr_cast<AbstractVVSVertexPtr>(vert));
perturbativeVertex_.push_back(dynamic_ptr_cast<VVSVertexPtr> (vert));
}
vector<ShowerInteraction> itemp={ShowerInteraction::QCD,ShowerInteraction::QED};
for(auto & inter : itemp) {
incomingVertex_[inter] = dynamic_ptr_cast<AbstractVSSVertexPtr>(inV.at(inter));
outgoingVertex1_[inter] = dynamic_ptr_cast<AbstractVVVVertexPtr>(outV[0].at(inter));
outgoingVertex2_[inter] = dynamic_ptr_cast<AbstractVVVVertexPtr>(outV[1].at(inter));
}
}
void SVVDecayer::persistentOutput(PersistentOStream & os) const {
os << vertex_ << perturbativeVertex_
<< incomingVertex_ << outgoingVertex1_
<< outgoingVertex2_;
}
void SVVDecayer::persistentInput(PersistentIStream & is, int) {
is >> vertex_ >> perturbativeVertex_
>> incomingVertex_ >> outgoingVertex1_
>> outgoingVertex2_;
}
// The following static variable is needed for the type
// description system in ThePEG.
-DescribeClass<SVVDecayer,GeneralTwoBodyDecayer>
+DescribeClass<SVVDecayer,GeneralTwoBodyDecayer2>
describeHerwigSVVDecayer("Herwig::SVVDecayer", "Herwig.so");
void SVVDecayer::Init() {
static ClassDocumentation<SVVDecayer> documentation
("This implements the decay of a scalar to 2 vector bosons.");
}
-double SVVDecayer::me2(const int , const Particle & inpart,
- const ParticleVector& decay,
+
+void SVVDecayer::
+constructSpinInfo(const Particle & part, ParticleVector decay) const {
+ bool photon[2];
+ for(unsigned int ix=0;ix<2;++ix)
+ photon[ix] = decay[ix]->mass()==ZERO;
+ ScalarWaveFunction::
+ constructSpinInfo(const_ptr_cast<tPPtr>(&part),incoming,true);
+ for(unsigned int ix=0;ix<2;++ix)
+ VectorWaveFunction::
+ constructSpinInfo(vectors_[ix],decay[ix],outgoing,true,photon[ix]);
+}
+
+double SVVDecayer::me2(const int,const Particle & part,
+ const tPDVector & outgoing,
+ const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin1,PDT::Spin1)));
bool photon[2];
for(unsigned int ix=0;ix<2;++ix)
- photon[ix] = decay[ix]->mass()==ZERO;
+ photon[ix] = outgoing[ix]->mass()==ZERO;
if(meopt==Initialize) {
ScalarWaveFunction::
- calculateWaveFunctions(rho_,const_ptr_cast<tPPtr>(&inpart),incoming);
- swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming);
+ calculateWaveFunctions(rho_,const_ptr_cast<tPPtr>(&part),incoming);
+ swave_ = ScalarWaveFunction(part.momentum(),part.dataPtr(),incoming);
// fix rho if no correlations
fixRho(rho_);
}
- if(meopt==Terminate) {
- ScalarWaveFunction::
- constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),incoming,true);
- for(unsigned int ix=0;ix<2;++ix)
- VectorWaveFunction::
- constructSpinInfo(vectors_[ix],decay[ix],outgoing,true,photon[ix]);
- }
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
- calculateWaveFunctions(vectors_[ix],decay[ix],outgoing,photon[ix]);
+ calculateWaveFunctions(vectors_[ix],momenta[ix],outgoing[ix],Helicity::outgoing,photon[ix]);
- Energy2 scale(sqr(inpart.mass()));
+ Energy2 scale(sqr(part.mass()));
unsigned int iv1,iv2;
for(iv2 = 0; iv2 < 3; ++iv2) {
if( photon[1] && iv2 == 1 ) ++iv2;
for(iv1=0;iv1<3;++iv1) {
if( photon[0] && iv1 == 1) ++iv1;
(*ME())(0, iv1, iv2) = 0.;
for(auto vert : vertex_)
(*ME())(0, iv1, iv2) += vert->evaluate(scale,vectors_[0][iv1],
vectors_[1][iv2],swave_);
}
}
double output = ME()->contract(rho_).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
- output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
- decay[1]->dataPtr());
+ output *= colourFactor(part.dataPtr(),outgoing[0],outgoing[1]);
// return the answer
return output;
}
Energy SVVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(perturbativeVertex_.size()==1 &&
perturbativeVertex_[0]) {
Energy2 scale(sqr(inpart.second));
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
perturbativeVertex_[0]->setCoupling(scale, outa.first ,
outb.first, in);
double mu1sq = sqr(outa.second/inpart.second);
double mu2sq = sqr(outb.second/inpart.second);
double m1pm2 = mu1sq + mu2sq;
double me2(0.);
if( mu1sq > 0. && mu2sq > 0.)
me2 = ( m1pm2*(m1pm2 - 2.) + 8.*mu1sq*mu2sq + 1.)/4./mu1sq/mu2sq;
else if( mu1sq == 0. || mu2sq == 0. )
me2 = 3.;
else
me2 = 4.;
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second,
outb.second);
Energy output = norm(perturbativeVertex_[0]->norm())*
me2*pcm/(8*Constants::pi)/scale*UnitRemoval::E2;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
- return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
+ return GeneralTwoBodyDecayer2::partialWidth(inpart,outa,outb);
}
}
double SVVDecayer::threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay,
ShowerInteraction inter, MEOption meopt) {
if(meopt==Initialize) {
// create scalar wavefunction for decaying particle
ScalarWaveFunction::
calculateWaveFunctions(rho3_,const_ptr_cast<tPPtr>(&inpart),incoming);
swave3_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming);
}
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),incoming,true);
VectorWaveFunction::
constructSpinInfo(vectors3_[0],decay[0],outgoing,true,false);
VectorWaveFunction::
constructSpinInfo(vectors3_[1],decay[1],outgoing,true,false);
VectorWaveFunction::
constructSpinInfo(gluon_ ,decay[2],outgoing,true,false);
return 0.;
}
// calculate colour factors and number of colour flows
unsigned int nflow;
vector<DVector> cfactors = getColourFactors(inpart, decay, nflow);
vector<GeneralDecayMEPtr> ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin0, PDT::Spin1,
PDT::Spin1, PDT::Spin1)));
bool massless[2];
for(unsigned int ix=0;ix<2;++ix)
massless[ix] = decay[ix]->mass()!=ZERO;
// create wavefunctions
VectorWaveFunction::calculateWaveFunctions(vectors3_[0],decay[0],outgoing,massless[0]);
VectorWaveFunction::calculateWaveFunctions(vectors3_[1],decay[1],outgoing,massless[1]);
VectorWaveFunction::calculateWaveFunctions(gluon_ ,decay[2],outgoing,true);
// gauge test
#ifdef GAUGE_CHECK
gluon_.clear();
for(unsigned int ix=0;ix<3;++ix) {
if(ix==1) gluon_.push_back(VectorWaveFunction());
else {
gluon_.push_back(VectorWaveFunction(decay[2]->momentum(),
decay[2]->dataPtr(),10,
outgoing));
}
}
#endif
// get the outgoing vertices
AbstractVVVVertexPtr outgoingVertex1;
AbstractVVVVertexPtr outgoingVertex2;
identifyVertices(inpart,decay, outgoingVertex1, outgoingVertex2,inter);
Energy2 scale(sqr(inpart.mass()));
- const GeneralTwoBodyDecayer::CFlow & colourFlow
+ const GeneralTwoBodyDecayer2::CFlow & colourFlow
= colourFlows(inpart, decay);
double gs(0.);
bool couplingSet(false);
#ifdef GAUGE_CHECK
double total=0.;
#endif
for(unsigned int iv1 = 0; iv1 < 3; ++iv1) {
if(massless[0] && iv1==1) continue;
for(unsigned int iv2 = 0; iv2 < 3; ++iv2) {
if(massless[1] && iv2==1) continue;
for(unsigned int ig = 0; ig < 2; ++ig) {
// radiation from the incoming vector
if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) ||
(inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) {
assert(incomingVertex_[inter]);
ScalarWaveFunction scalarInter =
incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),gluon_[2*ig],
swave3_,inpart.mass());
assert(swave3_.particle()->id()==scalarInter.particle()->id());
Complex diag = 0.;
for(auto vertex : vertex_)
diag += vertex->evaluate(scale,vectors3_[0][iv1],
vectors3_[1][iv2],scalarInter);
if(!couplingSet) {
gs = abs(incomingVertex_[inter]->norm());
couplingSet = true;
}
for(unsigned int ix=0;ix<colourFlow[0].size();++ix) {
(*ME[colourFlow[0][ix].first])(0, iv1, iv2, ig) +=
colourFlow[0][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
// radiation from the 1st outgoing vector
if((decay[0]->dataPtr()->coloured() && inter==ShowerInteraction::QCD) ||
(decay[0]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) {
assert(outgoingVertex1);
// ensure you get correct outgoing particle from first vertex
tcPDPtr off = decay[0]->dataPtr();
if(off->CC()) off = off->CC();
VectorWaveFunction vectorInter =
outgoingVertex1->evaluate(scale,3,off,gluon_[2*ig],vectors3_[0][iv1],decay[0]->mass());
assert(vectors3_[0][iv1].particle()->id()==vectorInter.particle()->id());
Complex diag =0.;
for(auto vertex : vertex_)
diag += vertex->evaluate(scale,vectorInter,vectors3_[1][iv2],swave3_);
if(!couplingSet) {
gs = abs(outgoingVertex1->norm());
couplingSet = true;
}
for(unsigned int ix=0;ix<colourFlow[1].size();++ix) {
(*ME[colourFlow[1][ix].first])(0, iv1, iv2, ig) +=
colourFlow[1][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
if((decay[1]->dataPtr()->coloured() && inter==ShowerInteraction::QCD) ||
(decay[1]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) {
assert(outgoingVertex2);
// ensure you get correct outgoing particle from first vertex
tcPDPtr off = decay[1]->dataPtr();
if(off->CC()) off = off->CC();
VectorWaveFunction vectorInter =
outgoingVertex2->evaluate(scale,3,off, gluon_[2*ig],vectors3_[1][iv2],decay[1]->mass());
assert(vectors3_[1][iv2].particle()->id()==vectorInter.particle()->id());
Complex diag = 0.;
for(auto vertex : vertex_)
diag += vertex->evaluate(scale,vectors3_[0][iv1],vectorInter,swave3_);
if(!couplingSet) {
gs = abs(outgoingVertex2->norm());
couplingSet = true;
}
for(unsigned int ix=0;ix<colourFlow[2].size();++ix) {
(*ME[colourFlow[2][ix].first])(0, iv1, iv2, ig) +=
colourFlow[2][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
}
}
}
// contract matrices
double output=0.;
for(unsigned int ix=0; ix<nflow; ++ix){
for(unsigned int iy=0; iy<nflow; ++iy){
output+=cfactors[ix][iy]*(ME[ix]->contract(*ME[iy],rho3_)).real();
}
}
// divide by alpha_(S,EM)
output*=(4.*Constants::pi)/sqr(gs);
#ifdef GAUGE_CHECK
double ratio = output/total;
if(abs(ratio)>1e-20) {
generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n";
for(unsigned int ix=0;ix<decay.size();++ix)
generator()->log() << *decay[ix] << "\n";
generator()->log() << "Test of gauge invariance " << ratio << "\n";
}
#endif
// return the answer
return output;
}
void SVVDecayer::identifyVertices(const Particle & inpart, const ParticleVector & decay,
AbstractVVVVertexPtr & outgoingVertex1,
AbstractVVVVertexPtr & outgoingVertex2,
ShowerInteraction inter) {
if(inter==ShowerInteraction::QCD) {
// work out which scalar each outgoing vertex corresponds to
// two outgoing vertices
if( inpart.dataPtr() ->iColour()==PDT::Colour0 &&
((decay[0]->dataPtr()->iColour()==PDT::Colour3 &&
decay[1]->dataPtr()->iColour()==PDT::Colour3bar) ||
(decay[0]->dataPtr()->iColour()==PDT::Colour8 &&
decay[1]->dataPtr()->iColour()==PDT::Colour8))){
if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->id()))){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[0]->id()))){
outgoingVertex1 = outgoingVertex2_[inter];
outgoingVertex2 = outgoingVertex1_[inter];
}
}
else if(inpart.dataPtr() ->iColour()==PDT::Colour8 &&
decay[0]->dataPtr()->iColour()==PDT::Colour3 &&
decay[1]->dataPtr()->iColour()==PDT::Colour3bar){
if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->id()))){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[0]->id()))){
outgoingVertex1 = outgoingVertex2_[inter];
outgoingVertex2 = outgoingVertex1_[inter];
}
}
// one outgoing vertex
else if(inpart.dataPtr()->iColour()==PDT::Colour3){
if(decay[0]->dataPtr()->iColour()==PDT::Colour3 &&
decay[1]->dataPtr()->iColour()==PDT::Colour0){
if (outgoingVertex1_[inter]) outgoingVertex1 = outgoingVertex1_[inter];
else if(outgoingVertex2_[inter]) outgoingVertex1 = outgoingVertex2_[inter];
}
else if (decay[0]->dataPtr()->iColour()==PDT::Colour3 &&
decay[1]->dataPtr()->iColour()==PDT::Colour8){
if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[1]->dataPtr()->id()))){
outgoingVertex1 = outgoingVertex2_[inter];
outgoingVertex2 = outgoingVertex1_[inter];
}
else {
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
}
}
else if(inpart.dataPtr()->iColour()==PDT::Colour3bar){
if(decay[1]->dataPtr()->iColour()==PDT::Colour3bar &&
decay[0]->dataPtr()->iColour()==PDT::Colour0){
if (outgoingVertex1_[inter]) outgoingVertex2 = outgoingVertex1_[inter];
else if(outgoingVertex2_[inter]) outgoingVertex2 = outgoingVertex2_[inter];
}
else if (decay[0]->dataPtr()->iColour()==PDT::Colour8 &&
decay[1]->dataPtr()->iColour()==PDT::Colour3bar){
if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->dataPtr()->id()))){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else {
outgoingVertex1 = outgoingVertex2_[inter];
outgoingVertex2 = outgoingVertex1_[inter];
}
}
}
if (! ((incomingVertex_[inter] && (outgoingVertex1 || outgoingVertex2)) ||
( outgoingVertex1 && outgoingVertex2)))
throw Exception()
<< "Invalid vertices for QCD radiation in SVV decay in SVVDecayer::identifyVertices"
<< Exception::runerror;
}
else {
if(decay[0]->dataPtr()->charged()) {
if (outgoingVertex1_[inter] &&
outgoingVertex1_[inter]->isIncoming(const_ptr_cast<tPDPtr>(decay[0]->dataPtr())))
outgoingVertex1 = outgoingVertex1_[inter];
else
outgoingVertex1 = outgoingVertex2_[inter];
}
if(decay[1]->dataPtr()->charged()) {
if (outgoingVertex1_[inter] &&
outgoingVertex1_[inter]->isIncoming(const_ptr_cast<tPDPtr>(decay[1]->dataPtr())))
outgoingVertex2 = outgoingVertex1_[inter];
else
outgoingVertex2 = outgoingVertex2_[inter];
}
}
}
diff --git a/Decay/General/SVVDecayer.h b/Decay/General/SVVDecayer.h
--- a/Decay/General/SVVDecayer.h
+++ b/Decay/General/SVVDecayer.h
@@ -1,230 +1,239 @@
// -*- C++ -*-
//
// SVVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SVVDecayer_H
#define HERWIG_SVVDecayer_H
//
// This is the declaration of the SVVDecayer class.
//
-#include "GeneralTwoBodyDecayer.h"
+#include "GeneralTwoBodyDecayer2.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VVSVertexPtr;
/** \ingroup Decay
* This SVVDecayer class implements the decay of a scalar to
* 2 vector bosons using either the tree level VVSVertex or the loop vertex.
* It inherits from
- * GeneralTwoBodyDecayer and implements the virtual member functions me2()
+ * GeneralTwoBodyDecayer2 and implements the virtual member functions me2()
* and partialWidth(). It also stores a pointer to the VVSVertex.
*
- * @see GeneralTwoBodyDecayer
+ * @see GeneralTwoBodyDecayer2
*
*/
-class SVVDecayer: public GeneralTwoBodyDecayer {
+class SVVDecayer: public GeneralTwoBodyDecayer2 {
public:
/**
* The default constructor.
*/
SVVDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
- * @param ichan The channel we are calculating the matrix element for.
+ * @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
- * @param decay The particles produced in the decay.
+ * @param outgoing The particles produced in the decay
+ * @param momenta The momenta of the particles produced in the decay
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
- virtual double me2(const int ichan, const Particle & part,
- const ParticleVector & decay, MEOption meopt) const;
+ double me2(const int ichan,const Particle & part,
+ const tPDVector & outgoing,
+ const vector<Lorentz5Momentum> & momenta,
+ MEOption meopt) const;
+
+ /**
+ * Construct the SpinInfos for the particles produced in the decay
+ */
+ virtual void constructSpinInfo(const Particle & part,
+ ParticleVector outgoing) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
/**
* Set the information on the decay
*/
virtual void setDecayInfo(PDPtr incoming, PDPair outgoing,
vector<VertexBasePtr>,
map<ShowerInteraction,VertexBasePtr> &,
const vector<map<ShowerInteraction,VertexBasePtr> > &,
map<ShowerInteraction,VertexBasePtr>);
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {
POWHEGType output = FSR;
for(auto vertex : vertex_) {
if(vertex->orderInAllCouplings()!=1) {
output = No;
break;
}
}
return output;
}
/**
* Three-body matrix element including additional QCD radiation
*/
virtual double threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay,
ShowerInteraction inter, MEOption meopt);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/**
* Find the vertices for the decay
*/
void identifyVertices(const Particle & inpart, const ParticleVector & decay,
AbstractVVVVertexPtr & outgoingVertex1,
AbstractVVVVertexPtr & outgoingVertex2,
ShowerInteraction inter);
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SVVDecayer & operator=(const SVVDecayer &);
private:
/**
* Abstract pointer to general VVS vertex
*/
vector<AbstractVVSVertexPtr> vertex_;
/**
* Pointer to the perturbative form
*/
vector<VVSVertexPtr> perturbativeVertex_;
/**
* Abstract pointer to AbstractVSSVertex for QCD radiation from incoming scalar
*/
map<ShowerInteraction,AbstractVSSVertexPtr> incomingVertex_;
/**
* Abstract pointer to AbstractFFVVertex for QCD radiation from the 1st outgoing vector
*/
map<ShowerInteraction,AbstractVVVVertexPtr> outgoingVertex1_;
/**
* Abstract pointer to AbstractFFVVertex for QCD radiation from the 2nd outgoing vector
*/
map<ShowerInteraction,AbstractVVVVertexPtr> outgoingVertex2_;
/**
* Spin density matrix
*/
mutable RhoDMatrix rho_;
/**
* Scalar wavefunction
*/
mutable Helicity::ScalarWaveFunction swave_;
/**
* Vector wavefunctions
*/
mutable vector<Helicity::VectorWaveFunction> vectors_[2];
private:
/**
* Member for the POWHEG correction
*/
//@{
/**
* Spin density matrix for 3 body decay
*/
mutable RhoDMatrix rho3_;
/**
* Scalar wavefunction for 3 body decay
*/
mutable ScalarWaveFunction swave3_;
/**
* Vector wavefunctions
*/
mutable vector<Helicity::VectorWaveFunction> vectors3_[2];
/**
* Vector wavefunction for 3 body decay
*/
mutable vector<Helicity::VectorWaveFunction> gluon_;
//@}
};
}
#endif /* HERWIG_SVVDecayer_H */
diff --git a/Decay/General/TVVDecayer.cc b/Decay/General/TVVDecayer.cc
--- a/Decay/General/TVVDecayer.cc
+++ b/Decay/General/TVVDecayer.cc
@@ -1,340 +1,344 @@
// -*- C++ -*-
//
// TVVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the TVVDecayer class.
//
#include "TVVDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "Herwig/Utilities/Kinematics.h"
#include "ThePEG/Helicity/LorentzTensor.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
IBPtr TVVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr TVVDecayer::fullclone() const {
return new_ptr(*this);
}
void TVVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing,
vector<VertexBasePtr> vertex,
map<ShowerInteraction,VertexBasePtr> &,
const vector<map<ShowerInteraction,VertexBasePtr> > & outV,
map<ShowerInteraction,VertexBasePtr> fourV) {
decayInfo(incoming,outgoing);
for(auto vert : vertex) {
vertex_ .push_back(dynamic_ptr_cast<AbstractVVTVertexPtr>(vert));
perturbativeVertex_.push_back(dynamic_ptr_cast<VVTVertexPtr> (vert));
}
vector<ShowerInteraction> itemp={ShowerInteraction::QCD,ShowerInteraction::QED};
for(auto & inter : itemp) {
fourPointVertex_[inter] = dynamic_ptr_cast<AbstractVVVTVertexPtr>(fourV.at(inter));
outgoingVertex1_[inter] = dynamic_ptr_cast<AbstractVVVVertexPtr> (outV[0].at(inter));
outgoingVertex2_[inter] = dynamic_ptr_cast<AbstractVVVVertexPtr> (outV[1].at(inter));
}
}
void TVVDecayer::persistentOutput(PersistentOStream & os) const {
os << vertex_ << perturbativeVertex_
<< outgoingVertex1_ << outgoingVertex2_
<< fourPointVertex_;
}
void TVVDecayer::persistentInput(PersistentIStream & is, int) {
is >> vertex_ >> perturbativeVertex_
>> outgoingVertex1_ >> outgoingVertex2_
>> fourPointVertex_;
}
// The following static variable is needed for the type
// description system in ThePEG.
-DescribeClass<TVVDecayer,GeneralTwoBodyDecayer>
+DescribeClass<TVVDecayer,GeneralTwoBodyDecayer2>
describeHerwigTVVDecayer("Herwig::TVVDecayer", "Herwig.so");
void TVVDecayer::Init() {
static ClassDocumentation<TVVDecayer> documentation
("This class implements the decay of a tensor to 2 vector bosons");
}
-double TVVDecayer::me2(const int , const Particle & inpart,
- const ParticleVector & decay,
+void TVVDecayer::
+constructSpinInfo(const Particle & part, ParticleVector decay) const {
+ bool photon[2];
+ for(unsigned int ix=0;ix<2;++ix)
+ photon[ix] = decay[ix]->mass()==ZERO;
+ TensorWaveFunction::
+ constructSpinInfo(tensors_,const_ptr_cast<tPPtr>(&part),
+ incoming,true,false);
+ for(unsigned int ix=0;ix<2;++ix)
+ VectorWaveFunction::
+ constructSpinInfo(vectors_[ix],decay[ix],outgoing,true,photon[ix]);
+}
+
+double TVVDecayer::me2(const int,const Particle & part,
+ const tPDVector & outgoing,
+ const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin2,PDT::Spin1,PDT::Spin1)));
bool photon[2];
for(unsigned int ix=0;ix<2;++ix)
- photon[ix] = decay[ix]->mass()==ZERO;
+ photon[ix] = outgoing[ix]->mass()==ZERO;
if(meopt==Initialize) {
TensorWaveFunction::
- calculateWaveFunctions(tensors_,rho_,const_ptr_cast<tPPtr>(&inpart),
- incoming,false);
+ calculateWaveFunctions(tensors_,rho_,const_ptr_cast<tPPtr>(&part),
+ incoming,false);
// fix rho if no correlations
fixRho(rho_);
}
- if(meopt==Terminate) {
- TensorWaveFunction::
- constructSpinInfo(tensors_,const_ptr_cast<tPPtr>(&inpart),
- incoming,true,false);
- for(unsigned int ix=0;ix<2;++ix)
- VectorWaveFunction::
- constructSpinInfo(vectors_[ix],decay[ix],outgoing,true,photon[ix]);
- return 0.;
- }
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
- calculateWaveFunctions(vectors_[ix],decay[ix],outgoing,photon[ix]);
- Energy2 scale(sqr(inpart.mass()));
+ calculateWaveFunctions(vectors_[ix],momenta[ix],outgoing[ix],Helicity::outgoing,photon[ix]);
+ Energy2 scale(sqr(part.mass()));
unsigned int thel,v1hel,v2hel;
for(thel=0;thel<5;++thel) {
for(v1hel=0;v1hel<3;++v1hel) {
for(v2hel=0;v2hel<3;++v2hel) {
- (*ME())(thel,v1hel,v2hel) = 0.;
- for(auto vert : vertex_)
- (*ME())(thel,v1hel,v2hel) += vert->evaluate(scale,
- vectors_[0][v1hel],
- vectors_[1][v2hel],
- tensors_[thel]);
- if(photon[1]) ++v2hel;
+ (*ME())(thel,v1hel,v2hel) = 0.;
+ for(auto vert : vertex_)
+ (*ME())(thel,v1hel,v2hel) += vert->evaluate(scale,
+ vectors_[0][v1hel],
+ vectors_[1][v2hel],
+ tensors_[thel]);
+ if(photon[1]) ++v2hel;
}
if(photon[0]) ++v1hel;
}
}
double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
- output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
- decay[1]->dataPtr());
+ output *= colourFactor(part.dataPtr(),outgoing[0],outgoing[1]);
// return the answer
return output;
}
Energy TVVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(perturbativeVertex_.size()==1 &&
perturbativeVertex_[0]) {
Energy2 scale(sqr(inpart.second));
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
perturbativeVertex_[0]->setCoupling(scale, outa.first, outb.first, in);
double mu2 = sqr(outa.second/inpart.second);
double b = sqrt(1 - 4.*mu2);
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second,
outb.second);
Energy2 me2;
if(outa.second > ZERO && outb.second > ZERO)
me2 = scale*(30 - 20.*b*b + 3.*pow(b,4))/120.;
else
me2 = scale/10.;
Energy output = norm(perturbativeVertex_[0]->norm())*me2*pcm
/(8.*Constants::pi)*UnitRemoval::InvE2;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
- return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
+ return GeneralTwoBodyDecayer2::partialWidth(inpart,outa,outb);
}
}
double TVVDecayer::threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay,
ShowerInteraction inter, MEOption meopt) {
bool massless[2];
for(unsigned int ix=0;ix<2;++ix)
massless[ix] = decay[ix]->mass()==ZERO;
int iglu(2);
if(meopt==Initialize) {
// create tensor wavefunction for decaying particle
TensorWaveFunction::
calculateWaveFunctions(tensors3_, rho3_, const_ptr_cast<tPPtr>(&inpart), incoming, false);
}
// setup spin information when needed
if(meopt==Terminate) {
TensorWaveFunction::
constructSpinInfo(tensors3_, const_ptr_cast<tPPtr>(&inpart),incoming,true, false);
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
constructSpinInfo(vectors3_[ix],decay[ix ],outgoing,true, massless[ix]);
VectorWaveFunction::
constructSpinInfo(gluon_ ,decay[iglu ],outgoing,true,false);
return 0.;
}
// calculate colour factors and number of colour flows
unsigned int nflow;
vector<DVector> cfactors = getColourFactors(inpart, decay, nflow);
vector<GeneralDecayMEPtr> ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin2, PDT::Spin1,
PDT::Spin1, PDT::Spin1)));
// create wavefunctions
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
calculateWaveFunctions(vectors3_[ix],decay[ix ],outgoing,massless[ix]);
VectorWaveFunction::
calculateWaveFunctions(gluon_ ,decay[iglu ],outgoing,true);
// gauge test
#ifdef GAUGE_CHECK
gluon_.clear();
for(unsigned int ix=0;ix<3;++ix) {
if(ix==1) gluon_.push_back(VectorWaveFunction());
else {
gluon_.push_back(VectorWaveFunction(decay[iglu ]->momentum(),
decay[iglu ]->dataPtr(),10,
outgoing));
}
}
#endif
// work out which vector each outgoing vertex corresponds to
if(outgoingVertex1_[inter]!=outgoingVertex2_[inter] &&
outgoingVertex1_[inter]->isIncoming(getParticleData(decay[1]->id())))
swap(outgoingVertex1_[inter], outgoingVertex2_[inter]);
if (! (outgoingVertex1_[inter] && outgoingVertex2_[inter]))
throw Exception()
<< "Invalid vertices for radiation in TVV decay in TVVDecayer::threeBodyME"
<< Exception::runerror;
if( !(!inpart.dataPtr()->coloured() && inter ==ShowerInteraction::QCD) &&
!(!inpart.dataPtr()->charged() && inter ==ShowerInteraction::QED))
throw Exception()
<< "Invalid vertices for radiation in TVV decay in TVVDecayer::threeBodyME"
<< Exception::runerror;
Energy2 scale(sqr(inpart.mass()));
- const GeneralTwoBodyDecayer::CFlow & colourFlow
+ const GeneralTwoBodyDecayer2::CFlow & colourFlow
= colourFlows(inpart, decay);
double gs(0.);
bool couplingSet(false);
#ifdef GAUGE_CHECK
double total=0.;
#endif
for(unsigned int it = 0; it < 5; ++it) {
for(unsigned int iv0 = 0; iv0 < 3; ++iv0) {
for(unsigned int iv1 = 0; iv1 < 3; ++iv1) {
for(unsigned int ig = 0; ig < 2; ++ig) {
// radiation from first outgoing vector
if((decay[0]->dataPtr()->coloured() && inter==ShowerInteraction::QCD) ||
(decay[0]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) {
assert(outgoingVertex1_[inter]);
// ensure you get correct outgoing particle from first vertex
tcPDPtr off = decay[0]->dataPtr();
if(off->CC()) off = off->CC();
VectorWaveFunction vectInter =
outgoingVertex1_[inter]->evaluate(scale,3,off,gluon_[2*ig],
vectors3_[0][iv0],decay[0]->mass());
assert(vectors3_[0][iv0].particle()->PDGName()==vectInter.particle()->PDGName());
Complex diag = 0.;
for(auto vertex : vertex_)
diag += vertex->evaluate(scale,vectors3_[1][iv1],
vectInter,tensors3_[it]);
if(!couplingSet) {
gs = abs(outgoingVertex1_[inter]->norm());
couplingSet = true;
}
for(unsigned int ix=0;ix<colourFlow[1].size();++ix) {
(*ME[colourFlow[1][ix].first])(it, iv0, iv1, ig) +=
colourFlow[1][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
// radiation from second outgoing vector
if((decay[1]->dataPtr()->coloured() && inter==ShowerInteraction::QCD) ||
(decay[1]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) {
assert(outgoingVertex2_[inter]);
// ensure you get correct outgoing particle from first vertex
tcPDPtr off = decay[1]->dataPtr();
if(off->CC()) off = off->CC();
VectorWaveFunction vectInter =
outgoingVertex2_[inter]->evaluate(scale,3,off,vectors3_[1][iv1],
gluon_[2*ig],decay[1]->mass());
assert(vectors3_[1][iv1].particle()->PDGName()==vectInter.particle()->PDGName());
Complex diag = 0.;
for(auto vertex : vertex_)
diag += vertex->evaluate(scale,vectInter,vectors3_[0][iv0],
tensors3_[it]);
if(!couplingSet) {
gs = abs(outgoingVertex2_[inter]->norm());
couplingSet = true;
}
for(unsigned int ix=0;ix<colourFlow[2].size();++ix) {
(*ME[colourFlow[2][ix].first])(it, iv0, iv1, ig) +=
colourFlow[2][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
// radiation from 4 point vertex
if (fourPointVertex_[inter]) {
Complex diag = fourPointVertex_[inter]->evaluate(scale, vectors3_[0][iv0],
vectors3_[1][iv1],gluon_[2*ig],
tensors3_[it]);
for(unsigned int ix=0;ix<colourFlow[3].size();++ix) {
(*ME[colourFlow[3][ix].first])(it, iv0, iv1, ig) +=
colourFlow[3][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
}
if(massless[1]) ++iv1;
}
if(massless[0]) ++iv0;
}
}
// contract matrices
double output=0.;
for(unsigned int ix=0; ix<nflow; ++ix){
for(unsigned int iy=0; iy<nflow; ++iy){
output+=cfactors[ix][iy]*(ME[ix]->contract(*ME[iy],rho3_)).real();
}
}
// divide by alpha_(s,em)
output *= (4.*Constants::pi)/sqr(gs);
#ifdef GAUGE_CHECK
double ratio = output/total;
if(abs(ratio)>1e-20) {
generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n";
for(unsigned int ix=0;ix<decay.size();++ix)
generator()->log() << *decay[ix] << "\n";
generator()->log() << "Test of gauge invariance " << ratio << "\n";
}
#endif
// return the answer
return output;
}
diff --git a/Decay/General/TVVDecayer.h b/Decay/General/TVVDecayer.h
--- a/Decay/General/TVVDecayer.h
+++ b/Decay/General/TVVDecayer.h
@@ -1,213 +1,222 @@
// -*- C++ -*-
//
// TVVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_TVVDecayer_H
#define HERWIG_TVVDecayer_H
//
// This is the declaration of the TVVDecayer class.
//
-#include "GeneralTwoBodyDecayer.h"
+#include "GeneralTwoBodyDecayer2.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h"
#include "ThePEG/Helicity/Vertex/Tensor/VVTVertex.h"
#include "ThePEG/Helicity/Vertex/Tensor/VVVTVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VVTVertexPtr;
/** \ingroup Decay
* The TVVDecayer class implements the decay of a tensor
* to 2 vector bosons in a general model. It holds a VVTVertex pointer
* that must be typecast from the VertexBase pointer held in
- * GeneralTwoBodyDecayer. It implents the virtual functions me2() and
+ * GeneralTwoBodyDecayer2. It implents the virtual functions me2() and
* partialWidth().
*
- * @see GeneralTwoBodyDecayer
+ * @see GeneralTwoBodyDecayer2
*/
-class TVVDecayer: public GeneralTwoBodyDecayer {
+class TVVDecayer: public GeneralTwoBodyDecayer2 {
public:
/**
* The default constructor.
*/
TVVDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
- * @param ichan The channel we are calculating the matrix element for.
+ * @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
- * @param decay The particles produced in the decay.
- * @param meopt Option for the matrix element
+ * @param outgoing The particles produced in the decay
+ * @param momenta The momenta of the particles produced in the decay
+ * @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
- virtual double me2(const int ichan, const Particle & part,
- const ParticleVector & decay, MEOption meopt) const;
+ double me2(const int ichan,const Particle & part,
+ const tPDVector & outgoing,
+ const vector<Lorentz5Momentum> & momenta,
+ MEOption meopt) const;
+
+ /**
+ * Construct the SpinInfos for the particles produced in the decay
+ */
+ virtual void constructSpinInfo(const Particle & part,
+ ParticleVector outgoing) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {
POWHEGType output = FSR;
for(auto vertex : vertex_) {
if(vertex->orderInAllCouplings()!=1) {
output = No;
break;
}
}
return output;
}
/**
* Three-body matrix element including additional QCD radiation
*/
virtual double threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay,
ShowerInteraction inter, MEOption meopt);
/**
* Set the information on the decay
*/
virtual void setDecayInfo(PDPtr incoming, PDPair outgoing,
vector<VertexBasePtr>,
map<ShowerInteraction,VertexBasePtr> &,
const vector<map<ShowerInteraction,VertexBasePtr> > &,
map<ShowerInteraction,VertexBasePtr>);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
TVVDecayer & operator=(const TVVDecayer &);
private:
/**
* Abstract pointer to AbstractVVTVertex
*/
vector<AbstractVVTVertexPtr> vertex_;
/**
* Pointer to the perturbative vertex
*/
vector<VVTVertexPtr> perturbativeVertex_;
/**
* Abstract pointer to AbstractVVVVertex for QCD radiation from outgoing vector
*/
map<ShowerInteraction,AbstractVVVVertexPtr> outgoingVertex1_;
/**
* Abstract pointer to AbstractVVVVertex for QCD radiation from outgoing vector
*/
map<ShowerInteraction,AbstractVVVVertexPtr> outgoingVertex2_;
/**
* Abstract pointer to AbstractVVVTVertex for QCD radiation from 4 point vertex
*/
map<ShowerInteraction,AbstractVVVTVertexPtr> fourPointVertex_;
/**
* Spin density matrix
*/
mutable RhoDMatrix rho_;
/**
* Polarization tensors of decaying particle
*/
mutable vector<Helicity::TensorWaveFunction> tensors_;
/**
* Polarization vectors of outgoing vector bosons
*/
mutable vector<Helicity::VectorWaveFunction> vectors_[2];
/**
* Spin density matrix for 3 body decay
*/
mutable RhoDMatrix rho3_;
/**
* Tensor wavefunction for 3 body decay
*/
mutable vector<Helicity::TensorWaveFunction> tensors3_;
/**
* Polarization vectors of outgoing vector bosons
*/
mutable vector<Helicity::VectorWaveFunction> vectors3_[2];
/**
* Vector wavefunction for 3 body decay
*/
mutable vector<Helicity::VectorWaveFunction> gluon_;
};
}
#endif /* HERWIG_TVVDecayer_H */
diff --git a/Decay/General/VVVDecayer.cc b/Decay/General/VVVDecayer.cc
--- a/Decay/General/VVVDecayer.cc
+++ b/Decay/General/VVVDecayer.cc
@@ -1,443 +1,448 @@
// -*- C++ -*-
//
// VVVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VVVDecayer class.
//
#include "VVVDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "Herwig/Utilities/Kinematics.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
IBPtr VVVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr VVVDecayer::fullclone() const {
return new_ptr(*this);
}
void VVVDecayer::setDecayInfo(PDPtr incoming, PDPair outgoing,
vector<VertexBasePtr> vertex,
map<ShowerInteraction,VertexBasePtr> & inV,
const vector<map<ShowerInteraction,VertexBasePtr> > & outV,
map<ShowerInteraction,VertexBasePtr> fourV) {
decayInfo(incoming,outgoing);
for(auto vert : vertex) {
vertex_ .push_back(dynamic_ptr_cast<AbstractVVVVertexPtr>(vert));
perturbativeVertex_ .push_back(dynamic_ptr_cast<VVVVertexPtr> (vert));
}
vector<ShowerInteraction> itemp={ShowerInteraction::QCD,ShowerInteraction::QED};
for(auto & inter : itemp) {
incomingVertex_[inter] = dynamic_ptr_cast<AbstractVVVVertexPtr>(inV.at(inter));
outgoingVertex1_[inter] = dynamic_ptr_cast<AbstractVVVVertexPtr>(outV[0].at(inter));
outgoingVertex2_[inter] = dynamic_ptr_cast<AbstractVVVVertexPtr>(outV[1].at(inter));
fourPointVertex_[inter] = dynamic_ptr_cast<AbstractVVVVVertexPtr>(fourV.at(inter));
}
}
void VVVDecayer::persistentOutput(PersistentOStream & os) const {
os << vertex_ << perturbativeVertex_
<< incomingVertex_ << outgoingVertex1_
<< outgoingVertex2_ << fourPointVertex_;
}
void VVVDecayer::persistentInput(PersistentIStream & is, int) {
is >> vertex_ >> perturbativeVertex_
>> incomingVertex_ >> outgoingVertex1_
>> outgoingVertex2_ >> fourPointVertex_;
}
// The following static variable is needed for the type
// description system in ThePEG.
-DescribeClass<VVVDecayer,GeneralTwoBodyDecayer>
+DescribeClass<VVVDecayer,GeneralTwoBodyDecayer2>
describeHerwigVVVDecayer("Herwig::VVVDecayer", "Herwig.so");
void VVVDecayer::Init() {
static ClassDocumentation<VVVDecayer> documentation
("The VVVDecayer class implements the decay of a vector boson "
"into 2 vector bosons");
}
-double VVVDecayer::me2(const int , const Particle & inpart,
- const ParticleVector & decay,
+void VVVDecayer::
+constructSpinInfo(const Particle & part, ParticleVector decay) const {
+ bool massless[2];
+ for(unsigned int ix=0;ix<2;++ix)
+ massless[ix] = (decay[ix]->id()==ParticleID::gamma ||
+ decay[ix]->id()==ParticleID::g);
+ VectorWaveFunction::constructSpinInfo(vectors_[0],const_ptr_cast<tPPtr>(&part),
+ incoming,true,false);
+ for(unsigned int ix=0;ix<2;++ix)
+ VectorWaveFunction::
+ constructSpinInfo(vectors_[ix+1],decay[ix],outgoing,true,massless[ix]);
+}
+
+double VVVDecayer::me2(const int,const Particle & part,
+ const tPDVector & outgoing,
+ const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin1)));
bool massless[2];
for(unsigned int ix=0;ix<2;++ix)
- massless[ix] = (decay[ix]->id()==ParticleID::gamma ||
- decay[ix]->id()==ParticleID::g);
+ massless[ix] = (outgoing[ix]->id()==ParticleID::gamma ||
+ outgoing[ix]->id()==ParticleID::g);
if(meopt==Initialize) {
VectorWaveFunction::calculateWaveFunctions(vectors_[0],rho_,
- const_ptr_cast<tPPtr>(&inpart),
+ const_ptr_cast<tPPtr>(&part),
incoming,false);
// fix rho if no correlations
fixRho(rho_);
}
- if(meopt==Terminate) {
- VectorWaveFunction::constructSpinInfo(vectors_[0],const_ptr_cast<tPPtr>(&inpart),
- incoming,true,false);
- for(unsigned int ix=0;ix<2;++ix)
- VectorWaveFunction::
- constructSpinInfo(vectors_[ix+1],decay[ix],outgoing,true,massless[ix]);
- return 0.;
- }
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
- calculateWaveFunctions(vectors_[ix+1],decay[ix],outgoing,massless[ix]);
- Energy2 scale(sqr(inpart.mass()));
+ calculateWaveFunctions(vectors_[ix],momenta[ix],outgoing[ix],Helicity::outgoing,massless[ix]);
+ Energy2 scale(sqr(part.mass()));
for(unsigned int iv3=0;iv3<3;++iv3) {
for(unsigned int iv2=0;iv2<3;++iv2) {
for(unsigned int iv1=0;iv1<3;++iv1) {
(*ME())(iv1,iv2,iv3) = 0.;
for(auto vert : vertex_) {
(*ME())(iv1,iv2,iv3) += vert->
evaluate(scale,vectors_[1][iv2],vectors_[2][iv3],vectors_[0][iv1]);
}
}
}
}
double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
- output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
- decay[1]->dataPtr());
+ output *= colourFactor(part.dataPtr(),outgoing[0],outgoing[1]);
// return the answer
return output;
}
Energy VVVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(perturbativeVertex_.size()==1 &&
perturbativeVertex_[0]) {
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
perturbativeVertex_[0]->setCoupling(sqr(inpart.second), in,
outa.first, outb.first);
double mu1(outa.second/inpart.second), mu1sq(sqr(mu1)),
mu2(outb.second/inpart.second), mu2sq(sqr(mu2));
double vn = norm(perturbativeVertex_[0]->norm());
if(vn == ZERO || mu1sq == ZERO || mu2sq == ZERO) return ZERO;
double me2 =
(mu1 - mu2 - 1.)*(mu1 - mu2 + 1.)*(mu1 + mu2 - 1.)*(mu1 + mu2 + 1.)
* (sqr(mu1sq) + sqr(mu2sq) + 10.*(mu1sq*mu2sq + mu1sq + mu2sq) + 1.)
/4./mu1sq/mu2sq;
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second,
outb.second);
Energy pWidth = vn*me2*pcm/24./Constants::pi;
// colour factor
pWidth *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return pWidth;
}
else {
- return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
+ return GeneralTwoBodyDecayer2::partialWidth(inpart,outa,outb);
}
}
double VVVDecayer::threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay,
ShowerInteraction inter, MEOption meopt) {
if(meopt==Initialize) {
// create vector wavefunction for decaying particle
VectorWaveFunction::calculateWaveFunctions(vector3_, rho3_, const_ptr_cast<tPPtr>(&inpart),
incoming, false);
}
if(meopt==Terminate) {
VectorWaveFunction::
constructSpinInfo(vector3_ ,const_ptr_cast<tPPtr>(&inpart),outgoing,true,false);
VectorWaveFunction::
constructSpinInfo(vectors3_[0],decay[0],outgoing,true,false);
VectorWaveFunction::
constructSpinInfo(vectors3_[1],decay[1],outgoing,true,false);
VectorWaveFunction::
constructSpinInfo(gluon_ ,decay[2],outgoing,true,false);
return 0.;
}
// calculate colour factors and number of colour flows
unsigned int nflow;
vector<DVector> cfactors = getColourFactors(inpart, decay, nflow);
vector<GeneralDecayMEPtr> ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1, PDT::Spin1,
PDT::Spin1, PDT::Spin1)));
bool massless[2];
for(unsigned int ix=0;ix<2;++ix)
massless[ix] = decay[ix]->mass()!=ZERO;
// create wavefunctions
VectorWaveFunction::calculateWaveFunctions(vectors3_[0],decay[0],outgoing,massless[0]);
VectorWaveFunction::calculateWaveFunctions(vectors3_[1],decay[1],outgoing,massless[1]);
VectorWaveFunction::calculateWaveFunctions(gluon_ ,decay[2],outgoing,true);
// gauge test
#ifdef GAUGE_CHECK
gluon_.clear();
for(unsigned int ix=0;ix<3;++ix) {
if(ix==1) gluon_.push_back(VectorWaveFunction());
else {
gluon_.push_back(VectorWaveFunction(decay[2]->momentum(),
decay[2]->dataPtr(),10,
outgoing));
}
}
#endif
// get the outgoing vertices
AbstractVVVVertexPtr outgoingVertex1;
AbstractVVVVertexPtr outgoingVertex2;
identifyVertices(inpart,decay, outgoingVertex1, outgoingVertex2,inter);
Energy2 scale(sqr(inpart.mass()));
- const GeneralTwoBodyDecayer::CFlow & colourFlow
+ const GeneralTwoBodyDecayer2::CFlow & colourFlow
= colourFlows(inpart, decay);
double gs(0.);
bool couplingSet(false);
#ifdef GAUGE_CHECK
double total=0.;
#endif
for(unsigned int iv0 = 0; iv0 < 3; ++iv0) {
for(unsigned int iv1 = 0; iv1 < 3; ++iv1) {
if(massless[0] && iv1==1) continue;
for(unsigned int iv2 = 0; iv2 < 3; ++iv2) {
if(massless[1] && iv2==1) continue;
for(unsigned int ig = 0; ig < 2; ++ig) {
// radiation from the incoming vector
if((inpart.dataPtr()->coloured() && inter==ShowerInteraction::QCD) ||
(inpart.dataPtr()->charged() && inter==ShowerInteraction::QED) ) {
assert(incomingVertex_[inter]);
VectorWaveFunction vectorInter =
incomingVertex_[inter]->evaluate(scale,3,inpart.dataPtr(),vector3_[iv0],
gluon_[2*ig],inpart.mass());
assert(vector3_[iv0].particle()->id()==vectorInter.particle()->id());
Complex diag = 0.;
for(auto vertex : vertex_)
diag += vertex->evaluate(scale,vectorInter,vectors3_[0][iv1],
vectors3_[1][iv2]);
if(!couplingSet) {
gs = abs(incomingVertex_[inter]->norm());
couplingSet = true;
}
for(unsigned int ix=0;ix<colourFlow[0].size();++ix) {
(*ME[colourFlow[0][ix].first])(iv0, iv1, iv2, ig) +=
colourFlow[0][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
// radiation from the 1st outgoing vector
if((decay[0]->dataPtr()->coloured() && inter==ShowerInteraction::QCD) ||
(decay[0]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) {
assert(outgoingVertex1);
// ensure you get correct outgoing particle from first vertex
tcPDPtr off = decay[0]->dataPtr();
if(off->CC()) off = off->CC();
VectorWaveFunction vectorInter =
outgoingVertex1->evaluate(scale,3,off,gluon_[2*ig],vectors3_[0][iv1],decay[0]->mass());
assert(vectors3_[0][iv1].particle()->id()==vectorInter.particle()->id());
Complex diag = 0.;
for(auto vertex : vertex_)
diag += vertex->evaluate(scale,vector3_[iv0],vectorInter,vectors3_[1][iv2]);
if(!couplingSet) {
gs = abs(outgoingVertex1->norm());
couplingSet = true;
}
for(unsigned int ix=0;ix<colourFlow[1].size();++ix) {
(*ME[colourFlow[1][ix].first])(iv0, iv1, iv2, ig) +=
colourFlow[1][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
// radiation from the second outgoing vector
if((decay[1]->dataPtr()->coloured() && inter==ShowerInteraction::QCD) ||
(decay[1]->dataPtr()->charged() && inter==ShowerInteraction::QED) ) {
assert(outgoingVertex2);
// ensure you get correct outgoing particle from first vertex
tcPDPtr off = decay[1]->dataPtr();
if(off->CC()) off = off->CC();
VectorWaveFunction vectorInter =
outgoingVertex2->evaluate(scale,3,off, gluon_[2*ig],vectors3_[1][iv2],decay[1]->mass());
assert(vectors3_[1][iv2].particle()->id()==vectorInter.particle()->id());
Complex diag = 0.;
for(auto vertex : vertex_)
diag += vertex->evaluate(scale,vector3_[iv0],vectors3_[0][iv1],vectorInter);
if(!couplingSet) {
gs = abs(outgoingVertex2->norm());
couplingSet = true;
}
for(unsigned int ix=0;ix<colourFlow[2].size();++ix) {
(*ME[colourFlow[2][ix].first])(iv0, iv1, iv2, ig) +=
colourFlow[2][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
// 4-point vertex
if (fourPointVertex_[inter]) {
Complex diag = fourPointVertex_[inter]->evaluate(scale,0, vector3_[iv0],
vectors3_[0][iv1],
vectors3_[1][iv2],gluon_[2*ig]);
for(unsigned int ix=0;ix<colourFlow[2].size();++ix) {
(*ME[colourFlow[3][ix].first])(iv0, iv1, iv2, ig) +=
colourFlow[3][ix].second*diag;
}
#ifdef GAUGE_CHECK
total+=norm(diag);
#endif
}
}
}
}
}
// contract matrices
double output=0.;
for(unsigned int ix=0; ix<nflow; ++ix){
for(unsigned int iy=0; iy<nflow; ++iy){
output+=cfactors[ix][iy]*(ME[ix]->contract(*ME[iy],rho3_)).real();
}
}
// divide by alpha_(S,EM)
output*=(4.*Constants::pi)/sqr(gs);
#ifdef GAUGE_CHECK
double ratio = output/total;
if(abs(ratio)>1e-20) {
generator()->log() << "Test of gauge invariance in decay\n" << inpart << "\n";
for(unsigned int ix=0;ix<decay.size();++ix)
generator()->log() << *decay[ix] << "\n";
generator()->log() << "Test of gauge invariance " << ratio << "\n";
}
#endif
// return the answer
return output;
}
void VVVDecayer::identifyVertices(const Particle & inpart, const ParticleVector & decay,
AbstractVVVVertexPtr & outgoingVertex1,
AbstractVVVVertexPtr & outgoingVertex2,
ShowerInteraction inter) {
if(inter==ShowerInteraction::QCD) {
// work out which scalar each outgoing vertex corresponds to
// two outgoing vertices
if( inpart.dataPtr() ->iColour()==PDT::Colour0 &&
((decay[0]->dataPtr()->iColour()==PDT::Colour3 &&
decay[1]->dataPtr()->iColour()==PDT::Colour3bar) ||
(decay[0]->dataPtr()->iColour()==PDT::Colour8 &&
decay[1]->dataPtr()->iColour()==PDT::Colour8))){
if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->id()))){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[0]->id()))){
outgoingVertex1 = outgoingVertex2_[inter];
outgoingVertex2 = outgoingVertex1_[inter];
}
}
else if(inpart.dataPtr() ->iColour()==PDT::Colour8 &&
decay[0]->dataPtr()->iColour()==PDT::Colour3 &&
decay[1]->dataPtr()->iColour()==PDT::Colour3bar){
if(outgoingVertex1_[inter]==outgoingVertex2_[inter]){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->id()))){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else if (outgoingVertex2_[inter]->isIncoming(getParticleData(decay[0]->id()))){
outgoingVertex1 = outgoingVertex2_[inter];
outgoingVertex2 = outgoingVertex1_[inter];
}
}
// one outgoing vertex
else if(inpart.dataPtr()->iColour()==PDT::Colour3){
if(decay[0]->dataPtr()->iColour()==PDT::Colour3 &&
decay[1]->dataPtr()->iColour()==PDT::Colour0){
if (outgoingVertex1_[inter]) outgoingVertex1 = outgoingVertex1_[inter];
else if(outgoingVertex2_[inter]) outgoingVertex1 = outgoingVertex2_[inter];
}
else if (decay[0]->dataPtr()->iColour()==PDT::Colour3 &&
decay[1]->dataPtr()->iColour()==PDT::Colour8){
if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[1]->dataPtr()->id()))){
outgoingVertex1 = outgoingVertex2_[inter];
outgoingVertex2 = outgoingVertex1_[inter];
}
else {
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
}
}
else if(inpart.dataPtr()->iColour()==PDT::Colour3bar){
if(decay[1]->dataPtr()->iColour()==PDT::Colour3bar &&
decay[0]->dataPtr()->iColour()==PDT::Colour0){
if (outgoingVertex1_[inter]) outgoingVertex2 = outgoingVertex1_[inter];
else if(outgoingVertex2_[inter]) outgoingVertex2 = outgoingVertex2_[inter];
}
else if (decay[0]->dataPtr()->iColour()==PDT::Colour8 &&
decay[1]->dataPtr()->iColour()==PDT::Colour3bar){
if (outgoingVertex1_[inter]->isIncoming(getParticleData(decay[0]->dataPtr()->id()))){
outgoingVertex1 = outgoingVertex1_[inter];
outgoingVertex2 = outgoingVertex2_[inter];
}
else {
outgoingVertex1 = outgoingVertex2_[inter];
outgoingVertex2 = outgoingVertex1_[inter];
}
}
}
if (! ((incomingVertex_[inter] && (outgoingVertex1 || outgoingVertex2)) ||
( outgoingVertex1 && outgoingVertex2)))
throw Exception()
<< "Invalid vertices for QCD radiation in VVV decay in VVVDecayer::identifyVertices"
<< Exception::runerror;
}
else {
if(decay[0]->dataPtr()->charged()) {
if (outgoingVertex1_[inter] &&
outgoingVertex1_[inter]->isIncoming(const_ptr_cast<tPDPtr>(decay[0]->dataPtr())))
outgoingVertex1 = outgoingVertex1_[inter];
else
outgoingVertex1 = outgoingVertex2_[inter];
}
if(decay[1]->dataPtr()->charged()) {
if (outgoingVertex1_[inter] &&
outgoingVertex1_[inter]->isIncoming(const_ptr_cast<tPDPtr>(decay[1]->dataPtr())))
outgoingVertex2 = outgoingVertex1_[inter];
else
outgoingVertex2 = outgoingVertex2_[inter];
}
}
}
diff --git a/Decay/General/VVVDecayer.h b/Decay/General/VVVDecayer.h
--- a/Decay/General/VVVDecayer.h
+++ b/Decay/General/VVVDecayer.h
@@ -1,228 +1,237 @@
// -*- C++ -*-
//
// VVVDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_VVVDecayer_H
#define HERWIG_VVVDecayer_H
//
// This is the declaration of the VVVDecayer class.
//
-#include "GeneralTwoBodyDecayer.h"
+#include "GeneralTwoBodyDecayer2.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VVVVertexPtr;
/** \ingroup Decay
* The VVVDecayer class implements the decay of a vector
* to 2 vectors in a general model. It holds an VVVVertex pointer
* that must be typecast from the VertexBase pointer held in
- * GeneralTwoBodyDecayer. It implents the virtual functions me2() and
+ * GeneralTwoBodyDecayer2. It implents the virtual functions me2() and
* partialWidth().
*
- * @see GeneralTwoBodyDecayer
+ * @see GeneralTwoBodyDecayer2
*/
-class VVVDecayer: public GeneralTwoBodyDecayer {
+class VVVDecayer: public GeneralTwoBodyDecayer2 {
public:
/**
* The default constructor.
*/
VVVDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
- * @param ichan The channel we are calculating the matrix element for.
+ * @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
- * @param decay The particles produced in the decay.
+ * @param outgoing The particles produced in the decay
+ * @param momenta The momenta of the particles produced in the decay
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
- virtual double me2(const int ichan, const Particle & part,
- const ParticleVector & decay, MEOption meopt) const;
+ double me2(const int ichan,const Particle & part,
+ const tPDVector & outgoing,
+ const vector<Lorentz5Momentum> & momenta,
+ MEOption meopt) const;
+
+ /**
+ * Construct the SpinInfos for the particles produced in the decay
+ */
+ virtual void constructSpinInfo(const Particle & part,
+ ParticleVector outgoing) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
/**
* Set the information on the decay
*/
virtual void setDecayInfo(PDPtr incoming, PDPair outgoing,
vector<VertexBasePtr>,
map<ShowerInteraction,VertexBasePtr> &,
const vector<map<ShowerInteraction,VertexBasePtr> > &,
map<ShowerInteraction,VertexBasePtr>);
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {
POWHEGType output = FSR;
for(auto vertex : vertex_) {
if(vertex->orderInAllCouplings()!=1) {
output = No;
break;
}
}
return output;
}
/**
* Three-body matrix element including additional QCD radiation
*/
virtual double threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay,
ShowerInteraction inter, MEOption meopt);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/**
* Find the vertices for the decay
*/
void identifyVertices(const Particle & inpart, const ParticleVector & decay,
AbstractVVVVertexPtr & outgoingVertex1,
AbstractVVVVertexPtr & outgoingVertex2,
ShowerInteraction inter);
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
VVVDecayer & operator=(const VVVDecayer &);
private:
/**
* Abstract pointer to AbstractVVVVertex
*/
vector<AbstractVVVVertexPtr> vertex_;
/**
* Pointer to the perturbative vertex
*/
vector<VVVVertexPtr> perturbativeVertex_;
/**
* Abstract pointer to AbstractVVVVertex for QCD radiation from incoming vector
*/
map<ShowerInteraction,AbstractVVVVertexPtr> incomingVertex_;
/**
* Abstract pointer to AbstractVVVVertex for QCD radiation from the first outgoing vector
*/
map<ShowerInteraction,AbstractVVVVertexPtr> outgoingVertex1_;
/**
* Abstract pointer to AbstractVVVVertex for QCD radiation from the second outgoing vector
*/
map<ShowerInteraction,AbstractVVVVertexPtr> outgoingVertex2_;
/**
* Abstract pointer to AbstractVVVVertex for QCD radiation from the 4-point vertex
*/
map<ShowerInteraction,AbstractVVVVVertexPtr> fourPointVertex_;
/**
* Spin density matrix
*/
mutable RhoDMatrix rho_;
/**
* Vector wavefunctions
*/
mutable vector<Helicity::VectorWaveFunction> vectors_[3];
private:
/**
* Members for the POWHEG correction
*/
//@{
/**
* Spin density matrix for 3 body decay
*/
mutable RhoDMatrix rho3_;
/**
* Vector wavefunction for 3 body decay
*/
mutable vector<Helicity::VectorWaveFunction> vector3_;
/**
* Vector wavefunctions
*/
mutable vector<Helicity::VectorWaveFunction> vectors3_[2];
/**
* Vector wavefunction for 3 body decay
*/
mutable vector<Helicity::VectorWaveFunction> gluon_;
//@}
};
}
#endif /* HERWIG_VVVDecayer_H */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 3:15 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3804927
Default Alt Text
(117 KB)
Attached To
R563 testingHerwigHG
Event Timeline
Log In to Comment