Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7879287
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
147 KB
Subscribers
None
View Options
diff --git a/Decay/General/GeneralThreeBodyDecayer.cc b/Decay/General/GeneralThreeBodyDecayer.cc
--- a/Decay/General/GeneralThreeBodyDecayer.cc
+++ b/Decay/General/GeneralThreeBodyDecayer.cc
@@ -1,830 +1,837 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GeneralThreeBodyDecayer class.
//
#include "GeneralThreeBodyDecayer.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
using namespace Herwig;
void GeneralThreeBodyDecayer::persistentOutput(PersistentOStream & os) const {
os << _incoming << _outgoing << _diagrams << _diagmap << _colour << _colourLargeNC
<< _nflow << _widthopt << _reftag << _reftagcc;
}
void GeneralThreeBodyDecayer::persistentInput(PersistentIStream & is, int) {
is >> _incoming >> _outgoing >> _diagrams >> _diagmap >> _colour >> _colourLargeNC
>> _nflow >> _widthopt >> _reftag >> _reftagcc;
}
AbstractClassDescription<GeneralThreeBodyDecayer>
GeneralThreeBodyDecayer::initGeneralThreeBodyDecayer;
// Definition of the static class description member.
void GeneralThreeBodyDecayer::Init() {
static ClassDocumentation<GeneralThreeBodyDecayer> documentation
("The GeneralThreeBodyDecayer class is the base class for the implementation of"
" all three body decays based on spin structures in Herwig++.");
static Switch<GeneralThreeBodyDecayer,unsigned int> interfaceWidthOption
("WidthOption",
"Option for the treatment of the widths of the intermediates",
&GeneralThreeBodyDecayer::_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 GeneralThreeBodyDecayer::decay(const Particle & parent,
const tPDVector & children) const {
// return empty vector if products heavier than parent
Energy mout(ZERO);
for(tPDVector::const_iterator it=children.begin();
it!=children.end();++it) mout+=(**it).massMin();
if(mout>parent.mass()) return ParticleVector();
// generate the decay
bool cc;
int imode=modeNumber(cc,parent.dataPtr(),children);
// generate the kinematics
ParticleVector decay=generate(generateIntermediates(),cc,imode,parent);
// make the colour connections
colourConnections(parent, decay);
// return the answer
return decay;
}
int GeneralThreeBodyDecayer::
modeNumber(bool & cc, tcPDPtr in, const tPDVector & outin) const {
assert( !_reftag.empty() && !_reftagcc.empty() );
// check number of outgoing particles
if( outin.size() != 3 || abs(in->id()) != _incoming->id() ) return -1;
OrderedParticles testmode(outin.begin(), outin.end());
OrderedParticles::const_iterator dit = testmode.begin();
string testtag(in->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 GeneralThreeBodyDecayer::setDecayInfo(PDPtr incoming,
vector<PDPtr> outgoing,
- const vector<TBDiagram> & process) {
+ const vector<TBDiagram> & process,
+ double symfac) {
// set the member variables from the info supplied
_incoming = incoming;
_outgoing = outgoing;
_diagrams = process;
assert( _outgoing.size() == 3 );
// Construct reference tags for testing in modeNumber function
OrderedParticles refmode(_outgoing.begin(), _outgoing.end());
OrderedParticles::const_iterator dit = refmode.begin();
_reftag = _incoming->name() + "->";
for( unsigned int i = 1; dit != refmode.end(); ++dit, ++i) {
_reftag += (**dit).name();
if( i != 3 ) _reftag += string(",");
}
//CC-mode
refmode.clear();
_reftagcc = _incoming->CC() ? _incoming->CC()->name() :
_incoming->name();
_reftagcc += "->";
for( unsigned int i = 0; i < 3; ++i ) {
if( _outgoing[i]->CC() ) refmode.insert( _outgoing[i]->CC() );
else refmode.insert( _outgoing[i] );
}
dit = refmode.begin();
for( unsigned int i = 1; dit != refmode.end(); ++dit , ++i) {
_reftagcc += (**dit).name();
if( i != 3 ) _reftagcc += string(",");
}
// set the colour factors and return the answer
- return setColourFactors();
+ return setColourFactors(symfac);
}
void GeneralThreeBodyDecayer::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) {
if(_diagrams[ix].channelType==TBDiagram::fourPoint||
_diagrams[ix].channelType==TBDiagram::UNDEFINED) continue;
// create the new channel
newchannel=new_ptr(DecayPhaseSpaceChannel(mode));
if(_diagrams[ix].channelType==TBDiagram::channel23) {
newchannel->addIntermediate(extpart[0],0,0.0,-1,1);
newchannel->addIntermediate(_diagrams[ix].intermediate,0,0.0, 2,3);
}
else if(_diagrams[ix].channelType==TBDiagram::channel13) {
newchannel->addIntermediate(extpart[0],0,0.0,-1,2);
newchannel->addIntermediate(_diagrams[ix].intermediate,0,0.0, 1,3);
}
else if(_diagrams[ix].channelType==TBDiagram::channel12) {
newchannel->addIntermediate(extpart[0],0,0.0,-1,3);
newchannel->addIntermediate(_diagrams[ix].intermediate,0,0.0, 1,2);
}
_diagmap.push_back(ix);
mode->addChannel(newchannel);
++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 GeneralThreeBodyDecayer::"
<< "doinit() for " << mode << "\n" << Exception::runerror;
}
// add the mode
vector<double> wgt(nmode,1./double(nmode));
addMode(mode,1.,wgt);
}
double GeneralThreeBodyDecayer::
threeBodyMatrixElement(const int imode, const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy m1,
const Energy m2, const Energy m3) const {
// calculate the momenta of the outgoing particles
Energy m0=sqrt(q2);
// energies
Energy eout[3] = {0.5*(q2+sqr(m1)-s1)/m0,
0.5*(q2+sqr(m2)-s2)/m0,
0.5*(q2+sqr(m3)-s3)/m0};
// magnitudes of the momenta
Energy pout[3] = {sqrt(sqr(eout[0])-sqr(m1)),
sqrt(sqr(eout[1])-sqr(m2)),
sqrt(sqr(eout[2])-sqr(m3))};
double cos2 = 0.5*(sqr(pout[0])+sqr(pout[1])-sqr(pout[2]))/pout[0]/pout[1];
double cos3 = 0.5*(sqr(pout[0])-sqr(pout[1])+sqr(pout[2]))/pout[0]/pout[2];
double sin2 = sqrt(1.-sqr(cos2)), sin3 = sqrt(1.-sqr(cos3));
Lorentz5Momentum out[3]=
{Lorentz5Momentum( ZERO , ZERO , pout[0] , eout[0] , m1),
Lorentz5Momentum( pout[1]*sin2 , ZERO , -pout[1]*cos2 , eout[1] , m2),
Lorentz5Momentum( -pout[2]*sin3 , ZERO , -pout[2]*cos3 , eout[2] , m3)};
// create the incoming
PPtr inpart=mode(imode)->externalParticles(0)->
produceParticle(Lorentz5Momentum(sqrt(q2)));
// and outgoing particles
ParticleVector decay;
for(unsigned int ix=1;ix<4;++ix)
decay.push_back(mode(imode)->externalParticles(ix)->produceParticle(out[ix-1]));
// return the matrix element
return me2(-1,*inpart,decay,Initialize);
}
double GeneralThreeBodyDecayer::brat(const DecayMode &, const Particle & p,
double oldbrat) const {
ParticleVector children = p.children();
if( children.size() != 3 || !p.data().widthGenerator() )
return oldbrat;
// partial width for this mode
Energy scale = p.mass();
Energy pwidth =
partialWidth( make_pair(p.dataPtr(), scale),
make_pair(children[0]->dataPtr(), children[0]->mass()),
make_pair(children[1]->dataPtr(), children[1]->mass()),
make_pair(children[2]->dataPtr(), children[2]->mass()) );
Energy width = p.data().widthGenerator()->width(p.data(), scale);
return pwidth/width;
}
Energy GeneralThreeBodyDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb, PMPair outc) const {
if(inpart.second<outa.second+outb.second+outc.second) return ZERO;
// create the object to calculate the width if it doesn't all ready exist
if(!_widthcalc) {
string tag = _incoming->name() + "->";
tag += _outgoing[0]->name() + "," + _outgoing[1]->name() + ","
+ _outgoing[2]->name() + ";";
DMPtr dm = generator()->findDecayMode(tag);
_widthcalc = threeBodyMEIntegrator(*dm);
}
return _widthcalc->partialWidth(sqr(inpart.second));
}
void GeneralThreeBodyDecayer::
colourConnections(const Particle & parent,
const ParticleVector & out) const {
// first extract the outgoing particles and intermediate
PPtr 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(3);
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 GeneralThreeBodyDecayer::"
<< "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 GeneralThreeBodyDecayer::"
<< "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 GeneralThreeBodyDecayer::"
<< "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 "
<< "GeneralThreeBodyDecayer::"
<< "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 "
<< "GeneralThreeBodyDecayer::"
<< "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 GeneralThreeBodyDecayer::"
<< "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"
<< " GeneralThreeBodyDecayer::"
<< "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 "
<< "GeneralThreeBodyDecayer::"
<< "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 GeneralThreeBodyDecayer::"
<< "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 GeneralThreeBodyDecayer::"
<< "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 GeneralThreeBodyDecayer::"
<< "colourConnections() for octet decaying particle"
<< mode << Exception::runerror;
}
}
}
void GeneralThreeBodyDecayer::
constructIntegratorChannels(vector<int> & intype, vector<Energy> & inmass,
vector<Energy> & inwidth, vector<double> & inpow,
vector<double> & inweights) const {
Energy min = incoming()->mass();
int nchannel(0);
pair<int,Energy> imin[4]={make_pair(-1,-1.*GeV),make_pair(-1,-1.*GeV),
make_pair(-1,-1.*GeV),make_pair(-1,-1.*GeV)};
for(unsigned int iy=0;iy<_diagmap.size();++iy) {
unsigned int ix=_diagmap[iy];
Energy deltam(min);
if(getProcessInfo()[ix].channelType==TBDiagram::fourPoint) continue;
int itype(0);
if (getProcessInfo()[ix].channelType==TBDiagram::channel23) {
deltam -= outgoing()[0]->mass();
itype = 3;
}
else if(getProcessInfo()[ix].channelType==TBDiagram::channel13) {
deltam -= outgoing()[1]->mass();
itype = 2;
}
else if(getProcessInfo()[ix].channelType==TBDiagram::channel12) {
deltam -= outgoing()[2]->mass();
itype = 1;
}
deltam -= getProcessInfo()[ix].intermediate->mass();
// if(deltam<ZERO&&getProcessInfo()[ix].intermediate->width()>ZERO) {
if(deltam<ZERO) {
if (imin[itype].first < 0 ) imin[itype] = make_pair(ix,deltam);
else if (imin[itype].second<deltam) imin[itype] = make_pair(ix,deltam);
}
if(deltam<ZERO) continue;
if(getProcessInfo()[ix].intermediate->id()!=ParticleID::gamma) {
intype.push_back(itype);
inpow.push_back(0.);
inmass.push_back(getProcessInfo()[ix].intermediate->mass());
inwidth.push_back(getProcessInfo()[ix].intermediate->width());
++nchannel;
}
else if(getProcessInfo()[ix].intermediate->id()==ParticleID::gamma) {
intype.push_back(itype);
inpow.push_back(-2.);
inmass.push_back(-1.*GeV);
inwidth.push_back(-1.*GeV);
++nchannel;
}
}
for(unsigned int ix=1;ix<4;++ix) {
if(imin[ix].first>=0) {
intype.push_back(ix);
if(getProcessInfo()[imin[ix].first].intermediate->id()!=ParticleID::gamma) {
inpow.push_back(0.);
inmass.push_back(getProcessInfo()[imin[ix].first].intermediate->mass());
inwidth.push_back(getProcessInfo()[imin[ix].first].intermediate->width());
}
else {
inpow.push_back(-2.);
inmass.push_back(-1.*GeV);
inwidth.push_back(-1.*GeV);
}
++nchannel;
}
}
inweights = vector<double>(nchannel,1./double(nchannel));
}
-bool GeneralThreeBodyDecayer::setColourFactors() {
+bool GeneralThreeBodyDecayer::setColourFactors(double symfac) {
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()==3) {
_nflow = 1;
_colour = vector<DVector>(1,DVector(1,1.));
_colourLargeNC = vector<DVector>(1,DVector(1,1.));
}
else if(sng.size()==1&&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()==2&&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) {
_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.;
// sort out the contribution of the different diagrams to the colour
// flows
for(unsigned int ix=0;ix<_diagrams.size();++ix) {
// colour singlet intermediate
if(_diagrams[ix].intermediate->iColour()==PDT::Colour0) {
if(_diagrams[ix].channelType==trip[0]) {
_diagrams[ix]. colourFlow = vector<CFPair>(1,make_pair(1,1.));
_diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
}
else {
_diagrams[ix].colourFlow = vector<CFPair>(1,make_pair(2,1.));
_diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
}
}
// colour octet intermediate
else if(_diagrams[ix].intermediate->iColour()==PDT::Colour8) {
if(_diagrams[ix].channelType==trip[0]) {
vector<CFPair> flow(1,make_pair(2, 0.5 ));
_diagrams[ix].largeNcColourFlow = flow;
flow.push_back( make_pair(1,-1./6.));
_diagrams[ix].colourFlow=flow;
}
else {
vector<CFPair> flow(1,make_pair(1, 0.5 ));
_diagrams[ix].largeNcColourFlow = flow;
flow.push_back( make_pair(2,-1./6.));
_diagrams[ix].colourFlow=flow;
}
}
else {
generator()->log() << "Unknown colour for the intermediate in "
<< "triplet -> triplet triplet antitriplet in "
<< "ThreeBodyDecayConstructor::getColourFactors()"
<< " for " << name << " omitting decay\n";
return false;
}
}
}
else if(trip.size()==1&&oct.size()==1&&sng.size()==1) {
_nflow = 1;
_colour = vector<DVector>(1,DVector(1,4./3.));
_colourLargeNC = vector<DVector>(1,DVector(1,4./3.));
}
else {
generator()->log() << "Unknown colour structure for "
<< "triplet decay in "
<< "ThreeBodyDecayConstructor::getColourFactors()"
<< " for " << name << " omitting decay\n";
return false;
}
}
// colour antitriplet decaying particle
else if( _incoming->iColour() == PDT::Colour3bar) {
if(sng.size()==2&&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) {
_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.;
// sort out the contribution of the different diagrams to the colour
// flows
for(unsigned int ix=0;ix<_diagrams.size();++ix) {
// colour singlet intermediate
if(_diagrams[ix].intermediate->iColour()==PDT::Colour0) {
if(_diagrams[ix].channelType==atrip[0]) {
_diagrams[ix]. colourFlow = vector<CFPair>(1,make_pair(1,1.));
_diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
}
else {
_diagrams[ix].colourFlow = vector<CFPair>(1,make_pair(2,1.));
_diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
}
}
// colour octet intermediate
else if(_diagrams[ix].intermediate->iColour()==PDT::Colour8) {
if(_diagrams[ix].channelType==atrip[0]) {
vector<CFPair> flow(1,make_pair(2, 0.5 ));
_diagrams[ix].largeNcColourFlow = flow;
flow.push_back( make_pair(1,-1./6.));
_diagrams[ix].colourFlow=flow;
}
else {
vector<CFPair> flow(1,make_pair(1, 0.5 ));
_diagrams[ix].largeNcColourFlow = flow;
flow.push_back( make_pair(2,-1./6.));
_diagrams[ix].colourFlow=flow;
}
}
else {
generator()->log() << "Unknown colour for the intermediate in "
<< "antitriplet -> antitriplet antitriplet triplet in "
<< "ThreeBodyDecayConstructor::getColourFactors()"
<< " for " << name << " omitting decay\n";
return false;
}
}
}
else if(atrip.size()==1&&oct.size()==1&&sng.size()==1) {
_nflow = 1;
_colour = vector<DVector>(1,DVector(1,4./3.));
_colourLargeNC = vector<DVector>(1,DVector(1,4./3.));
}
else {
generator()->log() << "Unknown colour antitriplet decay in "
<< "ThreeBodyDecayConstructor::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() == 1) {
_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 "
<< "ThreeBodyDecayConstructor::getColourFactors()"
<< " for " << name << " omitting decay\n";
return false;
}
}
+ for(unsigned int ix=0;ix<_nflow;++ix) {
+ for(unsigned int iy=0;iy<_nflow;++iy) {
+ _colour [ix][iy] /= symfac;
+ _colourLargeNC[ix][iy] /= symfac;
+ }
+ }
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/GeneralThreeBodyDecayer.h b/Decay/General/GeneralThreeBodyDecayer.h
--- a/Decay/General/GeneralThreeBodyDecayer.h
+++ b/Decay/General/GeneralThreeBodyDecayer.h
@@ -1,338 +1,339 @@
// -*- C++ -*-
#ifndef HERWIG_GeneralThreeBodyDecayer_H
#define HERWIG_GeneralThreeBodyDecayer_H
//
// This is the declaration of the GeneralThreeBodyDecayer class.
//
#include "Herwig++/Decay/DecayIntegrator.h"
#include "Herwig++/Models/General/TBDiagram.h"
#include "GeneralThreeBodyDecayer.fh"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the GeneralThreeBodyDecayer class.
*
* @see \ref GeneralThreeBodyDecayerInterfaces "The interfaces"
* defined for GeneralThreeBodyDecayer.
*/
class GeneralThreeBodyDecayer: public DecayIntegrator {
public:
/** A ParticleData ptr and (possible) mass pair.*/
typedef pair<tcPDPtr, Energy> PMPair;
public:
/**
* The default constructor.
*/
GeneralThreeBodyDecayer() : _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;
/**
* The matrix element to be integrated for the three-body decays as a function
* of the invariant masses of pairs of the outgoing particles.
* @param imode The mode for which the matrix element is needed.
* @param q2 The scale, \e i.e. the mass squared of the decaying particle.
* @param s3 The invariant mass squared of particles 1 and 2, \f$s_3=m^2_{12}\f$.
* @param s2 The invariant mass squared of particles 1 and 3, \f$s_2=m^2_{13}\f$.
* @param s1 The invariant mass squared of particles 2 and 3, \f$s_1=m^2_{23}\f$.
* @param m1 The mass of the first outgoing particle.
* @param m2 The mass of the second outgoing particle.
* @param m3 The mass of the third outgoing particle.
* @return The matrix element
*/
virtual double threeBodyMatrixElement(const int imode, const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy m1,
const Energy m2, const Energy m3) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa First decay product.
* @param outb Second decay product.
* @param outc Third decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb, PMPair outc) const;
/**
* An overidden member to calculate a branching ratio for a certain
* particle instance.
* @param dm The DecayMode of the particle
* @param p The particle object
* @param oldbrat The branching fraction given in the DecayMode object
*/
virtual double brat(const DecayMode & dm, const Particle & p,
double oldbrat) const;
//@}
/**
* Set the diagrams
*/
bool setDecayInfo(PDPtr incoming,vector<PDPtr> outgoing,
- const vector<TBDiagram> & process);
+ const vector<TBDiagram> & process,
+ double symfac);
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
protected:
/**
* Access the TBDiagrams that store the required information
* to create the diagrams
*/
const vector<TBDiagram> & getProcessInfo() const {
return _diagrams;
}
/**
* 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();
+ bool setColourFactors(double symfac);
/**
* 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;
}
/**
* Get the mapping between the phase-space channel and the diagram
*/
const vector<unsigned int> & diagramMap() const {
return _diagmap;
}
/**
* 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;
/**
* Method to construct the channels for the integrator to give the partial width
* @param intype Types of the channels
* @param inmass Mass for the channels
* @param inwidth Width for the channels
* @param inpow Power for the channels
* @param inweights Weights for the channels
*/
void constructIntegratorChannels(vector<int> & intype, vector<Energy> & inmass,
vector<Energy> & inwidth, vector<double> & inpow,
vector<double> & inweights) 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; }
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<GeneralThreeBodyDecayer> initGeneralThreeBodyDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GeneralThreeBodyDecayer & operator=(const GeneralThreeBodyDecayer &);
private:
/**
* Store the incoming particle
*/
PDPtr _incoming;
/**
* Outgoing particles
*/
vector<PDPtr> _outgoing;
/**
* Store the diagrams for the decay
*/
vector<TBDiagram> _diagrams;
/**
* Map between the diagrams and the phase-space channels
*/
vector<unsigned int> _diagmap;
/**
* Store colour factors for ME calc.
*/
vector<DVector> _colour;
/**
* Store cololur factors for ME calc at large N_c
*/
vector<DVector> _colourLargeNC;
/**
* 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;
/**
* 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;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of GeneralThreeBodyDecayer. */
template <>
struct BaseClassTrait<Herwig::GeneralThreeBodyDecayer,1> {
/** Typedef of the first base class of GeneralThreeBodyDecayer. */
typedef Herwig::DecayIntegrator NthBase;
};
/** This template specialization informs ThePEG about the name of
* the GeneralThreeBodyDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::GeneralThreeBodyDecayer>
: public ClassTraitsBase<Herwig::GeneralThreeBodyDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::GeneralThreeBodyDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_GeneralThreeBodyDecayer_H */
diff --git a/Models/General/FourBodyDecayConstructor.cc b/Models/General/FourBodyDecayConstructor.cc
--- a/Models/General/FourBodyDecayConstructor.cc
+++ b/Models/General/FourBodyDecayConstructor.cc
@@ -1,418 +1,243 @@
// -*- 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_;
}
void FourBodyDecayConstructor::persistentInput(PersistentIStream & is, int) {
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);
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);
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) {
+createDecayMode(vector<NBDiagram> & diagrams,
+ bool possibleOnShell, double symfac) {
// some basic checks for the modes we are interested in
// only looking at scalars
- if(diagrams[0]->incoming->iSpin()!=PDT::Spin0) return;
+ 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) {
+ for(OrderedParticles::const_iterator it=diagrams[0].outgoing.begin();
+ it!=diagrams[0].outgoing.end();++it) {
if((**it).iSpin()==PDT::Spin1Half) ++nferm;
}
if(nferm!=4) return;
// check for on-shell intermediates
- bool possibleOnShell=false;
- for(unsigned int iy=0;iy<diagrams.size();++iy)
- possibleOnShell |= diagrams[iy]->possibleOnShell;
bool inter = interOpt_ == 1 || (interOpt_ == 0 && possibleOnShell);
// incoming particle
- tPDPtr inpart = diagrams[0]->incoming;
+ tPDPtr inpart = diagrams[0].incoming;
// outgoing particles
- OrderedParticles outgoing=diagrams[0]->outPart;
+ OrderedParticles outgoing=diagrams[0].outgoing;
// 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);
+ GeneralFourBodyDecayerPtr decayer = createDecayer(diagrams,inter,symfac);
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) {
string test = 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);
+ GeneralFourBodyDecayerPtr decayer = createDecayer(diagrams,inter,symfac);
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();
}
-
-namespace {
-
-double factorial(const int i) {
- if(i>1) return i*factorial(i-1);
- else return 1.;
-}
-
-void constructIdenticalSwaps(unsigned int depth,
- vector<vector<unsigned int> > identical,
- vector<unsigned int> channelType,
- list<vector<unsigned int> > & swaps) {
- if(depth==0) {
- unsigned int size = identical.size();
- for(unsigned ix=0;ix<size;++ix) {
- for(unsigned int iy=2;iy<identical[ix].size();++iy)
- identical.push_back(identical[ix]);
- }
- }
- if(depth+1!=identical.size()) {
- constructIdenticalSwaps(depth+1,identical,channelType,swaps);
- }
- else {
- swaps.push_back(channelType);
- }
- for(unsigned int ix=0;ix<identical[depth].size();++ix) {
- for(unsigned int iy=ix+1;iy<identical[depth].size();++iy) {
- vector<unsigned int> newType=channelType;
- swap(newType[identical[depth][ix]],newType[identical[depth][iy]]);
- // at bottom of chain
- if(depth+1==identical.size()) {
- swaps.push_back(newType);
- }
- else {
- constructIdenticalSwaps(depth+1,identical,newType,swaps);
- }
- }
- }
-}
-
-void identicalFromSameDecay(unsigned int & loc, const NBVertex & vertex,
- vector<vector<unsigned int> > & sameDecay) {
- list<pair<PDPtr,NBVertex> >::const_iterator it = vertex.vertices.begin();
- while(it!=vertex.vertices.end()) {
- if(it->second.incoming) {
- identicalFromSameDecay(loc,it->second,sameDecay);
- ++it;
- continue;
- }
- ++loc;
- long id = it->first->id();
- ++it;
- if(it->second.incoming) continue;
- if(it->first->id()!=id) continue;
- sameDecay.push_back(vector<unsigned int>());
- sameDecay.back().push_back(loc-1);
- while(!it->second.incoming&&it->first->id()==id) {
- ++loc;
- ++it;
- sameDecay.back().push_back(loc-1);
- }
- };
-}
-
-}
-
GeneralFourBodyDecayerPtr
-FourBodyDecayConstructor::createDecayer(vector<PrototypeVertexPtr> & diagrams,
- bool inter) const {
+FourBodyDecayConstructor::createDecayer(vector<NBDiagram> & diagrams,
+ bool inter, double symfac) const {
if(diagrams.empty()) return GeneralFourBodyDecayerPtr();
// extract the external particles for the process
- PDPtr incoming = diagrams[0]->incoming;
+ PDPtr incoming = diagrams[0].incoming;
// outgoing particles
- vector<PDPtr> outgoing(diagrams[0]->outPart.begin(),
- diagrams[0]->outPart.end());
- vector<NBDiagram> newDiagrams;
- double symfac(1.);
- // convert the diagrams
- for(unsigned int ix=0;ix<diagrams.size();++ix) {
- symfac = 1.;
- NBDiagram templateDiagram = NBDiagram(diagrams[ix]);
- // extract the ordering
- vector<int> order(templateDiagram.channelType.size());
- for(unsigned int iz=0;iz<order.size();++iz) {
- order[templateDiagram.channelType[iz]-1]=iz;
- }
- // find any identical particles
- vector<vector<unsigned int> > identical;
- OrderedParticles::const_iterator it=templateDiagram.outgoing.begin();
- unsigned int iloc=0;
- while(it!=templateDiagram.outgoing.end()) {
- OrderedParticles::const_iterator lt = templateDiagram.outgoing.lower_bound(*it);
- OrderedParticles::const_iterator ut = templateDiagram.outgoing.upper_bound(*it);
- unsigned int nx=0;
- for(OrderedParticles::const_iterator jt=lt;jt!=ut;++jt) {++nx;}
- if(nx==1) {
- ++it;
- ++iloc;
- }
- else {
- symfac *= factorial(nx);
- identical.push_back(vector<unsigned int>());
- for(OrderedParticles::const_iterator jt=lt;jt!=ut;++jt) {
- identical.back().push_back(order[iloc]);
- ++iloc;
- }
- it = ut;
- }
- }
- // that's it if there outgoing are unqiue
- if(identical.empty()) {
- newDiagrams.push_back(templateDiagram);
- }
- else {
- // find any identical particles which shouldn't be swapped
- unsigned int loc=0;
- vector<vector<unsigned int> > sameDecay;
- identicalFromSameDecay(loc,templateDiagram,sameDecay);
- // compute the swaps
- list<vector<unsigned int> > swaps;
- constructIdenticalSwaps(0,identical,templateDiagram.channelType,swaps);
- // special if identical from same decay
- if(!sameDecay.empty()) {
- for(vector<vector<unsigned int> >::const_iterator st=sameDecay.begin();
- st!=sameDecay.end();++st) {
- for(list<vector<unsigned int> >::iterator it=swaps.begin();
- it!=swaps.end();++it) {
- for(unsigned int iy=0;iy<(*st).size();++iy) {
- for(unsigned int iz=iy+1;iz<(*st).size();++iz) {
- if((*it)[(*st)[iy]]>(*it)[(*st)[iz]])
- swap((*it)[(*st)[iy]],(*it)[(*st)[iz]]);
- }
- }
- }
- }
- }
- // remove any dupliciates
- for(list<vector<unsigned int> >::iterator it=swaps.begin();
- it!=swaps.end();++it) {
- for(list<vector<unsigned int> >::iterator jt=it;
- jt!=swaps.end();++jt) {
- if(it==jt) continue;
- bool different=false;
- for(unsigned int iz=0;iz<(*it).size();++iz) {
- if((*it)[iz]!=(*jt)[iz]) {
- different = true;
- break;
- }
- }
- if(!different) {
- jt = swaps.erase(jt);
- --jt;
- }
- }
- }
- // special for identical decay products
- if(templateDiagram.vertices.begin()->second.incoming) {
- if( templateDiagram.vertices.begin() ->first ==
- (++templateDiagram.vertices.begin())->first) {
- if(*( diagrams[ix]->outgoing.begin() ->second) ==
- *((++diagrams[ix]->outgoing.begin())->second)) {
- for(list<vector<unsigned int> >::iterator it=swaps.begin();
- it!=swaps.end();++it) {
- for(list<vector<unsigned int> >::iterator jt=it;
- jt!=swaps.end();++jt) {
- if(it==jt) continue;
- if((*it)[0]==(*jt)[2]&&(*it)[1]==(*jt)[3]) {
- jt = swaps.erase(jt);
- --jt;
- }
- }
- }
- }
- }
- }
- for(list<vector<unsigned int> >::iterator it=swaps.begin();
- it!=swaps.end();++it) {
- newDiagrams.push_back(templateDiagram);
- newDiagrams.back().channelType = *it;
- }
- }
- }
+ vector<PDPtr> outgoing(diagrams[0].outgoing.begin(),
+ diagrams[0].outgoing.end());
// get the name for the object
string objectname ("/Herwig/Decays/");
- string classname = DecayerClassName(incoming, diagrams[0]->outPart, objectname);
+ string classname = DecayerClassName(incoming, diagrams[0].outgoing, objectname);
if(classname=="") return GeneralFourBodyDecayerPtr();
// create the object
GeneralFourBodyDecayerPtr decayer =
dynamic_ptr_cast<GeneralFourBodyDecayerPtr>
(generator()->preinitCreate(classname, objectname));
// set up the decayer and return if doesn't work
- if(!decayer->setDecayInfo(incoming,outgoing,newDiagrams,symfac))
+ if(!decayer->setDecayInfo(incoming,outgoing,diagrams,symfac))
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) {}
/**
* 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> &);
+ void createDecayMode(vector<NBDiagram> &,bool,double);
/**
* Create the decayer
* @param diagrams The diagrams for the decay
* @param inter Option for intermediates
*/
- GeneralFourBodyDecayerPtr createDecayer(vector<PrototypeVertexPtr> & diagrams,
- bool inter) const;
+ GeneralFourBodyDecayerPtr createDecayer(vector<NBDiagram> & diagrams,
+ bool inter, double symfac) 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_;
/**
* How to treat the widths of the intermediate particles
*/
unsigned int widthOpt_;
};
}
#endif /* THEPEG_FourBodyDecayConstructor_H */
diff --git a/Models/General/NBodyDecayConstructorBase.cc b/Models/General/NBodyDecayConstructorBase.cc
--- a/Models/General/NBodyDecayConstructorBase.cc
+++ b/Models/General/NBodyDecayConstructorBase.cc
@@ -1,447 +1,643 @@
// -*- C++ -*-
//
// NBodyDecayConstructorBase.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the NBodyDecayConstructorBase class.
//
#include "NBodyDecayConstructorBase.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "DecayConstructor.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
using namespace Herwig;
using namespace ThePEG;
void NBodyDecayConstructorBase::persistentOutput(PersistentOStream & os ) const {
os << init_ << iteration_ << points_ << info_ << decayConstructor_
<< removeOnShell_ << excludeEffective_ << includeTopOnShell_
<< excludedVerticesVector_ << excludedVerticesSet_
<< excludedParticlesVector_ << excludedParticlesSet_;
}
void NBodyDecayConstructorBase::persistentInput(PersistentIStream & is , int) {
is >> init_ >> iteration_ >> points_ >> info_ >> decayConstructor_
>> removeOnShell_ >> excludeEffective_ >> includeTopOnShell_
>> excludedVerticesVector_ >> excludedVerticesSet_
>> excludedParticlesVector_ >> excludedParticlesSet_;
}
AbstractClassDescription<NBodyDecayConstructorBase>
NBodyDecayConstructorBase::initNBodyDecayConstructorBase;
// Definition of the static class description member.
void NBodyDecayConstructorBase::Init() {
static ClassDocumentation<NBodyDecayConstructorBase> documentation
("The NBodyDecayConstructorBase class is the base class for the automatic"
"construction of the decay modes");
static Switch<NBodyDecayConstructorBase,bool> interfaceInitializeDecayers
("InitializeDecayers",
"Initialize new decayers",
&NBodyDecayConstructorBase::init_, true, false, false);
static SwitchOption interfaceInitializeDecayersInitializeDecayersOn
(interfaceInitializeDecayers,
"Yes",
"Initialize new decayers to find max weights",
true);
static SwitchOption interfaceInitializeDecayersoff
(interfaceInitializeDecayers,
"No",
"Use supplied weights for integration",
false);
static Parameter<NBodyDecayConstructorBase,int> interfaceInitIteration
("InitIteration",
"Number of iterations to optimise integration weights",
&NBodyDecayConstructorBase::iteration_, 1, 0, 10,
false, false, true);
static Parameter<NBodyDecayConstructorBase,int> interfaceInitPoints
("InitPoints",
"Number of points to generate when optimising integration",
&NBodyDecayConstructorBase::points_, 1000, 100, 100000000,
false, false, true);
static Switch<NBodyDecayConstructorBase,bool> interfaceOutputInfo
("OutputInfo",
"Whether to output information about the decayers",
&NBodyDecayConstructorBase::info_, false, false, false);
static SwitchOption interfaceOutputInfoOff
(interfaceOutputInfo,
"No",
"Do not output information regarding the created decayers",
false);
static SwitchOption interfaceOutputInfoOn
(interfaceOutputInfo,
"Yes",
"Output information regarding the decayers",
true);
static Switch<NBodyDecayConstructorBase,bool> interfaceCreateDecayModes
("CreateDecayModes",
"Whether to create the ThePEG::DecayMode objects as well as the decayers",
&NBodyDecayConstructorBase::createModes_, true, false, false);
static SwitchOption interfaceCreateDecayModesOn
(interfaceCreateDecayModes,
"Yes",
"Create the ThePEG::DecayMode objects",
true);
static SwitchOption interfaceCreateDecayModesOff
(interfaceCreateDecayModes,
"No",
"Only create the Decayer objects",
false);
static Switch<NBodyDecayConstructorBase,unsigned int> interfaceRemoveOnShell
("RemoveOnShell",
"Remove on-shell diagrams as should be treated as a sequence of 1->2 decays",
&NBodyDecayConstructorBase::removeOnShell_, 1, false, false);
static SwitchOption interfaceRemoveOnShellYes
(interfaceRemoveOnShell,
"Yes",
"Remove the diagrams if neither the production of decay or the intermediate"
" can happen",
1);
static SwitchOption interfaceRemoveOnShellNo
(interfaceRemoveOnShell,
"No",
"Never remove the intermediate",
0);
static SwitchOption interfaceRemoveOnShellProduction
(interfaceRemoveOnShell,
"Production",
"Remove the diagram if the on-shell production of the intermediate is allowed",
2);
static RefVector<NBodyDecayConstructorBase,VertexBase> interfaceExcludedVertices
("ExcludedVertices",
"Vertices which are not included in the three-body decayers",
&NBodyDecayConstructorBase::excludedVerticesVector_,
-1, false, false, true, true, false);
static RefVector<NBodyDecayConstructorBase,ParticleData> interfaceExcludedIntermediates
("ExcludedIntermediates",
"Excluded intermediate particles",
&NBodyDecayConstructorBase::excludedParticlesVector_,
-1, false, false, true, true, false);
static Switch<NBodyDecayConstructorBase,bool> interfaceExcludeEffectiveVertices
("ExcludeEffectiveVertices",
"Exclude effectice vertices",
&NBodyDecayConstructorBase::excludeEffective_, true, false, false);
static SwitchOption interfaceExcludeEffectiveVerticesYes
(interfaceExcludeEffectiveVertices,
"Yes",
"Exclude the effective vertices",
true);
static SwitchOption interfaceExcludeEffectiveVerticesNo
(interfaceExcludeEffectiveVertices,
"No",
"Don't exclude the effective vertices",
false);
static Parameter<NBodyDecayConstructorBase,double> interfaceMinReleaseFraction
("MinReleaseFraction",
"The minimum energy release for a three-body decay, as a "
"fraction of the parent mass.",
&NBodyDecayConstructorBase::minReleaseFraction_, 1e-3, 0.0, 1.0,
false, false, Interface::limited);
static Switch<NBodyDecayConstructorBase,unsigned int> interfaceMaximumGaugeBosons
("MaximumGaugeBosons",
"Maximum number of electroweak gauge bosons"
" to be produced as decay products",
&NBodyDecayConstructorBase::maxBoson_, 1, false, false);
static SwitchOption interfaceMaximumGaugeBosonsNone
(interfaceMaximumGaugeBosons,
"None",
"Produce no W/Zs",
0);
static SwitchOption interfaceMaximumGaugeBosonsSingle
(interfaceMaximumGaugeBosons,
"Single",
"Produce at most one W/Zs",
1);
static SwitchOption interfaceMaximumGaugeBosonsDouble
(interfaceMaximumGaugeBosons,
"Double",
"Produce at most two W/Zs",
2);
static SwitchOption interfaceMaximumGaugeBosonsTriple
(interfaceMaximumGaugeBosons,
"Triple",
"Produce at most three W/Zs",
3);
static Switch<NBodyDecayConstructorBase,unsigned int> interfaceMaximumNewParticles
("MaximumNewParticles",
"Maximum number of particles from the list of "
"decaying particles to be allowed as decay products",
&NBodyDecayConstructorBase::maxList_, 0, false, false);
static SwitchOption interfaceMaximumNewParticlesNone
(interfaceMaximumNewParticles,
"None",
"No particles from the list",
0);
static SwitchOption interfaceMaximumNewParticlesOne
(interfaceMaximumNewParticles,
"One",
"A single particle from the list",
1);
static SwitchOption interfaceMaximumNewParticlesTwo
(interfaceMaximumNewParticles,
"Two",
"Two particles from the list",
2);
static SwitchOption interfaceMaximumNewParticlesThree
(interfaceMaximumNewParticles,
"Three",
"Three particles from the list",
3);
static SwitchOption interfaceMaximumNewParticlesFour
(interfaceMaximumNewParticles,
"Four",
"Four particles from the list",
4);
static Switch<NBodyDecayConstructorBase,bool> interfaceIncludeOnShellTop
("IncludeOnShellTop",
"Include the on-shell diagrams involving t -> bW",
&NBodyDecayConstructorBase::includeTopOnShell_, false, false, false);
static SwitchOption interfaceIncludeOnShellTopYes
(interfaceIncludeOnShellTop,
"Yes",
"Inlude them",
true);
static SwitchOption interfaceIncludeOnShellTopNo
(interfaceIncludeOnShellTop,
"No",
"Don't include them",
true);
}
void NBodyDecayConstructorBase::setBranchingRatio(tDMPtr dm, Energy pwidth) {
//Need width and branching ratios for all currently created decay modes
PDPtr parent = const_ptr_cast<PDPtr>(dm->parent());
DecaySet modes = parent->decayModes();
if( modes.empty() ) return;
double dmbrat(0.);
if( modes.size() == 1 ) {
parent->width(pwidth);
if( pwidth > ZERO ) parent->cTau(hbarc/pwidth);
dmbrat = 1.;
}
else {
Energy currentwidth(parent->width());
Energy newWidth(currentwidth + pwidth);
parent->width(newWidth);
if( newWidth > ZERO ) parent->cTau(hbarc/newWidth);
//need to reweight current branching fractions if there are any
double factor = newWidth > ZERO ? double(currentwidth/newWidth) : 0.;
for(DecaySet::const_iterator dit = modes.begin();
dit != modes.end(); ++dit) {
if( **dit == *dm || !(**dit).on() ) continue;
double newbrat = (**dit).brat()*factor;
ostringstream brf;
brf << setprecision(13)<< newbrat;
generator()->preinitInterface(*dit, "BranchingRatio",
"set", brf.str());
}
//set brat for current mode
dmbrat = newWidth > ZERO ? double(pwidth/newWidth) : 0.;
}
ostringstream br;
br << setprecision(13) << dmbrat;
generator()->preinitInterface(dm, "BranchingRatio",
"set", br.str());
}
void NBodyDecayConstructorBase::setDecayerInterfaces(string fullname) const {
if( initialize() ) {
ostringstream value;
value << initialize();
generator()->preinitInterface(fullname, "Initialize", "set",
value.str());
value.str("");
value << iteration();
generator()->preinitInterface(fullname, "Iteration", "set",
value.str());
value.str("");
value << points();
generator()->preinitInterface(fullname, "Points", "set",
value.str());
}
// QED stuff if needed
if(decayConstructor()->QEDGenerator())
generator()->preinitInterface(fullname, "PhotonGenerator", "set",
decayConstructor()->QEDGenerator()->fullName());
string outputmodes;
if( info() ) outputmodes = string("Output");
else outputmodes = string("NoOutput");
generator()->preinitInterface(fullname, "OutputModes", "set",
outputmodes);
}
void NBodyDecayConstructorBase::doinit() {
Interfaced::doinit();
excludedVerticesSet_ = set<VertexBasePtr>(excludedVerticesVector_.begin(),
excludedVerticesVector_.end());
excludedParticlesSet_ = set<PDPtr>(excludedParticlesVector_.begin(),
excludedParticlesVector_.end());
if(removeOnShell_==0&&numBodies()>2)
generator()->log() << "Warning: Including diagrams with on-shell "
<< "intermediates in " << numBodies() << "-body BSM decays, this"
<< " can lead to double counting and is not"
<< " recommended unless you really know what you are doing\n"
<< "This can be switched off using\n set "
<< fullName() << ":RemoveOnShell Yes\n";
}
+namespace {
+
+double factorial(const int i) {
+ if(i>1) return i*factorial(i-1);
+ else return 1.;
+}
+
+void constructIdenticalSwaps(unsigned int depth,
+ vector<vector<unsigned int> > identical,
+ vector<unsigned int> channelType,
+ list<vector<unsigned int> > & swaps) {
+ if(depth==0) {
+ unsigned int size = identical.size();
+ for(unsigned ix=0;ix<size;++ix) {
+ for(unsigned int iy=2;iy<identical[ix].size();++iy)
+ identical.push_back(identical[ix]);
+ }
+ }
+ if(depth+1!=identical.size()) {
+ constructIdenticalSwaps(depth+1,identical,channelType,swaps);
+ }
+ else {
+ swaps.push_back(channelType);
+ }
+ for(unsigned int ix=0;ix<identical[depth].size();++ix) {
+ for(unsigned int iy=ix+1;iy<identical[depth].size();++iy) {
+ vector<unsigned int> newType=channelType;
+ swap(newType[identical[depth][ix]],newType[identical[depth][iy]]);
+ // at bottom of chain
+ if(depth+1==identical.size()) {
+ swaps.push_back(newType);
+ }
+ else {
+ constructIdenticalSwaps(depth+1,identical,newType,swaps);
+ }
+ }
+ }
+}
+
+void identicalFromSameDecay(unsigned int & loc, const NBVertex & vertex,
+ vector<vector<unsigned int> > & sameDecay) {
+ list<pair<PDPtr,NBVertex> >::const_iterator it = vertex.vertices.begin();
+ while(it!=vertex.vertices.end()) {
+ if(it->second.incoming) {
+ identicalFromSameDecay(loc,it->second,sameDecay);
+ ++it;
+ continue;
+ }
+ ++loc;
+ long id = it->first->id();
+ ++it;
+ if(it->second.incoming) continue;
+ if(it->first->id()!=id) continue;
+ sameDecay.push_back(vector<unsigned int>());
+ sameDecay.back().push_back(loc-1);
+ while(!it->second.incoming&&it->first->id()==id) {
+ ++loc;
+ ++it;
+ sameDecay.back().push_back(loc-1);
+ }
+ };
+}
+
+}
+
void NBodyDecayConstructorBase::DecayList(const set<PDPtr> & particles) {
if( particles.empty() ) return;
// cast the StandardModel to the Hw++ one to get the vertices
tHwSMPtr model = dynamic_ptr_cast<tHwSMPtr>(generator()->standardModel());
unsigned int nv(model->numberOfVertices());
// loop over the particles and create the modes
for(set<PDPtr>::const_iterator ip=particles.begin();
ip!=particles.end();++ip) {
// get the decaying particle
tPDPtr parent = *ip;
// first create prototype 1->2 decays
std::queue<PrototypeVertexPtr> prototypes;
for(unsigned int iv = 0; iv < nv; ++iv) {
VertexBasePtr vertex = model->vertex(iv);
if(excluded(vertex)) continue;
PrototypeVertex::createPrototypes(parent, vertex, prototypes);
}
// now expand them into potential decay modes
list<vector<PrototypeVertexPtr> > modes;
while(!prototypes.empty()) {
// get the first prototype from the queue
PrototypeVertexPtr proto = prototypes.front();
prototypes.pop();
// multiplcity too low
if(proto->npart<numBodies()) {
// loop over all vertices and expand
for(unsigned int iv = 0; iv < nv; ++iv) {
VertexBasePtr vertex = model->vertex(iv);
if(excluded(vertex) ||
proto->npart+vertex->getNpoint()>numBodies()+2) continue;
PrototypeVertex::expandPrototypes(proto,vertex,prototypes,
excludedParticlesSet_);
}
}
// multiplcity too high disgard
else if(proto->npart>numBodies()) {
continue;
}
// right multiplicity
else {
// check it's kinematical allowed for physical masses
if( proto->incomingMass() < proto->outgoingMass() ) continue;
// and for constituent masses
Energy outgoingMass = proto->outgoingConstituentMass();
if( proto->incomingMass() < proto->outgoingConstituentMass() ) continue;
// remove processes which aren't kinematically allowed within
// the release fraction
if( proto->incomingMass() - outgoingMass <=
minReleaseFraction_ * proto->incomingMass() ) continue;
// check the external particles
if(!proto->checkExternal()) continue;
// check if first piece on-shell
bool onShell = proto->canBeOnShell(removeOnShell(),proto->incomingMass(),true);
// special treatment for three-body top decays
if(onShell) {
if(includeTopOnShell_ &&
abs(proto->incoming->id())==ParticleID::t && proto->npart==3) {
unsigned int nprimary=0;
bool foundW=false, foundQ=false;
for(OrderedVertices::const_iterator it = proto->outgoing.begin();
it!=proto->outgoing.end();++it) {
if(abs(it->first->id())==ParticleID::Wplus)
foundW = true;
if(abs(it->first->id())==ParticleID::b ||
abs(it->first->id())==ParticleID::s ||
abs(it->first->id())==ParticleID::d)
foundQ = true;
++nprimary;
}
if(!(foundW&&foundQ&&nprimary==2)) continue;
}
else continue;
}
// check if should be added to an existing decaymode
bool added = false;
for(list<vector<PrototypeVertexPtr> >::iterator it=modes.begin();
it!=modes.end();++it) {
// is the same ?
if(!(*it)[0]->sameDecay(*proto)) continue;
// it is the same
added = true;
// check if it is a duplicate
bool already = false;
for(unsigned int iz = 0; iz < (*it).size(); ++iz) {
if( *(*it)[iz] == *proto) {
already = true;
break;
}
}
if(!already) (*it).push_back(proto);
break;
}
if(!added) modes.push_back(vector<PrototypeVertexPtr>(1,proto));
}
}
// now look at the decay modes
for(list<vector<PrototypeVertexPtr> >::iterator mit = modes.begin();
mit!=modes.end();++mit) {
// count the number of gauge bosons and particles from the list
unsigned int nlist(0),nbos(0);
for(OrderedParticles::const_iterator it=(*mit)[0]->outPart.begin();
it!=(*mit)[0]->outPart.end();++it) {
if(abs((**it).id()) == ParticleID::Wplus ||
abs((**it).id()) == ParticleID::Z0) ++nbos;
if(particles.find(*it)!=particles.end()) ++nlist;
if((**it).CC() && particles.find((**it).CC())!=particles.end()) ++nlist;
}
// if too many ignore the mode
if(nbos > maxBoson_ || nlist > maxList_) continue;
+ // translate the prototypes into diagrams
+ vector<NBDiagram> newDiagrams;
+ double symfac(1.);
+ bool possibleOnShell=false;
+ for(unsigned int ix=0;ix<(*mit).size();++ix) {
+ symfac = 1.;
+ possibleOnShell |= (*mit)[ix]->possibleOnShell;
+ NBDiagram templateDiagram = NBDiagram((*mit)[ix]);
+ // extract the ordering
+ vector<int> order(templateDiagram.channelType.size());
+ for(unsigned int iz=0;iz<order.size();++iz) {
+ order[templateDiagram.channelType[iz]-1]=iz;
+ }
+ // find any identical particles
+ vector<vector<unsigned int> > identical;
+ OrderedParticles::const_iterator it=templateDiagram.outgoing.begin();
+ unsigned int iloc=0;
+ while(it!=templateDiagram.outgoing.end()) {
+ OrderedParticles::const_iterator lt = templateDiagram.outgoing.lower_bound(*it);
+ OrderedParticles::const_iterator ut = templateDiagram.outgoing.upper_bound(*it);
+ unsigned int nx=0;
+ for(OrderedParticles::const_iterator jt=lt;jt!=ut;++jt) {++nx;}
+ if(nx==1) {
+ ++it;
+ ++iloc;
+ }
+ else {
+ symfac *= factorial(nx);
+ identical.push_back(vector<unsigned int>());
+ for(OrderedParticles::const_iterator jt=lt;jt!=ut;++jt) {
+ identical.back().push_back(order[iloc]);
+ ++iloc;
+ }
+ it = ut;
+ }
+ }
+ // that's it if there outgoing are unqiue
+ if(identical.empty()) {
+ newDiagrams.push_back(templateDiagram);
+ continue;
+ }
+ // find any identical particles which shouldn't be swapped
+ unsigned int loc=0;
+ vector<vector<unsigned int> > sameDecay;
+ identicalFromSameDecay(loc,templateDiagram,sameDecay);
+ // compute the swaps
+ list<vector<unsigned int> > swaps;
+ constructIdenticalSwaps(0,identical,templateDiagram.channelType,swaps);
+ // special if identical from same decay
+ if(!sameDecay.empty()) {
+ for(vector<vector<unsigned int> >::const_iterator st=sameDecay.begin();
+ st!=sameDecay.end();++st) {
+ for(list<vector<unsigned int> >::iterator it=swaps.begin();
+ it!=swaps.end();++it) {
+ for(unsigned int iy=0;iy<(*st).size();++iy) {
+ for(unsigned int iz=iy+1;iz<(*st).size();++iz) {
+ if((*it)[(*st)[iy]]>(*it)[(*st)[iz]])
+ swap((*it)[(*st)[iy]],(*it)[(*st)[iz]]);
+ }
+ }
+ }
+ }
+ }
+ // remove any dupliciates
+ for(list<vector<unsigned int> >::iterator it=swaps.begin();
+ it!=swaps.end();++it) {
+ for(list<vector<unsigned int> >::iterator jt=it;
+ jt!=swaps.end();++jt) {
+ if(it==jt) continue;
+ bool different=false;
+ for(unsigned int iz=0;iz<(*it).size();++iz) {
+ if((*it)[iz]!=(*jt)[iz]) {
+ different = true;
+ break;
+ }
+ }
+ if(!different) {
+ jt = swaps.erase(jt);
+ --jt;
+ }
+ }
+ }
+ // special for identical decay products
+ if(templateDiagram.vertices.begin()->second.incoming) {
+ if( templateDiagram.vertices.begin() ->first ==
+ (++templateDiagram.vertices.begin())->first) {
+ if(*( (*mit)[ix]->outgoing.begin() ->second) ==
+ *((++(*mit)[ix]->outgoing.begin())->second)) {
+ for(list<vector<unsigned int> >::iterator it=swaps.begin();
+ it!=swaps.end();++it) {
+ for(list<vector<unsigned int> >::iterator jt=it;
+ jt!=swaps.end();++jt) {
+ if(it==jt) continue;
+ if((*it)[0]==(*jt)[2]&&(*it)[1]==(*jt)[3]) {
+ jt = swaps.erase(jt);
+ --jt;
+ }
+ }
+ }
+ }
+ }
+ }
+ for(list<vector<unsigned int> >::iterator it=swaps.begin();
+ it!=swaps.end();++it) {
+ newDiagrams.push_back(templateDiagram);
+ newDiagrams.back().channelType = *it;
+ }
+ }
// create the decay
- createDecayMode(*mit);
+ createDecayMode(newDiagrams,possibleOnShell,symfac);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
if( Debug::level > 1 ) {
generator()->log() << "Mode: ";
generator()->log() << (*mit)[0]->incoming->PDGName() << " -> ";
for(OrderedParticles::const_iterator it=(*mit)[0]->outPart.begin();
it!=(*mit)[0]->outPart.end();++it)
generator()->log() << (**it).PDGName() << " ";
generator()->log() << "\n";
generator()->log() << "There are " << (*mit).size() << " diagrams\n";
for(unsigned int iy=0;iy<(*mit).size();++iy) {
generator()->log() << "Diagram: " << iy << "\n";
generator()->log() << *(*mit)[iy] << "\n";
}
}
}
}
}
-void NBodyDecayConstructorBase::createDecayMode(vector<PrototypeVertexPtr> &) {
+void NBodyDecayConstructorBase::createDecayMode(vector<NBDiagram> &,
+ bool, double) {
throw Exception() << "In NBodyDecayConstructorBase::createDecayMode() which"
<< " should have be overridden in an inheriting class"
<< Exception::abortnow;
}
diff --git a/Models/General/NBodyDecayConstructorBase.h b/Models/General/NBodyDecayConstructorBase.h
--- a/Models/General/NBodyDecayConstructorBase.h
+++ b/Models/General/NBodyDecayConstructorBase.h
@@ -1,334 +1,336 @@
// -*- C++ -*-
//
// NBodyDecayConstructorBase.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_NBodyDecayConstructorBase_H
#define HERWIG_NBodyDecayConstructorBase_H
//
// This is the declaration of the NBodyDecayConstructorBase class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "ThePEG/Utilities/Exception.h"
#include "ThePEG/PDT/ParticleData.h"
#include "NBodyDecayConstructorBase.fh"
#include "PrototypeVertex.h"
#include "DecayConstructor.fh"
namespace Herwig {
using namespace ThePEG;
/**
* This is the base class for NBodyDecayConstructors. An N-body
* decay constructor should inherit from this and implement the
* DecayList virtual funtcion to create the decays and decayers.
*
* @see \ref NBodyDecayConstructorBaseInterfaces "The interfaces"
* defined for NBodyDecayConstructor.
*/
class NBodyDecayConstructorBase: public Interfaced {
public:
/**
* The default constructor.
*/
NBodyDecayConstructorBase() :
init_(true),iteration_(1), points_(1000), info_(false),
createModes_(true), removeOnShell_(1), excludeEffective_(true),
minReleaseFraction_(1e-3), maxBoson_(1), maxList_(1),
includeTopOnShell_(false) {}
/**
* 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 = 0;
/**
* Set the pointer to the DecayConstrcutor
*/
void decayConstructor(tDecayConstructorPtr d) {
decayConstructor_ = d;
}
protected:
/**
* Method to set up the decay mode, should be overidden in inheriting class
*/
- virtual void createDecayMode(vector<PrototypeVertexPtr> & mode);
+ virtual void createDecayMode(vector<NBDiagram> & mode,
+ bool possibleOnShell,
+ double symfac);
/**
* Set the branching ratio of this mode. This requires
* calculating a new width for the decaying particle and reweighting
* the current branching fractions.
* @param dm The decaymode for which to set the branching ratio
* @param pwidth The calculated width of the mode
*/
void setBranchingRatio(tDMPtr dm, Energy pwidth);
/**
* Set the interfaces of the decayers depending on the flags stored.
* @param name Fullname of the decayer in the EventGenerator
* including the path
*/
void setDecayerInterfaces(string name) const;
/**
* Whether to initialize decayers or not
*/
bool initialize() const { return init_; }
/**
* Number of iterations if initializing (default 1)
*/
int iteration() const { return iteration_; }
/**
* Number of points to do in initialization
*/
int points() const { return points_; }
/**
* Whether to output information on the decayers
*/
bool info() const { return info_; }
/**
* Whether to create the DecayModes as well as the Decayer objects
*/
bool createDecayModes() const { return createModes_; }
/**
* Maximum number of electroweak gauge bosons
*/
unsigned int maximumGaugeBosons() const { return maxBoson_;}
/**
* Maximum number of particles from the list whose decays we are calculating
*/
unsigned int maximumList() const { return maxList_;}
/**
* Minimum energy release fraction
*/
double minimumReleaseFraction() const {return minReleaseFraction_;}
/**
* Get the pointer to the DecayConstructor object
*/
tDecayConstructorPtr decayConstructor() const {
return decayConstructor_;
}
/**
* Option for on-shell particles
*/
unsigned int removeOnShell() const { return removeOnShell_; }
/**
* Check if a vertex is excluded
*/
bool excluded(VertexBasePtr vertex) const {
// skip an effective vertex
if( excludeEffective_ &&
int(vertex->orderInGs() + vertex->orderInGem()) != int(vertex->getNpoint())-2)
return true;
// check if explicitly forbidden
return excludedVerticesSet_.find(vertex)!=excludedVerticesSet_.end();
}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<NBodyDecayConstructorBase>
initNBodyDecayConstructorBase;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
NBodyDecayConstructorBase & operator=(const NBodyDecayConstructorBase &);
private:
/**
* Whether to initialize decayers or not
*/
bool init_;
/**
* Number of iterations if initializing (default 1)
*/
int iteration_;
/**
* Number of points to do in initialization
*/
int points_;
/**
* Whether to output information on the decayers
*/
bool info_;
/**
* Whether to create the DecayModes as well as the Decayer objects
*/
bool createModes_;
/**
* Whether or not to remove on-shell diagrams
*/
unsigned int removeOnShell_;
/**
* Excluded Vertices
*/
vector<VertexBasePtr> excludedVerticesVector_;
/**
* Excluded Vertices
*/
set<VertexBasePtr> excludedVerticesSet_;
/**
* Excluded Particles
*/
vector<PDPtr> excludedParticlesVector_;
/**
* Excluded Particles
*/
set<PDPtr> excludedParticlesSet_;
/**
* Whether or not to exclude effective vertices
*/
bool excludeEffective_;
/**
* A pointer to the DecayConstructor object
*/
tDecayConstructorPtr decayConstructor_;
/**
* The minimum energy release for a three-body decay as a
* fraction of the parent mass
*/
double minReleaseFraction_;
/**
* Maximum number of EW gauge bosons
*/
unsigned int maxBoson_;
/**
* Maximum number of particles from the decaying particle list
*/
unsigned int maxList_;
/**
* Include on-shell for \f$t\to b W\f$
*/
bool includeTopOnShell_;
};
/** An Exception class that can be used by all inheriting classes to
* indicate a setup problem. */
class NBodyDecayConstructorError : public Exception {
public:
NBodyDecayConstructorError() : Exception() {}
NBodyDecayConstructorError(const string & str,
Severity sev) : Exception(str,sev)
{}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of NBodyDecayConstructorBase. */
template <>
struct BaseClassTrait<Herwig::NBodyDecayConstructorBase,1> {
/** Typedef of the first base class of NBodyDecayConstructorBase. */
typedef Interfaced NthBase;
};
/** This template specialization informs ThePEG about the name of
* the NBodyDecayConstructorBase class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::NBodyDecayConstructorBase>
: public ClassTraitsBase<Herwig::NBodyDecayConstructorBase> {
/** Return a platform-independent class name */
static string className() { return "Herwig::NBodyDecayConstructorBase"; }
};
/** @endcond */
}
#endif /* HERWIG_NBodyDecayConstructorBase_H */
diff --git a/Models/General/TBDiagram.h b/Models/General/TBDiagram.h
--- a/Models/General/TBDiagram.h
+++ b/Models/General/TBDiagram.h
@@ -1,216 +1,212 @@
// -*- C++ -*-
//
// TBDiagram.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_TBDiagram_H
#define HERWIG_TBDiagram_H
//
// This is the declaration of the TBDiagram struct.
//
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "PrototypeVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
/** Pair of particle ids. */
typedef pair<long, long> IDPair;
/** Pair of bool's*/
typedef pair<bool, bool> BPair;
/** Convenient typedef of VertexBasePtr */
typedef VertexBasePtr VBPtr;
/** Pair of VertexBasePtrs */
typedef pair<VBPtr, VBPtr> VBPair;
/** Pair of int,double */
typedef pair<unsigned int, double> CFPair;
/**
* The TBDiagram struct contains information about a \f$1\to3\f$ decay that
* has been automatically generated by ThreeBodyDecayConstructor.
*/
struct TBDiagram {
/** Enumeration for channel type */
enum Channel {UNDEFINED = -1, channel23=0, channel13=1, channel12=2, fourPoint=3};
/** Standard Constructor */
TBDiagram()
: incoming(0), outgoing(0), outgoingPair(make_pair(0, 0)),
channelType(UNDEFINED), colourFlow(0), ids(4, 0)
{}
/** Constructor taking ids as arguments.*/
TBDiagram(long a, long b, IDPair c)
: incoming(a), outgoing(b), outgoingPair(c),
channelType(UNDEFINED), colourFlow(0), ids(4, 0) {
ids[0] = a;
ids[1] = b;
ids[2] = c.first;
ids[3] = c.second;
}
/** Incoming particle id's */
long incoming;
/** Outgoing particle from first vertex */
long outgoing;
/** Outgoing particle id's fropm resonance*/
IDPair outgoingPair;
/** ParticleData pointer to intermediate, null for 4-point vertices */
PDPtr intermediate;
/** The two vertices for the diagram */
VBPair vertices;
/** Enum of channel type */
Channel channelType;
/** 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;
/** Store the ids in a vector for easy use of comparison operator. */
vector<long> ids;
/**
* 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;
}
- /** Constructor from PrototypeVertex */
- TBDiagram(PrototypeVertexPtr vertex)
+ /** Constructor from NBDiagram */
+ TBDiagram(const NBDiagram & diagram)
: channelType(UNDEFINED),
- colourFlow (vector<CFPair>(1,make_pair(1,1.))),
- largeNcColourFlow(vector<CFPair>(1,make_pair(1,1.))), ids(4,0) {
- incoming = vertex->incoming->id();
- PrototypeVertexPtr child;
- if(vertex->outgoing.size()==2) {
- for(OrderedVertices::const_iterator it = vertex->outgoing.begin();
- it!=vertex->outgoing.end();++it) {
- if(it->second) child=it->second;
- else outgoing = it->first->id();
- }
+ colourFlow (diagram.colourFlow),
+ largeNcColourFlow(diagram.largeNcColourFlow), ids(4,0) {
+ incoming = diagram.incoming->id();
+ if(diagram.vertices.size()==2) {
+ const NBVertex & child = (++diagram.vertices.begin())->second;
+ outgoing = diagram.vertices.begin()->first->id();
unsigned int iloc=0;
- for(OrderedVertices::const_iterator it = child->outgoing.begin();
- it!=child->outgoing.end();++it) {
- if (iloc==0) outgoingPair.first = it->first->id();
- else if (iloc==1) outgoingPair.second = it->first->id();
+ for(OrderedParticles::const_iterator it = child.outgoing.begin();
+ it!=child.outgoing.end();++it) {
+ if (iloc==0) outgoingPair.first = (**it).id();
+ else if (iloc==1) outgoingPair.second = (**it).id();
++iloc;
}
- intermediate = child->incoming;
- vertices.second = child->vertex;
+ intermediate = child.incoming;
+ vertices.second = child.vertex;
}
else {
unsigned int iloc=0;
- for(OrderedVertices::const_iterator it = vertex->outgoing.begin();
- it!=vertex->outgoing.end();++it) {
- if(iloc==0) outgoing = it->first->id();
- else if (iloc==1) outgoingPair.first = it->first->id();
- else if (iloc==2) outgoingPair.second = it->first->id();
+ for(OrderedParticles::const_iterator it = diagram.outgoing.begin();
+ it!=diagram.outgoing.end();++it) {
+ if(iloc==0) outgoing = (**it).id();
+ else if (iloc==1) outgoingPair.first = (**it).id();
+ else if (iloc==2) outgoingPair.second = (**it).id();
++iloc;
}
}
- vertices.first = vertex->vertex;
+ vertices.first = diagram.vertex;
ids[0] = incoming;
ids[1] = outgoing;
ids[2] = outgoingPair.first;
ids[3] = outgoingPair.second;
}
};
/**
* Test whether two diagrams are identical.
*/
inline bool operator==(const TBDiagram & x, const TBDiagram & y) {
if( x.incoming != y.incoming) return false;
if( x.outgoing != y.outgoing) return false;
if( x.intermediate != y.intermediate) return false;
if( x.vertices != y.vertices ) return false;
if( (x.outgoingPair.first == y.outgoingPair.first &&
x.outgoingPair.second == y.outgoingPair.second ) ||
(x.outgoingPair.first == y.outgoingPair.second &&
x.outgoingPair.second == y.outgoingPair.first ) ) return true;
else return false;
}
/**
* Output to a stream
*/
inline ostream & operator<<(ostream & os, const TBDiagram & diag) {
os << diag.incoming << " -> ";
os << diag.outgoing << " + ( ";
if(diag.intermediate) os << diag.intermediate->id();
os << " ) -> ";
os << diag.outgoingPair.first << " " << diag.outgoingPair.second
<< " channel: " << diag.channelType << " ";
for(size_t cf = 0; cf < diag.colourFlow.size(); ++cf)
os << "(" << diag.colourFlow[cf].first << ","
<<diag.colourFlow[cf].second << ")";
os << '\n';
return os;
}
/**
* Output operator to allow the structure to be persistently written
* @param os The output stream
* @param x The TBDiagram
*/
inline PersistentOStream & operator<<(PersistentOStream & os,
const TBDiagram & x) {
os << x.incoming << x.outgoing << x.outgoingPair << x.intermediate
<< x.vertices << oenum(x.channelType) << x.colourFlow
<< x.largeNcColourFlow << x.ids;
return os;
}
/**
* Input operator to allow persistently written data to be read in
* @param is The input stream
* @param x The TBDiagram
*/
inline PersistentIStream & operator>>(PersistentIStream & is,
TBDiagram & x) {
is >> x.incoming >> x.outgoing >> x.outgoingPair >> x.intermediate
>> x.vertices >> ienum(x.channelType) >> x.colourFlow
>> x.largeNcColourFlow >> x.ids;
return is;
}
}
#endif /* HERWIG_TBDiagram_H */
diff --git a/Models/General/ThreeBodyDecayConstructor.cc b/Models/General/ThreeBodyDecayConstructor.cc
--- a/Models/General/ThreeBodyDecayConstructor.cc
+++ b/Models/General/ThreeBodyDecayConstructor.cc
@@ -1,288 +1,289 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ThreeBodyDecayConstructor class.
//
#include "ThreeBodyDecayConstructor.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "Herwig++/Decay/General/GeneralThreeBodyDecayer.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Utilities/Throw.h"
#include "DecayConstructor.h"
#include "WeakCurrentDecayConstructor.h"
using namespace Herwig;
IBPtr ThreeBodyDecayConstructor::clone() const {
return new_ptr(*this);
}
IBPtr ThreeBodyDecayConstructor::fullclone() const {
return new_ptr(*this);
}
void ThreeBodyDecayConstructor::persistentOutput(PersistentOStream & os) const {
os << interOpt_ << widthOpt_;
}
void ThreeBodyDecayConstructor::persistentInput(PersistentIStream & is, int) {
is >> interOpt_ >> widthOpt_;
}
ClassDescription<ThreeBodyDecayConstructor>
ThreeBodyDecayConstructor::initThreeBodyDecayConstructor;
// Definition of the static class description member.
void ThreeBodyDecayConstructor::Init() {
static ClassDocumentation<ThreeBodyDecayConstructor> documentation
("The ThreeBodyDecayConstructor class constructs the three body decay modes");
static Switch<ThreeBodyDecayConstructor,unsigned int> interfaceWidthOption
("WidthOption",
"Option for the treatment of the widths of the intermediates",
&ThreeBodyDecayConstructor::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<ThreeBodyDecayConstructor,unsigned int> interfaceIntermediateOption
("IntermediateOption",
"Option for the inclusion of intermediates in the event",
&ThreeBodyDecayConstructor::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 ThreeBodyDecayConstructor::DecayList(const set<PDPtr> & particles) {
if( particles.empty() ) return;
// special for weak decays
for(unsigned int ix=0;ix<decayConstructor()->decayConstructors().size();++ix) {
Ptr<Herwig::WeakCurrentDecayConstructor>::pointer
weak = dynamic_ptr_cast<Ptr<Herwig::WeakCurrentDecayConstructor>::pointer >
(decayConstructor()->decayConstructors()[ix]);
if(!weak) continue;
weakMassCut_ = max(weakMassCut_,weak->massCut());
}
NBodyDecayConstructorBase::DecayList(particles);
}
GeneralThreeBodyDecayerPtr ThreeBodyDecayConstructor::
-createDecayer(vector<TBDiagram> & diagrams, bool inter) const {
+createDecayer(vector<TBDiagram> & diagrams, bool inter,
+ double symfac) const {
if(diagrams.empty()) return GeneralThreeBodyDecayerPtr();
// extract the external particles for the process
PDPtr incoming = getParticleData(diagrams[0].incoming);
// outgoing particles
OrderedParticles outgoing;
outgoing.insert(getParticleData(diagrams[0].outgoing ));
outgoing.insert(getParticleData(diagrams[0].outgoingPair.first ));
outgoing.insert(getParticleData(diagrams[0].outgoingPair.second));
// sort out ordering and labeling of diagrams
vector<PDPtr> outVector(outgoing.begin(),outgoing.end());
for(unsigned int ix=0;ix<diagrams.size();++ix) {
unsigned int iy=0;
for(;iy<3;++iy)
if(diagrams[ix].outgoing == outVector[iy]->id()) break;
if(diagrams[ix].channelType == TBDiagram::UNDEFINED) {
diagrams[ix].channelType = TBDiagram::Channel(iy);
if( ( iy == 0 && outVector[1]->id() != diagrams[ix].outgoingPair.first)||
( iy == 1 && outVector[0]->id() != diagrams[ix].outgoingPair.first)||
( iy == 2 && outVector[0]->id() != diagrams[ix].outgoingPair.first) )
swap(diagrams[ix].outgoingPair.first, diagrams[ix].outgoingPair.second);
}
}
// get the object name
string objectname ("/Herwig/Decays/");
string classname = DecayerClassName(incoming, outgoing, objectname);
if(classname=="") return GeneralThreeBodyDecayerPtr();
// create the object
GeneralThreeBodyDecayerPtr decayer =
dynamic_ptr_cast<GeneralThreeBodyDecayerPtr>
(generator()->preinitCreate(classname, objectname));
// set up the decayer and return if doesn't work
- if(!decayer->setDecayInfo(incoming,outVector,diagrams))
+ if(!decayer->setDecayInfo(incoming,outVector,diagrams,symfac))
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;
}
string ThreeBodyDecayConstructor::
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(ns==1&&nf==2) classname += "StoSFFDecayer";
else if(nf==2&&nv==1) classname += "StoFFVDecayer";
else classname = "";
}
else if(incoming->iSpin()==PDT::Spin1Half) {
if(nf==3) classname += "FtoFFFDecayer";
else if(nf==1&&nv==2) classname += "FtoFVVDecayer";
else classname = "";
}
else if(incoming->iSpin()==PDT::Spin1) {
if(nf==2&&nv==1) classname += "VtoFFVDecayer";
else classname = "";
}
else {
classname="";
}
return classname;
}
void ThreeBodyDecayConstructor::
-createDecayMode(vector<PrototypeVertexPtr> & mode) {
+createDecayMode(vector<NBDiagram> & mode,
+ bool possibleOnShell,
+ double symfac) {
// convert the diagrams from the general to the three body structure
vector<TBDiagram> diagrams;
- bool possibleOnShell=false;
for(unsigned int iy=0;iy<mode.size();++iy) {
diagrams.push_back(TBDiagram(mode[iy]));
// remove weak processes simulated using the weak current
if(weakMassCut_>ZERO && diagrams.back().intermediate &&
abs(diagrams.back().intermediate->id())==ParticleID::Wplus) {
Energy deltaM =
getParticleData(diagrams.back().incoming)->mass() -
getParticleData(diagrams.back().outgoing)->mass();
if(deltaM<weakMassCut_) diagrams.pop_back();
}
- possibleOnShell |= mode[iy]->possibleOnShell;
}
if(diagrams.empty()) return;
// check if possible on-shell internal particles
bool inter = interOpt_ == 1 || (interOpt_ == 0 && possibleOnShell);
// incoming particle
tPDPtr inpart = getParticleData(diagrams[0].incoming);
// outgoing particles
OrderedParticles outgoing;
outgoing.insert(getParticleData(diagrams[0].outgoing));
outgoing.insert(getParticleData(diagrams[0].outgoingPair.first ));
outgoing.insert(getParticleData(diagrams[0].outgoingPair.second));
// incoming particle is now unstable
inpart->stable(false);
// construct the tag for the decay mode
string tag = inpart->name() + "->";
unsigned int iprod=0;
for(OrderedParticles::const_iterator it = outgoing.begin();
it != outgoing.end(); ++it) {
++iprod;
tag += (**it).name();
if(iprod != 3) tag += ",";
}
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;
}
// create mode if needed
if( createDecayModes() && (!dm || inpart->id() == ParticleID::h0) ) {
// create the decayer
- GeneralThreeBodyDecayerPtr decayer = createDecayer(diagrams,inter);
+ GeneralThreeBodyDecayerPtr decayer = createDecayer(diagrams,inter,symfac);
if(!decayer) {
if(Debug::level > 1 ) generator()->log() << "Can't create the decayer for "
<< tag << " so mode not created\n";
return;
}
tDMPtr ndm = generator()->preinitCreateDecayMode(tag);
if(ndm) {
generator()->preinitInterface(ndm, "Decayer", "set",
decayer->fullName());
generator()->preinitInterface(ndm, "OnOff", "set", "On");
OrderedParticles::const_iterator pit=outgoing.begin();
tPDPtr pa = *pit; ++pit;
tPDPtr pb = *pit; ++pit;
tPDPtr pc = *pit;
Energy width =
decayer->partialWidth(make_pair(inpart,inpart->mass()),
make_pair(pa,pa->mass()) ,
make_pair(pb,pb->mass()) ,
make_pair(pc,pc->mass()));
setBranchingRatio(ndm, width);
}
else
throw NBodyDecayConstructorError()
<< "ThreeBodyDecayConstructor::createDecayMode - Needed to create "
<< "new decaymode but one could not be created for the tag "
<< tag << Exception::warning;
}
else if( dm ) {
if((dm->decayer()->fullName()).find("Mambo") != string::npos) {
// create the decayer
- GeneralThreeBodyDecayerPtr decayer = createDecayer(diagrams,inter);
+ GeneralThreeBodyDecayerPtr decayer = createDecayer(diagrams,inter,symfac);
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();
}
diff --git a/Models/General/ThreeBodyDecayConstructor.h b/Models/General/ThreeBodyDecayConstructor.h
--- a/Models/General/ThreeBodyDecayConstructor.h
+++ b/Models/General/ThreeBodyDecayConstructor.h
@@ -1,181 +1,183 @@
// -*- C++ -*-
#ifndef HERWIG_ThreeBodyDecayConstructor_H
#define HERWIG_ThreeBodyDecayConstructor_H
//
// This is the declaration of the ThreeBodyDecayConstructor class.
//
#include "NBodyDecayConstructorBase.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "TBDiagram.h"
#include "PrototypeVertex.h"
#include "Herwig++/Decay/General/GeneralThreeBodyDecayer.fh"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
/**
* The ThreeBodyDecayConstructor class inherits from the dummy base class
* NBodyDecayConstructorBase and implements the necessary functions in
* order to create the 3 body decaymodes for a given set of vertices
* stored in a Model class.
*
* @see \ref ThreeBodyDecayConstructorInterfaces "The interfaces"
* defined for ThreeBodyDecayConstructor.
* @see NBodyDecayConstructor
*/
class ThreeBodyDecayConstructor: public NBodyDecayConstructorBase {
public:
/**
* The default constructor.
*/
ThreeBodyDecayConstructor() :
interOpt_(0), widthOpt_(1), weakMassCut_(-GeV) {}
/**
* Function used to determine allowed decaymodes, to be implemented
* in derived class.
*@param part vector of ParticleData pointers containing particles in model
*/
virtual void DecayList(const set<PDPtr> & part);
/**
* Number of outgoing lines. Required for correct ordering.
*/
virtual unsigned int numBodies() const { return 3; }
protected:
/**
* Create the decayer
* @param diagrams The diagrams for the decay
* @param inter Option for intermediates
*/
GeneralThreeBodyDecayerPtr createDecayer(vector<TBDiagram> & diagrams,
- bool inter) const;
+ bool inter,double symfac) 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;
/**
* Create the DecayMode from the diagrams
* @param diagrams The diagrams
* @param inter Option for intermediates
*/
- virtual void createDecayMode(vector<PrototypeVertexPtr> & mode);
+ virtual void createDecayMode(vector<NBDiagram> & mode,
+ bool possibleOnShell,
+ double symfac);
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<ThreeBodyDecayConstructor> initThreeBodyDecayConstructor;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ThreeBodyDecayConstructor & operator=(const ThreeBodyDecayConstructor &);
private:
/**
* Option for the inclusion of intermediates
*/
unsigned int interOpt_;
/**
* How to treat the widths of the intermediate particles
*/
unsigned int widthOpt_;
/**
* Cut off or decays via the weak current
*/
Energy weakMassCut_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of ThreeBodyDecayConstructor. */
template <>
struct BaseClassTrait<Herwig::ThreeBodyDecayConstructor,1> {
/** Typedef of the first base class of ThreeBodyDecayConstructor. */
typedef Herwig::NBodyDecayConstructorBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the ThreeBodyDecayConstructor class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::ThreeBodyDecayConstructor>
: public ClassTraitsBase<Herwig::ThreeBodyDecayConstructor> {
/** Return a platform-independent class name */
static string className() { return "Herwig::ThreeBodyDecayConstructor"; }
};
/** @endcond */
}
#endif /* HERWIG_ThreeBodyDecayConstructor_H */
diff --git a/Models/Susy/SusyBase.cc b/Models/Susy/SusyBase.cc
--- a/Models/Susy/SusyBase.cc
+++ b/Models/Susy/SusyBase.cc
@@ -1,912 +1,922 @@
// -*- C++ -*-
//
// SusyBase.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SusyBase class.
//
#include "SusyBase.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/PDT/MassGenerator.h"
#include "ThePEG/PDT/WidthGenerator.h"
#include "ThePEG/PDT/DecayMode.h"
using namespace Herwig;
SusyBase::SusyBase() : readFile_(false), topModesFromFile_(false),
tolerance_(1e-6), MPlanck_(2.4e18*GeV),
gravitino_(false),
tanBeta_(0), mu_(ZERO),
M1_(ZERO), M2_(ZERO), M3_(ZERO),
mH12_(ZERO),mH22_(ZERO),
meL_(ZERO),mmuL_(ZERO),mtauL_(ZERO),
meR_(ZERO),mmuR_(ZERO),mtauR_(ZERO),
mq1L_(ZERO),mq2L_(ZERO),mq3L_(ZERO),
mdR_(ZERO),muR_(ZERO),msR_(ZERO),
mcR_(ZERO),mbR_(ZERO),mtR_(ZERO),
gluinoPhase_(1.)
{}
IBPtr SusyBase::clone() const {
return new_ptr(*this);
}
IBPtr SusyBase::fullclone() const {
return new_ptr(*this);
}
void SusyBase::doinit() {
addVertex(WSFSFVertex_);
addVertex(NFSFVertex_);
addVertex(GFSFVertex_);
addVertex(HSFSFVertex_);
addVertex(CFSFVertex_);
addVertex(GSFSFVertex_);
addVertex(GGSQSQVertex_);
addVertex(GSGSGVertex_);
addVertex(NNZVertex_);
if(NNPVertex_) addVertex(NNPVertex_);
if(GNGVertex_) addVertex(GNGVertex_);
addVertex(CCZVertex_);
addVertex(CNWVertex_);
addVertex(GOGOHVertex_);
addVertex(WHHVertex_);
addVertex(NCTVertex_);
if(gravitino_) {
if(GVNHVertex_) addVertex(GVNHVertex_);
if(GVNVVertex_) addVertex(GVNVVertex_);
if(GVFSVertex_) addVertex(GVFSVertex_);
}
StandardModel::doinit();
}
void SusyBase::persistentOutput(PersistentOStream & os) const {
os << readFile_ << topModesFromFile_ << gravitino_
<< NMix_ << UMix_ << VMix_ << WSFSFVertex_
<< NFSFVertex_ << GFSFVertex_ << HSFSFVertex_ << CFSFVertex_
<< GSFSFVertex_ << GGSQSQVertex_ << GSGSGVertex_
<< NNZVertex_ << NNPVertex_ << CCZVertex_ << CNWVertex_
<< GOGOHVertex_ << WHHVertex_ << GNGVertex_ << NCTVertex_
<< GVNHVertex_ << GVNVVertex_ << GVFSVertex_
<< tanBeta_ << ounit(mu_,GeV)
<< ounit(M1_,GeV) << ounit(M2_,GeV) << ounit(M3_,GeV)
<< ounit(mH12_,GeV2) << ounit(mH22_,GeV2)
<< ounit(meL_,GeV) << ounit(mmuL_,GeV) << ounit(mtauL_,GeV)
<< ounit(meR_,GeV) << ounit(mmuR_,GeV) << ounit(mtauR_,GeV)
<< ounit(mq1L_,GeV) << ounit(mq2L_,GeV) << ounit(mq3L_,GeV)
<< ounit(mdR_,GeV) << ounit(muR_,GeV) << ounit(msR_,GeV)
<< ounit(mcR_,GeV) << ounit(mbR_,GeV) << ounit(mtR_,GeV)
<< gluinoPhase_ << tolerance_ << ounit(MPlanck_,GeV);
}
void SusyBase::persistentInput(PersistentIStream & is, int) {
is >> readFile_ >> topModesFromFile_ >> gravitino_
>> NMix_ >> UMix_ >> VMix_ >> WSFSFVertex_
>> NFSFVertex_ >> GFSFVertex_ >> HSFSFVertex_ >> CFSFVertex_
>> GSFSFVertex_ >> GGSQSQVertex_ >> GSGSGVertex_
>> NNZVertex_ >> NNPVertex_ >> CCZVertex_ >> CNWVertex_
>> GOGOHVertex_ >> WHHVertex_ >> GNGVertex_ >> NCTVertex_
>> GVNHVertex_ >> GVNVVertex_ >> GVFSVertex_
>> tanBeta_ >> iunit(mu_,GeV)
>> iunit(M1_,GeV) >> iunit(M2_,GeV) >> iunit(M3_,GeV)
>> iunit(mH12_,GeV2) >> iunit(mH22_,GeV2)
>> iunit(meL_,GeV) >> iunit(mmuL_,GeV) >> iunit(mtauL_,GeV)
>> iunit(meR_,GeV) >> iunit(mmuR_,GeV) >> iunit(mtauR_,GeV)
>> iunit(mq1L_,GeV) >> iunit(mq2L_,GeV) >> iunit(mq3L_,GeV)
>> iunit(mdR_,GeV) >> iunit(muR_,GeV) >> iunit(msR_,GeV)
>> iunit(mcR_,GeV) >> iunit(mbR_,GeV) >> iunit(mtR_,GeV)
>> gluinoPhase_ >> tolerance_ >> iunit(MPlanck_,GeV);
}
ClassDescription<SusyBase> SusyBase::initSusyBase;
// Definition of the static class description member.
void SusyBase::Init() {
static ClassDocumentation<SusyBase> documentation
("This is the base class for any SUSY model.",
"SUSY spectrum files follow the Les Houches accord"
" \\cite{Skands:2003cj,Allanach:2008qq}.",
" %\\cite{Skands:2003cj}\n"
"\\bibitem{Skands:2003cj}\n"
" P.~Skands {\\it et al.},\n"
" ``SUSY Les Houches accord: Interfacing SUSY spectrum calculators, decay\n"
" %packages, and event generators,''\n"
" JHEP {\\bf 0407}, 036 (2004)\n"
" [arXiv:hep-ph/0311123].\n"
" %%CITATION = JHEPA,0407,036;%%\n"
"%\\cite{Allanach:2008qq}\n"
"\\bibitem{Allanach:2008qq}\n"
" B.~Allanach {\\it et al.},\n"
" %``SUSY Les Houches Accord 2,''\n"
" Comput.\\ Phys.\\ Commun.\\ {\\bf 180}, 8 (2009)\n"
" [arXiv:0801.0045 [hep-ph]].\n"
" %%CITATION = CPHCB,180,8;%%\n"
);
static Switch<SusyBase,bool> interfaceTopModes
("TopModes",
"Whether ro use the Herwig++ SM top decays or those from the SLHA file",
&SusyBase::topModesFromFile_, false, false, false);
static SwitchOption interfaceTopModesFile
(interfaceTopModes,
"File",
"Take the modes from the files",
true);
static SwitchOption interfaceTopModesHerwig
(interfaceTopModes,
"Herwig",
"Use the SM ones",
false);
static Reference<SusyBase,Helicity::AbstractVSSVertex> interfaceVertexWSS
("Vertex/WSFSF",
"Reference to Susy W SF SF vertex",
&SusyBase::WSFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFSVertex> interfaceVertexNFSF
("Vertex/NFSF",
"Reference to the neutralino-fermion-sfermion vertex",
&SusyBase::NFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFSVertex> interfaceVertexGFSF
("Vertex/GFSF",
"Reference to the gluino-fermion-sfermion vertex",
&SusyBase::GFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractSSSVertex> interfaceVertexHSFSF
("Vertex/HSFSF",
"Reference to the Higgs-fermion-sfermion vertex",
&SusyBase::HSFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFSVertex> interfaceVertexCFSF
("Vertex/CFSF",
"Reference to the chargino-fermion-sfermion vertex",
&SusyBase::CFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractVSSVertex> interfaceVertexGSFSF
("Vertex/GSFSF",
"Reference to the gluon-sfermion-sfermion vertex",
&SusyBase::GSFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractVVSSVertex> interfaceVertexGGSS
("Vertex/GGSQSQ",
"Reference to the gluon-gluon-squark-squark vertex",
&SusyBase::GGSQSQVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexGSGSG
("Vertex/GSGSG",
"Reference to the gluon-gluino-gluino vertex",
&SusyBase::GSGSGVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexNNZ
("Vertex/NNZ",
"Reference to Z-~chi_i0-~chi_i0 vertex",
&SusyBase::NNZVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexNNP
("Vertex/NNP",
"Reference to photon-~chi_i0-~chi_i0 vertex",
&SusyBase::NNPVertex_, false, false, true, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexGNG
("Vertex/GNG",
"Reference to gluon-~chi_i0-gluino vertex",
&SusyBase::GNGVertex_, false, false, true, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexCCZ
("Vertex/CCZ",
"Reference to ~chi_i+-~chi_i-Z vertex",
&SusyBase::CCZVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexCNW
("Vertex/CNW",
"Reference to ~chi_i+-chi_i0-W vertex",
&SusyBase::CNWVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFSVertex> interfaceVertexGOGOH
("Vertex/GOGOH",
"Reference to the gaugino-gaugino-higgs vertex",
&SusyBase::GOGOHVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractVSSVertex> interfaceVertexWHH
("Vertex/SSWHH",
"Reference to Susy WHHVertex",
&SusyBase::WHHVertex_, false, false, true, false);
static Reference<SusyBase,AbstractFFSVertex> interfaceVertexNCT
("Vertex/NCT",
"Vertex for the flavour violating coupling of the top squark "
"to the neutralino and charm quark.",
&SusyBase::NCTVertex_, false, false, true, false, false);
static Reference<SusyBase,AbstractRFSVertex> interfaceVertexGVNH
("Vertex/GVNH",
"Vertex for the interfaction of the gravitino-neutralino"
" and Higgs bosons",
&SusyBase::GVNHVertex_, false, false, true, true, false);
static Reference<SusyBase,AbstractRFVVertex> interfaceVertexGVNV
("Vertex/GVNV",
"Vertex for the interfaction of the gravitino-neutralino"
" and vector bosons",
&SusyBase::GVNVVertex_, false, false, true, true, false);
static Reference<SusyBase,AbstractRFSVertex> interfaceVertexGVFS
("Vertex/GVFS",
"Vertex for the interfaction of the gravitino-fermion"
" and sfermion",
&SusyBase::GVFSVertex_, false, false, true, true, false);
static Parameter<SusyBase,double> interfaceBRTolerance
("BRTolerance",
"Tolerance for the sum of branching ratios to be difference from one.",
&SusyBase::tolerance_, 1e-6, 1e-8, 0.01,
false, false, Interface::limited);
static Parameter<SusyBase,Energy> interfaceMPlanck
("MPlanck",
"The Planck mass for GMSB models",
&SusyBase::MPlanck_, GeV, 2.4e18*GeV, 1.e16*GeV, 1.e20*GeV,
false, false, Interface::limited);
}
void SusyBase::readSetup(istream & is) {
string filename = dynamic_ptr_cast<istringstream*>(&is)->str();
if(readFile_)
throw SetupException()
<< "A second SLHA file " << filename << " has been opened."
<< "This is probably unintended and as it can cause crashes"
<< " and other unpredictable behaviour it is not allowed."
<< Exception::runerror;
CFileLineReader cfile;
cfile.open(filename);
if( !cfile ) throw SetupException()
<< "SusyBase::readSetup - An error occurred in opening the "
<< "spectrum file \"" << filename << "\". A SUSY model cannot be "
<< "run without this."
<< Exception::runerror;
useMe();
//Before reading the spectrum/decay files the SM higgs
//decay modes, mass and width generators need to be turned off.
PDPtr h0 = getParticleData(ParticleID::h0);
h0->widthGenerator(WidthGeneratorPtr());
h0->massGenerator(MassGenPtr());
h0->width(ZERO);
DecaySet::const_iterator dit = h0->decayModes().begin();
DecaySet::const_iterator dend = h0->decayModes().end();
for( ; dit != dend; ++dit ) {
const InterfaceBase * ifb =
BaseRepository::FindInterface(*dit, "BranchingRatio");
ifb->exec(**dit, "set", "0.0");
ifb = BaseRepository::FindInterface(*dit, "OnOff");
ifb->exec(**dit, "set", "Off");
}
// if taking the top modes from the file
// delete the SM stuff
if(topModesFromFile_) {
PDPtr top = getParticleData(ParticleID::t);
top->widthGenerator(WidthGeneratorPtr());
top->massGenerator(MassGenPtr());
DecaySet::const_iterator dit = top->decayModes().begin();
DecaySet::const_iterator dend = top->decayModes().end();
for( ; dit != dend; ++dit ) {
const InterfaceBase * ifb =
BaseRepository::FindInterface(*dit, "BranchingRatio");
ifb->exec(**dit, "set", "0.0");
ifb = BaseRepository::FindInterface(*dit, "OnOff");
ifb->exec(**dit, "set", "Off");
}
}
// read first line and check if this is a Les Houches event file
cfile.readline();
bool lesHouches = cfile.find("<LesHouchesEvents");
bool reading = !lesHouches;
if(lesHouches) cfile.readline();
//function pointer for putting all characters to lower case.
int (*pf)(int) = tolower;
do {
string line = cfile.getline();
// check for start of slha block in SLHA files
if(lesHouches && !reading) {
if(line.find("<slha")==0) reading = true;
if(!cfile.readline()) break;
continue;
}
// ignore comment lines
if(line[0] == '#') {
if(!cfile.readline()) break;
continue;
}
// make everything lower case
transform(line.begin(), line.end(), line.begin(), pf);
// start of a block
if(line.find("block") == 0) {
string name = StringUtils::car(StringUtils::cdr(line), " #");
name = StringUtils::stripws(name);
// mixing matrix
if((name.find("mix") != string::npos &&
name.find("hmix") != 0)) {
unsigned int row(0),col(0);
MixingVector vals = readMatrix(cfile,row,col);
mixings_[name] = make_pair(make_pair(row,col),vals);
}
else if(name.find("au") == 0 || name.find("ad") == 0 ||
name.find("ae") == 0 ) {
string test = StringUtils::car(line, "#");
while (test.find("=")!= string::npos) {
test = StringUtils::cdr(test, "=");
}
istringstream is(test);
double scale;
is >> scale;
unsigned int row(0),col(0);
MixingVector vals = readMatrix(cfile,row,col);
if(scale>1e10) continue;
mixings_[name] = make_pair(make_pair(row,col),vals);
}
else if( name.find("info") == string::npos) {
readBlock(cfile,name,line);
}
else {
if(!cfile.readline()) break;
}
continue;
}
// decays
else if( line.find("decay") == 0 ) {
readDecay(cfile, line);
continue;
}
else if( lesHouches && line.find("</slha") == 0 ) {
reading = false;
break;
}
if(!cfile.readline()) break;
}
while(true);
// extract the relevant parameters
extractParameters();
// create the mixing matrices we need
createMixingMatrices();
// set the masses, this has to be done after the
// mixing matrices have been created
resetRepositoryMasses();
// have now read the file
readFile_=true;
}
void SusyBase::readBlock(CFileLineReader & cfile,string name,string linein) {
if(!cfile)
throw SetupException()
<< "SusyBase::readBlock() - The input stream is in a bad state"
<< Exception::runerror;
// storage or the parameters
string test = StringUtils::car(linein, "#");
ParamMap store;
bool set = true;
// special for the alpha block
if(name.find("alpha") == 0 ) {
double alpha;
cfile.readline();
string line = cfile.getline();
istringstream iss(line);
iss >> alpha;
store.insert(make_pair(1,alpha));
}
else {
// extract the scale from the block if present
if(test.find("=")!= string::npos) {
while(test.find("=")!=string::npos)
test= StringUtils::cdr(test,"=");
istringstream is(test);
double scale;
is >> scale;
// only store the lowest scale block
if(parameters_.find(name)!=parameters_.end()) {
set = scale < parameters_[name][-1];
}
else {
store.insert(make_pair(-1,scale));
}
}
while(cfile.readline()) {
string line = cfile.getline();
// skip comments
if(line[0] == '#') continue;
// reached the end
if( line[0] == 'B' || line[0] == 'b' ||
line[0] == 'D' || line[0] == 'd' ||
line[0] == '<' ) {
cfile.resetline();
break;
}
istringstream is(line);
long index;
double value;
if(name.find("rvlam")!= string::npos||
name=="rvt" || name=="rvtp" || name=="rvtpp") {
int i,j,k;
is >> i >> j >> k >> value;
index = i*100+j*10+k;
}
else {
is >> index >> value;
}
store.insert(make_pair(index, value));
}
}
if(set) parameters_[name]=store;
}
void SusyBase::readDecay(CFileLineReader & cfile,
string decay) const{
map<string,ParamMap>::const_iterator fit=parameters_.find("mass");
if(fit==parameters_.end())
throw Exception() << "SusyBase::readDecay() "
<< "BLOCK MASS not found in input file"
<< "it must be before the decays so the kinematics can be checked"
<< Exception::runerror;
ParamMap theMasses = fit->second;
if(!cfile)
throw SetupException()
<<"SusyBase::readDecay - The input stream is in a bad state";
// extract parent PDG code and width
long parent(0);
Energy width(ZERO);
istringstream iss(decay);
string dummy;
iss >> dummy >> parent >> iunit(width, GeV);
PDPtr inpart = getParticleData(parent);
if(!topModesFromFile_&&abs(parent)==ParticleID::t) {
cfile.readline();
return;
}
if(!inpart) throw SetupException()
<< "SusyBase::readDecay() - "
<< "A ParticleData object with the PDG code "
<< parent << " does not exist. "
<< Exception::runerror;
inpart->width(width);
if( width > ZERO ) inpart->cTau(hbarc/width);
inpart->widthCut(5.*width);
ParamMap::iterator it = theMasses.find(abs(inpart->id()));
Energy inMass = it!=theMasses.end() ? abs(it->second*GeV) : inpart->mass();
string prefix("decaymode " + inpart->name() + "->");
double brsum(0.);
unsigned int nmode = 0;
while(cfile.readline()) {
string line = cfile.getline();
// skip comments
if(line[0] == '#') continue;
// reached the end
if( line[0] == 'B' || line[0] == 'b' ||
line[0] == 'D' || line[0] == 'd' ||
line[0] == '<' ) {
cfile.resetline();
break;
}
// read the mode
// get the branching ratio and no of decay products
istringstream is(line);
double brat(0.);
unsigned int nda(0),npr(0);
is >> brat >> nda;
vector<tcPDPtr> products,bosons;
Energy mout(ZERO),moutnoWZ(ZERO);
string tag = prefix;
while( true ) {
long t;
is >> t;
if( is.fail() ) break;
if( t == abs(parent) ) {
throw SetupException()
<< "An error occurred while read a decay of the "
<< inpart->PDGName() << ". One of its products has the same PDG code "
<< "as the parent particle. Please check the SLHA file.\n"
<< Exception::runerror;
}
tcPDPtr p = getParticleData(t);
if( !p ) {
throw SetupException()
<< "SusyBase::readDecay() - An unknown PDG code has been encounterd "
<< "while reading a decay mode. ID: " << t
<< Exception::runerror;
}
++npr;
tag += p->name() + ",";
ParamMap::iterator it = theMasses.find(abs(p->id()));
Energy mass = it!=theMasses.end() ? abs(it->second*GeV) : p->mass();
mout += mass;
if(abs(p->id())==ParticleID::Wplus||p->id()==ParticleID::Z0) {
bosons.push_back(p);
}
else {
products.push_back(p);
moutnoWZ += mass;
}
}
if( npr != nda ) {
throw SetupException()
<< "SusyBase::readDecay - While reading a decay of the "
<< inpart->PDGName() << " from an SLHA file, an inconsistency "
<< "between the number of decay products and the value in "
<< "the 'NDA' column was found. Please check if the spectrum "
<< "file is correct.\n"
<< Exception::warning;
}
if( npr > 1 ) {
tag.replace(tag.size() - 1, 1, ";");
// normal option
if(mout<=inMass) {
inpart->stable(false);
brsum += brat;
createDecayMode(tag, brat);
}
// no possible off-shell gauge bosons throw it away
else if(bosons.empty() || bosons.size()>2 ||
moutnoWZ>=inMass) {
cerr << "SusyBase::readDecay() "
<< "The decay " << tag << " cannot proceed for on-shell "
<< "particles, skipping it.\n";
}
else {
Energy maxMass = inMass - moutnoWZ;
string newTag = prefix;
for(unsigned int ix=0;ix<products.size();++ix)
newTag += products[ix]->name() + ",";
if(bosons.size()==1) {
cerr << "SusyBase::readDecay() "
<< "The decay " << tag << " cannot proceed for on-shell\n"
<< "particles, replacing gauge boson with its decay products\n";
vector<pair<double,string> > modes =
createWZDecayModes(newTag,brat,bosons[0],maxMass);
for(unsigned int ix=0;ix<modes.size();++ix) {
modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
createDecayMode(modes[ix].second,modes[ix].first);
brsum += modes[ix].first;
}
}
else if(bosons.size()==2) {
bool identical = bosons[0]->id()==bosons[1]->id();
if(maxMass>bosons[0]->mass()&&maxMass>bosons[1]->mass()) {
cerr << "SusyBase::readDecay() "
<< "The decay " << tag << " cannot proceed for on-shell\n"
<< "particles, replacing one of the gauge bosons"
<< " with its decay products\n";
unsigned int imax = identical ? 1 : 2;
if(imax==2) brat *= 0.5;
for(unsigned int ix=0;ix<imax;++ix) {
string newTag2 = newTag+bosons[ix]->name()+',';
vector<pair<double,string> > modes =
createWZDecayModes(newTag2,brat,bosons[ix],maxMass);
for(unsigned int ix=0;ix<modes.size();++ix) {
modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
createDecayMode(modes[ix].second,modes[ix].first);
brsum += modes[ix].first;
}
}
}
else {
cerr << "SusyBase::readDecay() "
<< "The decay " << tag << " cannot proceed for on-shell\n"
<< "particles, and has too many off-shell gauge bosons,"
<< " skipping it.\n";
}
}
else {
cerr << "SusyBase::readDecay() "
<< "The decay " << tag << " cannot proceed for on-shell\n"
<< "particles, and has too many outgoing gauge bosons skipping it.\n";
}
}
}
}
if( abs(brsum - 1.) > tolerance_ && nmode!=0 ) {
cerr << "Warning: The total branching ratio for " << inpart->PDGName()
<< " from the spectrum file does not sum to 1. The branching fractions"
<< " will be rescaled.\n";
cerr << setprecision(13) << abs(brsum - 1.) << "\n";
}
}
const MixingVector
SusyBase::readMatrix(CFileLineReader & cfile,
unsigned int & row, unsigned int & col) {
if(!cfile)
throw SetupException()
<< "SusyBase::readMatrix() - The input stream is in a bad state."
<< Exception::runerror;
unsigned int rowmax(0), colmax(0);
MixingVector values;
while(cfile.readline()) {
string line = cfile.getline();
// skip comments
if(line[0] == '#') continue;
// reached the end
if( line[0] == 'B' || line[0] == 'b' ||
line[0] == 'D' || line[0] == 'd' ||
line[0] == '<' ) {
cfile.resetline();
break;
}
istringstream is(line);
unsigned int index1, index2;
double real(0.), imag(0.);
is >> index1 >> index2 >> real >> imag;
values.push_back(MixingElement(index1,index2,Complex(real, imag)));
if(index1 > rowmax) rowmax = index1;
if(index2 > colmax) colmax = index2;
}
col=colmax;
row=rowmax;
return values;
}
void SusyBase::createDecayMode(string tag, double brat) const {
ostringstream cmd;
cmd << tag << string(" ")
<< setprecision(13) << brat << string(" 1 /Herwig/Decays/Mambo");
Repository::exec(cmd.str(), cerr);
}
void SusyBase::createMixingMatrix(MixingMatrixPtr & matrix,
string name, const MixingVector & values,
MatrixSize size) {
matrix = new_ptr(MixingMatrix(size.first,size.second));
for(unsigned int ix=0; ix < values.size(); ++ix)
(*matrix)(values[ix].row-1,values[ix].col-1) = values[ix].value;
if(name == "nmix") {
vector<long> ids(4);
ids[0] = 1000022; ids[1] = 1000023;
ids[2] = 1000025; ids[3] = 1000035;
matrix->setIds(ids);
}
else if(name == "nmnmix") {
vector<long> ids(5);
ids[0] = 1000022; ids[1] = 1000023;
ids[2] = 1000025; ids[3] = 1000035;
ids[4] = 1000045;
matrix->setIds(ids);
}
else if(name == "umix") {
vector<long> ids(2);
ids[0] = 1000024; ids[1] = 1000037;
matrix->setIds(ids);
}
else if(name == "vmix") {
vector<long> ids(2);
ids[0] = 1000024; ids[1] = 1000037;
matrix->setIds(ids);
}
else if(name == "stopmix") {
vector<long> ids(2);
ids[0] = 1000006; ids[1] = 2000006;
matrix->setIds(ids);
}
else if(name == "sbotmix") {
vector<long> ids(2);
ids[0] = 1000005; ids[1] = 2000005;
matrix->setIds(ids);
}
else if(name == "staumix") {
vector<long> ids(2);
ids[0] = 1000015; ids[1] = 2000015;
matrix->setIds(ids);
}
else if(name == "nmhmix") {
vector<long> ids(3);
ids[0] = 25; ids[1] = 35; ids[2] = 45;
matrix->setIds(ids);
}
else if(name == "nmamix") {
vector<long> ids(2);
ids[0] = 36; ids[1] = 46;
matrix->setIds(ids);
}
else
throw SetupException() << "Cannot find correct title for mixing matrix "
<< name << Exception::runerror;
}
void SusyBase::resetRepositoryMasses() {
map<string,ParamMap>::const_iterator fit=parameters_.find("mass");
if(fit==parameters_.end())
throw Exception() << "BLOCK MASS not found in input file"
<< " can't set masses of SUSY particles"
<< Exception::runerror;
ParamMap theMasses = fit->second;
for(ParamMap::iterator it = theMasses.begin(); it != theMasses.end();
++it) {
long id = it->first;
double mass = it->second;
//a negative mass requires an adjustment to the
//associated mixing matrix by a factor of i
if(mass < 0.0) adjustMixingMatrix(id);
PDPtr part = getParticleData(id);
if(!part) throw SetupException()
<< "SusyBase::resetRepositoryMasses() - Particle with PDG code " << id
<< " not found." << Exception::warning;
//Find interface nominal mass interface
const InterfaceBase * ifb = BaseRepository::FindInterface(part, "NominalMass");
ostringstream os;
os << abs(it->second);
ifb->exec(*part, "set", os.str());
// switch on gravitino interactions?
gravitino_ |= id== ParticleID::SUSY_Gravitino;
}
theMasses.clear();
}
void SusyBase::adjustMixingMatrix(long id) {
//get correct mixing matrix
switch(id) {
case 1000021 :
gluinoPhase_ = Complex(0.,1.);
break;
case 1000022 :
case 1000023 :
case 1000025 :
case 1000035 :
case 1000045 :
if(NMix_)
NMix_->adjustPhase(id);
else
throw SetupException() << "SusyBase::adjustMixingMatrix - "
<< "The neutralino mixing matrix pointer "
<< "is null!" << Exception::runerror;
break;
case 1000024 :
case 1000037 :
if(UMix_)
UMix_->adjustPhase(id);
else
throw SetupException() << "SusyBase::adjustMixingMatrix - "
<< "The U-Type chargino mixing matrix pointer "
<< "is null!" << Exception::runerror;
if(VMix_)
VMix_->adjustPhase(id);
else
throw SetupException() << "SusyBase::adjustMixingMatrix - "
<< "The V-Type chargino mixing matrix pointer "
<< "is null!" << Exception::runerror;
break;
default :
throw SetupException()
<< "SusyBase::adjustMixingMatrix - Trying to adjust mixing matrix "
<< "phase for a particle that does not have a mixing matrix "
<< "associated with it. " << id << " must have a negative mass in "
<< "the spectrum file, this should only occur for particles that mix."
<< Exception::runerror;
}
}
void SusyBase::createMixingMatrices() {
map<string,pair<MatrixSize, MixingVector > >::const_iterator it;
for(it=mixings_.begin();it!=mixings_.end();++it) {
string name=it->first;
// create the gaugino mixing matrices
if(name == "nmix" || name == "nmnmix" ){
createMixingMatrix(NMix_,name,it->second.second,it->second.first);
}
else if (name == "umix" ) {
createMixingMatrix(UMix_,name,it->second.second,it->second.first);
}
else if (name == "vmix") {
createMixingMatrix(VMix_,name,it->second.second,it->second.first);
}
}
}
void SusyBase::extractParameters(bool checkmodel) {
map<string,ParamMap>::const_iterator pit;
ParamMap::const_iterator it;
// try and get tan beta from extpar first
pit=parameters_.find("extpar");
// extract tan beta
tanBeta_ = -1.;
- if(pit!=parameters_.end()) {
- it = pit->second.find(25);
- if(it!=pit->second.end()) tanBeta_ = it->second;
+ if(tanBeta_<0.) {
+ pit=parameters_.find("hmix");
+ if(pit!=parameters_.end()) {
+ it = pit->second.find(2);
+ if(it!=pit->second.end()) tanBeta_ = it->second;
+ }
+ }
+ if(tanBeta_<0.) {
+ pit=parameters_.find("extpar");
+ if(pit!=parameters_.end()) {
+ it = pit->second.find(25);
+ if(it!=pit->second.end()) tanBeta_ = it->second;
+ }
}
// otherwise from minpar
if(tanBeta_<0.) {
pit=parameters_.find("minpar");
if(pit!=parameters_.end()) {
it = pit->second.find(3);
if(it!=pit->second.end()) tanBeta_ = it->second;
}
}
if(tanBeta_<0.)
throw Exception() << "SusyBase::extractParameters() "
<< "Can't find tan beta in BLOCK MINPAR"
<< " or BLOCK EXTPAR " << Exception::runerror;
// extract parameters from hmix
pit=parameters_.find("hmix");
if(pit==parameters_.end()) {
if(generator())
generator()->logWarning(Exception("SusyBase::extractParameters() BLOCK HMIX not found setting mu to zero\n",
Exception::warning));
else
cerr << "SusyBase::extractParameters() BLOCK HMIX not found setting mu to zero\n";
mu_=ZERO;
}
else {
mu_=findValue(pit,1,"HMIX","mu")*GeV;
}
pit = parameters_.find("msoft");
if( pit == parameters_.end() )
throw Exception() << "SusyBase::extractParameters() "
<< "BLOCK MSOFT not found in "
<< "SusyBase::extractParameters()"
<< Exception::runerror;
M1_ = findValue(pit,1 ,"MSOFT","M_1" )*GeV;
M2_ = findValue(pit,2 ,"MSOFT","M_2" )*GeV;
M3_ = findValue(pit,3 ,"MSOFT","M_3" )*GeV;
mH12_ = findValue(pit,21,"MSOFT","m_H1^2")*GeV2;
mH22_ = findValue(pit,22,"MSOFT","m_H2^2")*GeV2;
meL_ = findValue(pit,31,"MSOFT","M_eL" )*GeV;
mmuL_ = findValue(pit,32,"MSOFT","M_muL" )*GeV;
mtauL_ = findValue(pit,33,"MSOFT","M_tauL")*GeV;
meR_ = findValue(pit,34,"MSOFT","M_eR" )*GeV;
mmuR_ = findValue(pit,35,"MSOFT","M_muR" )*GeV;
mtauR_ = findValue(pit,36,"MSOFT","M_tauR")*GeV;
mq1L_ = findValue(pit,41,"MSOFT","M_q1L" )*GeV;
mq2L_ = findValue(pit,42,"MSOFT","M_q2L" )*GeV;
mq3L_ = findValue(pit,43,"MSOFT","M_q3L" )*GeV;
muR_ = findValue(pit,44,"MSOFT","M_uR" )*GeV;
mcR_ = findValue(pit,45,"MSOFT","M_cR" )*GeV;
mtR_ = findValue(pit,46,"MSOFT","M_tR" )*GeV;
mdR_ = findValue(pit,47,"MSOFT","M_dR" )*GeV;
msR_ = findValue(pit,48,"MSOFT","M_sR" )*GeV;
mbR_ = findValue(pit,49,"MSOFT","M_bR" )*GeV;
if(checkmodel) {
throw Exception() << "The SusyBase class should not be used as a "
<< "Model class, use one of the models which inherit"
<< " from it" << Exception::runerror;
}
}
vector<pair<double,string> >
SusyBase::createWZDecayModes(string tag, double brat,
tcPDPtr boson, Energy maxMass) const {
vector<pair<double,string> > modes;
double sum(0.);
for(DecaySet::const_iterator dit=boson->decayModes().begin();
dit!=boson->decayModes().end();++dit) {
tcDMPtr mode = *dit;
if(!mode->on()) continue;
string extra;
Energy outMass(ZERO);
for(ParticleMSet::const_iterator pit=mode->products().begin();
pit!=mode->products().end();++pit) {
extra += (**pit).name() + ",";
outMass += (**pit).mass();
}
if(outMass<maxMass) {
sum += mode->brat();
modes.push_back(make_pair(mode->brat(),tag+extra));
}
}
for(unsigned int ix=0;ix<modes.size();++ix)
modes[ix].first *= brat/sum;
return modes;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 7:49 PM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805923
Default Alt Text
(147 KB)
Attached To
rHERWIGHG herwighg
Event Timeline
Log In to Comment