Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7879301
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
99 KB
Subscribers
None
View Options
diff --git a/Decay/General/GeneralFourBodyDecayer.cc b/Decay/General/GeneralFourBodyDecayer.cc
--- a/Decay/General/GeneralFourBodyDecayer.cc
+++ b/Decay/General/GeneralFourBodyDecayer.cc
@@ -1,87 +1,918 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GeneralFourBodyDecayer class.
//
#include "GeneralFourBodyDecayer.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Switch.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
-GeneralFourBodyDecayer::GeneralFourBodyDecayer() {}
-
void GeneralFourBodyDecayer::persistentOutput(PersistentOStream & os) const {
- os << _incoming << _outgoing << _diagrams << _reftag << _reftagcc;
+ os << _incoming << _outgoing << _diagrams << _reftag << _reftagcc
+ << _widthopt << _colour << _colourLargeNC << _nflow << _diagmap;
}
void GeneralFourBodyDecayer::persistentInput(PersistentIStream & is, int) {
- is >> _incoming >> _outgoing >> _diagrams >> _reftag >> _reftagcc;
+ is >> _incoming >> _outgoing >> _diagrams >> _reftag >> _reftagcc
+ >> _widthopt >> _colour >> _colourLargeNC >> _nflow >> _diagmap;
}
DescribeAbstractClass<GeneralFourBodyDecayer,DecayIntegrator>
describeGeneralFourBodyDecayer("Herwig::GeneralFourBodyDecayer",
"Herwig.so");
void GeneralFourBodyDecayer::Init() {
static ClassDocumentation<GeneralFourBodyDecayer> documentation
- ("There is no documentation for the GeneralFourBodyDecayer class");
+ ("The GeneralFourBodyDecayer class is the base class for the implementation "
+ "of all four-body decays based on spin structures in Herwig++.");
+
+ static Switch<GeneralFourBodyDecayer,unsigned int> interfaceWidthOption
+ ("WidthOption",
+ "Option for the treatment of the widths of the intermediates",
+ &GeneralFourBodyDecayer::_widthopt, 1, false, false);
+ static SwitchOption interfaceWidthOptionFixed
+ (interfaceWidthOption,
+ "Fixed",
+ "Use fixed widths",
+ 1);
+ static SwitchOption interfaceWidthOptionRunning
+ (interfaceWidthOption,
+ "Running",
+ "Use running widths",
+ 2);
+ static SwitchOption interfaceWidthOptionZero
+ (interfaceWidthOption,
+ "Zero",
+ "Set the widths to zero",
+ 3);
}
ParticleVector GeneralFourBodyDecayer::decay(const Particle & parent,
const tPDVector & children) const {
- assert(false);
- return ParticleVector();
+ // 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;
}
int GeneralFourBodyDecayer::modeNumber(bool & cc, tcPDPtr parent,
const tPDVector & children) const {
- assert(false);
- return 0;
+ assert( !_reftag.empty() && !_reftagcc.empty() );
+ // check number of outgoing particles
+ if( children.size() != 4 || abs(parent->id()) != _incoming->id() ) return -1;
+ OrderedParticles testmode(children.begin(), children.end());
+ OrderedParticles::const_iterator dit = testmode.begin();
+ string testtag(parent->name() + "->");
+ for( unsigned int i = 1; dit != testmode.end(); ++dit, ++i) {
+ testtag += (**dit).name();
+ if( i != 3 ) testtag += string(",");
+ }
+ if( testtag == _reftag ) {
+ cc = false;
+ return 0;
+ }
+ else if ( testtag == _reftagcc ) {
+ cc = true;
+ return 0;
+ }
+ else return -1;
}
-
-bool GeneralFourBodyDecayer::setDecayInfo(PDPtr incoming,vector<PDPtr> outgoing,
- const vector<PrototypeVertexPtr> & process) {
+
+bool GeneralFourBodyDecayer::setDecayInfo(PDPtr incoming,
+ vector<PDPtr> outgoing,
+ const vector<NBDiagram> & process) {
// set the member variables from the info supplied
// external particles
_incoming = incoming;
_outgoing = outgoing;
+ _diagrams = process;
assert( _outgoing.size() == 4 );
- // convert and store the diagrams
- for(unsigned int ix=0;ix<process.size();++ix)
- _diagrams.push_back(NBDiagram(process[ix]));
// Construct reference tags for testing in modeNumber function
OrderedParticles refmode(_outgoing.begin(), _outgoing.end());
OrderedParticles::const_iterator dit = refmode.begin();
_reftag = _incoming->name() + "->";
for( ; dit != refmode.end(); ++dit) {
if( dit != refmode.begin() ) _reftag += string(",");
_reftag += (**dit).name();
}
//CC-mode
refmode.clear();
_reftagcc = _incoming->CC() ? _incoming->CC()->name() : _incoming->name();
_reftagcc += "->";
- for( unsigned int i = 0; i < 3; ++i ) {
+ for( unsigned int i = 0; i < _outgoing.size(); ++i ) {
if( _outgoing[i]->CC() ) refmode.insert( _outgoing[i]->CC() );
else refmode.insert( _outgoing[i] );
}
dit = refmode.begin();
for( ; dit != refmode.end(); ++dit) {
if( dit != refmode.begin() ) _reftag += string(",");
_reftagcc += (**dit).name();
}
- // set the color factors
- cerr << "testing in setDecayInfo\n";
-// return setColourFactors();
- exit(0);
+ // set the colour factors and return the answer
+ return setColourFactors();
}
+
+Energy GeneralFourBodyDecayer::partialWidth(tPDPtr inpart,
+ OrderedParticles outgoing) const {
+ tPDVector temp = tPDVector(outgoing.begin(),outgoing.end());
+ bool cc=false;
+ int imode = modeNumber(cc,inpart,temp);
+ if(imode<0) return ZERO;
+ else return initializePhaseSpaceMode(0,true);
+}
+
+namespace {
+ bool addIntermediate(DecayPhaseSpaceChannelPtr newChannel,
+ const NBVertex &vertex,int &order,
+ int & ioff, int & loc) {
+ if(vertex.vertices.size()!=2) return false;
+ assert(!vertex.vertices.begin()->second.incoming);
+ int first = order/pow(10,loc);
+ order = order%int(pow(10,loc));
+ --loc;
+ // one off-shell
+ if((++vertex.vertices.begin())->second.incoming) {
+ newChannel->addIntermediate(vertex.incoming,0,0.0,ioff,first);
+ --ioff;
+ return addIntermediate(newChannel,(++vertex.vertices.begin())->second,
+ order,ioff,loc);
+ }
+ // no off-shell
+ else {
+ int second = order/pow(10,loc);
+ order = order%int(pow(10,loc));
+ --loc;
+ newChannel->addIntermediate(vertex.incoming,0,0.0,first,second);
+ --ioff;
+ return true;
+ }
+ }
+}
+
+void GeneralFourBodyDecayer::doinit() {
+ DecayIntegrator::doinit();
+ // create the phase space integrator
+ tPDVector extpart(1,_incoming);
+ extpart.insert(extpart.end(),_outgoing.begin(),_outgoing.end());
+ // create the integration channels for the decay
+ DecayPhaseSpaceModePtr mode(new_ptr(DecayPhaseSpaceMode(extpart,this,true)));
+ DecayPhaseSpaceChannelPtr newChannel;
+ // create the phase-space channels for the integration
+ unsigned int nmode(0);
+ for(unsigned int ix=0;ix<_diagrams.size();++ix) {
+ // check not four point
+ if(_diagrams[ix].vertices.size()!=2) continue;
+ // create the new channel
+ newChannel=new_ptr(DecayPhaseSpaceChannel(mode));
+ int order = _diagrams[ix].channelType;
+ int ioff = -1;
+ int loc=3;
+ // two off-shell particles
+ if(_diagrams[ix].vertices.begin()->second.incoming) {
+ newChannel->addIntermediate(extpart[0],0,0.0,-1,-2);
+ if(!addIntermediate(newChannel,( _diagrams[ix].vertices.begin())->second,
+ order,ioff,loc)) continue;
+ if(!addIntermediate(newChannel,(++_diagrams[ix].vertices.begin())->second,
+ order,ioff,loc)) continue;
+ }
+ // only one off-shell particle
+ else {
+ int first = order/pow(10,loc);
+ order = order%int(pow(10,loc));
+ --loc;
+ newChannel->addIntermediate(extpart[0],0,0.0,-1,first);
+ --ioff;
+ if(!addIntermediate(newChannel,(++_diagrams[ix].vertices.begin())->second,
+ order,ioff,loc)) continue;
+ }
+ _diagmap.push_back(ix);
+ mode->addChannel(newChannel);
+ cerr << "testing channel " << *newChannel << "\n";
+ ++nmode;
+ }
+ if(nmode==0) {
+ string mode = extpart[0]->PDGName() + "->";
+ for(unsigned int ix=1;ix<extpart.size();++ix) mode += extpart[ix]->PDGName() + " ";
+ throw Exception() << "No decay channels in GeneralFourBodyDecayer::"
+ << "doinit() for " << mode << "\n" << Exception::runerror;
+ }
+ // add the mode
+ vector<double> wgt(nmode,1./double(nmode));
+ addMode(mode,1.,wgt);
+}
+
+void GeneralFourBodyDecayer::colourConnections(const Particle & parent,
+ const ParticleVector & out) const {
+ // first extract the outgoing particles and intermediate
+ ParticleVector inter;
+ ParticleVector outgoing;
+ if(!generateIntermediates()) {
+ outgoing=out;
+ }
+ else {
+ // find the diagram
+ unsigned int idiag = diagramMap()[mode(imode())->selectedChannel()];
+// PPtr child;
+// for(unsigned int ix=0;ix<out.size();++ix) {
+// if(out[ix]->children().empty()) child = out[ix];
+// else inter = out[ix];
+// }
+ outgoing.resize(4);
+// switch(_diagrams[idiag].channelType) {
+// case TBDiagram::channel23:
+// outgoing[0] = child;
+// outgoing[1] = inter->children()[0];
+// outgoing[2] = inter->children()[1];
+// break;
+// case TBDiagram::channel13:
+// outgoing[0] = inter->children()[0];
+// outgoing[1] = child;
+// outgoing[2] = inter->children()[1];
+// break;
+// case TBDiagram::channel12:
+// outgoing[0] = inter->children()[0];
+// outgoing[1] = inter->children()[1];
+// outgoing[2] = child;
+// break;
+// default:
+// throw Exception() << "unknown diagram type in GeneralFourBodyDecayer::"
+// << "colourConnections()" << Exception::runerror;
+// }
+ }
+// // extract colour of the incoming and outgoing particles
+// PDT::Colour inColour(parent.data().iColour());
+// vector<PDT::Colour> outColour;
+// vector<int> singlet,octet,triplet,antitriplet;
+// for(unsigned int ix=0;ix<outgoing.size();++ix) {
+// outColour.push_back(outgoing[ix]->data().iColour());
+// switch(outColour.back()) {
+// case PDT::Colour0 :
+// singlet.push_back(ix);
+// break;
+// case PDT::Colour3 :
+// triplet.push_back(ix);
+// break;
+// case PDT::Colour3bar:
+// antitriplet.push_back(ix);
+// break;
+// case PDT::Colour8 :
+// octet.push_back(ix);
+// break;
+// default:
+// throw Exception() << "Unknown colour for particle in GeneralFourBodyDecayer::"
+// << "colourConnections()" << Exception::runerror;
+// }
+// }
+// // colour neutral decaying particle
+// if ( inColour == PDT::Colour0) {
+// // options are all neutral or triplet/antitriplet+ neutral
+// if(singlet.size()==3) return;
+// else if(singlet.size()==1&&triplet.size()==1&&antitriplet.size()==1) {
+// outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]);
+// // add intermediate if needed
+// if(inter&&inter->coloured()) {
+// if(inter->dataPtr()->iColour()==PDT::Colour3)
+// outgoing[triplet[0]]->colourLine()->addColoured(inter);
+// else if(inter->dataPtr()->iColour()==PDT::Colour3bar)
+// outgoing[triplet[0]]->colourLine()->addAntiColoured(inter);
+// }
+// }
+// else if(octet.size()==1&&triplet.size()==1&&antitriplet.size()==1) {
+// outgoing[ triplet[0]]->antiColourNeighbour(outgoing[octet[0]]);
+// outgoing[antitriplet[0]]-> colourNeighbour(outgoing[octet[0]]);
+// if(inter&&inter->coloured()) {
+// if(inter->dataPtr()->iColour()==PDT::Colour3)
+// outgoing[antitriplet[0]]->antiColourLine()->addColoured(inter);
+// else if(inter->dataPtr()->iColour()==PDT::Colour3bar)
+// outgoing[ triplet[0]]-> colourLine()->addAntiColoured(inter);
+// else if(inter->dataPtr()->iColour()==PDT::Colour8) {
+// outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter);
+// outgoing[ triplet[0]]-> colourLine()->addColoured(inter);
+// }
+// }
+// }
+// else if(triplet.size()==3) {
+// tColinePtr col[3] = {ColourLine::create(outgoing[0]),
+// ColourLine::create(outgoing[1]),
+// ColourLine::create(outgoing[2])};
+// col[0]->setSourceNeighbours(col[1],col[2]);
+// }
+// else if(antitriplet.size()==3) {
+// tColinePtr col[3] = {ColourLine::create(outgoing[0],true),
+// ColourLine::create(outgoing[1],true),
+// ColourLine::create(outgoing[2],true)};
+// col[0]->setSinkNeighbours(col[1],col[2]);
+// }
+// else {
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception()
+// << "Unknown colour structure in GeneralFourBodyDecayer::"
+// << "colourConnections() for singlet decaying particle "
+// << mode << Exception::runerror;
+// }
+// }
+// // colour triplet decaying particle
+// else if( inColour == PDT::Colour3) {
+// if(singlet.size()==2&&triplet.size()==1) {
+// outgoing[triplet[0]]->incomingColour(const_ptr_cast<tPPtr>(&parent));
+// if(inter&&inter->coloured())
+// outgoing[triplet[0]]->colourLine()->addColoured(inter);
+// }
+// else if(antitriplet.size()==1&&triplet.size()==2) {
+// if(colourFlow()==0) {
+// outgoing[triplet[0]]->incomingColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[antitriplet[0]]->colourNeighbour(outgoing[triplet[1]]);
+// if(inter&&inter->coloured()) {
+// switch (inter->dataPtr()->iColour()) {
+// case PDT::Colour8:
+// inter->incomingColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[triplet[1]]->colourLine()->addAntiColoured(inter);
+// break;
+// default:
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception() << "Unknown colour for intermediate in "
+// << "GeneralFourBodyDecayer::"
+// << "colourConnections() for "
+// << "decaying colour triplet "
+// << mode << Exception::runerror;
+// }
+// }
+// }
+// else {
+// outgoing[triplet[1]]->incomingColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[antitriplet[0]]->colourNeighbour(outgoing[triplet[0]]);
+// if(inter&&inter->coloured()) {
+// switch (inter->dataPtr()->iColour()) {
+// case PDT::Colour8:
+// inter->incomingColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[triplet[0]]->colourLine()->addAntiColoured(inter);
+// break;
+// default:
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception() << "Unknown colour for intermediate in "
+// << "GeneralFourBodyDecayer::"
+// << "colourConnections() for "
+// << "decaying colour triplet "
+// << mode << Exception::runerror;
+// }
+// }
+// }
+// }
+// else if (singlet.size()==1&&triplet.size()==1&&octet.size()==1) {
+// if(inter) {
+// if(inter->children()[0]->dataPtr()->iColour()==PDT::Colour8 ||
+// inter->children()[1]->dataPtr()->iColour()==PDT::Colour8) {
+// inter->incomingColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[octet[0]]->incomingColour(inter);
+// outgoing[octet[0]]->colourNeighbour(outgoing[triplet[0]]);
+// }
+// else {
+// outgoing[octet[0]]->incomingColour(inter);
+// outgoing[octet[0]]->colourNeighbour(inter);
+// outgoing[triplet[0]]->incomingColour(inter);
+// }
+// }
+// else {
+// outgoing[octet[0]]->incomingColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[octet[0]]->colourNeighbour(outgoing[triplet[0]]);
+// }
+// }
+// else {
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception()
+// << "Unknown colour structure in GeneralFourBodyDecayer::"
+// << "colourConnections() for triplet decaying particle "
+// << mode << Exception::runerror;
+// }
+// }
+// else if( inColour == PDT::Colour3bar) {
+// if(singlet.size()==2&&antitriplet.size()==1) {
+// outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
+// }
+// else if(antitriplet.size()==2&&triplet.size()==1) {
+// if(colourFlow()==0) {
+// outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[1]]);
+// if(inter&&inter->coloured()) {
+// switch (inter->dataPtr()->iColour()) {
+// case PDT::Colour8:
+// inter->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[antitriplet[1]]->antiColourLine()->addAntiColoured(inter);
+// break;
+// default:
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception() << "Unknown colour for intermediate in"
+// << " GeneralFourBodyDecayer::"
+// << "colourConnections() for "
+// << "decaying colour antitriplet "
+// << mode << Exception::runerror;
+// }
+// }
+// }
+// else {
+// outgoing[antitriplet[1]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]);
+// if(inter&&inter->coloured()) {
+// switch (inter->dataPtr()->iColour()) {
+// case PDT::Colour8:
+// inter->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter);
+// break;
+// default:
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception() << "Unknown colour for intermediate in "
+// << "GeneralFourBodyDecayer::"
+// << "colourConnections() for "
+// << "decaying colour antitriplet "
+// << mode << Exception::runerror;
+// }
+// }
+// }
+// }
+// else if (singlet.size()==1&&antitriplet.size()==1&&octet.size()==1) {
+// if(inter) {
+// if(inter->children()[0]->dataPtr()->iColour()==PDT::Colour8 ||
+// inter->children()[1]->dataPtr()->iColour()==PDT::Colour8) {
+// inter->incomingColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[octet[0]]->incomingAntiColour(inter);
+// outgoing[octet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]);
+// }
+// else {
+// outgoing[octet[0]]->incomingAntiColour(inter);
+// outgoing[octet[0]]->antiColourNeighbour(inter);
+// outgoing[antitriplet[0]]->incomingAntiColour(inter);
+// }
+// }
+// else {
+// outgoing[octet[0]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
+// outgoing[octet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]);
+// }
+// }
+// else {
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception()
+// << "Unknown colour structure in GeneralFourBodyDecayer::"
+// << "colourConnections() for anti-triplet decaying particle"
+// << mode << Exception::runerror;
+// }
+// }
+// else if( inColour == PDT::Colour8) {
+// if(triplet.size()==1&&antitriplet.size()==1&&singlet.size()==1) {
+// outgoing[ triplet[0]]->incomingColour (const_ptr_cast<tPPtr>(&parent));
+// outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
+// if(inter&&inter->coloured()) {
+// switch (inter->dataPtr()->iColour()) {
+// case PDT::Colour3:
+// outgoing[triplet[0]]->colourLine()->addColoured(inter);
+// break;
+// case PDT::Colour3bar:
+// outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter);
+// break;
+// default:
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception() << "Unknown colour for intermediate"
+// << " in GeneralFourBodyDecayer::"
+// << "colourConnections() for "
+// << "decaying colour octet "
+// << mode << Exception::runerror;
+// }
+// }
+// }
+// else {
+// string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+// + out[1]->PDGName() + " " + out[2]->PDGName();
+// throw Exception()
+// << "Unknown colour structure in GeneralFourBodyDecayer::"
+// << "colourConnections() for octet decaying particle"
+// << mode << Exception::runerror;
+// }
+// }
+}
+
+bool GeneralFourBodyDecayer::setColourFactors() {
+ string name = _incoming->PDGName() + "->";
+ vector<int> sng,trip,atrip,oct;
+ unsigned int iloc(0);
+ for(vector<PDPtr>::const_iterator it = _outgoing.begin();
+ it != _outgoing.end();++it) {
+ name += (**it).PDGName() + " ";
+ if ((**it).iColour() == PDT::Colour0 ) sng.push_back(iloc) ;
+ else if((**it).iColour() == PDT::Colour3 ) trip.push_back(iloc) ;
+ else if((**it).iColour() == PDT::Colour3bar ) atrip.push_back(iloc);
+ else if((**it).iColour() == PDT::Colour8 ) oct.push_back(iloc) ;
+ ++iloc;
+ }
+ // colour neutral decaying particle
+ if ( _incoming->iColour() == PDT::Colour0) {
+ // options are all neutral or triplet/antitriplet+ neutral
+ if(sng.size()==4) {
+ _nflow = 1;
+ _colour = vector<DVector>(1,DVector(1,1.));
+ _colourLargeNC = vector<DVector>(1,DVector(1,1.));
+ }
+ else if(sng.size()==2&&trip.size()==1&&atrip.size()==1) {
+ _nflow = 1;
+ _colour = vector<DVector>(1,DVector(1,3.));
+ _colourLargeNC = vector<DVector>(1,DVector(1,3.));
+ }
+// else if(trip.size()==1&&atrip.size()==1&&oct.size()==1) {
+// _nflow = 1;
+// _colour = vector<DVector>(1,DVector(1,4.));
+// _colourLargeNC = vector<DVector>(1,DVector(1,4.));
+// }
+// else if( trip.size() == 3 || atrip.size() == 3 ) {
+// _nflow = 1;
+// _colour = vector<DVector>(1,DVector(1,6.));
+// _colourLargeNC = vector<DVector>(1,DVector(1,6.));
+// for(unsigned int ix=0;ix<_diagrams.size();++ix) {
+// tPDPtr inter = _diagrams[ix].intermediate;
+// if(inter->CC()) inter = inter->CC();
+// unsigned int io[2]={1,2};
+// double sign = _diagrams[ix].channelType == TBDiagram::channel13 ? -1. : 1.;
+// for(unsigned int iy=0;iy<3;++iy) {
+// if (iy==1) io[0]=0;
+// else if(iy==2) io[1]=1;
+// tPDVector decaylist = _diagrams[ix].vertices.second->search(iy, inter);
+// if(decaylist.empty()) continue;
+// bool found=false;
+// for(unsigned int iz=0;iz<decaylist.size();iz+=3) {
+// if(decaylist[iz+io[0]]->id()==_diagrams[ix].outgoingPair.first &&
+// decaylist[iz+io[1]]->id()==_diagrams[ix].outgoingPair.second) {
+// sign *= 1.;
+// found = true;
+// }
+// else if(decaylist[iz+io[0]]->id()==_diagrams[ix].outgoingPair.second &&
+// decaylist[iz+io[1]]->id()==_diagrams[ix].outgoingPair.first ) {
+// sign *= -1.;
+// found = true;
+// }
+// }
+// if(found) {
+// if(iy==1) sign *=-1.;
+// break;
+// }
+// }
+// _diagrams[ix]. colourFlow = vector<CFPair>(1,make_pair(1,sign));
+// _diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(1,sign));
+// }
+// }
+ else {
+ generator()->log() << "Unknown colour flow structure for "
+ << "colour neutral decay " << name
+ << " in getColourFactors(), omitting decay\n";
+ return false;
+ }
+ }
+ // colour triplet decaying particle
+ else if( _incoming->iColour() == PDT::Colour3) {
+ if(sng.size()==3&&trip.size()==1) {
+ _nflow = 1;
+ _colour = vector<DVector>(1,DVector(1,1.));
+ _colourLargeNC = vector<DVector>(1,DVector(1,1.));
+ }
+ else if(trip.size()==2&&atrip.size()==1&&sng.size()==1) {
+ _nflow = 2;
+ _colour.resize(2,DVector(2,0.));
+ _colour[0][0] = 3.; _colour[0][1] = 1.;
+ _colour[1][0] = 1.; _colour[1][1] = 3.;
+ _colourLargeNC.resize(2,DVector(2,0.));
+ _colourLargeNC[0][0] = 3.; _colourLargeNC[1][1] = 3.;
+ // particle connect to incoming in first flow
+ unsigned int ifirst(0);
+ for(unsigned int ix=0;ix<_outgoing.size();++ix) {
+ if(_outgoing[ix]->iColour()==PDT::Colour3&&ifirst==0) {
+ ifirst = ix+1;
+ break;
+ }
+ }
+ // sort out the contribution of the different diagrams
+ // to the colour flows
+ for(vector<NBDiagram>::iterator it = _diagrams.begin();
+ it!=_diagrams.end();++it) {
+ // first topology
+ if(it->vertices.begin()->second.incoming) {
+ tPDPair inter = make_pair(it->vertices.begin() ->second.incoming,
+ (++(it->vertices.begin()))->second.incoming);
+ // one neutral and one triplet
+ if(inter. first->iColour()==PDT::Colour3 &&
+ inter.second->iColour()==PDT::Colour0) {
+ if( it->channelType/1000 == ifirst ||
+ (it->channelType%1000)/100 == ifirst) {
+ it-> colourFlow = vector<CFPair>(1,make_pair(1,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
+ }
+ else {
+ it->colourFlow = vector<CFPair>(1,make_pair(2,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
+ }
+ }
+ else if(inter. first->iColour()==PDT::Colour0 &&
+ inter.second->iColour()==PDT::Colour3) {
+ if((it->channelType%100)/10 == ifirst ||
+ it->channelType%10 == ifirst) {
+ it-> colourFlow = vector<CFPair>(1,make_pair(1,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
+ }
+ else {
+ it->colourFlow = vector<CFPair>(1,make_pair(2,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
+ }
+ }
+ // one neutral and one octet
+ else if(inter. first->iColour()==PDT::Colour3 &&
+ inter.second->iColour()==PDT::Colour8) {
+ if( it->channelType/1000 == ifirst ||
+ (it->channelType%1000)/100 == ifirst) {
+ vector<CFPair> flow(1,make_pair(2, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(1,-1./6.));
+ it->colourFlow=flow;
+ }
+ else {
+ vector<CFPair> flow(1,make_pair(1, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(2,-1./6.));
+ it->colourFlow=flow;
+ }
+ }
+ else if(inter. first->iColour()==PDT::Colour8 &&
+ inter.second->iColour()==PDT::Colour3) {
+ if((it->channelType%100)/10 == ifirst ||
+ it->channelType%10 == ifirst) {
+ vector<CFPair> flow(1,make_pair(2, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(1,-1./6.));
+ it->colourFlow=flow;
+ }
+ else {
+ vector<CFPair> flow(1,make_pair(1, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(2,-1./6.));
+ it->colourFlow=flow;
+ }
+ }
+ else
+ return false;
+ }
+ // second topology
+ else {
+ tPDPtr inter = (++(it->vertices.begin()))->second.incoming;
+ unsigned int iloc;
+ if(inter->iColour()==PDT::Colour3) {
+ iloc = (it->channelType%1000)/100;
+ const NBVertex & vertex = (++(it->vertices.begin()))->second;
+ inter = (++vertex.vertices.begin())->second.incoming;
+ }
+ else {
+ iloc = it->channelType/1000;
+ }
+ if(inter->iColour()==PDT::Colour0) {
+ if( iloc == ifirst) {
+ it-> colourFlow = vector<CFPair>(1,make_pair(1,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
+ }
+ else {
+ it->colourFlow = vector<CFPair>(1,make_pair(2,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
+ }
+ }
+ else if(inter->iColour()==PDT::Colour8) {
+ if( iloc == ifirst) {
+ vector<CFPair> flow(1,make_pair(2, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(1,-1./6.));
+ it->colourFlow=flow;
+ }
+ else {
+ vector<CFPair> flow(1,make_pair(1, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(2,-1./6.));
+ it->colourFlow=flow;
+ }
+ }
+ else
+ return false;
+ }
+ }
+ }
+ else {
+ generator()->log() << "Unknown colour structure for "
+ << "triplet decay in "
+ << "FourBodyDecayConstructor::getColourFactors()"
+ << " for " << name << " omitting decay\n";
+ return false;
+ }
+ }
+ // colour antitriplet decaying particle
+ else if( _incoming->iColour() == PDT::Colour3bar) {
+ if(sng.size()==3&&atrip.size()==1) {
+ _nflow = 1;
+ _colour = vector<DVector>(1,DVector(1,1.));
+ _colourLargeNC = vector<DVector>(1,DVector(1,1.));
+ }
+ else if(atrip.size()==2&&trip.size()==1&&sng.size()==1) {
+ _nflow = 2;
+ _colour.resize(2,DVector(2,0.));
+ _colour[0][0] = 3.; _colour[0][1] = 1.;
+ _colour[1][0] = 1.; _colour[1][1] = 3.;
+ _colourLargeNC.resize(2,DVector(2,0.));
+ // particle connect to incoming in first flow
+ unsigned int ifirst(0);
+ for(unsigned int ix=0;ix<_outgoing.size();++ix) {
+ if(_outgoing[ix]->iColour()==PDT::Colour3&&ifirst==0) {
+ ifirst = ix+1;
+ break;
+ }
+ }
+ // sort out the contribution of the different diagrams
+ // to the colour flows
+ for(vector<NBDiagram>::iterator it = _diagrams.begin();
+ it!=_diagrams.end();++it) {
+ // first topology
+ if(it->vertices.begin()->second.incoming) {
+ tPDPair inter = make_pair(it->vertices.begin() ->second.incoming,
+ (++(it->vertices.begin()))->second.incoming);
+ // one neutral and one triplet
+ if(inter. first->iColour()==PDT::Colour3bar &&
+ inter.second->iColour()==PDT::Colour0) {
+ if( it->channelType/1000 == ifirst ||
+ (it->channelType%1000)/100 == ifirst) {
+ it-> colourFlow = vector<CFPair>(1,make_pair(1,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
+ }
+ else {
+ it->colourFlow = vector<CFPair>(1,make_pair(2,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
+ }
+ }
+ else if(inter. first->iColour()==PDT::Colour0 &&
+ inter.second->iColour()==PDT::Colour3bar) {
+ if((it->channelType%100)/10 == ifirst ||
+ it->channelType%10 == ifirst) {
+ it-> colourFlow = vector<CFPair>(1,make_pair(1,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
+ }
+ else {
+ it->colourFlow = vector<CFPair>(1,make_pair(2,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
+ }
+ }
+ // one neutral and one octet
+ else if(inter. first->iColour()==PDT::Colour3bar &&
+ inter.second->iColour()==PDT::Colour8) {
+ if( it->channelType/1000 == ifirst ||
+ (it->channelType%1000)/100 == ifirst) {
+ vector<CFPair> flow(1,make_pair(2, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(1,-1./6.));
+ it->colourFlow=flow;
+ }
+ else {
+ vector<CFPair> flow(1,make_pair(1, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(2,-1./6.));
+ it->colourFlow=flow;
+ }
+ }
+ else if(inter. first->iColour()==PDT::Colour8 &&
+ inter.second->iColour()==PDT::Colour3bar) {
+ if((it->channelType%100)/10 == ifirst ||
+ it->channelType%10 == ifirst) {
+ vector<CFPair> flow(1,make_pair(2, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(1,-1./6.));
+ it->colourFlow=flow;
+ }
+ else {
+ vector<CFPair> flow(1,make_pair(1, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(2,-1./6.));
+ it->colourFlow=flow;
+ }
+ }
+ else
+ return false;
+ }
+ // second topology
+ else {
+ tPDPtr inter = (++(it->vertices.begin()))->second.incoming;
+ unsigned int iloc;
+ if(inter->iColour()==PDT::Colour3bar) {
+ iloc = (it->channelType%1000)/100;
+ const NBVertex & vertex = (++(it->vertices.begin()))->second;
+ inter = (++vertex.vertices.begin())->second.incoming;
+ }
+ else {
+ iloc = it->channelType/1000;
+ }
+ if(inter->iColour()==PDT::Colour0) {
+ if( iloc == ifirst) {
+ it-> colourFlow = vector<CFPair>(1,make_pair(1,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
+ }
+ else {
+ it->colourFlow = vector<CFPair>(1,make_pair(2,1.));
+ it->largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
+ }
+ }
+ else if(inter->iColour()==PDT::Colour8) {
+ if( iloc == ifirst) {
+ vector<CFPair> flow(1,make_pair(2, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(1,-1./6.));
+ it->colourFlow=flow;
+ }
+ else {
+ vector<CFPair> flow(1,make_pair(1, 0.5 ));
+ it->largeNcColourFlow = flow;
+ flow.push_back( make_pair(2,-1./6.));
+ it->colourFlow=flow;
+ }
+ }
+ else
+ return false;
+ }
+ }
+ }
+ else {
+ generator()->log() << "Unknown colour antitriplet decay in "
+ << "FourBodyDecayConstructor::getColourFactors()"
+ << " for " << name << " omitting decay\n";
+ return false;
+ }
+ }
+ else if( _incoming->iColour() == PDT::Colour8) {
+ // triplet antitriplet
+ if(trip.size() == 1 && atrip.size() == 1 && sng.size() == 2) {
+ _nflow = 1;
+ _colour = vector<DVector>(1,DVector(1,0.5));
+ _colourLargeNC = vector<DVector>(1,DVector(1,0.5));
+ }
+ else {
+ generator()->log() << "Unknown colour octet decay in "
+ << "FourBodyDecayConstructor::getColourFactors()"
+ << " for " << name << " omitting decay\n";
+ return false;
+ }
+ }
+ if( Debug::level > 1 ) {
+ generator()->log() << "Mode: " << name << " has colour factors\n";
+ for(unsigned int ix=0;ix<_nflow;++ix) {
+ for(unsigned int iy=0;iy<_nflow;++iy) {
+ generator()->log() << _colour[ix][iy] << " ";
+ }
+ generator()->log() << "\n";
+ }
+ }
+ return true;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Decay/General/GeneralFourBodyDecayer.h b/Decay/General/GeneralFourBodyDecayer.h
--- a/Decay/General/GeneralFourBodyDecayer.h
+++ b/Decay/General/GeneralFourBodyDecayer.h
@@ -1,159 +1,251 @@
// -*- C++ -*-
#ifndef HERWIG_GeneralFourBodyDecayer_H
#define HERWIG_GeneralFourBodyDecayer_H
//
// This is the declaration of the GeneralFourBodyDecayer class.
//
#include "Herwig++/Decay/DecayIntegrator.h"
#include "Herwig++/Models/General/PrototypeVertex.h"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the GeneralFourBodyDecayer class.
*
* @see \ref GeneralFourBodyDecayerInterfaces "The interfaces"
* defined for GeneralFourBodyDecayer.
*/
class GeneralFourBodyDecayer: public DecayIntegrator {
public:
/**
* The default constructor.
*/
- GeneralFourBodyDecayer();
+ GeneralFourBodyDecayer(): _nflow(999), _widthopt(1),
+ _reftag(), _reftagcc(), _iflow(999)
+ {}
/** @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;
+ virtual int modeNumber(bool & cc, tcPDPtr parent,
+ const tPDVector & children) const;
/**
* Set the diagrams
*/
bool setDecayInfo(PDPtr incoming,vector<PDPtr> outgoing,
- const vector<PrototypeVertexPtr> & process);
+ const vector<NBDiagram> & process);
//@}
+
+ /**
+ * Function to return partial Width
+ * @param inpart Pointer to incoming particle data object
+ * @param outgoing the decay products
+ */
+ virtual Energy partialWidth(tPDPtr inpart,
+ OrderedParticles outgoing) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
+protected:
+
+ /**
+ * Incoming particle
+ */
+ PDPtr incoming() const { return _incoming; }
+
+ /**
+ * Outgoing particles
+ */
+ const vector<PDPtr> & outgoing() const { return _outgoing; }
+
+ /**
+ * Number of colour flows
+ */
+ unsigned int numberOfFlows() const { return _nflow; }
+
+ /**
+ * Set up the colour factors
+ */
+ bool setColourFactors();
+
+ /**
+ * Return the matrix of colour factors
+ */
+ const vector<DVector> & getColourFactors() const { return _colour; }
+
+ /**
+ * Return the matrix of colour factors
+ */
+ const vector<DVector> & getLargeNcColourFactors() const {
+ return _colourLargeNC;
+ }
+
+ /**
+ * Option for the handling of the widths of the intermediate particles
+ */
+ unsigned int widthOption() const { return _widthopt; }
+
+ /**
+ * 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;
+
+ /**
+ * Set the colour flow
+ * @param flow The value for the colour flow
+ */
+ void colourFlow(unsigned int flow) const { _iflow = flow; }
+
+ /**
+ * Set the colour flow
+ */
+ unsigned int const & colourFlow() const { return _iflow; }
+
+ /**
+ * Access the TBDiagrams that store the required information
+ * to create the diagrams
+ */
+ const vector<NBDiagram> & getProcessInfo() const {
+ return _diagrams;
+ }
+
+ /**
+ * Get the mapping between the phase-space channel and the diagram
+ */
+ const vector<unsigned int> & diagramMap() const {
+ return _diagmap;
+ }
+
+protected:
+
+ /** @name Standard Interfaced functions. */
+ //@{
+ /**
+ * Initialize this object after the setup phase before saving an
+ * EventGenerator to disk.
+ * @throws InitException if object could not be initialized properly.
+ */
+ virtual void doinit();
+ //@}
+
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GeneralFourBodyDecayer & operator=(const GeneralFourBodyDecayer &);
private:
/**
* Store the incoming particle
*/
PDPtr _incoming;
/**
* Outgoing particles
*/
vector<PDPtr> _outgoing;
/**
* Store the diagrams for the decay
*/
vector<NBDiagram> _diagrams;
-// /**
-// * Map between the diagrams and the phase-space channels
-// */
-// vector<unsigned int> _diagmap;
+ /**
+ * Map between the diagrams and the phase-space channels
+ */
+ vector<unsigned int> _diagmap;
-// /**
-// * Store colour factors for ME calc.
-// */
-// vector<DVector> _colour;
+ /**
+ * Store colour factors for ME calc.
+ */
+ vector<DVector> _colour;
-// /**
-// * Store cololur factors for ME calc at large N_c
-// */
-// vector<DVector> _colourLargeNC;
+ /**
+ * Store cololur factors for ME calc at large N_c
+ */
+ vector<DVector> _colourLargeNC;
-// /**
-// * The number of colourflows.
-// */
-// unsigned int _nflow;
+ /**
+ * The number of colourflows.
+ */
+ unsigned int _nflow;
-// /**
-// * Reference to object to calculate the partial width
-// */
-// mutable WidthCalculatorBasePtr _widthcalc;
-
-// /**
-// * Option for the treatment of the widths
-// */
-// unsigned int _widthopt;
+ /**
+ * Option for the treatment of the widths
+ */
+ unsigned int _widthopt;
/**
* Store a decay tag for this mode that can be tested when
* trying to determine whether it can be generated by
* this Decayer
*/
string _reftag;
/**
* Store a decay tag for the cc-mode that can be tested when
* trying to determine whether it can be generated by
* this Decayer
*/
string _reftagcc;
-// /**
-// * The colour flow
-// */
-// mutable unsigned int _iflow;
+ /**
+ * The colour flow
+ */
+ mutable unsigned int _iflow;
};
}
#endif /* HERWIG_GeneralFourBodyDecayer_H */
diff --git a/Decay/General/StoFFFFDecayer.cc b/Decay/General/StoFFFFDecayer.cc
--- a/Decay/General/StoFFFFDecayer.cc
+++ b/Decay/General/StoFFFFDecayer.cc
@@ -1,50 +1,409 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the StoFFFFDecayer class.
//
#include "StoFFFFDecayer.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
+#include <numeric>
using namespace Herwig;
-StoFFFFDecayer::StoFFFFDecayer() {}
-
IBPtr StoFFFFDecayer::clone() const {
return new_ptr(*this);
}
IBPtr StoFFFFDecayer::fullclone() const {
return new_ptr(*this);
}
void StoFFFFDecayer::persistentOutput(PersistentOStream & os) const {
+ os << firstVVS_ << firstVSS_ << firstSSS_ << firstFFS_
+ << secondFFV_ << secondFFS_
+ << thirdFFV_ << thirdFFS_ << sign_;
}
void StoFFFFDecayer::persistentInput(PersistentIStream & is, int) {
+ is >> firstVVS_ >> firstVSS_ >> firstSSS_ >> firstFFS_
+ >> secondFFV_ >> secondFFS_
+ >> thirdFFV_ >> thirdFFS_ >> sign_;
}
DescribeClass<StoFFFFDecayer,GeneralFourBodyDecayer>
describeStoFFFFDecayer("Herwig::StoFFFFDecayer", "Herwig.so");
void StoFFFFDecayer::Init() {
static ClassDocumentation<StoFFFFDecayer> documentation
- ("The StoFFFFDecayer class performs the 4-body decays of scalar particles in BSM models");
+ ("The StoFFFFDecayer class performs the 4-fermion "
+ "decays of scalar particles in BSM models");
}
-double StoFFFFDecayer::me2(const int ichan, const Particle & part,
+void StoFFFFDecayer::doinit() {
+ GeneralFourBodyDecayer::doinit();
+ unsigned int ndiags = getProcessInfo().size();
+ firstVVS_ .resize(ndiags);
+ firstVSS_ .resize(ndiags);
+ firstSSS_ .resize(ndiags);
+ firstFFS_ .resize(ndiags);
+ secondFFV_.resize(ndiags);
+ secondFFS_.resize(ndiags);
+ thirdFFV_ .resize(ndiags);
+ thirdFFS_ .resize(ndiags);
+ for(unsigned int ix = 0;ix < ndiags; ++ix) {
+ const NBDiagram & current = getProcessInfo()[ix];
+ // first vertex
+ firstVVS_[ix] = dynamic_ptr_cast<AbstractVVSVertexPtr>(current.vertex);
+ firstVSS_[ix] = dynamic_ptr_cast<AbstractVSSVertexPtr>(current.vertex);
+ firstSSS_[ix] = dynamic_ptr_cast<AbstractSSSVertexPtr>(current.vertex);
+ firstFFS_[ix] = dynamic_ptr_cast<AbstractFFSVertexPtr>(current.vertex);
+ // get the other vertices
+ const NBVertex & second = current.vertices.begin()->second.incoming ?
+ current.vertices.begin()->second : (++current.vertices.begin())->second;
+ // get the other vertices
+ const NBVertex & third = current.vertices.begin()->second.incoming ?
+ (++current.vertices.begin())->second : (++second.vertices.begin())->second;
+ // second vertex
+ secondFFV_[ix] = dynamic_ptr_cast<AbstractFFVVertexPtr>(second.vertex);
+ secondFFS_[ix] = dynamic_ptr_cast<AbstractFFSVertexPtr>(second.vertex);
+ // third vertex
+ thirdFFV_ [ix] = dynamic_ptr_cast<AbstractFFVVertexPtr>(third .vertex);
+ thirdFFS_ [ix] = dynamic_ptr_cast<AbstractFFSVertexPtr>(third .vertex);
+ assert( ( firstVVS_[ix] || firstVSS_[ix] ||
+ firstSSS_[ix] || firstFFS_[ix] ) &&
+ (secondFFV_[ix] || secondFFS_[ix] ) &&
+ ( thirdFFV_[ix] || thirdFFS_[ix] ));
+ // NO sign
+ switch(current.channelType) {
+ case 1234: case 1342: case 1423:
+ case 2143: case 2314: case 2431:
+ case 3124: case 3241: case 3412:
+ case 4132: case 4213: case 4321:
+ sign_.push_back( 1.);
+ break;
+ case 1243: case 1324: case 1432:
+ case 2134: case 2341: case 2413:
+ case 3142: case 3214: case 3421:
+ case 4123: case 4231: case 4312:
+ sign_.push_back(-1.);
+ break;
+ default:
+ assert(false);
+ }
+ }
+}
+
+double StoFFFFDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay, MEOption meopt) const {
- assert(false);
- return 0.;
+ // particle or CC of particle
+ bool cc = (*getProcessInfo().begin()).incoming->id() != inpart.id();
+ // special handling or first/last call
+ const vector<vector<double> > & cfactors(getColourFactors());
+ const vector<vector<double> > & nfactors(getLargeNcColourFactors());
+ const size_t ncf(numberOfFlows());
+ Energy2 scale(sqr(inpart.mass()));
+ if(meopt==Initialize) {
+ ScalarWaveFunction::
+ calculateWaveFunctions(rho_,const_ptr_cast<tPPtr>(&inpart),
+ Helicity::incoming);
+ swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),
+ Helicity::incoming);
+ }
+ // setup spin info when needed
+ if(meopt==Terminate) {
+ ScalarWaveFunction::
+ constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),
+ Helicity::incoming,true);
+ // outgoing particles
+ for(unsigned int ix = 0; ix < 4; ++ix) {
+ SpinorWaveFunction::
+ constructSpinInfo(outwave_[ix].first,decay[ix],Helicity::outgoing,true);
+ }
+ }
+ // outgoing particles
+ for(unsigned int ix = 0; ix < 4; ++ix) {
+ SpinorWaveFunction::
+ calculateWaveFunctions(outwave_[ix].first,decay[ix],Helicity::outgoing);
+ outwave_[ix].second.resize(2);
+ if(outwave_[ix].first[0].wave().Type() == u_spinortype) {
+ for(unsigned int iy = 0; iy < 2; ++iy) {
+ outwave_[ix].second[iy] = outwave_[ix].first[iy].bar();
+ outwave_[ix].first[iy].conjugate();
+ }
+ }
+ else {
+ for(unsigned int iy = 0; iy < 2; ++iy) {
+ outwave_[ix].second[iy] = outwave_[ix].first[iy].bar();
+ outwave_[ix].second[iy].conjugate();
+ }
+ }
+ }
+ // matrix element for the colour flows
+ vector<Complex> flows(ncf, Complex(0.)),largeflows(ncf, Complex(0.));
+ vector<DecayMatrixElement> mes(ncf,DecayMatrixElement(PDT::Spin0,
+ PDT::Spin1Half,PDT::Spin1Half,
+ PDT::Spin1Half,PDT::Spin1Half));
+ vector<DecayMatrixElement> mel(ncf,DecayMatrixElement(PDT::Spin0,
+ PDT::Spin1Half,PDT::Spin1Half,
+ PDT::Spin1Half,PDT::Spin1Half));
+ // calculate the matrix element
+ unsigned int ihel[4];
+ for(ihel[0] = 0; ihel[0] < 2; ++ihel[0]) {
+ for(ihel[1] = 0; ihel[1] < 2; ++ihel[1]) {
+ for(ihel[2] = 0; ihel[2] < 2; ++ihel[2]) {
+ for(ihel[3] = 0; ihel[3] < 2; ++ihel[3]) {
+ flows = vector<Complex>(ncf, Complex(0.));
+ largeflows = vector<Complex>(ncf, Complex(0.));
+ unsigned int idiag=0;
+ for(vector<NBDiagram>::const_iterator dit=getProcessInfo().begin();
+ dit!=getProcessInfo().end();++dit) {
+ if(ichan>=0&&diagramMap()[ichan]!=idiag) {
+ ++idiag;
+ continue;
+ }
+ // location of the particles
+ int iloc[4]={ dit->channelType/1000 -1,
+ (dit->channelType%1000)/100-1,
+ (dit->channelType%100)/10 -1,
+ dit->channelType%10 -1};
+ // NO sign
+ double sign = sign_[idiag];
+ // work out the type of topology
+ bool topo = dit->vertices.begin()->second.incoming;
+ const NBVertex & second = topo ?
+ dit->vertices.begin() ->second :
+ (++(dit->vertices.begin()))->second;
+ const NBVertex & third = topo ?
+ (++(dit-> vertices.begin()))->second :
+ (++(second.vertices.begin()))->second;
+ // extract the intermediates
+ tPDPair inter = make_pair(second.incoming,
+ third .incoming->CC());
+ if(cc&&inter.first ->CC()) inter.first = inter.first ->CC();
+ if(cc&&inter.second->CC()) inter.second = inter.second->CC();
+
+// //\todo remove testing
+// if(abs(inter.first ->id())!=ParticleID::t||
+// abs(inter.second->id())!=ParticleID::Wplus) {
+// ++idiag;
+// continue;
+// }
+
+ // value for the diagram
+ Complex diag(0.);
+ // first compute the last part of the diagram
+ VectorWaveFunction offVector2;
+ ScalarWaveFunction offScalar2;
+ // intermeidate scalar
+ if(inter.second->iSpin()==PDT::Spin0) {
+ if(decay[iloc[2]]->id()<0&&
+ decay[iloc[3]]->id()>0) {
+ sign *= -1.;
+ offScalar2 = thirdFFS_[idiag]->
+ evaluate(scale, widthOption(),inter.second,
+ outwave_[iloc[2]].first [ihel[iloc[2]]],
+ outwave_[iloc[3]].second[ihel[iloc[3]]]);
+ }
+ else {
+ offScalar2 = thirdFFS_[idiag]->
+ evaluate(scale, widthOption(),inter.second,
+ outwave_[iloc[3]].first [ihel[iloc[3]]],
+ outwave_[iloc[2]].second[ihel[iloc[2]]]);
+ }
+ }
+ // intermediate vector
+ else if(inter.second->iSpin()==PDT::Spin1) {
+ if(decay[iloc[2]]->id()<0&&
+ decay[iloc[3]]->id()>0) {
+ sign *= -1.;
+ offVector2 = thirdFFV_[idiag]->
+ evaluate(scale, widthOption(),inter.second,
+ outwave_[iloc[2]].first [ihel[iloc[2]]],
+ outwave_[iloc[3]].second[ihel[iloc[3]]]);
+ }
+ else {
+ offVector2 = thirdFFV_[idiag]->
+ evaluate(scale, widthOption(),inter.second,
+ outwave_[iloc[3]].first [ihel[iloc[3]]],
+ outwave_[iloc[2]].second[ihel[iloc[2]]]);
+ }
+ }
+ // unknown
+ else
+ assert(false);
+ // first topology
+ if(topo) {
+ // first intermediate
+ if(inter.first->CC()) inter.first = inter.first->CC();
+ VectorWaveFunction offVector1;
+ ScalarWaveFunction offScalar1;
+ // intermeidate scalar
+ if(inter.first->iSpin()==PDT::Spin0) {
+ if(decay[iloc[0]]->id()<0&&
+ decay[iloc[1]]->id()>0) {
+ sign *= -1.;
+ offScalar1 = secondFFS_[idiag]->
+ evaluate(scale, widthOption(),inter.first,
+ outwave_[iloc[0]].first [ihel[iloc[0]]],
+ outwave_[iloc[1]].second[ihel[iloc[1]]]);
+ }
+ else {
+ offScalar1 = secondFFS_[idiag]->
+ evaluate(scale, widthOption(),inter.first,
+ outwave_[iloc[1]].first [ihel[iloc[1]]],
+ outwave_[iloc[0]].second[ihel[iloc[0]]]);
+ }
+ }
+ // intermediate vector
+ else if(inter.first->iSpin()==PDT::Spin1) {
+ if(decay[iloc[0]]->id()<0&&
+ decay[iloc[1]]->id()>0) {
+ sign *= -1.;
+ offVector1 = secondFFV_[idiag]->
+ evaluate(scale, widthOption(),inter.first,
+ outwave_[iloc[0]].first [ihel[iloc[0]]],
+ outwave_[iloc[1]].second[ihel[iloc[1]]]);
+ }
+ else {
+ offVector1 = secondFFV_[idiag]->
+ evaluate(scale, widthOption(),inter.first,
+ outwave_[iloc[1]].first [ihel[iloc[1]]],
+ outwave_[iloc[0]].second[ihel[iloc[0]]]);
+ }
+ }
+ // unknown
+ else
+ assert(false);
+ // put it all together
+ if(inter.first->iSpin()==PDT::Spin0) {
+ if(inter.second->iSpin()==PDT::Spin0) {
+ diag = firstSSS_[idiag]->
+ evaluate(scale,swave_,offScalar1,offScalar2);
+ }
+ else if(inter.second->iSpin()==PDT::Spin1) {
+ diag = firstVSS_[idiag]->
+ evaluate(scale,offVector2,offScalar1,swave_);
+ }
+ }
+ else if(inter.first->iSpin()==PDT::Spin1) {
+ if(inter.second->iSpin()==PDT::Spin0) {
+ diag = firstVSS_[idiag]->
+ evaluate(scale,offVector1,offScalar2,swave_);
+ }
+ else if(inter.second->iSpin()==PDT::Spin1) {
+ diag = firstVVS_[idiag]->
+ evaluate(scale,offVector1,offVector2,swave_);
+ }
+ }
+ }
+ // second topology
+ else {
+ if(decay[iloc[0]]->id()<0&&decay[iloc[1]]->id()>0) {
+ sign *= -1.;
+ SpinorWaveFunction inters = firstFFS_[idiag]->
+ evaluate(scale,widthOption(),inter.first,
+ outwave_[iloc[0]].first [ihel[iloc[0]]],swave_);
+ if(inter.second->iSpin()==PDT::Spin0) {
+ diag = secondFFS_[idiag]->
+ evaluate(scale,inters,outwave_[iloc[1]].second[ihel[iloc[1]]],
+ offScalar2);
+ }
+ else {
+ diag = secondFFV_[idiag]->
+ evaluate(scale,inters,outwave_[iloc[1]].second[ihel[iloc[1]]],
+ offVector2);
+ }
+ }
+ else {
+ SpinorBarWaveFunction inters = firstFFS_[idiag]->
+ evaluate(scale,widthOption(),inter.first,
+ outwave_[iloc[0]].second[ihel[iloc[0]]],swave_);
+ if(inter.second->iSpin()==PDT::Spin0) {
+ diag = secondFFS_[idiag]->
+ evaluate(scale,outwave_[iloc[1]].first [ihel[iloc[1]]],inters,
+ offScalar2);
+ }
+ else {
+ diag = secondFFV_[idiag]->
+ evaluate(scale,outwave_[iloc[1]].first [ihel[iloc[1]]],inters,
+ offVector2);
+ }
+ }
+ }
+ // apply NO sign
+ diag *= sign;
+ // matrix element for the different colour flows
+ if(ichan<0) {
+ for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
+ flows[dit->colourFlow[iy].first - 1] +=
+ dit->colourFlow[iy].second * diag;
+ }
+ for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
+ largeflows[dit->largeNcColourFlow[iy].first - 1] +=
+ dit->largeNcColourFlow[iy].second * diag;
+ }
+ }
+ else {
+ for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
+ if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
+ flows[dit->colourFlow[iy].first - 1] +=
+ dit->colourFlow[iy].second * diag;
+ }
+ for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
+ if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
+ largeflows[dit->largeNcColourFlow[iy].first - 1] +=
+ dit->largeNcColourFlow[iy].second * diag;
+ }
+ }
+ ++idiag;
+ }
+ // now add the flows to the me2 with appropriate colour factors
+ for(unsigned int ix = 0; ix < ncf; ++ix) {
+ mes[ix](0,ihel[0],ihel[1],ihel[2],ihel[3]) = flows[ix];
+ mel[ix](0,ihel[0],ihel[1],ihel[2],ihel[3]) = largeflows[ix];
+ }
+ }
+ }
+ }
+ }
+ double me2(0.);
+ if(ichan<0) {
+ vector<double> pflows(ncf,0.);
+ for(unsigned int ix = 0; ix < ncf; ++ix) {
+ for(unsigned int iy = 0; iy < ncf; ++ iy) {
+ double con = cfactors[ix][iy]*(mes[ix].contract(mes[iy],rho_)).real();
+ me2 += con;
+ if(ix==iy) {
+ con = nfactors[ix][iy]*(mel[ix].contract(mel[iy],rho_)).real();
+ pflows[ix] += con;
+ }
+ }
+ }
+ double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
+ ptotal *=UseRandom::rnd();
+ for(unsigned int ix=0;ix<pflows.size();++ix) {
+ if(ptotal<=pflows[ix]) {
+ colourFlow(ix);
+ ME(mes[ix]);
+ break;
+ }
+ ptotal-=pflows[ix];
+ }
+ }
+ else {
+ unsigned int iflow = colourFlow();
+ me2 = nfactors[iflow][iflow]*(mel[iflow].contract(mel[iflow],rho_)).real();
+ }
+ // return the matrix element squared
+ return me2*scale*UnitRemoval::InvE2;
}
diff --git a/Decay/General/StoFFFFDecayer.h b/Decay/General/StoFFFFDecayer.h
--- a/Decay/General/StoFFFFDecayer.h
+++ b/Decay/General/StoFFFFDecayer.h
@@ -1,100 +1,184 @@
// -*- C++ -*-
#ifndef HERWIG_StoFFFFDecayer_H
#define HERWIG_StoFFFFDecayer_H
//
// This is the declaration of the StoFFFFDecayer class.
//
#include "GeneralFourBodyDecayer.h"
+#include "ThePEG/Helicity/Vertex/AbstractSSSVertex.h"
+#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h"
+#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
+#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h"
+#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the StoFFFFDecayer class.
*
* @see \ref StoFFFFDecayerInterfaces "The interfaces"
* defined for StoFFFFDecayer.
*/
class StoFFFFDecayer: public GeneralFourBodyDecayer {
public:
/**
- * The default constructor.
- */
- StoFFFFDecayer();
-
- /**
* Return the matrix element squared for a given mode and phase-space channel
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
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:
-// If needed, insert declarations of virtual function defined in the
-// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
-
+ /** @name Standard Interfaced functions. */
+ //@{
+ /**
+ * Initialize this object after the setup phase before saving an
+ * EventGenerator to disk.
+ * @throws InitException if object could not be initialized properly.
+ */
+ virtual void doinit();
+ //@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
StoFFFFDecayer & operator=(const StoFFFFDecayer &);
+private:
+
+ /**
+ * Signs for NO
+ */
+ vector<double> sign_;
+
+ /**
+ * Potential vertices for the first step
+ */
+ //@{
+ /**
+ * VVS Vertex
+ */
+ vector<AbstractVVSVertexPtr> firstVVS_;
+
+ /**
+ * VSS Vertex
+ */
+ vector<AbstractVSSVertexPtr> firstVSS_;
+
+ /**
+ * SSS Vertex
+ */
+ vector<AbstractSSSVertexPtr> firstSSS_;
+
+ /**
+ * FFS Vertex
+ */
+ vector<AbstractFFSVertexPtr> firstFFS_;
+ //@}
+
+ /**
+ * Potential vertices for the second step
+ */
+ //@{
+ /**
+ * FFV Vertex
+ */
+ vector<AbstractFFVVertexPtr> secondFFV_;
+
+ /**
+ * FFS Vertex
+ */
+ vector<AbstractFFSVertexPtr> secondFFS_;
+ //@}
+
+ /**
+ * Potential vertices for the third step
+ */
+ //@{
+ /**
+ * FFV Vertex
+ */
+ vector<AbstractFFVVertexPtr> thirdFFV_;
+
+ /**
+ * FFS Vertex
+ */
+ vector<AbstractFFSVertexPtr> thirdFFS_;
+ //@}
+
+ /**
+ * Spin density matrix
+ */
+ mutable RhoDMatrix rho_;
+
+ /**
+ * Scalar wavefunction
+ */
+ mutable ScalarWaveFunction swave_;
+
+ /**
+ * Spinors for outgoing particles
+ */
+ mutable pair<vector<SpinorWaveFunction>,vector<SpinorBarWaveFunction> > outwave_[4];
+
};
}
#endif /* HERWIG_StoFFFFDecayer_H */
diff --git a/Models/General/FourBodyDecayConstructor.cc b/Models/General/FourBodyDecayConstructor.cc
--- a/Models/General/FourBodyDecayConstructor.cc
+++ b/Models/General/FourBodyDecayConstructor.cc
@@ -1,232 +1,258 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FourBodyDecayConstructor class.
//
#include "FourBodyDecayConstructor.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "Herwig++/Decay/General/GeneralFourBodyDecayer.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "DecayConstructor.h"
#include <queue>
using namespace Herwig;
FourBodyDecayConstructor::~FourBodyDecayConstructor() {}
IBPtr FourBodyDecayConstructor::clone() const {
return new_ptr(*this);
}
IBPtr FourBodyDecayConstructor::fullclone() const {
return new_ptr(*this);
}
void FourBodyDecayConstructor::persistentOutput(PersistentOStream & os) const {
- os << interopt_ << widthopt_;
+ os << interOpt_ << widthOpt_;
}
void FourBodyDecayConstructor::persistentInput(PersistentIStream & is, int) {
- is >> interopt_ >> widthopt_;
+ is >> interOpt_ >> widthOpt_;
}
DescribeClass<FourBodyDecayConstructor,NBodyDecayConstructorBase>
describeFourBodyDecayConstructor("Herwig::FourBodyDecayConstructor","Herwig.so");
void FourBodyDecayConstructor::Init() {
static ClassDocumentation<FourBodyDecayConstructor> documentation
("The FourBodyDecayConstructor class implements a small number"
" of 4-body decays in general models");
static Switch<FourBodyDecayConstructor,unsigned int> interfaceWidthOption
("WidthOption",
"Option for the treatment of the widths of the intermediates",
- &FourBodyDecayConstructor::widthopt_, 1, false, false);
+ &FourBodyDecayConstructor::widthOpt_, 1, false, false);
static SwitchOption interfaceWidthOptionFixed
(interfaceWidthOption,
"Fixed",
"Use fixed widths",
1);
static SwitchOption interfaceWidthOptionRunning
(interfaceWidthOption,
"Running",
"Use running widths",
2);
static SwitchOption interfaceWidthOptionZero
(interfaceWidthOption,
"Zero",
"Set the widths to zero",
3);
static Switch<FourBodyDecayConstructor,unsigned int> interfaceIntermediateOption
("IntermediateOption",
"Option for the inclusion of intermediates in the event",
- &FourBodyDecayConstructor::interopt_, 0, false, false);
+ &FourBodyDecayConstructor::interOpt_, 0, false, false);
static SwitchOption interfaceIntermediateOptionAlways
(interfaceIntermediateOption,
"Always",
"Always include the intermediates",
1);
static SwitchOption interfaceIntermediateOptionNever
(interfaceIntermediateOption,
"Never",
"Never include the intermediates",
2);
static SwitchOption interfaceIntermediateOptionOnlyIfOnShell
(interfaceIntermediateOption,
"OnlyIfOnShell",
"Only if there are on-shell diagrams",
0);
}
void FourBodyDecayConstructor::DecayList(const set<PDPtr> & particles) {
if( particles.empty() ) return;
NBodyDecayConstructorBase::DecayList(particles);
}
void FourBodyDecayConstructor::
createDecayMode(vector<PrototypeVertexPtr> & diagrams) {
- // incoming particle
- tPDPtr inpart = diagrams[0]->incoming;
// some basic checks for the modes we are interested in
// only looking at scalars
if(diagrams[0]->incoming->iSpin()!=PDT::Spin0) return;
// which decay to 4 fermions
unsigned int nferm=0;
for(OrderedParticles::const_iterator it=diagrams[0]->outPart.begin();
it!=diagrams[0]->outPart.end();++it) {
if((**it).iSpin()==PDT::Spin1Half) ++nferm;
}
if(nferm!=4) return;
- cerr << "!!!!!!!!!!!!!!!!!! MODE !!!!!!!!!!!\n";
- cerr << "Number of diagrams " << diagrams.size() << "\n";
- cerr << diagrams[0]->incoming->PDGName() << " -> ";
- for(OrderedParticles::const_iterator it=diagrams[0]->outPart.begin();
- it!=diagrams[0]->outPart.end();++it)
- cerr << (**it).PDGName() << " ";
- cerr << "\n";
+ // check for on-shell intermediates
+ bool possibleOnShell=false;
for(unsigned int iy=0;iy<diagrams.size();++iy)
- cerr << "DIAGRAM " << iy << "\n" << *diagrams[iy] << "\n";
-// // outgoing particles
-// OrderedParticles outgoing=diagrams[0]->outPart;
-// // incoming particle is now unstable
-// inpart->stable(false);
-// // construct the tag for the decay mode
-// string tag = inpart->name() + "->";
-// for(OrderedParticles::const_iterator it = outgoing.begin();
-// it != outgoing.end(); ++it) {
-// if(it!=outgoing.begin()) tag += ",";
-// tag += (**it).name();
-// }
-// tag += ";";
-// tDMPtr dm = generator()->findDecayMode(tag);
-// if( decayConstructor()->disableDecayMode(tag) ) {
-// // If mode alread exists, ie has been read from file,
-// // disable it
-// if( dm ) {
-// generator()->preinitInterface(dm, "BranchingRatio", "set", "0.0");
-// generator()->preinitInterface(dm, "OnOff", "set", "Off");
-// }
-// return;
-// }
-// if( createDecayModes() && (!dm || inpart->id() == ParticleID::h0) ) {
-// cerr << "testing calling create " << tag << "\n";
-// // create the decayer
-// GeneralFourBodyDecayerPtr decayer = createDecayer(diagrams,inter);
-// if(!decayer) return;
-// }
-// else if (dm) {
-// assert(false);
-// }
-// //update CC mode if it exists
-// if( inpart->CC() )
-// inpart->CC()->synchronize();
+ possibleOnShell |= diagrams[iy]->possibleOnShell;
+ bool inter = interOpt_ == 1 || (interOpt_ == 0 && possibleOnShell);
+ // incoming particle
+ tPDPtr inpart = diagrams[0]->incoming;
+ // outgoing particles
+ OrderedParticles outgoing=diagrams[0]->outPart;
+ // incoming particle is now unstable
+ inpart->stable(false);
+ // construct the tag for the decay mode
+ string tag = inpart->name() + "->";
+ for(OrderedParticles::const_iterator it = outgoing.begin();
+ it != outgoing.end(); ++it) {
+ if(it!=outgoing.begin()) tag += ",";
+ tag += (**it).name();
+ }
+ tag += ";";
+ tDMPtr dm = generator()->findDecayMode(tag);
+ // if mode disabled zero BR and return
+ if( decayConstructor()->disableDecayMode(tag) ) {
+ // If mode alread exists, ie has been read from file,
+ // disable it
+ if( dm ) {
+ generator()->preinitInterface(dm, "BranchingRatio", "set", "0.0");
+ generator()->preinitInterface(dm, "OnOff", "set", "Off");
+ }
+ return;
+ }
+ // create mode if needed
+ if( createDecayModes() && (!dm || inpart->id() == ParticleID::h0) ) {
+ // create the decayer
+ GeneralFourBodyDecayerPtr decayer = createDecayer(diagrams,inter);
+ if(!decayer) {
+ if(Debug::level > 1 ) generator()->log() << "Can't create the decayer for "
+ << tag << " so mode not created\n";
+ return;
+ }
+ // create the decay mode
+ tDMPtr ndm = generator()->preinitCreateDecayMode(tag);
+ if(ndm) {
+ generator()->preinitInterface(ndm, "Decayer", "set",
+ decayer->fullName());
+ generator()->preinitInterface(ndm, "OnOff", "set", "On");
+ Energy width =
+ decayer->partialWidth(inpart,outgoing);
+ setBranchingRatio(ndm, width);
+ }
+ else
+ throw NBodyDecayConstructorError()
+ << "FourBodyDecayConstructor::createDecayMode - Needed to create "
+ << "new decaymode but one could not be created for the tag "
+ << tag << Exception::warning;
+ }
+ // otherwise
+ else if (dm && (dm->decayer()->fullName()).find("Mambo") != string::npos) {
+ // create the decayer
+ GeneralFourBodyDecayerPtr decayer = createDecayer(diagrams,inter);
+ if(!decayer) {
+ if(Debug::level > 1 ) generator()->log() << "Can't create the decayer for "
+ << tag << " so mode not created\n";
+ return;
+ }
+ generator()->preinitInterface(dm, "Decayer", "set",
+ decayer->fullName());
+ }
+ //update CC mode if it exists
+ if( inpart->CC() )
+ inpart->CC()->synchronize();
}
GeneralFourBodyDecayerPtr
FourBodyDecayConstructor::createDecayer(vector<PrototypeVertexPtr> & diagrams,
bool inter) const {
if(diagrams.empty()) return GeneralFourBodyDecayerPtr();
// extract the external particles for the process
PDPtr incoming = diagrams[0]->incoming;
// outgoing particles
vector<PDPtr> outgoing(diagrams[0]->outPart.begin(),
diagrams[0]->outPart.end());
+ vector<NBDiagram> newDiagrams;
+ cerr << "!!!!!!!!!!!!!!!!!! MODE !!!!!!!!!!!\n";
+ cerr << "Number of diagrams " << diagrams.size() << "\n";
+ cerr << diagrams[0]->incoming->PDGName() << " -> ";
+ for(OrderedParticles::const_iterator it=diagrams[0]->outPart.begin();
+ it!=diagrams[0]->outPart.end();++it)
+ cerr << (**it).PDGName() << " ";
+ cerr << "\n";
+ // convert the diagrams
+ for(unsigned int ix=0;ix<diagrams.size();++ix) {
+ cerr << "DIAGRAM " << ix << "\n" << *diagrams[ix] << "\n";
+ newDiagrams.push_back(NBDiagram(diagrams[ix]));
+ }
// get the name for the object
string objectname ("/Herwig/Decays/");
string classname = DecayerClassName(incoming, diagrams[0]->outPart, objectname);
if(classname=="") return GeneralFourBodyDecayerPtr();
// create the object
GeneralFourBodyDecayerPtr decayer =
dynamic_ptr_cast<GeneralFourBodyDecayerPtr>
(generator()->preinitCreate(classname, objectname));
- // set up the decayer
- cerr << "testing made the decayer\n";
- decayer->setDecayInfo(incoming,outgoing,diagrams);
-
-
-// // get the colour flows
-// unsigned int ncf(0);
-// pair<vector<DVector>, vector<DVector> > cfactors;
-// try {
-// cfactors = getColourFactors(incoming,outgoing,diagrams,ncf);
-// }
-// catch ( Veto ) { return GeneralThreeBodyDecayerPtr(); }
-// // set decayer options from base class
-// setDecayerInterfaces(objectname);
-// // set the width option
-// ostringstream value;
-// value << _widthopt;
-// generator()->preinitInterface(objectname, "WidthOption", "set", value.str());
-// // set the intermediates option
-// ostringstream value2;
-// value2 << inter;
-// generator()->preinitInterface(objectname, "GenerateIntermediates", "set",
-// value2.str());
-// // initialize the decayer
-// decayer->init();
-// // return the decayer
-// return decayer;
-
-
- assert(false);
+ // set up the decayer and return if doesn't work
+ if(!decayer->setDecayInfo(incoming,outgoing,newDiagrams))
+ return GeneralFourBodyDecayerPtr();
+ // set decayer options from base class
+ setDecayerInterfaces(objectname);
+ // set the width option
+ ostringstream value;
+ value << widthOpt_;
+ generator()->preinitInterface(objectname, "WidthOption", "set", value.str());
+ // set the intermediates option
+ ostringstream value2;
+ value2 << inter;
+ generator()->preinitInterface(objectname, "GenerateIntermediates", "set",
+ value2.str());
+ // initialize the decayer
+ decayer->init();
+ // return the decayer
+ return decayer;
}
string FourBodyDecayConstructor::DecayerClassName(tcPDPtr incoming,
const OrderedParticles & outgoing,
string & objname) const {
string classname("Herwig::");
// spins of the outgoing particles
unsigned int ns(0),nf(0),nv(0);
objname += incoming->PDGName() + "2";
for(OrderedParticles::const_iterator it=outgoing.begin();
it!=outgoing.end();++it) {
if ((**it).iSpin()==PDT::Spin0 ) ++ns;
else if((**it).iSpin()==PDT::Spin1Half) ++nf;
else if((**it).iSpin()==PDT::Spin1 ) ++nv;
objname += (**it).PDGName();
}
objname += "Decayer";
if(incoming->iSpin()==PDT::Spin0) {
if(nf==4) classname += "StoFFFFDecayer";
else classname = "";
}
else {
classname="";
}
return classname;
}
diff --git a/Models/General/FourBodyDecayConstructor.h b/Models/General/FourBodyDecayConstructor.h
--- a/Models/General/FourBodyDecayConstructor.h
+++ b/Models/General/FourBodyDecayConstructor.h
@@ -1,141 +1,141 @@
// -*- C++ -*-
#ifndef THEPEG_FourBodyDecayConstructor_H
#define THEPEG_FourBodyDecayConstructor_H
//
// This is the declaration of the FourBodyDecayConstructor class.
//
#include "NBodyDecayConstructorBase.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "Herwig++/Decay/General/GeneralFourBodyDecayer.fh"
#include "PrototypeVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
/**
* Here is the documentation of the FourBodyDecayConstructor class.
*
* @see \ref FourBodyDecayConstructorInterfaces "The interfaces"
* defined for FourBodyDecayConstructor.
*/
class FourBodyDecayConstructor: public NBodyDecayConstructorBase {
public:
/**
* The default constructor.
*/
FourBodyDecayConstructor() :
- interopt_(0), widthopt_(1) {}
+ interOpt_(0), widthOpt_(1) {}
/**
* Destructor
*/
~FourBodyDecayConstructor();
/**
* Function used to determine allowed decaymodes, to be implemented
* in derived class.
* @param particles vector of ParticleData pointers containing
* particles in model
*/
virtual void DecayList(const set<PDPtr> & particles);
/**
* Number of outgoing lines. Required for correct ordering.
*/
virtual unsigned int numBodies() const {return 4;}
/**
* Create a decay mode
*/
void createDecayMode(vector<PrototypeVertexPtr> &);
/**
* Create the decayer
* @param diagrams The diagrams for the decay
* @param inter Option for intermediates
*/
GeneralFourBodyDecayerPtr createDecayer(vector<PrototypeVertexPtr> & diagrams,
bool inter) const;
/**
* Contruct the classname and object name for the Decayer
* @param incoming The incoming particle
* @param outgoing The decay products
* @param objname a string containing the default path of the Decayer object
*/
string DecayerClassName(tcPDPtr incoming, const OrderedParticles & outgoing,
string & objname) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FourBodyDecayConstructor & operator=(const FourBodyDecayConstructor &);
private:
/**
* Option for the inclusion of intermediates
*/
- unsigned int interopt_;
+ unsigned int interOpt_;
/**
* How to treat the widths of the intermediate particles
*/
- unsigned int widthopt_;
+ unsigned int widthOpt_;
};
}
#endif /* THEPEG_FourBodyDecayConstructor_H */
diff --git a/Models/General/PrototypeVertex.cc b/Models/General/PrototypeVertex.cc
--- a/Models/General/PrototypeVertex.cc
+++ b/Models/General/PrototypeVertex.cc
@@ -1,251 +1,297 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FourBodyDecayConstructor class.
//
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/Exception.h"
#include "PrototypeVertex.h"
using namespace Herwig;
void PrototypeVertex::createPrototypes(tPDPtr inpart, VertexBasePtr vertex,
std::queue<PrototypeVertexPtr> & prototypes) {
int id = inpart->id();
if(!vertex->isIncoming(inpart)) return;
for(unsigned int list=0;list<vertex->getNpoint();++list) {
tPDVector decaylist = vertex->search(list, inpart);
tPDVector::size_type nd = decaylist.size();
for( tPDVector::size_type i = 0; i < nd; i += vertex->getNpoint() ) {
tPDVector pout(decaylist.begin()+i,
decaylist.begin()+i+vertex->getNpoint());
OrderedVertices out;
for(unsigned int ix=1;ix<pout.size();++ix) {
if(pout[ix]->id() == id ) swap(pout[0], pout[ix]);
if(pout[ix]->CC()) pout[ix] = pout[ix]->CC();
out.insert(make_pair(pout[ix],PrototypeVertexPtr()));
}
if(vertex->getNpoint()==3) {
// remove radiation
if((pout[0]==pout[1] && (pout[2]->id()==ParticleID::gamma||
pout[2]->id()==ParticleID::g||
pout[2]->id()==ParticleID::Z0)) ||
(pout[0]==pout[2] && (pout[1]->id()==ParticleID::gamma||
pout[1]->id()==ParticleID::g||
pout[1]->id()==ParticleID::Z0)))
continue;
}
prototypes.push(new_ptr(PrototypeVertex(inpart,out,vertex,
int(vertex->getNpoint())-1)));
}
}
}
PrototypeVertexPtr PrototypeVertex::replicateTree(PrototypeVertexPtr parent,
PrototypeVertexPtr oldChild,
PrototypeVertexPtr & newChild) {
PrototypeVertexPtr newParent =
new_ptr(PrototypeVertex(parent->incoming,OrderedVertices(),
parent->vertex,parent->npart));
for(OrderedVertices::const_iterator it = parent->outgoing.begin();
it!=parent->outgoing.end();++it) {
PrototypeVertexPtr child = it->second ?
replicateTree(it->second,oldChild,newChild) :
PrototypeVertexPtr();
newParent->outgoing.insert(make_pair(it->first,child));
if(child) child->parent = newParent;
if(it->second==oldChild) newChild=child;
}
if(oldChild==parent) newChild=newParent;
return newParent;
}
void PrototypeVertex::expandPrototypes(PrototypeVertexPtr proto, VertexBasePtr vertex,
std::queue<PrototypeVertexPtr> & prototypes,
const set<PDPtr> & excluded) {
for(OrderedVertices::const_iterator it = proto->outgoing.begin();
it!=proto->outgoing.end();++it) {
if(it->second) {
expandPrototypes(it->second,vertex,prototypes,excluded);
}
else {
if(!vertex->isIncoming(it->first)) continue;
if(excluded.find(it->first)!=excluded.end()) continue;
if(it->first->CC() &&
excluded.find(it->first->CC())!=excluded.end()) continue;
int id = it->first->id();
PrototypeVertexPtr parent=proto;
while(parent->parent) parent=parent->parent;
for(unsigned int il = 0; il < vertex->getNpoint(); ++il) {
tPDVector decaylist = vertex->search(il,it->first );
tPDVector::size_type nd = decaylist.size();
for( tPDVector::size_type i = 0; i < nd; i += vertex->getNpoint() ) {
tPDVector pout(decaylist.begin()+i,
decaylist.begin()+i+vertex->getNpoint());
OrderedVertices outgoing;
for(unsigned int iy=1;iy<pout.size();++iy) {
if(pout[iy]->id() == id ) swap(pout[0], pout[iy]);
if(pout[iy]->CC()) pout[iy] = pout[iy]->CC();
outgoing.insert(make_pair(pout[iy],PrototypeVertexPtr()));
}
if(vertex->getNpoint()==3) {
if((pout[0]==pout[1] && (pout[2]->id()==ParticleID::gamma||
pout[2]->id()==ParticleID::g||
pout[2]->id()==ParticleID::Z0)) ||
(pout[0]==pout[2] && (pout[1]->id()==ParticleID::gamma||
pout[1]->id()==ParticleID::g||
pout[1]->id()==ParticleID::Z0)))
continue;
// remove weak decays of quarks other than top
if(StandardQCDPartonMatcher::Check(pout[0]->id()) &&
((StandardQCDPartonMatcher::Check(pout[1]->id()) &&
abs(pout[2]->id())==ParticleID::Wplus)||
(StandardQCDPartonMatcher::Check(pout[2]->id())&&
abs(pout[1]->id())==ParticleID::Wplus))) continue;
// remove weak decays of leptons
if((abs(pout[0]->id())>=11&&abs(pout[0]->id())<=16) &&
(((abs(pout[1]->id())>=11&&abs(pout[1]->id())<=16) &&
abs(pout[2]->id())==ParticleID::Wplus)||
((abs(pout[2]->id())>=11&&abs(pout[2]->id())<=16)&&
abs(pout[1]->id())==ParticleID::Wplus))) continue;
}
PrototypeVertexPtr newBranch =
new_ptr(PrototypeVertex(it->first,
outgoing,vertex,int(vertex->getNpoint())-1));
PrototypeVertexPtr newChild;
PrototypeVertexPtr newVertex = replicateTree(parent,proto,newChild);
newBranch->parent = newChild;
OrderedVertices::iterator kt = newChild->outgoing.begin();
for(OrderedVertices::const_iterator jt = proto->outgoing.begin();
jt!=it;++jt,++kt) {;}
pair< tPDPtr, PrototypeVertexPtr > newPair = make_pair(kt->first,newBranch);
newChild->outgoing.erase(kt);
newChild->outgoing.insert(newPair);
newChild->incrementN(newBranch->npart-1);
prototypes.push(newVertex);
}
}
}
}
}
bool PrototypeVertex::canBeOnShell(unsigned int opt,Energy maxMass,bool first) {
Energy outMass = outgoingMass();
if(!first) {
bool in = maxMass>incomingMass();
bool out = incomingMass()>outMass;
if(opt!=0) {
if( in && ( out || opt==2 ) ) return true;
}
else if (incoming->width() == ZERO) {
tPrototypeVertexPtr original = this;
while(original->parent) {
original=original->parent;
};
ostringstream name;
name << original->incoming->PDGName() << " -> ";
for(OrderedParticles::const_iterator it = original->outPart.begin();
it!= original->outPart.end();++it)
name << (**it).PDGName() << " ";
Throw<InitException>()
<< "Trying to include on-shell diagram in decay"
<< name.str() << "including on-shell "
<< incoming->PDGName() << " with zero width.\n"
<< "You should make sure that the width for the intermediate is either"
<< " read from an SLHA file or the intermediate is included in the "
<< "DecayParticles list of the ModelGenerator.\n"
<< Exception::runerror;
}
}
else maxMass = incomingMass();
// check the decay products
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
if(!it->second) continue;
Energy newMax = maxMass-outMass+it->second->outgoingMass();
if(it->second->canBeOnShell(opt,newMax,false)) {
if(first) possibleOnShell = true;
return true;
}
}
return false;
}
+namespace {
+ void constructTag(unsigned int & loc,unsigned int & order,NBVertex & vertex,
+ const OrderedParticles & outgoing,
+ vector<bool> & matched) {
+ for(list<pair<PDPtr,NBVertex> >::iterator it=vertex.vertices.begin();
+ it!=vertex.vertices.end();++it) {
+ // search down the tree
+ if(it->second.vertex) {
+ constructTag(loc,order,it->second,outgoing,matched);
+ }
+ // identify this particle
+ else {
+ unsigned int ix=0;
+ for(OrderedParticles::const_iterator pit=outgoing.begin();
+ pit!=outgoing.end();++pit) {
+ if(*pit==it->first&&!matched[ix]) {
+ matched[ix] = true;
+ order += (ix+1)*pow(10,loc);
+ --loc;
+ break;
+ }
+ ++ix;
+ }
+ }
+ }
+ }
+}
+
NBDiagram::NBDiagram(PrototypeVertexPtr proto)
- : incoming(proto->incoming), outgoing(proto->outPart),
- vertex(proto->vertex) {
+ : channelType(0),
+ colourFlow (vector<CFPair>(1,make_pair(1,1.))),
+ largeNcColourFlow(vector<CFPair>(1,make_pair(1,1.))) {
+ if(!proto) return;
+ incoming = proto->incoming;
+ outgoing = proto->outPart;
+ vertex = proto->vertex;
// create the vertices
for(OrderedVertices::const_iterator it=proto->outgoing.begin();
it!=proto->outgoing.end();++it) {
vertices.push_back(make_pair(it->first,NBVertex(it->second)));
}
// now let's re-order so that branchings are at the end
for(list<pair<PDPtr,NBVertex> >::iterator it=vertices.begin();
it!=vertices.end();++it) {
if(!it->second.incoming) continue;
list<pair<PDPtr,NBVertex> >::iterator jt=it;
for( ; jt!=vertices.end();++jt) {
if(jt==it) continue;
if(!jt->second.incoming) {
break;
}
}
if(jt!=vertices.end()) {
list<pair<PDPtr,NBVertex> >::iterator kt = it;
while(kt!=jt) {
list<pair<PDPtr,NBVertex> >::iterator lt = kt;
++lt;
swap(*kt,*lt);
kt=lt;
}
}
}
// finally work out the channel and the ordering
- unsigned int loc(outgoing.size());
+ unsigned int order(0);
+ unsigned int loc(outgoing.size()-1);
+ vector<bool> matched(outgoing.size(),false);
for(list<pair<PDPtr,NBVertex> >::iterator it=vertices.begin();
it!=vertices.end();++it) {
- unsigned int ipart(0);
- for( ; ipart<outgoing.size(); ++ipart) {
+ // search down the tree
+ if(it->second.vertex) {
+ constructTag(loc,order,it->second,outgoing,matched);
}
-
-
- --loc;
+ // identify this particle
+ else {
+ unsigned int ix=0;
+ for(OrderedParticles::const_iterator pit=outgoing.begin();
+ pit!=outgoing.end();++pit) {
+ if(*pit==it->first&&!matched[ix]) {
+ matched[ix] = true;
+ order += (ix+1)*pow(10,loc);
+ --loc;
+ break;
+ }
+ ++ix;
+ }
+ }
}
-
- exit(0);
+ channelType=order;
}
NBVertex::NBVertex(PrototypeVertexPtr proto) {
if(!proto) return;
incoming = proto->incoming;
outgoing = proto->outPart;
vertex = proto->vertex;
for(OrderedVertices::const_iterator it=proto->outgoing.begin();
it!=proto->outgoing.end();++it) {
vertices.push_back(make_pair(it->first,NBVertex(it->second)));
}
// now let's re-order so that branchings are at the end
for(list<pair<PDPtr,NBVertex> >::iterator it=vertices.begin();
it!=vertices.end();++it) {
if(!it->second.incoming) continue;
list<pair<PDPtr,NBVertex> >::iterator jt=it;
for( ; jt!=vertices.end();++jt) {
if(jt==it) continue;
if(!jt->second.incoming) {
break;
}
}
if(jt!=vertices.end()) {
list<pair<PDPtr,NBVertex> >::iterator kt = it;
while(kt!=jt) {
list<pair<PDPtr,NBVertex> >::iterator lt = kt;
++lt;
swap(*kt,*lt);
kt=lt;
}
}
}
}
diff --git a/Models/General/PrototypeVertex.h b/Models/General/PrototypeVertex.h
--- a/Models/General/PrototypeVertex.h
+++ b/Models/General/PrototypeVertex.h
@@ -1,440 +1,455 @@
// -*- C++ -*-
//
// PrototypeVertex.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2007 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_PrototypeVertex_H
#define HERWIG_PrototypeVertex_H
#include <queue>
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/EnumIO.h"
//
// This is the declaration of the PrototypeVertex class.
//
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
class PrototypeVertex;
ThePEG_DECLARE_POINTERS(Herwig::PrototypeVertex,PrototypeVertexPtr);
/** Pair of int,double */
typedef pair<unsigned int, double> CFPair;
/**
* A struct to order the particles in the same way as in the DecayMode's
*/
struct ParticleOrdering {
/**
* Operator for the ordering
* @param p1 The first ParticleData object
* @param p2 The second ParticleData object
*/
- bool operator()(PDPtr p1, PDPtr p2) {
+ bool operator() (PDPtr p1, PDPtr p2) {
return abs(p1->id()) > abs(p2->id()) ||
( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) ||
( p1->id() == p2->id() && p1->fullName() > p2->fullName() );
}
};
/**
* A struct to order the particles in the same way as in the DecayMode's
*/
struct VertexOrdering {
/**
* Operator for the ordering
* @param p1 The first ParticleData object
* @param p2 The second ParticleData object
*/
bool operator()(pair< tPDPtr, PrototypeVertexPtr > p1,
pair< tPDPtr, PrototypeVertexPtr > p2) {
return abs(p1.first->id()) > abs(p2.first->id()) ||
( abs(p1.first->id()) == abs(p2.first->id()) && p1.first->id() > p2.first->id() ) ||
( p1.first->id() == p2.first->id() && p1.first->fullName() > p2.first->fullName() );
}
};
typedef multiset<pair< tPDPtr, PrototypeVertexPtr >,VertexOrdering > OrderedVertices;
/**
* A set of ParticleData objects ordered as for the DecayMode's
*/
typedef multiset<PDPtr,ParticleOrdering> OrderedParticles;
/**
* Storage of a potenital n-body decay
*/
class PrototypeVertex : public Base {
public:
/**
* Default Constructor
*/
PrototypeVertex() : npart(0), possibleOnShell(false) {}
/**
* Constructor
*/
PrototypeVertex(tPDPtr in, OrderedVertices out,
VertexBasePtr v, int n) :
incoming(in), outgoing(out), vertex(v), npart(n),
possibleOnShell(false) {}
/**
* Incoming particle
*/
tPDPtr incoming;
/**
* Outgoing particles
*/
OrderedVertices outgoing;
/**
* The vertex for the interaction
*/
VertexBasePtr vertex;
/**
* The parent of the vertex
*/
tPrototypeVertexPtr parent;
/**
* Number of particles
*/
unsigned int npart;
/**
* Outgoing particles
*/
mutable OrderedParticles outPart;
/**
* Can have on-shell intermediates
*/
bool possibleOnShell;
/**
* Increment the number of particles
*/
void incrementN(int in) {
npart += in;
if(parent) parent->incrementN(in);
}
/**
* Mass of the incoming particle
*/
Energy incomingMass() {
return incoming->mass();
}
/**
* Total mass of all the outgoing particles
*/
Energy outgoingMass() {
Energy mass(ZERO);
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
mass += it->second ?
it->second->outgoingMass() : it->first->mass();
}
return mass;
}
/**
* Total constituent mass of all the outgoing particles
*/
Energy outgoingConstituentMass() {
Energy mass(ZERO);
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
mass += it->second ?
it->second->outgoingConstituentMass() : it->first->constituentMass();
}
return mass;
}
/**
* Check the external particles
*/
bool checkExternal(bool first=true) {
if(outPart.empty()) setOutgoing();
if(first&&outPart.find(incoming)!=outPart.end()) return false;
bool output = true;
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
if(it->second&& !it->second->checkExternal(false)) output = false;
}
return output;
}
/**
* Set the outgoing particles
*/
void setOutgoing() const {
assert(outPart.empty());
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
if(it->second) {
it->second->setOutgoing();
outPart.insert(it->second->outPart.begin(),
it->second->outPart.end());
}
else
outPart.insert(it->first);
}
}
/**
* Are there potential on-shell intermediates?
*/
bool canBeOnShell(unsigned int opt,Energy maxMass,bool first);
/**
* Check if same external particles
*/
bool sameDecay(const PrototypeVertex & x) const {
if(incoming != x.incoming) return false;
if(outPart.empty()) setOutgoing();
if(x.outPart.empty()) x.setOutgoing();
OrderedParticles::const_iterator cit = outPart.begin();
OrderedParticles::const_iterator cjt = x.outPart.begin();
if(x.npart!=npart) return false;
for(;cit!=outPart.end();++cit,++cjt) {
if(*cit!=*cjt) return false;
}
return true;
}
/**
* Create a \f$1\to2\f$ prototype
*/
static void createPrototypes(tPDPtr inpart, VertexBasePtr vertex,
std::queue<PrototypeVertexPtr> & prototypes);
/**
* Expand the prototypes by adding more legs
*/
static void expandPrototypes(PrototypeVertexPtr proto, VertexBasePtr vertex,
std::queue<PrototypeVertexPtr> & prototypes,
const set<PDPtr> & excluded);
/**
* Copy the whole structure with a new branching
*/
static PrototypeVertexPtr replicateTree(PrototypeVertexPtr parent,
PrototypeVertexPtr oldChild,
PrototypeVertexPtr & newChild);
};
/**
* Output to a stream
*/
inline ostream & operator<<(ostream & os, const PrototypeVertex & diag) {
os << diag.incoming->PDGName() << " -> ";
bool seq=false;
for(OrderedVertices::const_iterator it = diag.outgoing.begin();
it!=diag.outgoing.end();++it) {
os << it->first->PDGName() << " ";
if(it->second) seq = true;
}
os << " decays via "
<< diag.vertex->fullName() << " in a "
<< diag.npart << "-body decay\n";
if(!seq) return os;
os << "Followed by\n";
for(OrderedVertices::const_iterator it = diag.outgoing.begin();
it!=diag.outgoing.end();++it) {
if(it->second) os << *it->second;
}
return os;
}
/**
* Test whether two diagrams are identical.
*/
inline bool operator==(const PrototypeVertex & x, const PrototypeVertex & y) {
if(x.incoming != y.incoming) return false;
if(x.vertex != y.vertex) return false;
if(x.npart != y.npart) return false;
if(x.outgoing.size() != y.outgoing.size()) return false;
OrderedVertices::const_iterator xt = x.outgoing.begin();
OrderedVertices::const_iterator yt = y.outgoing.begin();
for(;xt!=x.outgoing.end();++xt,++yt) {
if(xt->first != yt->first) return false;
if(xt->second && yt->second) {
if(*(xt->second)==*(yt->second)) continue;
else return false;
}
else if(xt->second || yt->second)
return false;
}
return true;
}
/**
* A simple vertex for the N-body diagram
*/
struct NBVertex {
/**
* Constructor taking a prototype vertex as the arguments
*/
NBVertex(PrototypeVertexPtr proto = PrototypeVertexPtr() );
/**
* Incoming particle
*/
tPDPtr incoming;
/**
* Outgoing particles
*/
mutable OrderedParticles outgoing;
/**
* The vertices
*/
list<pair<PDPtr,NBVertex> > vertices;
/**
* The vertex
*/
VertexBasePtr vertex;
};
/**
* The NBDiagram struct contains information about a \f$1\ton\f$ decay
* that has been automatically generated.
*/
struct NBDiagram {
/**
- * Enumeration for the channel type
- */
- enum Channel {UNDEFINED = -1,
- TBchannel23=0, TBchannel13=1,
- TBchannel12=2, TBfourPoint=3};
-
- /**
- * Standard Constructor
- */
- NBDiagram() : channelType(UNDEFINED) {}
-
- /**
* Constructor taking a prototype vertex as the arguments*/
- NBDiagram(PrototypeVertexPtr proto);
+ NBDiagram(PrototypeVertexPtr proto=PrototypeVertexPtr());
/**
* Incoming particle
*/
tPDPtr incoming;
/**
* The type of channel
*/
- Channel channelType;
+ unsigned int channelType;
/**
* Outgoing particles
*/
mutable OrderedParticles outgoing;
/**
* The vertices
*/
list<pair<PDPtr,NBVertex> > vertices;
/**
* The vertex for the parent branching
*/
VertexBasePtr vertex;
/** Store colour flow at \f$N_c=3\f$ information */
mutable vector<CFPair> colourFlow;
/** Store colour flow at \f$N_c=\infty\f$ information */
mutable vector<CFPair> largeNcColourFlow;
};
-// /**
-// * Test whether this and x are the same decay
-// * @param x The other process to check
-// */
-// bool sameDecay(const TBDiagram & x) const {
-// if(ids[0] != x.ids[0]) return false;
-// bool used[4]={false,false,false,false};
-// for(unsigned int ix=1;ix<4;++ix) {
-// bool found=false;
-// for(unsigned int iy=1;iy<4;++iy) {
-// if(used[iy]) continue;
-// if(ids[ix]==x.ids[iy]) {
-// used[iy]=true;
-// found=true;
-// break;
-// }
-// }
-// if(!found) return false;
-// }
-// return true;
-// }
/**
* Output operator to allow the structure to be persistently written
* @param os The output stream
- * @param x The TBVertex
+ * @param x The NBVertex
*/
inline PersistentOStream & operator<<(PersistentOStream & os,
const NBVertex & x) {
os << x.incoming << x.outgoing << x.vertices << x.vertex;
return os;
}
/**
* Input operator to allow persistently written data to be read in
* @param is The input stream
- * @param x The TBVertex
+ * @param x The NBVertex
*/
inline PersistentIStream & operator>>(PersistentIStream & is,
NBVertex & x) {
is >> x.incoming >> x.outgoing >> x.vertices >> x.vertex;
return is;
}
/**
* Output operator to allow the structure to be persistently written
* @param os The output stream
- * @param x The TBDiagram
+ * @param x The NBDiagram
*/
inline PersistentOStream & operator<<(PersistentOStream & os,
const NBDiagram & x) {
os << x.incoming << oenum(x.channelType) << x.outgoing << x.vertices << x.vertex
<< x.colourFlow << x.largeNcColourFlow;
return os;
}
/**
* Input operator to allow persistently written data to be read in
* @param is The input stream
- * @param x The TBDiagram
+ * @param x The NBDiagram
*/
inline PersistentIStream & operator>>(PersistentIStream & is,
NBDiagram & x) {
is >> x.incoming >> ienum(x.channelType) >> x.outgoing >> x.vertices >> x.vertex
>> x.colourFlow >> x.largeNcColourFlow;
return is;
}
+/**
+ * Output a NBVertex to a stream
+ */
+inline ostream & operator<<(ostream & os, const NBVertex & vertex) {
+ os << vertex.incoming->PDGName() << " -> ";
+ bool seq=false;
+ for(list<pair<PDPtr,NBVertex> >::const_iterator it=vertex.vertices.begin();
+ it!=vertex.vertices.end();++it) {
+ os << it->first->PDGName() << " ";
+ if(it->second.incoming) seq = true;
+ }
+ os << "via vertex " << vertex.vertex->fullName() << "\n";
+ if(!seq) return os;
+ os << "Followed by\n";
+ for(list<pair<PDPtr,NBVertex> >::const_iterator it=vertex.vertices.begin();
+ it!=vertex.vertices.end();++it) {
+ if(it->second.incoming) os << it->second;
+ }
+ return os;
+}
+
+/**
+ * Output a NBDiagram to a stream
+ */
+inline ostream & operator<<(ostream & os, const NBDiagram & diag) {
+ os << diag.incoming->PDGName() << " -> ";
+ for(OrderedParticles::const_iterator it=diag.outgoing.begin();
+ it!=diag.outgoing.end();++it) {
+ os << (**it).PDGName() << " ";
+ }
+ os << " has order " << diag.channelType << "\n";
+ os << "First decay " << diag.incoming->PDGName() << " -> ";
+ bool seq=false;
+ for(list<pair<PDPtr,NBVertex> >::const_iterator it=diag.vertices.begin();
+ it!=diag.vertices.end();++it) {
+ os << it->first->PDGName() << " ";
+ if(it->second.incoming) seq = true;
+ }
+ os << "via vertex " << diag.vertex->fullName() << "\n";
+ if(!seq) return os;
+ os << "Followed by\n";
+ for(list<pair<PDPtr,NBVertex> >::const_iterator it=diag.vertices.begin();
+ it!=diag.vertices.end();++it) {
+ if(it->second.incoming) os << it->second;
+ }
+ return os;
+}
+
}
#endif /* HERWIG_PrototypeVertex_H */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 7:50 PM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805926
Default Alt Text
(99 KB)
Attached To
rHERWIGHG herwighg
Event Timeline
Log In to Comment