Page MenuHomeHEPForge

No OneTemporary

diff --git a/Handlers/StandardXComb.cc b/Handlers/StandardXComb.cc
--- a/Handlers/StandardXComb.cc
+++ b/Handlers/StandardXComb.cc
@@ -1,701 +1,798 @@
// -*- C++ -*-
//
// StandardXComb.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
// Copyright (C) 2009-2011 Simon Platzer
//
// ThePEG 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 StandardXComb class.
//
#include "StandardXComb.h"
#include "StdXCombGroup.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Handlers/SubProcessHandler.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/Maths.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/SubProcessGroup.h"
#include "ThePEG/Vectors/LorentzRotation.h"
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/MatrixElement/ColourLines.h"
#include "ThePEG/Handlers/LuminosityFunction.h"
#include "ThePEG/Handlers/CascadeHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/EventRecord/TmpTransform.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
#include "StandardXComb.tcc"
#endif
using namespace ThePEG;
StandardXComb::StandardXComb()
: XComb(), isMirror(false), theNDim(0),
partonDims(make_pair(0, 0)), theKinematicsGenerated(false),
theLastDiagramIndex(0), theLastPDFWeight(0.0),
theLastCrossSection(ZERO), theLastJacobian(1.0), theLastME2(-1.0), theLastPreweight(1.0),
theLastMECrossSection(ZERO), theLastMEPDFWeight(1.0), theLastMECouplings(1.0),
- checkedCuts(false), passedCuts(false), theCutWeight(1.0) {}
+ checkedCuts(false), passedCuts(false), theCutWeight(1.0), theNeedsReshuffling(false) {}
StandardXComb::
StandardXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler, tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts,
tMEPtr newME, const DiagramVector & newDiagrams, bool mir,
tStdXCombPtr newHead)
: XComb(newMaxEnergy, inc, newEventHandler,
newExtractor, newCKKW, newPartonBins, newCuts),
theSubProcessHandler(newSubProcessHandler), theME(newME),
- theDiagrams(newDiagrams), isMirror(mir), theKinematicsGenerated(false),
- theLastDiagramIndex(0), theLastPDFWeight(0.0),
- theLastCrossSection(ZERO), theLastME2(-1.0), theLastPreweight(1.0), theLastMECrossSection(ZERO),
+ theDiagrams(newDiagrams), isMirror(mir), theNDim(0), partonDims(0,0),
+ theKinematicsGenerated(false), theLastDiagramIndex(0), theLastPDFWeight(0.0),
+ theLastCrossSection(ZERO), theLastJacobian(0.0), theLastME2(-1.0),
+ theLastPreweight(1.0), theLastMECrossSection(ZERO),
theLastMEPDFWeight(1.0), theLastMECouplings(1.0), theHead(newHead),
- checkedCuts(false), passedCuts(false) {
+ checkedCuts(false), passedCuts(false), theCutWeight(1.0), theNeedsReshuffling(false) {
partonDims = pExtractor()->nDims(partonBins());
if ( matrixElement()->haveX1X2() ) {
partonDims.first = 0;
partonDims.second = 0;
}
theNDim = matrixElement()->nDim() + partonDims.first + partonDims.second;
mePartonData() = lastDiagram()->partons();
+ checkReshufflingNeeds();
}
StandardXComb::StandardXComb(tMEPtr me, const tPVector & parts,
DiagramIndex indx)
: theME(me), isMirror(false), theNDim(0), partonDims(make_pair(0, 0)),
theKinematicsGenerated(false),
theLastDiagramIndex(0), theLastPDFWeight(0.0), theLastCrossSection(ZERO),
theLastME2(-1.0), theLastPreweight(1.0), theLastMECrossSection(ZERO), theLastMEPDFWeight(1.0),
theLastMECouplings(1.0),
- checkedCuts(false), passedCuts(false) {
+ checkedCuts(false), passedCuts(false), theCutWeight(1.0), theNeedsReshuffling(false) {
subProcess(new_ptr(SubProcess(make_pair(parts[0], parts[1]),
tCollPtr(), me)));
for ( int i = 0, N = parts.size(); i < N; ++i ) {
subProcess()->addOutgoing(parts[i], false);
theMEPartonData.push_back(parts[i]->dataPtr());
theMEMomenta.push_back(parts[i]->momentum());
}
lastSHat((meMomenta()[0] + meMomenta()[1]).m2());
string tag = me->diagrams()[indx]->getTag();
for ( int i = 0, N = me->diagrams().size(); i < N; ++i )
if ( me->diagrams()[i]->getTag() == tag )
theDiagrams.push_back(me->diagrams()[i]);
+ checkReshufflingNeeds();
}
StandardXComb::StandardXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins, tMEPtr newME,
const DiagramVector & newDiagrams)
: XComb(newHead->maxEnergy(), newHead->particles(),
newHead->eventHandlerPtr(), newHead->pExtractor(),
newHead->CKKWHandler(), newPartonBins, newHead->cuts()),
theSubProcessHandler(const_ptr_cast<tSubHdlPtr>(newHead->subProcessHandler())),
- theME(newME), theDiagrams(newDiagrams), isMirror(newHead->mirror()),
- theKinematicsGenerated(false), theLastDiagramIndex(0), theLastPDFWeight(0.0),
- theLastCrossSection(ZERO), theLastME2(-1.0), theLastPreweight(1.0), theLastMECrossSection(ZERO),
+ theME(newME), theDiagrams(newDiagrams), isMirror(newHead->mirror()), theNDim(0),
+ partonDims(0,0), theKinematicsGenerated(false), theLastDiagramIndex(0), theLastPDFWeight(0.0),
+ theLastCrossSection(ZERO), theLastJacobian(0.0), theLastME2(-1.0),
+ theLastPreweight(1.0), theLastMECrossSection(ZERO),
theLastMEPDFWeight(1.0), theLastMECouplings(1.0), theHead(newHead),
- checkedCuts(false), passedCuts(false) {
+ checkedCuts(false), passedCuts(false), theCutWeight(1.0), theNeedsReshuffling(false) {
partonDims = pExtractor()->nDims(partonBins());
if ( matrixElement()->haveX1X2() ) {
partonDims.first = 0;
partonDims.second = 0;
}
theNDim = matrixElement()->nDim() + partonDims.first + partonDims.second;
mePartonData() = lastDiagram()->partons();
+ checkReshufflingNeeds();
/* // wait for C++11
StandardXComb(newHead->maxEnergy(),newHead->particles(),
newHead->eventHandlerPtr(),
const_ptr_cast<tSubHdlPtr>(newHead->subProcessHandler()),
newHead->pExtractor(),newHead->CKKWHandler(),
newPartonBins,newHead->cuts(),newME,newDiagrams,newHead->mirror(),
newHead);
*/
}
StandardXComb::~StandardXComb() {}
void StandardXComb::recreatePartonBinInstances(Energy2 scale) {
PBIPair newBins;
Direction<0> dir(true);
newBins.first =
new_ptr(PartonBinInstance(lastPartons().first,partonBins().first,scale));
dir.reverse();
newBins.second =
new_ptr(PartonBinInstance(lastPartons().second,partonBins().second,scale));
resetPartonBinInstances(newBins);
setPartonBinInfo();
lastPartons().first->scale(partonBinInstances().first->scale());
lastPartons().second->scale(partonBinInstances().second->scale());
}
void StandardXComb::refillPartonBinInstances(const double* r) {
pExtractor()->select(this);
pExtractor()->updatePartonBinInstances(partonBinInstances());
pExtractor()->generateSHat(lastS(), partonBinInstances(),
r, r + nDim() - partonDims.second,true);
}
void StandardXComb::setIncomingPartons(tStdXCombPtr labHead) {
if ( lastPartons().first )
return;
if ( !labHead )
labHead = head();
createPartonBinInstances();
lastParticles(labHead->lastParticles());
setPartonBinInfo();
lastPartons(make_pair(mePartonData()[0]->produceParticle(Lorentz5Momentum()),
mePartonData()[1]->produceParticle(Lorentz5Momentum())));
Lorentz5Momentum pFirst = meMomenta()[0];
Lorentz5Momentum pSecond = meMomenta()[1];
if ( labHead->matrixElement()->wantCMS() ) {
Boost toLab = (labHead->lastPartons().first->momentum() +
labHead->lastPartons().second->momentum()).boostVector();
if ( toLab.mag2() > Constants::epsilon ) {
pFirst.boost(toLab);
pSecond.boost(toLab);
}
}
lastPartons().first->set5Momentum(pFirst);
lastPartons().second->set5Momentum(pSecond);
partonBinInstances().first->parton(lastPartons().first);
partonBinInstances().second->parton(lastPartons().second);
lastS((lastParticles().first->momentum() +
lastParticles().second->momentum()).m2());
lastSHat((lastPartons().first->momentum() +
lastPartons().second->momentum()).m2());
lastP1P2(make_pair(labHead->lastP1(),labHead->lastP2()));
double x1 =
lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus();
double x2 =
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus();
lastX1X2(make_pair(x1,x2));
lastY((lastPartons().first->momentum()+
lastPartons().second->momentum()).rapidity());
}
void StandardXComb::fill(const PPair& newParticles,
const PPair& newPartons,
const vector<Lorentz5Momentum>& newMEMomenta,
const DVector& newLastRandomNumbers) {
lastParticles(newParticles);
lastP1P2(make_pair(0.0, 0.0));
lastS((lastParticles().first->momentum() +
lastParticles().second->momentum()).m2());
lastPartons(newPartons);
lastSHat((lastPartons().first->momentum() +
lastPartons().second->momentum()).m2());
lastX1X2(make_pair(lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus(),
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus()));
lastY((lastPartons().first->momentum() +
lastPartons().second->momentum()).rapidity());
meMomenta().resize(newMEMomenta.size());
copy(newMEMomenta.begin(),newMEMomenta.end(),
meMomenta().begin());
lastRandomNumbers().resize(newLastRandomNumbers.size());
copy(newLastRandomNumbers.begin(),newLastRandomNumbers.end(),
lastRandomNumbers().begin());
}
bool StandardXComb::checkInit() {
Energy summin = ZERO;
for ( int i = 2, N = mePartonData().size(); i < N; ++i ) {
summin += mePartonData()[i]->massMin();
}
return ( summin < min(maxEnergy(), cuts()->mHatMax()) );
}
bool StandardXComb::willPassCuts() {
if ( checkedCuts )
return passedCuts;
checkedCuts = true;
if ( !head() ) {
if ( !cuts()->initSubProcess(lastSHat(), lastY(), mirror()) ) {
passedCuts = false;
theCutWeight = 0.0;
return false;
}
} else {
cuts()->initSubProcess(lastSHat(), lastY(), mirror());
}
// check for exceptional configurations which may happen in NLO
// dijets subtraction with an extremely soft incoming parton giving
// rise to about lightlike CM momentum
if ( (meMomenta()[0]+meMomenta()[1]).m2() <= ZERO ) {
passedCuts = false;
return false;
}
tcPDVector outdata(mePartonData().begin()+2,mePartonData().end());
vector<LorentzMomentum> outmomenta(meMomenta().begin()+2,meMomenta().end());
Boost tocm = (meMomenta()[0]+meMomenta()[1]).findBoostToCM();
if ( tocm.mag2() > Constants::epsilon ) {
for ( vector<LorentzMomentum>::iterator p = outmomenta.begin();
p != outmomenta.end(); ++p ) {
p->boost(tocm);
}
}
if ( !cuts()->passCuts(outdata,outmomenta,mePartonData()[0],mePartonData()[1]) ) {
theCutWeight = cuts()->cutWeight();
passedCuts = false;
return false;
}
theCutWeight = cuts()->cutWeight();
passedCuts = true;
return true;
}
void StandardXComb::clean() {
XComb::clean();
theLastPDFWeight = 0.0;
theLastCrossSection = ZERO;
theLastJacobian = 0.0;
theLastME2 = 0.0;
theLastPreweight = 1.0;
theLastMECrossSection = ZERO;
theLastMEPDFWeight = 0.0;
theLastMECouplings = 0.0;
theProjectors.clear();
theProjector = StdXCombPtr();
theKinematicsGenerated = false;
checkedCuts = false;
passedCuts = false;
theCutWeight = 1.0;
matrixElement()->flushCaches();
}
CrossSection StandardXComb::dSigDR(const double * r) {
matrixElement()->setXComb(this);
if ( !matrixElement()->apply() ) {
subProcess(SubProPtr());
lastCrossSection(ZERO);
return ZERO;
}
meMomenta().resize(mePartonData().size());
if ( !matrixElement()->generateKinematics(r) ) {
subProcess(SubProPtr());
lastCrossSection(ZERO);
return ZERO;
}
setIncomingPartons();
lastScale(matrixElement()->scale());
lastAlphaS(matrixElement()->alphaS());
lastAlphaEM(matrixElement()->alphaEM());
if ( (!willPassCuts() &&
!matrixElement()->headCuts() &&
!matrixElement()->ignoreCuts()) ||
!matrixElement()->apply() ) {
subProcess(SubProPtr());
lastCrossSection(ZERO);
return ZERO;
}
lastPDFWeight(head()->lastPDFWeight());
matrixElement()->setKinematics();
CrossSection xsec = matrixElement()->dSigHatDR() * lastPDFWeight();
xsec *= cutWeight();
subProcess(SubProPtr());
lastCrossSection(xsec);
return xsec;
}
CrossSection StandardXComb::
dSigDR(const pair<double,double> ll, int nr, const double * r) {
if ( matrixElement()->keepRandomNumbers() ) {
lastRandomNumbers().resize(nDim());
copy(r,r+nDim(),lastRandomNumbers().begin());
}
pExtractor()->select(this);
setPartonBinInfo();
lastP1P2(ll);
lastS(sqr(maxEnergy())/exp(lastP1() + lastP2()));
meMomenta().resize(mePartonData().size());
matrixElement()->setXComb(this);
PPair partons;
if ( !matrixElement()->haveX1X2() ) {
if ( !pExtractor()->generateL(partonBinInstances(),
r, r + nr - partonDims.second) ) {
lastCrossSection(ZERO);
return ZERO;
}
partons = make_pair(partonBinInstances().first->parton(),
partonBinInstances().second->parton());
lastSHat(lastS()/exp(partonBinInstances().first->l() +
partonBinInstances().second->l()));
meMomenta()[0] = partons.first->momentum();
meMomenta()[1] = partons.second->momentum();
} else {
if ( !matrixElement()->generateKinematics(r + partonDims.first) ) {
lastCrossSection(ZERO);
return ZERO;
}
lastSHat((meMomenta()[0]+meMomenta()[1]).m2());
matrixElement()->setKinematics();
lastScale(matrixElement()->scale());
partons.first = mePartonData()[0]->produceParticle(meMomenta()[0]);
partons.second = mePartonData()[1]->produceParticle(meMomenta()[1]);
Direction<0> dir(true);
partonBinInstances().first =
new_ptr(PartonBinInstance(lastParticles().first,partons.first,
partonBins().first,lastScale()));
dir.reverse();
partonBinInstances().second =
new_ptr(PartonBinInstance(lastParticles().second,partons.second,
partonBins().second,lastScale()));
}
lastPartons(partons);
if ( lastSHat() < cuts()->sHatMin() ) {
lastCrossSection(ZERO);
return ZERO;
}
lastY(0.5*(partonBinInstances().second->l() -
partonBinInstances().first->l()));
if ( !cuts()->initSubProcess(lastSHat(), lastY(), mirror()) ) {
lastCrossSection(ZERO);
return ZERO;
}
if ( mirror() ) swap(meMomenta()[0], meMomenta()[1]);
if ( matrixElement()->wantCMS() &&
!matrixElement()->haveX1X2() )
SimplePhaseSpace::CMS(meMomenta()[0], meMomenta()[1], lastSHat());
Energy summ = ZERO;
if ( meMomenta().size() == 3 ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[2] = Lorentz5Momentum(sqrt(lastSHat()));
} else {
for ( int i = 2, N = meMomenta().size(); i < N; ++i ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[i] = Lorentz5Momentum(mePartonData()[i]->mass());
summ += mePartonData()[i]->massMin();
}
if ( sqr(summ) >= lastSHat() ) {
lastCrossSection(ZERO);
return ZERO;
}
}
if ( !matrixElement()->haveX1X2() )
lastScale(max(lastSHat()/4.0, cuts()->scaleMin()));
lastSHat(pExtractor()->generateSHat(lastS(), partonBinInstances(),
r, r + nr - partonDims.second,
matrixElement()->haveX1X2()));
if ( !cuts()->sHat(lastSHat()) ) {
lastCrossSection(ZERO);
return ZERO;
}
r += partonDims.first;
lastX1X2(make_pair(lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus(),
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus()));
if ( !cuts()->x1(lastX1()) || !cuts()->x2(lastX2()) ) {
lastCrossSection(ZERO);
return ZERO;
}
lastY((lastPartons().first->momentum() +
lastPartons().second->momentum()).rapidity());
if ( !cuts()->yHat(lastY()) ) {
lastCrossSection(ZERO);
return ZERO;
}
if ( !cuts()->initSubProcess(lastSHat(), lastY(), mirror()) ) {
lastCrossSection(ZERO);
return ZERO;
}
meMomenta()[0] = lastPartons().first->momentum();
meMomenta()[1] = lastPartons().second->momentum();
if ( mirror() ) swap(meMomenta()[0], meMomenta()[1]);
if ( matrixElement()->wantCMS() &&
!matrixElement()->haveX1X2() )
SimplePhaseSpace::CMS(meMomenta()[0], meMomenta()[1], lastSHat());
if ( meMomenta().size() == 3 ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[2] = Lorentz5Momentum(sqrt(lastSHat()));
} else {
if ( sqr(summ) >= lastSHat() ) {
lastCrossSection(ZERO);
return ZERO;
}
}
if ( !matrixElement()->haveX1X2() ) {
if ( !matrixElement()->generateKinematics(r) ) {
lastCrossSection(ZERO);
return ZERO;
}
}
lastScale(matrixElement()->scale());
if ( !cuts()->scale(lastScale()) ) {
lastCrossSection(ZERO);
return ZERO;
}
// get information on cuts; we don't take this into account here for
// reasons of backward compatibility but this will change eventually
willPassCuts();
pair<bool,bool> evalPDFS =
make_pair(matrixElement()->havePDFWeight1(),
matrixElement()->havePDFWeight2());
if ( mirror() )
swap(evalPDFS.first,evalPDFS.second);
lastPDFWeight(pExtractor()->fullFn(partonBinInstances(), lastScale(),
evalPDFS));
if ( lastPDFWeight() == 0.0 ) {
lastCrossSection(ZERO);
return ZERO;
}
matrixElement()->setKinematics();
CrossSection xsec = matrixElement()->dSigHatDR() * lastPDFWeight();
if ( xsec == ZERO ) {
lastCrossSection(ZERO);
return ZERO;
}
xsec *= cutWeight();
lastAlphaS (matrixElement()->orderInAlphaS () >0 ?
matrixElement()->alphaS() : -1.);
lastAlphaEM(matrixElement()->orderInAlphaEW() >0 ?
matrixElement()->alphaEM() : -1.);
matrixElement()->fillProjectors();
if ( !projectors().empty() ) {
lastProjector(projectors().select(UseRandom::rnd()));
}
subProcess(SubProPtr());
if ( CKKWHandler() && matrixElement()->maxMultCKKW() > 0 &&
matrixElement()->maxMultCKKW() > matrixElement()->minMultCKKW() ) {
newSubProcess();
CKKWHandler()->setXComb(this);
xsec *= CKKWHandler()->reweightCKKW(matrixElement()->minMultCKKW(),
matrixElement()->maxMultCKKW());
}
if ( matrixElement()->reweighted() ) {
newSubProcess();
xsec *= matrixElement()->reWeight() * matrixElement()->preWeight();
}
lastCrossSection(xsec);
return xsec;
}
void StandardXComb::newSubProcess(bool group) {
if ( subProcess() ) return;
if ( head() && matrixElement()->wantCMS() ) {
// first get the meMomenta in their CMS, as this may
// not be the case
Boost cm = (meMomenta()[0] + meMomenta()[1]).findBoostToCM();
if ( cm.mag2() > Constants::epsilon ) {
for ( vector<Lorentz5Momentum>::iterator m = meMomenta().begin();
m != meMomenta().end(); ++m ) {
*m = m->boost(cm);
}
}
}
if ( !lastProjector() ) {
if ( !group )
subProcess(new_ptr(SubProcess(lastPartons(), tCollPtr(), matrixElement())));
else
subProcess(new_ptr(SubProcessGroup(lastPartons(), tCollPtr(), matrixElement())));
lastDiagramIndex(matrixElement()->diagram(diagrams()));
const ColourLines & cl = matrixElement()->selectColourGeometry(lastDiagram());
Lorentz5Momentum p1 = lastPartons().first->momentum();
Lorentz5Momentum p2 = lastPartons().second->momentum();
tPPair inc = lastPartons();
if ( mirror() ) swap(inc.first, inc.second);
if ( matrixElement()->wantCMS() &&
!matrixElement()->haveX1X2() ) {
LorentzRotation r = Utilities::boostToCM(inc);
lastDiagram()->construct(subProcess(), *this, cl);
subProcess()->transform(r.inverse());
lastPartons().first->set5Momentum(p1);
lastPartons().second->set5Momentum(p2);
} else {
lastDiagram()->construct(subProcess(), *this, cl);
}
lastPartons().first ->scale(partonBinInstances().first ->scale());
lastPartons().second->scale(partonBinInstances().second->scale());
for ( int i = 0, N = subProcess()->outgoing().size(); i < N; ++i )
subProcess()->outgoing()[i]->scale(lastScale());
// construct the spin information for the interaction
matrixElement()->constructVertex(subProcess(),&cl);
// set veto scales
matrixElement()->setVetoScales(subProcess());
} else {
lastProjector()->newSubProcess();
subProcess(lastProjector()->subProcess());
lastPartons(lastProjector()->lastPartons());
lastSHat((lastPartons().first->momentum() +
lastPartons().second->momentum()).m2());
lastX1X2(make_pair(lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus(),
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus()));
lastY(log(lastX1()/lastX2())*0.5);
partonBinInstances().first->parton(lastPartons().first);
partonBinInstances().second->parton(lastPartons().second);
if ( !matrixElement()->keepRandomNumbers() )
throw Exception() << "Matrix element needs to request random number storage "
<< "for creating projected subprocesses."
<< Exception::runerror;
const double * r = &lastRandomNumbers()[0];
pExtractor()->generateSHat(lastS(), partonBinInstances(),
r, r + nDim() - partonDims.second,true);
pExtractor()->updatePartonBinInstances(partonBinInstances());
}
}
+void StandardXComb::checkReshufflingNeeds() {
+
+ theNeedsReshuffling = false;
+
+ for ( cPDVector::const_iterator p = mePartonData().begin() + 2;
+ p != mePartonData().end(); ++p ) {
+ theNeedsReshuffling |= ( (**p).mass() != (**p).hardProcessMass() );
+ }
+
+}
+
+double StandardXComb::reshuffleEquation(double k,
+ const vector<pair<Energy2,Energy2> >& coeffs,
+ Energy2 Q2) const {
+ double res = 0.;
+ for ( vector<pair<Energy2,Energy2> >::const_iterator c = coeffs.begin();
+ c != coeffs.end(); ++c ) {
+ double x = sqr(k)*c->first/Q2+c->second/Q2;
+ if ( x < 0.0 )
+ throw Veto();
+ res += sqrt(x);
+ }
+ return res - 1.;
+}
+
+double StandardXComb::solveReshuffleEquation(const vector<pair<Energy2,Energy2> >& coeffs,
+ Energy2 Q2) const {
+ // shamelessly adapted from Herwig++'s QTildeReconstructor
+ // in principle we could have included the exact solution for two
+ // outgoing particles, but for this to be simple we would require
+ // boosting to the CM so the gain is questionable
+ double k1 = 0.,k2 = 1.,k = 0.;
+ if ( reshuffleEquation(k1,coeffs,Q2) < 0.0 ) {
+ while ( reshuffleEquation(k2, coeffs, Q2) < 0.0 ) {
+ k1 = k2;
+ k2 *= 2;
+ }
+ while ( abs( (k1 - k2)/(k1 + k2) ) > 1.e-10 ) {
+ if( reshuffleEquation(k2,coeffs,Q2) == 0.0 ) {
+ return k2;
+ } else {
+ k = (k1+k2)/2.;
+ if ( reshuffleEquation(k,coeffs,Q2) > 0.0 ) {
+ k2 = k;
+ } else {
+ k1 = k;
+ }
+ }
+ }
+ return k1;
+ }
+ throw Veto();
+ return 1.;
+}
+
+void StandardXComb::reshuffle(vector<Lorentz5Momentum>& pout) const {
+
+ Lorentz5Momentum Q(ZERO,ZERO,ZERO,ZERO);
+ for ( vector<Lorentz5Momentum>::const_iterator p = pout.begin();
+ p != pout.end(); ++p )
+ Q += *p;
+
+ if ( Q.m2() <= ZERO )
+ throw Veto();
+
+ LorentzVector<double> Qhat = Q/sqrt(Q.m2());
+
+ vector<Energy> pQhat;
+ vector<pair<Energy2,Energy2> > coeffs;
+
+ vector<Lorentz5Momentum>::const_iterator p = pout.begin();
+ cPDVector::const_iterator pd = mePartonData().begin() + 2;
+
+ for ( ; p != pout.end(); ++p, ++pd ) {
+ pQhat.push_back((*p)*Qhat);
+ coeffs.push_back(make_pair(sqr(pQhat.back())-sqr((**pd).hardProcessMass()),
+ sqr((**pd).mass())));
+ }
+
+ double k = solveReshuffleEquation(coeffs,Q.m2());
+
+ vector<Lorentz5Momentum>::iterator px = pout.begin();
+ vector<Energy>::const_iterator pQ = pQhat.begin();
+ vector<pair<Energy2,Energy2> >::const_iterator coeff = coeffs.begin();
+
+ for ( ; px != pout.end(); ++px, ++pQ, ++coeff ) {
+ *px = k*((*px) - (*pQ) * Qhat) + sqrt(sqr(k)*coeff->first + coeff->second)*Qhat;
+ px->rescaleMass();
+ }
+
+}
+
tSubProPtr StandardXComb::construct() {
matrixElement()->setXComb(this);
if ( !head() ) {
if ( !cuts()->initSubProcess(lastSHat(), lastY()) ) throw Veto();
} else {
cuts()->initSubProcess(lastSHat(), lastY());
}
if ( head() )
if ( !matrixElement()->apply() )
return tSubProPtr();
setPartonBinInfo();
matrixElement()->setKinematics();
newSubProcess();
TmpTransform<tSubProPtr>
tmp(subProcess(), Utilities::getBoostToCM(subProcess()->incoming()));
if ( !cuts()->passCuts(*subProcess()) ) throw Veto();
if ( head() ) {
subProcess()->head(head()->subProcess());
if(lastCrossSection()!=ZERO&&head()->lastCrossSection()!=ZERO)
subProcess()->groupWeight(lastCrossSection()/head()->lastCrossSection());
else
subProcess()->groupWeight(0.);
}
return subProcess();
}
void StandardXComb::Init() {}
void StandardXComb::persistentOutput(PersistentOStream & os) const {
os << theSubProcessHandler << theME << theStats
<< theDiagrams << isMirror << theNDim << partonDims
<< theLastDiagramIndex << theMEInfo << theLastRandomNumbers << theMEPartonData
<< theLastPDFWeight << ounit(theLastCrossSection,nanobarn) << theLastJacobian
<< theLastME2 << theLastPreweight
<< ounit(theLastMECrossSection,nanobarn) << theLastMEPDFWeight << theLastMECouplings
<< theHead << theProjectors << theProjector << theKinematicsGenerated
- << checkedCuts << passedCuts << theCutWeight;
+ << checkedCuts << passedCuts << theCutWeight << theNeedsReshuffling;
}
void StandardXComb::persistentInput(PersistentIStream & is, int) {
is >> theSubProcessHandler >> theME >> theStats
>> theDiagrams >> isMirror >> theNDim >> partonDims
>> theLastDiagramIndex >> theMEInfo >> theLastRandomNumbers >> theMEPartonData
>> theLastPDFWeight >> iunit(theLastCrossSection,nanobarn) >> theLastJacobian
>> theLastME2 >> theLastPreweight
>> iunit(theLastMECrossSection,nanobarn) >> theLastMEPDFWeight >> theLastMECouplings
>> theHead >> theProjectors >> theProjector >> theKinematicsGenerated
- >> checkedCuts >> passedCuts >> theCutWeight;
+ >> checkedCuts >> passedCuts >> theCutWeight >> theNeedsReshuffling;
}
ClassDescription<StandardXComb> StandardXComb::initStandardXComb;
diff --git a/Handlers/StandardXComb.h b/Handlers/StandardXComb.h
--- a/Handlers/StandardXComb.h
+++ b/Handlers/StandardXComb.h
@@ -1,710 +1,744 @@
// -*- C++ -*-
//
// StandardXComb.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
// Copyright (C) 2009-2011 Simon Platzer
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_StandardXComb_H
#define ThePEG_StandardXComb_H
// This is the declaration of the StandardXComb class.
#include "ThePEG/Config/ThePEG.h"
#include "SubProcessHandler.fh"
#include "ThePEG/PDF/PartonExtractor.fh"
#include "ThePEG/PDF/PartonBin.h"
#include "ThePEG/PDF/PartonBinInstance.h"
#include "ThePEG/Utilities/VSelector.h"
#include "ThePEG/Utilities/ClassDescription.h"
#include "ThePEG/Utilities/Maths.h"
#include "ThePEG/Utilities/XSecStat.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/Handlers/XComb.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Handlers/SubProcessHandler.fh"
#include "StandardXComb.fh"
namespace ThePEG {
/**
* The StandardXComb class inherits from the more general XComb class
* which stores all information about the generation of a hard
* sub-proces for a given pair of incoming particles, a pair of
* extracted partons, etc. This class stores more information related
* to thestandard process generation scheme in ThePEG, such as the
* PartonExtractor and MEBase object used. It also does some of the
* administration of the process generation.
*
* The main function is dSigDR() which returns the differential cross
* section w.r.t. a given vector of random numbers in the interval
* ]0,1[. In the initialization this is used to pre-sample the phase
* space. In the generation phase it is used to give the cross section
* for a phase space point, and if this StandardXComb is chosen the
* construct() function is called to generate the actual sub-process.
*
* @see ParonExtractor
* @see MEBase
* @see Cuts
* @see StdXCombGroup
*/
class StandardXComb: public XComb {
public:
/** A vector of DiagramBase objects. */
typedef MEBase::DiagramVector DiagramVector;
/** A vector of indices. */
typedef MEBase::DiagramIndex DiagramIndex;
/** MEBase needs to be a friend. */
friend class MEBase;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* Standard constructor.
*/
StandardXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts, tMEPtr newME,
const DiagramVector & newDiagrams, bool mir,
tStdXCombPtr newHead = tStdXCombPtr());
/**
* Constructor given a head xcomb.
*/
StandardXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins, tMEPtr newME,
const DiagramVector & newDiagrams);
/**
* Default constructor.
*/
StandardXComb();
/**
* Destructor.
*/
virtual ~StandardXComb();
/**
* Constructor used by MEBase to create a temporary object to store info.
*/
StandardXComb(tMEPtr me, const tPVector & parts, DiagramIndex i);
//@}
/** @name Utilities for incoming partons. */
//@{
/**
* Properly setup the PartonBinInstance objects provided a sub
* process has been constructed using this XComb.
*/
void recreatePartonBinInstances(Energy2 scale);
/**
* Fill the variables needed to generate remnants; momenta will be
* used from the partons set in this xcomb, but random numbers need
* to be provided to (re)generate variables not fixed by the
* incoming partons.
*/
void refillPartonBinInstances(const double* r);
/**
* Setup information on incoming partons depending
* on the information previously supplied through the
* choice of diagram and incoming momenta in the first
* two entries of meMomenta(). Partons are not actually
* extracted from the incoming particles, though a subprocess
* detached from the current Event may be created.
*/
void setIncomingPartons(tStdXCombPtr labHead = tStdXCombPtr());
/**
* Fill phase space information as far as possible
*/
void fill(const PPair& newParticles,
const PPair& newPartons,
const vector<Lorentz5Momentum>& newMEMomenta,
const DVector& newLastRandomNumbers = DVector());
//@}
/** @name Access the assigned objects used in the generation. */
//@{
/**
* Return a pointer to the corresponding sub-process handler. May be
* null if the standard process generation in ThePEG was not used.
*/
tcSubHdlPtr subProcessHandler() const { return theSubProcessHandler; }
/**
* The matrix element to be used.
*/
tMEPtr matrixElement() const { return theME; }
/**
* Return a pointer to the head XComb this XComb
* depends on. May return NULL, if this is not a
* member of a XComb group.
*/
tStdXCombPtr head() const { return theHead; }
/**
* Set the head XComb pointer.
*/
void head(tStdXCombPtr headXC) { theHead = headXC; }
/**
* Return a selector object of xcombs to choose subprocesses
* different than the one currently integrated.
*/
Selector<tStdXCombPtr>& projectors() { return theProjectors; }
/**
* Return a selector object of xcombs to choose subprocesses
* different than the one currently integrated.
*/
const Selector<tStdXCombPtr>& projectors() const { return theProjectors; }
/**
* Return a pointer to a projector xcomb which will generate a subprocess
* different from the one just integrated.
*/
tStdXCombPtr lastProjector() const { return theProjector; }
/**
* Set a pointer to a projector xcomb which will generate a subprocess
* different from the one just integrated.
*/
void lastProjector(tStdXCombPtr pxc) { theProjector = pxc; }
//@}
/** @name Main functions used for the generation. */
//@{
/**
* Try to determine if this subprocess is at all possible.
*/
virtual bool checkInit();
/**
* The number of dimensions of the phase space used to generate this
* process.
*/
virtual int nDim() const { return theNDim; }
/**
* Return the parton extraction dimensions
*/
const pair<int,int>& partonDimensions() const { return partonDims; }
/**
* Return true, if the current configuration will pass the cuts
*/
bool willPassCuts();
/**
* Return the cut weight encountered from fuzzy cuts
*/
double cutWeight() const { return theCutWeight; }
/**
* Reset all saved data about last generated phasespace point;
*/
virtual void clean();
/**
* Return true, if kinematics have already been generated
*/
bool kinematicsGenerated() const { return theKinematicsGenerated; }
/**
* Indicate that kinematics have been generated
*/
void didGenerateKinematics() { theKinematicsGenerated = true; }
/**
* Generate a phase space point from a vector \a r of \a nr numbers
* in the interval ]0,1[ and return the corresponding differential
* cross section.
*/
virtual CrossSection dSigDR(const pair<double,double> ll, int nr, const double * r);
/**
* If this XComb has a head XComb, return the cross section
* differential in the variables previously supplied. The PDF weight
* is taken from the lastPDFWeight supplied by the head XComb
* object.
*/
CrossSection dSigDR(const double * r);
/**
* Return the PDF weight used in the last call to dSigDR
*/
double lastPDFWeight() const { return theLastPDFWeight; }
/**
* Return the cross section calculated in the last call to dSigDR
*/
CrossSection lastCrossSection() const { return theLastCrossSection; }
/**
+ * Check if a reshuffling is required when constructing the hard
+ * subprocess.
+ */
+ void checkReshufflingNeeds();
+
+ /**
+ * Return true if a reshuffling is required when constructing the hard
+ * subprocess.
+ */
+ bool needsReshuffling() const { return theNeedsReshuffling; }
+
+ /**
+ * Perform the reshuffling from hardProcessMass to mass values,
+ * given outgoing momenta
+ */
+ void reshuffle(vector<Lorentz5Momentum>&) const;
+
+ /**
* Construct a sub-process object from the information available.
*/
virtual tSubProPtr construct();
//@}
/** @name Functions used for collecting statistics. */
//@{
/**
* The statistics object for this XComb.
*/
virtual const XSecStat & stats() const { return theStats; }
/**
* Select the current event. It will later be rejected with a
* probability given by \a weight.
*/
virtual void select(double weight) { theStats.select(weight); }
/**
* Accept the current event assuming it was previously selcted.
*/
virtual void accept() { theStats.accept(); }
/**
* Reweight a selected and accepted event.
*/
void reweight(double oldWeight, double newWeight) {
theStats.reweight(oldWeight,newWeight);
}
/**
* Reject the current event assuming it was previously accepted. If
* weighted events are produced, the \a weight should be the same as
* the previous call to select(double).
*/
virtual void reject(double weight = 1.0) { theStats.reject(weight); }
/**
* Reset statistics.
*/
virtual void reset() { theStats.reset(); }
//@}
/** @name Access information used by the MEBase object. */
//@{
/**
* The diagrams used by the matrix element.
*/
const DiagramVector & diagrams() const { return theDiagrams; }
/**
* True if the TreeDiagram's for this matrix element should in fact
* be mirrored before used to create an actual sub-rocess.
*/
bool mirror() const { return isMirror; }
/**
* Return the momenta of the partons to be used by the matrix
* element object, in the order specified by the TreeDiagram objects
* given by the matrix element.
*/
const vector<Lorentz5Momentum> & meMomenta() const { return theMEMomenta; }
/**
* Return the last selected diagram.
*/
tcDiagPtr lastDiagram() const { return diagrams()[lastDiagramIndex()]; }
/**
* Return the parton types to be used by the matrix element object,
* in the order specified by the TreeDiagram objects given by the
* matrix element.
*/
const cPDVector & mePartonData() const { return theMEPartonData; }
/**
* Return the index of the last selected diagram.
*/
DiagramIndex lastDiagramIndex() const { return theLastDiagramIndex; }
/**
* Get information saved by the matrix element in the calculation of
* the cross section to be used later when selecting diagrams and
* colour flow.
*/
const DVector & meInfo() const { return theMEInfo; }
/**
* Set information saved by the matrix element in the calculation of
* the cross section to be used later when selecting diagrams and
* colour flow.
*/
void meInfo(const DVector & info) { theMEInfo = info; }
/**
* Return the random numbers used to generate the
* last phase space point, if the matrix element
* requested so.
*/
const DVector& lastRandomNumbers() const { return theLastRandomNumbers; }
/**
* Get the last jacobian obtained when generating the kinematics
* for the call to dSigHatDR.
*/
double jacobian() const { return theLastJacobian; }
/**
* Return the matrix element squared as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
double lastME2() const { return theLastME2; }
/**
* Return the last preweight factor
*/
double lastPreweight() const { return theLastPreweight; }
/**
* Return the partonic cross section as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
CrossSection lastMECrossSection() const { return theLastMECrossSection; }
/**
* Return the PDF weight as calculated
* for the last phase space point, if the matrix
* element does supply PDF weights. This may optionally
* be used by a matrix element for caching.
*/
double lastMEPDFWeight() const { return theLastMEPDFWeight; }
/**
* Return the coupling factor as calculated for the lats phase space
* point.
*/
double lastMECouplings() const { return theLastMECouplings; }
//@}
/**
* Construct the corresponding SubProcess object if it hasn't been
* done before.
*/
virtual void newSubProcess(bool group = false);
/**
* Return the momenta of the partons to be used by the matrix
* element object, in the order specified by the TreeDiagram objects
* given by the matrix element.
*/
vector<Lorentz5Momentum> & meMomenta() { return theMEMomenta; }
/**
* Access the random numbers used to generate the
* last phase space point, if the matrix element
* requested so.
*/
DVector& lastRandomNumbers() { return theLastRandomNumbers; }
/**
* Return the parton types to be used by the matrix element object,
* in the order specified by the TreeDiagram objects given by the
* matrix element.
*/
cPDVector & mePartonData() { return theMEPartonData; }
/**
* Set the last selected diagram.
*/
void lastDiagramIndex(DiagramIndex i) { theLastDiagramIndex = i; }
/**
* Set the PDF weight used in the last call to dSigDR
*/
void lastPDFWeight(double w) { theLastPDFWeight = w; }
/**
* Set the cross section calculated in the last call to dSigDR
*/
void lastCrossSection(CrossSection s) { theLastCrossSection = s; }
/**
* Set the last jacobian obtained when generating the kinematics for
* the call to dSigHatDR.
*/
void jacobian(double j) { theLastJacobian = j; }
/**
* Set the matrix element squared as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
void lastME2(double v) { theLastME2 = v; }
/**
* Set the last preweight factor
*/
void lastPreweight(double w) { theLastPreweight = w; }
/**
* Set the partonic cross section as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
void lastMECrossSection(CrossSection v) { theLastMECrossSection = v; }
/**
* Set the PDF weight as calculated
* for the last phase space point, if the matrix
* element does supply PDF weights. This may optionally
* be used by a matrix element for caching.
*/
void lastMEPDFWeight(double v) { theLastMEPDFWeight = v; }
/**
* Set the coupling factor
*/
void lastMECouplings(double v) { theLastMECouplings = v; }
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);
//@}
/**
* Standard Init function used to initialize the interface.
*/
static void Init();
private:
/**
* The corresponding sub-process handler
*/
tSubHdlPtr theSubProcessHandler;
/**
* The matrix element to be used.
*/
tMEPtr theME;
/**
* Statistics gathering for this XComb.
*/
XSecStat theStats;
/**
* The diagrams used by the matrix element.
*/
DiagramVector theDiagrams;
/**
* True if the TreeDiagram's for this matrix element should in fact
* be mirrored before used to create an actual sub-rocess.
*/
bool isMirror;
/**
* The number of dimensions of the phase space used to generate this
* process.
*/
int theNDim;
protected:
/**
* The number of dimensions of the phase space used for each of the
* incoming partons.
*/
pair<int,int> partonDims;
private:
/**
* True, if kinematics have already been generated
*/
bool theKinematicsGenerated;
/**
* The momenta of the partons to be used by the matrix element
* object, in the order specified by the TreeDiagram objects given
* by the matrix element.
*/
vector<Lorentz5Momentum> theMEMomenta;
/**
* The parton types to be used by the matrix element object, in the
* order specified by the TreeDiagram objects given by the matrix
* element.
*/
cPDVector theMEPartonData;
/**
* The last selected tree diagram.
*/
DiagramIndex theLastDiagramIndex;
/**
* Information saved by the matrix element in the calculation of the
* cross section to be used later when selecting diagrams and colour
* flow.
*/
DVector theMEInfo;
/**
* The random numbers used to generate the
* last phase space point, if the matrix element
* requested so.
*/
DVector theLastRandomNumbers;
/**
* The PDF weight used in the last call to dSigDR
*/
double theLastPDFWeight;
/**
* The cross section calculated in the last call to dSigDR
*/
CrossSection theLastCrossSection;
/**
* Save the last jacobian obtained when generating the kinematics for
* the call to dSigHatDR.
*/
double theLastJacobian;
/**
* The matrix element squared as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
double theLastME2;
/**
* The last preweight factor
*/
double theLastPreweight;
/**
* The partonic cross section as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
CrossSection theLastMECrossSection;
/**
* The PDF weight as calculated
* for the last phase space point, if the matrix
* element does supply PDF weights. This may optionally
* be used by a matrix element for caching.
*/
double theLastMEPDFWeight;
/**
* The coupling factor
*/
double theLastMECouplings;
/**
* A pointer to the head XComb this XComb
* depends on. May return NULL, if this is not a
* member of a XComb group.
*/
tStdXCombPtr theHead;
/**
* A selector object of xcombs to choose subprocesses
* different than the one currently integrated.
*/
Selector<tStdXCombPtr> theProjectors;
/**
* A pointer to a projector xcomb which will generate a subprocess
* different from the one just integrated.
*/
tStdXCombPtr theProjector;
/**
* True, if cuts have already been checked
*/
bool checkedCuts;
/**
* The result of the last call to willPassCuts
*/
bool passedCuts;
/**
* The cut weight encountered from fuzzy cuts
*/
double theCutWeight;
+ /**
+ * True if a reshuffling is required when constructing the hard
+ * subprocess.
+ */
+ bool theNeedsReshuffling;
+
+ /**
+ * Calculate the reshuffling equation given the coefficients
+ */
+ double reshuffleEquation(double, const vector<pair<Energy2,Energy2> >&, Energy2) const;
+
+ /**
+ * Solve the reshuffling equation given the coefficients
+ */
+ double solveReshuffleEquation(const vector<pair<Energy2,Energy2> >&, Energy2) const;
+
private:
/**
* Describe a concrete class with persistent data.
*/
static ClassDescription<StandardXComb> initStandardXComb;
/**
* Private and non-existent assignment operator.
*/
StandardXComb & operator=(const StandardXComb &);
};
/** @cond TRAITSPECIALIZATIONS */
/**
* This template specialization informs ThePEG about the base class of
* StandardXComb.
*/
template <>
struct BaseClassTrait<StandardXComb,1>: public ClassTraitsType {
/** Typedef of the base class of StandardXComb. */
typedef XComb NthBase;
};
/**
* This template specialization informs ThePEG about the name of the
* StandardXComb class.
*/
template <>
struct ClassTraits<StandardXComb>:
public ClassTraitsBase<StandardXComb> {
/** Return the class name. */
static string className() { return "ThePEG::StandardXComb"; }
};
/** @endcond */
}
#endif /* ThePEG_StandardXComb_H */
diff --git a/MatrixElement/Tree2toNDiagram.cc b/MatrixElement/Tree2toNDiagram.cc
--- a/MatrixElement/Tree2toNDiagram.cc
+++ b/MatrixElement/Tree2toNDiagram.cc
@@ -1,440 +1,440 @@
// -*- C++ -*-
//
// Tree2toNDiagram.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG 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 Tree2toNDiagram class.
//
#include "Tree2toNDiagram.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/Rebinder.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/EnumParticles.h"
using namespace ThePEG;
Tree2toNDiagram::~Tree2toNDiagram() {}
Tree2toNDiagram & Tree2toNDiagram::add(tcPDPtr pd) {
if ( thePartons.size() < theNSpace ) addSpacelike(pd);
else addTimelike(pd, nextOrig);
return *this;
}
void Tree2toNDiagram::addTimelike(tcPDPtr pd, size_type orig) {
if ( allPartons().size() < theNSpace ||
orig >= allPartons().size())
throw Tree2toNDiagramError();
thePartons.push_back(pd);
theParents.push_back(orig);
}
tPVector Tree2toNDiagram::
construct(SubProPtr sp, const StandardXComb & xc, const ColourLines & cl) const {
tPVector out;
vector<Lorentz5Momentum> pout(xc.meMomenta().begin() + 2,
xc.meMomenta().end());
-// Utilities::transform(pout.begin(), pout.end(),
-// Utilities::getBoostFromCM(xc.lastPartons()));
+ if ( xc.needsReshuffling() )
+ xc.reshuffle(pout);
tPPair in = xc.lastPartons();
if ( xc.mirror() ) swap(in.first, in.second);
tPVector ret;
if ( in.first->dataPtr() != allPartons()[0] ||
in.second->dataPtr() != allPartons()[nSpace() - 1] )
throw Tree2toNDiagramError();
PVector slike;
slike.push_back(in.first);
for ( int i = 1; i < nSpace() - 1; ++i )
slike.push_back(allPartons()[i]->produceParticle());
slike.push_back(in.second);
ret = tPVector(slike.begin(), slike.end());
for ( size_type i = 1; i < slike.size() - 1; ++i ) {
slike[i-1]->addChild(slike[i]);
sp->addIntermediate(slike[xc.mirror()? i: slike.size() - 1 - i], false);
}
int io = pout.size();
PVector tlike(allPartons().size() - nSpace());
ParticleSet done;
for ( int i = allPartons().size() - 1; i >= nSpace(); --i ) {
int it = i - nSpace();
pair<int,int> ch = children(i);
bool iso = ch.first < 0;
if ( iso ) {
tlike[it] = allPartons()[i]->produceParticle(pout[--io]);
done.insert(tlike[it]);
} else {
Lorentz5Momentum p = tlike[ch.first - nSpace()]->momentum() +
tlike[ch.second - nSpace()]->momentum();
tlike[it] = allPartons()[i]->produceParticle(p);
}
if ( parent(i) < nSpace() ) {
slike[parent(i)]->addChild(tlike[it]);
if ( parent(i) == nSpace() - 2 )
slike[parent(i) + 1]->addChild(tlike[it]);
}
if ( !iso ) {
tlike[it]->addChild(tlike[ch.first - nSpace()]);
tlike[it]->addChild(tlike[ch.second - nSpace()]);
}
if ( iso ) out.push_back(tlike[it]);
else sp->addIntermediate(tlike[it], false);
}
ret.insert(ret.end(), tlike.begin(), tlike.end());
for ( int i = 0, N = out.size(); i < N; ++i )
sp->addOutgoing(out[xc.mirror()? i: out.size() - i - 1], false);
for ( PVector::size_type i = 0; i < slike.size() - 2; ++i ) {
pair<int,int> ch = children(i);
slike[ch.first]->set5Momentum(slike[i]->momentum() -
tlike[ch.second - nSpace()]->momentum());
}
cl.connect(ret);
return out;
}
tcPDVector Tree2toNDiagram::outgoing() const {
tcPDVector pdv;
for ( size_type i = nSpace(); i < allPartons().size(); ++i )
if ( children(i).first < 0 ) pdv.push_back(allPartons()[i]);
return pdv;
}
tcPDVector Tree2toNDiagram::external() const {
tcPDVector pdv;
pdv.push_back(allPartons()[0]);
pdv.push_back(allPartons()[nSpace() - 1]);
for ( size_type i = nSpace(); i < allPartons().size(); ++i )
if ( children(i).first < 0 ) pdv.push_back(allPartons()[i]);
return pdv;
}
tcPDPair Tree2toNDiagram::incoming() const {
return tcPDPair(allPartons()[0], allPartons()[nSpace() - 1]);
}
pair<int,int> Tree2toNDiagram::children(int ii) const {
pair<int,int> ret = make_pair(-1, -1);
for ( size_type i = 0; i < theParents.size(); ++i ) {
if ( parent(i) == ii ) {
if ( ret.first < 0 ) ret.first = i;
else if ( ret.second < 0 ) ret.second = i;
else throw Tree2toNDiagramError();
}
}
return ret;
}
void Tree2toNDiagram::check() {
vector< pair<int,int> > children(allPartons().size(), make_pair(-1, -1));
theNOutgoing = 0;
for ( size_type i = nSpace(); i < allPartons().size(); ++i ) {
if ( children[parent(i)].first < 0 ) children[parent(i)].first = i;
else if ( children[parent(i)].second < 0 ) children[parent(i)].second = i;
else throw Tree2toNDiagramError();
}
for ( size_type i = nSpace(); i < allPartons().size(); ++i ) {
if ( children[i].first < 0 && children[i].second < 0 ) ++theNOutgoing;
else if ( children[i].first < 0 || children[i].second < 0 )
throw Tree2toNDiagramError();
}
cPDVector parts(2);
parts[0] = incoming().first;
parts[1] = incoming().second;
tcPDVector out(outgoing());
parts.insert(parts.end(), out.begin(), out.end());
partons(2, parts, nextOrig + 1);
}
bool Tree2toNDiagram::isSame (tcDiagPtr diag) const {
Ptr<Tree2toNDiagram>::tcptr cmp =
dynamic_ptr_cast<Ptr<Tree2toNDiagram>::tcptr>( diag );
if ( !cmp )
return false;
return equals(cmp) && external() == cmp->external();
}
bool Tree2toNDiagram::isSame (tcDiagPtr diag, map<int,int>& remap) const {
Ptr<Tree2toNDiagram>::tcptr cmp =
dynamic_ptr_cast<Ptr<Tree2toNDiagram>::tcptr>( diag );
if ( !cmp )
return false;
remap.clear();
remap[0] = 0;
return equals(cmp,remap);
}
bool Tree2toNDiagram::equals(Ptr<Tree2toNDiagram>::tcptr diag,
int start, int startCmp) const {
if ( start < 0 && startCmp < 0 )
return true;
if ( allPartons()[start] != diag->allPartons()[startCmp] )
return false;
pair<int,int> ch = children(start);
pair<int,int> chCmp = diag->children(startCmp);
bool match =
equals(diag,ch.first,chCmp.first) &&
equals(diag,ch.second,chCmp.second);
// also try swapped outgoing legs on same vertex
if ( !match && start > nSpace() - 1 &&
children(ch.first).first < 0 && children(ch.second).first < 0 &&
diag->children(chCmp.first).first < 0 && diag->children(chCmp.second).first < 0 )
match =
equals(diag,ch.first,chCmp.second) &&
equals(diag,ch.second,chCmp.first);
return match;
}
bool Tree2toNDiagram::equals(Ptr<Tree2toNDiagram>::tcptr diag,
map<int,int>& remap,
int start, int startCmp) const {
if ( start < 0 && startCmp < 0 )
return true;
if ( allPartons()[start] != diag->allPartons()[startCmp] )
return false;
pair<int,int> ch = children(start);
pair<int,int> chCmp = diag->children(startCmp);
if ( ch.first < 0 && chCmp.first < 0 ) {
remap[externalId(start)] = diag->externalId(startCmp);
}
bool match =
equals(diag,remap,ch.first,chCmp.first) &&
equals(diag,remap,ch.second,chCmp.second);
// also try swapped outgoing legs on same vertex
if ( !match && start > nSpace() - 1 &&
children(ch.first).first < 0 && children(ch.second).first < 0 &&
diag->children(chCmp.first).first < 0 && diag->children(chCmp.second).first < 0 )
match =
equals(diag,remap,ch.first,chCmp.second) &&
equals(diag,remap,ch.second,chCmp.first);
return match;
}
int Tree2toNDiagram::externalId(int id) const {
if ( id < 0 )
return -1;
if ( id == 0 )
return 0;
if ( id == nSpace() - 1 )
return 1;
int k = 1;
for ( size_type i = nSpace(); i < allPartons().size(); ++i ) {
if ( children(i).first < 0 ) ++k;
if ( i == size_type(id) )
break;
}
return k;
}
int Tree2toNDiagram::diagramId(int id) const {
if ( id < 0 )
return -1;
if ( id == 0 ) return 0;
if ( id == 1 ) return nSpace() - 1;
int k = 1;
size_type i = nSpace();
for ( ; i < allPartons().size(); ++i ) {
if ( children(i).first < 0 ) ++k;
if ( k == id )
break;
}
return i;
}
int Tree2toNDiagram::mergeEmission(int emitter, int id, map<int,int>& remap) {
if ( id < 2 )
return -1;
if ( remap.find(emitter) != remap.end() ) {
remap.erase(emitter);
}
if ( remap.find(id) != remap.end() ) {
remap.erase(id);
}
for ( map<int,int>::iterator rm = remap.begin();
rm != remap.end(); ++rm ) {
if ( rm->first == 0 || rm->first == 1 ) {
rm->second = rm->first;
} else {
rm->second = diagramId(rm->first);
}
}
// translate to diagram id
int did = diagramId(id);
int demitter = diagramId(emitter);
if ( children(did) != make_pair(-1,-1) )
return -1;
// now get the parent
int p = parent(did);
int npos = -1;
if ( p == 0 || p == nSpace() - 2 ) {
npos = ( p == 0 ? 0 : 1 );
} else if ( p >= nSpace() ) {
if ( id > emitter )
npos = emitter;
else
npos = emitter - 1;
}
pair<int,int> remove;
size_type theNSpaceBackup = theNSpace;
int theNOutgoingBackup = theNOutgoing;
int nextOrigBackup = nextOrig;
cPDVector thePartonsBackup = thePartons;
vector<int> theParentsBackup = theParents;
int deltaFlow = 0;
if ( npos == 1 ) {
if ( thePartons[did]->CC() )
deltaFlow -= ( thePartons[did]->id() < 0 ? -1 : 1 );
if ( thePartons[nSpace()-1]->CC() )
deltaFlow += ( thePartons[nSpace()-1]->id() < 0 ? -1 : 1 );
}
// emitted from spacelike
if ( p == 0 || p == nSpace() - 2 ) {
if ( p == 0 && p != demitter )
return -1;
if ( p == nSpace() - 2 && demitter != nSpace()-1 )
return -1;
if ( p == 0 )
remove = make_pair(p,did);
else
remove = make_pair(nSpace()-1,did);
--theNSpace;
--theNOutgoing;
} else if ( p >= nSpace() ) {
remove = children(p);
if ( remove.first != demitter )
swap(remove.first,remove.second);
if ( remove != make_pair(demitter,did) )
return -1;
--theNOutgoing;
} else {
return -1;
}
if ( remove.first > remove.second )
swap(remove.first,remove.second);
for ( map<int,int>::iterator rm = remap.begin();
rm != remap.end(); ++rm ) {
if ( rm->first > 1 ) {
if ( rm->second > remove.first &&
rm->second < remove.second )
rm->second -= 1;
else if ( rm->second > remove.second )
rm->second -= 2;
}
}
for ( unsigned int k = remove.first + 1; k < theParents.size(); ++k ) {
if ( theParents[k] >= remove.first &&
theParents[k] < remove.second &&
theParents[k] >= 0 )
theParents[k] -= 1;
else if ( theParents[k] > remove.second && theParents[k] > 0 )
theParents[k] -= 2;
}
thePartons.erase(thePartons.begin() + remove.second);
theParents.erase(theParents.begin() + remove.second);
thePartons.erase(thePartons.begin() + remove.first);
theParents.erase(theParents.begin() + remove.first);
if ( npos > 1 )
if ( npos != externalId(p) ) {
pair<int,int> swapDiagIds(p,diagramId(npos));
swap(thePartons[swapDiagIds.first],thePartons[swapDiagIds.second]);
swap(theParents[swapDiagIds.first],theParents[swapDiagIds.second]);
for ( map<int,int>::iterator rm = remap.begin();
rm != remap.end(); ++rm ) {
if ( rm->first > 1 ) {
if ( rm->second == swapDiagIds.first ) {
rm->second = swapDiagIds.second;
} else if ( rm->second == swapDiagIds.second ) {
rm->second = swapDiagIds.first;
}
}
}
}
for ( map<int,int>::iterator rm = remap.begin();
rm != remap.end(); ++rm ) {
if ( rm->first > 1 ) {
rm->second = externalId(rm->second);
}
}
if ( npos == 1 ) {
if ( thePartons[nSpace()-1]->CC() )
deltaFlow -= ( thePartons[nSpace()-1]->id() < 0 ? -1 : 1 );
if ( deltaFlow != 0 )
thePartons[nSpace()-1] = thePartons[nSpace()-1]->CC();
}
try {
check();
} catch (Tree2toNDiagramError&) {
theNSpace = theNSpaceBackup;
theNOutgoing = theNOutgoingBackup;
nextOrig = nextOrigBackup;
thePartons = thePartonsBackup;
theParents = theParentsBackup;
return -1;
}
return npos;
}
ClassDescription<Tree2toNDiagram> Tree2toNDiagram::initTree2toNDiagram;
void Tree2toNDiagram::persistentInput(PersistentIStream & is, int) {
is >> theNSpace >> theNOutgoing >> thePartons >> theParents >> nextOrig;
}
void Tree2toNDiagram::persistentOutput(PersistentOStream & os) const {
os << theNSpace << theNOutgoing << thePartons << theParents << nextOrig;
}
Tree2toNDiagramError::Tree2toNDiagramError() {
theMessage << "An error occurred while setting up a diagram of class "
<< "'Tree2toNDiagram'.";
severity(abortnow);
}
diff --git a/PDT/Matcher.cc b/PDT/Matcher.cc
--- a/PDT/Matcher.cc
+++ b/PDT/Matcher.cc
@@ -1,67 +1,69 @@
// -*- C++ -*-
//
// Matcher.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG 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 Matcher class.
//
#include "Matcher.h"
#include "StandardMatchers.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
#include "Matcher.tcc"
#endif
#define THEPEG_MATCH_DESC(T) \
/** \
* This template specialization registers the Matcher \
*/ \
template <> \
NoPIOClassDescription<T> T::initMatcher \
= NoPIOClassDescription<T>(); \
namespace ThePEG {
THEPEG_MATCH_DESC(MatchAny)
THEPEG_MATCH_DESC(MatchStandardQCDParton)
THEPEG_MATCH_DESC(MatchLightAntiQuark)
THEPEG_MATCH_DESC(MatchLightQuark)
THEPEG_MATCH_DESC(MatchLepton)
THEPEG_MATCH_DESC(MatchDiquark)
THEPEG_MATCH_DESC(MatchMeson)
THEPEG_MATCH_DESC(MatchBaryon)
THEPEG_MATCH_DESC(MatchNegative)
THEPEG_MATCH_DESC(MatchNeutral)
THEPEG_MATCH_DESC(MatchPositive)
THEPEG_MATCH_DESC(MatchCharged)
+ THEPEG_MATCH_DESC(MatchNeutrino)
}
using namespace ThePEG;
namespace {
void dummy() {
static MatchAny m00;
static MatchStandardQCDParton m01;
static MatchLightAntiQuark m02;
static MatchLightQuark m03;
static MatchLepton m04;
static MatchDiquark m05;
static MatchMeson m06;
static MatchBaryon m07;
static MatchNegative m08;
static MatchNeutral m09;
static MatchPositive m11;
static MatchCharged m12;
+ static MatchNeutrino m13;
}
}
diff --git a/PDT/ParticleData.cc b/PDT/ParticleData.cc
--- a/PDT/ParticleData.cc
+++ b/PDT/ParticleData.cc
@@ -1,954 +1,1034 @@
// -*- C++ -*-
//
// ParticleData.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG 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 ParticleData class.
//
#include "ParticleData.h"
#include "ParticleData.xh"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Utilities/HoldFlag.h"
#include "ThePEG/Utilities/Rebinder.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Config/algorithm.h"
#include "ThePEG/Utilities/Exception.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ThePEG/Repository/UseRandom.h"
namespace ThePEG {
ParticleData::ParticleData()
: theId(0), thePDGName(""), theMass(-1.0*GeV), theWidth(-1.0*GeV),
+ theHardProcessMass(-1.0*GeV), hardProcessMassSet(false),
+ theHardProcessWidth(-1.0*GeV), hardProcessWidthSet(false),
theWidthUpCut(-1.0*GeV), theWidthLoCut(-1.0*GeV), theCTau(-1.0*mm),
theCharge(PDT::ChargeUnknown),
theSpin(PDT::SpinUnknown), theColour(PDT::ColourUnknown), isStable(true),
theVariableRatio(false), syncAnti(false), theDefMass(-1.0*GeV),
theDefWidth(-1.0*GeV), theDefCut(-1.0*GeV), theDefCTau(-1.0*mm),
theDefCharge(PDT::ChargeUnknown), theDefSpin(PDT::SpinUnknown),
theDefColour(PDT::ColourUnknown) {}
ParticleData::
ParticleData(PID newId, const string & newPDGName)
: theId(newId), thePDGName(newPDGName), theMass(-1.0*GeV), theWidth(-1.0*GeV),
+ theHardProcessMass(-1.0*GeV), hardProcessMassSet(false),
+ theHardProcessWidth(-1.0*GeV), hardProcessWidthSet(false),
theWidthUpCut(-1.0*GeV), theWidthLoCut(-1.0*GeV), theCTau(-1.0*mm),
theCharge(PDT::ChargeUnknown),
theSpin(PDT::SpinUnknown), theColour(PDT::ColourUnknown), isStable(true),
theVariableRatio(false), syncAnti(false), theDefMass(-1.0*GeV),
theDefWidth(-1.0*GeV), theDefCut(-1.0*GeV), theDefCTau(-1.0*mm),
theDefCharge(PDT::ChargeUnknown), theDefSpin(PDT::SpinUnknown),
theDefColour(PDT::ColourUnknown) {}
ParticleData::~ParticleData() {}
PDPtr ParticleData::Create(PID newId, const string & newPDGName) {
return new_ptr(ParticleData(newId, newPDGName));
}
PDPair ParticleData::
Create(PID newId, const string & newPDGName, const string & newAntiPDGName) {
PDPair pap;
pap.first = new_ptr(ParticleData(newId, newPDGName));
pap.second = new_ptr(ParticleData(-newId, newAntiPDGName));
antiSetup(pap);
return pap;
}
void ParticleData::readSetup(istream & is) {
long id;
is >> id >> thePDGName >> iunit(theDefMass, GeV) >> iunit(theDefWidth, GeV)
>> iunit(theDefCut, GeV) >> iunit(theDefCTau, mm) >> ienum(theDefCharge)
>> ienum(theDefColour) >> ienum(theDefSpin) >> ienum(isStable);
theId = id;
theMass = theDefMass;
theWidth = theDefWidth;
theWidthUpCut = theDefCut;
theWidthLoCut = theDefCut;
theCTau = theDefCTau;
theCharge = theDefCharge;
theColour = theDefColour;
theSpin = theDefSpin;
if ( PDGName() == "-" ) thePDGName = name();
return;
}
void ParticleData::antiSetup(const PDPair & pap) {
pap.first->theAntiPartner = pap.second;
pap.second->theAntiPartner = pap.first;
pap.first->syncAnti = pap.second->syncAnti = true;
}
PDPtr ParticleData::pdclone() const {
return new_ptr(*this);
}
IBPtr ParticleData::clone() const {
return pdclone();
}
IBPtr ParticleData::fullclone() const {
PDPtr pd = pdclone();
Repository::Register(pd);
pd->theDecaySelector.clear();
pd->theDecayModes.clear();
pd->isStable = true;
PDPtr apd;
if ( CC() ) {
apd = CC()->pdclone();
Repository::Register(apd);
apd->theDecaySelector.clear();
apd->theDecayModes.clear();
apd->isStable = true;
pd->theAntiPartner = apd;
apd->theAntiPartner = pd;
pd->syncAnti = syncAnti;
apd->syncAnti = CC()->syncAnti;
}
HoldFlag<> dosync(pd->syncAnti, true);
for ( DecaySet::const_iterator it = theDecayModes.begin();
it != theDecayModes.end(); ++it )
pd->addDecayMode(*it);
return pd;
}
Energy ParticleData::width(Energy wi) {
theWidth = wi;
if ( synchronized() && CC() ) CC()->theWidth = theWidth;
return theWidth;
}
Energy ParticleData::widthUpCut(Energy wci) {
theWidthUpCut = wci;
if ( synchronized() && CC() ) CC()->theWidthUpCut = theWidthUpCut;
return theWidthUpCut;
}
Energy ParticleData::widthLoCut(Energy wci) {
theWidthLoCut = wci;
if ( synchronized() && CC() ) CC()->theWidthLoCut = theWidthLoCut;
return theWidthLoCut;
}
Length ParticleData::cTau(Length ti) {
theCTau = ti;
if ( synchronized() && CC() ) CC()->theCTau = theCTau;
return theCTau;
}
PDT::Charge ParticleData::iCharge(PDT::Charge ci) {
theCharge = ci;
if ( synchronized() && CC() ) CC()->theCharge = PDT::Charge(-ci);
return theCharge;
}
PDT::Spin ParticleData::iSpin(PDT::Spin si) {
theSpin = si;
if ( synchronized() && CC() ) CC()->theSpin = si;
return si;
}
PDT::Colour ParticleData::iColour(PDT::Colour ci) {
theColour = ci;
if ( synchronized() && CC() ) CC()->theColour = PDT::Colour(-ci);
return theColour;
}
void ParticleData::stable(bool s) {
isStable = s;
if ( synchronized() && CC() ) CC()->isStable = s;
}
void ParticleData::synchronized(bool h) {
syncAnti = h;
if ( CC() ) CC()->syncAnti = h;
}
void ParticleData::variableRatio(bool varRatio) {
theVariableRatio=varRatio;
}
void ParticleData::addDecayMode(tDMPtr dm) {
if ( member(theDecayModes, dm) ) return;
cPDPtr parent = dm->parent();
if ( !parent ) parent = this;
if ( parent != this ) {
dm = dm->clone(this);
}
theDecayModes.insert(dm);
theDecaySelector.insert(dm->brat(), dm);
if ( CC() ) {
if ( !synchronized() ) dm->CC()->switchOff();
CC()->theDecayModes.insert(dm->CC());
CC()->theDecaySelector.insert(dm->CC()->brat(), dm->CC());
}
}
void ParticleData::removeDecayMode(tDMPtr dm) {
theDecayModes.erase(theDecayModes.find(dm));
if(theDecayModes.empty()) isStable = true;
theDecaySelector.erase(dm);
if ( !CC() ) return;
CC()->theDecayModes.erase(dm->CC());
if(CC()->theDecayModes.empty()) CC()->isStable = true;
CC()->theDecaySelector.erase(dm->CC());
}
void ParticleData::synchronize() {
if ( !CC() ) return;
isStable = CC()->isStable;
theMass = CC()->theMass;
+ theHardProcessMass = CC()->theHardProcessMass;
+ hardProcessMassSet = CC()->hardProcessMassSet;
theWidth = CC()->theWidth;
+ theHardProcessWidth = CC()->theHardProcessWidth;
+ hardProcessWidthSet = CC()->hardProcessWidthSet;
theWidthUpCut = CC()->theWidthUpCut;
theWidthLoCut = CC()->theWidthLoCut;
theCTau = CC()->theCTau;
theCharge = PDT::Charge(-CC()->theCharge);
theSpin = CC()->theSpin;
theColour = PDT::antiColour(CC()->theColour);
theMassGenerator = CC()->theMassGenerator;
theWidthGenerator = CC()->theWidthGenerator;
syncAnti = CC()->syncAnti;
theDecaySelector.clear();
for ( DecaySet::iterator it = theDecayModes.begin();
it != theDecayModes.end(); ++it ) {
(*it)->synchronize();
theDecaySelector.insert((*it)->brat(), *it);
}
}
void ParticleData::doupdate() {
Interfaced::doupdate();
bool redo = touched();
for_each(theDecayModes, UpdateChecker(redo));
UpdateChecker::check(theMassGenerator, redo);
UpdateChecker::check(theWidthGenerator, redo);
if ( !redo ) return;
theDecaySelector.clear();
for ( DecaySet::const_iterator dit = theDecayModes.begin();
dit != theDecayModes.end(); ++dit ) {
tDMPtr dm = *dit;
dm->resetOverlap();
for ( DecaySet::const_iterator dit2 = theDecayModes.begin();
dit2 != theDecayModes.end(); ++dit2 )
if ( dit2 != dit ) dm->addOverlap(dm);
if ( dm->brat() > 0.0 ) theDecaySelector.insert(dm->brat(), dm);
}
if ( theMassGenerator && !theMassGenerator->accept(*this) )
throw UpdateException();
if ( theWidthGenerator &&
!theWidthGenerator->accept(*this) )
throw UpdateException();
if ( theWidthGenerator ) theDecaySelector = theWidthGenerator->rate(*this);
touch();
}
tDMPtr ParticleData::selectMode(Particle & p) const {
if ( &(p.data()) != this ) return tDMPtr();
try {
if ( !theWidthGenerator || !theVariableRatio )
return theDecaySelector.select(UseRandom::current());
DecaySelector local;
if ( theWidthGenerator )
local = theWidthGenerator->rate(p);
else
for ( DecaySet::const_iterator mit = theDecayModes.begin();
mit != theDecayModes.end(); ++mit )
local.insert((*mit)->brat(p), *mit);
return local.select(UseRandom::current());
}
catch (range_error) {
return tDMPtr();
}
}
void ParticleData::rebind(const TranslationMap & trans) {
if ( CC() ) theAntiPartner = trans.translate(theAntiPartner);
DecaySet newModes;
DecaySelector newSelector;
for ( DecaySet::iterator it = theDecayModes.begin();
it != theDecayModes.end(); ++it ) {
DMPtr dm;
dm = trans.translate(*it);
if ( !dm ) throw RebindException();
newModes.insert(dm);
newSelector.insert(dm->brat(), dm);
}
theDecayModes.swap(newModes);
theDecaySelector.swap(newSelector);
}
IVector ParticleData::getReferences() {
IVector refs = Interfaced::getReferences();
if ( CC() ) refs.push_back(CC());
refs.insert(refs.end(), theDecayModes.begin(), theDecayModes.end());
return refs;
}
void ParticleData::massGenerator(tMassGenPtr mg) {
if ( mg && !mg->accept(*this) ) return;
if ( mg && synchronized() && CC() && !mg->accept(*CC()) ) return;
theMassGenerator = mg;
if ( synchronized() && CC() ) CC()->theMassGenerator = mg;
}
void ParticleData::widthGenerator(tWidthGeneratorPtr newGen) {
if ( newGen && !newGen->accept(*this) ) return;
if ( newGen && synchronized() && CC() && !newGen->accept(*CC()) ) return;
theWidthGenerator = newGen;
if ( synchronized() && CC() ) CC()->theWidthGenerator = newGen;
}
Energy ParticleData::generateMass() const {
return massGenerator()? massGenerator()->mass(*this): mass();
}
Energy ParticleData::generateWidth(Energy m) const {
return widthGenerator()? widthGenerator()->width(*this, m): width();
}
Length ParticleData::generateLifeTime(Energy m, Energy w) const {
return widthGenerator() ?
widthGenerator()->lifeTime(*this, m, w) :
UseRandom::rndExp(cTau());
}
PPtr ParticleData::produceParticle(const Lorentz5Momentum & pp) const {
PPtr p = new_ptr(Particle(this));
p->set5Momentum(pp);
return p;
}
PPtr ParticleData::produceParticle(const LorentzMomentum & pp) const {
PPtr p(produceParticle(Lorentz5Momentum(pp)));
return p;
}
PPtr ParticleData::produceParticle(const LorentzMomentum & pp, Energy m) const {
PPtr p(produceParticle(Lorentz5Momentum(pp, m)));
return p;
}
PPtr ParticleData::produceParticle(Energy m, const Momentum3 & pp) const {
PPtr p(produceParticle(Lorentz5Momentum(m, pp)));
return p;
}
PPtr ParticleData::produceParticle(const Momentum3 & pp) const {
PPtr p(produceParticle(Lorentz5Momentum(generateMass(), pp)));
return p;
}
PPtr ParticleData::
produceParticle(Energy plus, Energy minus, Energy px, Energy py) const {
PPtr p(produceParticle(LorentzMomentum(px, py, 0.5*(plus-minus),
0.5*(plus+minus))));
return p;
}
void ParticleData::setMass(Energy mi) {
theMass = mi;
ParticleData * apd = CC().operator->();
if ( synchronized() && apd ) apd->theMass = theMass;
}
+void ParticleData::setHardProcessMass(Energy mi) {
+ theHardProcessMass = mi;
+ hardProcessMassSet = true;
+ ParticleData * apd = CC().operator->();
+ if ( synchronized() && apd ) {
+ apd->theHardProcessMass = theHardProcessMass;
+ apd->hardProcessMassSet = true;
+ }
+}
+
+void ParticleData::setHardProcessWidth(Energy mi) {
+ theHardProcessWidth = mi;
+ hardProcessWidthSet = true;
+ ParticleData * apd = CC().operator->();
+ if ( synchronized() && apd ) {
+ apd->theHardProcessWidth = theHardProcessWidth;
+ apd->hardProcessWidthSet = true;
+ }
+}
+
+string ParticleData::doUnsetHardProcessMass(string) {
+ hardProcessMassSet = false;
+ theHardProcessMass = -1.*GeV;
+ return "";
+}
+
+string ParticleData::doAdjustNominalMass(string) {
+ if ( hardProcessMassSet )
+ setMass(theHardProcessMass);
+ return "";
+}
+
+string ParticleData::doUnsetHardProcessWidth(string) {
+ hardProcessWidthSet = false;
+ theHardProcessWidth = -1.*GeV;
+ return "";
+}
+
Energy ParticleData::defMass() const {
return theDefMass;
}
void ParticleData::setWidth(Energy wi) {
width(wi);
}
Energy ParticleData::getWidth() const {
return width();
}
Energy ParticleData::defWidth() const {
return theDefWidth;
}
void ParticleData::setCut(Energy ci) {
widthCut(ci);
}
Energy ParticleData::getCut() const {
return (theWidthUpCut >= ZERO && theWidthLoCut >= ZERO)?
max(theWidthUpCut, theWidthLoCut): min(theWidthUpCut, theWidthLoCut);
}
Energy ParticleData::defCut() const {
return theDefCut;
}
void ParticleData::setUpCut(Energy ci) {
widthUpCut(ci);
}
Energy ParticleData::getUpCut() const {
return theWidthUpCut;
}
void ParticleData::setLoCut(Energy ci) {
widthLoCut(ci);
}
Energy ParticleData::getLoCut() const {
return theWidthLoCut;
}
void ParticleData::setCTau(Length ti) {
cTau(ti);
}
Length ParticleData::getCTau() const {
return cTau();
}
Length ParticleData::defCTau() const {
return theDefCTau;
}
void ParticleData::setStable(long is) {
stable(is);
}
long ParticleData::getStable() const {
return stable();
}
void ParticleData::setSync(long is) {
synchronized(is);
}
long ParticleData::getSync() const {
return synchronized();
}
void ParticleData::setVariableRatio(long is) {
variableRatio(is);
}
long ParticleData::getVariableRatio() const {
return variableRatio();
}
string ParticleData::doSync(string) {
synchronize();
return "";
}
void ParticleData::setMassGenerator(MassGenPtr gi) {
massGenerator(gi);
}
void ParticleData::setWidthGenerator(WidthGeneratorPtr wg) {
widthGenerator(wg);
}
void ParticleData::setColour(long c) {
theColour = PDT::Colour(c);
}
long ParticleData::getColour() const {
return theColour;
}
long ParticleData::defColour() const {
return theDefColour;
}
void ParticleData::setCharge(int c) {
theCharge = PDT::Charge(c);
}
string ParticleData::ssetCharge(string arg) {
istringstream is(arg);
long i;
if ( is >> i ) {
theCharge = PDT::Charge(i);
return "New charge is " + arg;
}
if ( arg == "unknown" )
theCharge = PDT::ChargeUnknown;
else if ( arg == "charged" )
theCharge = PDT::Charged;
else if ( arg == "positive" )
theCharge = PDT::Positive;
else if ( arg == "negative" )
theCharge = PDT::Negative;
else throw ParticleChargeCommand(*this, arg);
return "New charge is " + arg;
}
int ParticleData::getCharge() const {
return theCharge;
}
int ParticleData::defCharge() const {
return theDefCharge;
}
void ParticleData::setSpin(int s) {
theSpin = PDT::Spin(s);
}
int ParticleData::getSpin() const {
return theSpin;
}
int ParticleData::defSpin() const {
return theDefSpin;
}
ClassDescription<ParticleData> ParticleData::initParticleData;
struct ParticleOrdering {
bool operator()(tcPDPtr p1, tcPDPtr p2) {
return abs(p1->id()) > abs(p2->id()) ||
( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) ||
( p1->id() == p2->id() && p1->fullName() > p2->fullName() );
}
};
struct ModeOrdering {
bool operator()(const tcDMPtr & d1, const tcDMPtr & d2) {
ParticleOrdering ord;
return ord(d1->parent(), d2->parent()) ||
( !ord(d2->parent(), d1->parent()) &&
( d1->tag() < d2->tag() ||
( d1->tag() == d2->tag() && d1->fullName() < d2->fullName() ) ) );
}
};
void ParticleData::persistentOutput(PersistentOStream & os) const {
multiset<tcDMPtr,ModeOrdering>
modes(theDecayModes.begin(), theDecayModes.end());
os << long(theId) << thePDGName << ounit(theMass, GeV) << ounit(theWidth, GeV)
+ << ounit(theHardProcessMass,GeV) << hardProcessMassSet
+ << ounit(theHardProcessWidth,GeV) << hardProcessWidthSet
<< ounit(theWidthUpCut, GeV) << ounit(theWidthLoCut, GeV)
<< ounit(theCTau, mm) << oenum(theCharge) << oenum(theSpin)
<< oenum(theColour);
os << theMassGenerator << isStable << modes << theDecaySelector
<< theWidthGenerator << theVariableRatio << theAntiPartner << syncAnti
<< ounit(theDefMass, GeV) << ounit(theDefWidth, GeV)
<< ounit(theDefCut, GeV) << ounit(theDefCTau, mm) << oenum(theDefColour)
<< oenum(theDefCharge) << oenum(theDefSpin);
}
void ParticleData::persistentInput(PersistentIStream & is, int) {
long id;
is >> id >> thePDGName >> iunit(theMass, GeV) >> iunit(theWidth, GeV)
+ >> iunit(theHardProcessMass,GeV) >> hardProcessMassSet
+ >> iunit(theHardProcessWidth,GeV) >> hardProcessWidthSet
>> iunit(theWidthUpCut, GeV) >> iunit(theWidthLoCut, GeV)
>> iunit(theCTau, mm) >> ienum(theCharge) >> ienum(theSpin)
>> ienum(theColour) >> theMassGenerator >> isStable
>> theDecayModes >> theDecaySelector >> theWidthGenerator >> theVariableRatio
>> theAntiPartner >> syncAnti >> iunit(theDefMass, GeV)
>> iunit(theDefWidth, GeV) >> iunit(theDefCut, GeV)
>> iunit(theDefCTau, mm) >> ienum(theDefColour) >> ienum(theDefCharge)
>> ienum(theDefSpin);
theId = id;
}
void ParticleData::Init() {
static ClassDocumentation<ParticleData> documentation
("There is no documentation for the ThePEG::ParticleData class");
static Parameter<ParticleData,Energy> interfaceMass
("NominalMass",
"The nominal mass in GeV of the particle. The actual mass "
"of a particle instance is generated depending on the "
"nominal mass and the width and is generated by the "
"<interface>Mass_generator</interface> object associated with the "
"particle.",
&ParticleData::theMass, GeV, ZERO, ZERO, Constants::MaxEnergy,
false, false, Interface::lowerlim,
&ParticleData::setMass, 0, 0, 0, &ParticleData::defMass);
+ static Parameter<ParticleData,Energy> interfaceHardProcessMass
+ ("HardProcessMass",
+ "The mass in GeV of the particle to be used in calculating hard process cross sections.",
+ &ParticleData::theHardProcessMass, GeV, ZERO, ZERO, Constants::MaxEnergy,
+ false, false, Interface::lowerlim,
+ &ParticleData::setHardProcessMass, 0, 0, 0, 0);
+
static Parameter<ParticleData,Energy> interfaceDefMass
("DefaultMass",
"The default nominal mass in GeV of the particle. The actual mass "
"of a particle instance is generated depending on the "
"nominal mass and the width and is generated by the "
"<interface>Mass_generator</interface> object associated with the "
"particle.",
&ParticleData::theDefMass, GeV, ZERO, ZERO, Constants::MaxEnergy,
false, true, Interface::lowerlim);
interfaceDefMass.setHasDefault(false);
static Parameter<ParticleData,Energy> interfaceWidth
("Width",
"The width of the particle in GeV.",
0, GeV, ZERO, ZERO, Constants::MaxEnergy,
false, false, Interface::lowerlim,
&ParticleData::setWidth, &ParticleData::getWidth,
0, 0, &ParticleData::defWidth);
+ static Parameter<ParticleData,Energy> interfaceHardProcessWidth
+ ("HardProcessWidth",
+ "The width in GeV of the particle to be used in calculating hard process cross sections.",
+ &ParticleData::theHardProcessWidth, GeV, ZERO, ZERO, Constants::MaxEnergy,
+ false, false, Interface::lowerlim,
+ &ParticleData::setHardProcessWidth, 0, 0, 0, 0);
+
static Parameter<ParticleData,Energy> interfaceDefWidth
("DefaultWidth",
"The default width of the particle in GeV.",
&ParticleData::theDefWidth, GeV, ZERO, ZERO, Constants::MaxEnergy,
false, true, Interface::lowerlim);
interfaceDefWidth.setHasDefault(false);
static Parameter<ParticleData,Energy> interfaceWidthUpCut
("WidthUpCut",
"The upper hard cutoff in GeV in generated mass, which is the maximum "
"allowed upwards deviation from the nominal mass. A negative value "
"corresponds to no limit.",
0, GeV, ZERO, -1.0*GeV, Constants::MaxEnergy,
false, false, Interface::lowerlim,
&ParticleData::setUpCut, &ParticleData::getUpCut,
0, 0, &ParticleData::defCut);
static Parameter<ParticleData,Energy> interfaceWidthLoCut
("WidthLoCut",
"The lower hard cutoff in GeV in generated mass, which is the maximum "
"allowed downwards deviation from the nominal mass. A negative value "
"corresponds to no limit.",
0, GeV, ZERO, -1.0*GeV, Constants::MaxEnergy,
false, false, Interface::lowerlim,
&ParticleData::setLoCut, &ParticleData::getLoCut,
0, 0, &ParticleData::defCut);
static Parameter<ParticleData,Energy> interfaceWidthCut
("WidthCut",
"The hard cutoff in GeV in generated mass, which is the maximum "
"allowed deviation from the nominal mass. Sets both the upper and lower "
"cut. (The displayed value is the maximium of the upper and lower cut.) "
"A negative value corresponds to no limit.",
0, GeV, ZERO, -1.0*GeV, Constants::MaxEnergy,
false, false, Interface::lowerlim,
&ParticleData::setCut, &ParticleData::getCut,
0, 0, &ParticleData::defCut);
interfaceWidthCut.setHasDefault(false);
static Parameter<ParticleData,Energy> interfaceDefWidthCut
("DefaultWidthCut",
"The default hard cutoff in GeV in generated mass, which is the maximum "
"allowed deviation from the nominal mass. For the actual cutoff, the "
"upper and lower cut can be set separately.",
&ParticleData::theDefCut, GeV, ZERO, ZERO, Constants::MaxEnergy,
false, true, Interface::lowerlim);
interfaceDefWidthCut.setHasDefault(false);
static Parameter<ParticleData,Length> interfaceCTau
("LifeTime",
"c times the average lifetime of the particle measuerd in mm."
"The actual lifetime of a particle instance is generated "
"from this number by the <interface>Mass_generator</interface> "
"object associated with the particle.",
0, mm, ZERO, ZERO, Constants::MaxLength,
false, false, Interface::lowerlim,
&ParticleData::setCTau, &ParticleData::getCTau,
0, 0, &ParticleData::defCTau);
interfaceCTau.setHasDefault(false);
static Parameter<ParticleData,Length> interfaceDefCTau
("DefaultLifeTime",
"c times the default average lifetime of the particle measuerd in mm."
"The actual lifetime of a particle instance is generated "
"from this number by the <interface>Mass_generator</interface> "
"object associated with the particle.",
&ParticleData::theDefCTau, mm, ZERO, ZERO, Constants::MaxLength,
false, true, Interface::lowerlim);
interfaceDefCTau.setHasDefault(false);
static Switch<ParticleData> interfaceColour
("Colour",
"The colour quantum number of this particle type.",
0, -1, false, false, &ParticleData::setColour, &ParticleData::getColour,
&ParticleData::defColour);
static SwitchOption interfaceColourUndefined
(interfaceColour, "Undefined", "The coulur is undefined.", -1);
static SwitchOption interfaceColourNeutral
(interfaceColour, "Neutral", "This particle is colour neutral.", 0);
static SwitchOption interfaceColour3
(interfaceColour, "Triplet", "This particle is a colour triplet.", 3);
static SwitchOption interfaceColour3bar
(interfaceColour, "AntiTriplet",
"This particle is a colour anti-triplet.", -3);
static SwitchOption interfaceColour6
(interfaceColour, "Sextet", "This particle is a colour sextet.", 6);
static SwitchOption interfaceColour6bar
(interfaceColour, "AntiSextet",
"This particle is a colour anti-sextet.", -6);
static SwitchOption interfaceColour8
(interfaceColour, "Octet", "This particle is a colour octet.", 8);
static Switch<ParticleData,PDT::Colour> interfaceDefColour
("DefaultColour",
"The default colour quantum number of this particle type.",
&ParticleData::theDefColour, PDT::Colour(-1), false, true);
static SwitchOption interfaceDefColourUndefined
(interfaceDefColour, "Undefined", "The coulur is undefined.", -1);
static SwitchOption interfaceDefColourNeutral
(interfaceDefColour, "Neutral", "This particle is colour neutral.", 0);
static SwitchOption interfaceDefColour3
(interfaceDefColour, "Triplet", "This particle is a colour triplet.", 3);
static SwitchOption interfaceDefColour3bar
(interfaceDefColour, "AntiTriplet",
"This particle is a colour anti-triplet.", -3);
static SwitchOption interfaceDefColour6
(interfaceDefColour, "Sextet", "This particle is a colour sextet.", 6);
static SwitchOption interfaceDefColour6bar
(interfaceDefColour, "AntiSextet",
"This particle is a colour anti-sextet.", -6);
static SwitchOption interfaceDefColour8
(interfaceDefColour, "Octet", "This particle is a colour octet.", 8);
interfaceDefColour.setHasDefault(false);
static Parameter<ParticleData, int> interfaceCharge
("Charge",
"The charge of this particle in units of e/3. "
"See also the command interface <interface>SetCharge</interface>.",
0, 0, -24, 24, false, false, true,
&ParticleData::setCharge, &ParticleData::getCharge, 0, 0,
&ParticleData::defCharge);
static Parameter<ParticleData, PDT::Charge> interfaceDefCharge
("DefaultCharge",
"The default charge of this particle in units of e/3. "
"See also the command interface <interface>SetCharge</interface>.",
&ParticleData::theDefCharge, PDT::Charge(0), PDT::Charge(-24),
PDT::Charge(24), false, true, true);
interfaceDefCharge.setHasDefault(false);
static Command<ParticleData> interfaceSetCharge
("SetCharge",
"Set the charge of this particle. The argument should be given as an "
"interger giving three times the unit charge, or 'unknown', "
"'charged', 'positive' or 'negative'", &ParticleData::ssetCharge);
static Parameter<ParticleData, int> interfaceSpin
("Spin",
"The spin quantim number of this particle on the form 2j+1.",
0, 0, 0, 9, false, false, true,
&ParticleData::setSpin, &ParticleData::getSpin, 0, 0,
&ParticleData::defSpin);
static Parameter<ParticleData, PDT::Spin> interfaceDefSpin
("DefaultSpin",
"The default spin quantim number of this particle on the form 2j+1.",
&ParticleData::theDefSpin, PDT::Spin(0), PDT::Spin(0), PDT::Spin(9),
false, true, true);
interfaceDefSpin.setHasDefault(false);
static Switch<ParticleData> interfaceStable
("Stable",
"Indicates if the particle is stable or not.",
0, 0, false, false,
&ParticleData::setStable, &ParticleData::getStable, 0);
static SwitchOption interfaceStableYes
(interfaceStable,
"Stable",
"This particle is stable",
1);
static SwitchOption interfaceStableNo
(interfaceStable,
"Unstable",
"This particle is not stable",
0);
interfaceStable.setHasDefault(false);
static Switch<ParticleData> interfaceVariableRatio
("VariableRatio",
"Indicates if the branching ratios of the particle are allowed"
" to vary for given Particle instances depending on the mass of the instance.",
0, 0, false, false,
&ParticleData::setVariableRatio, &ParticleData::getVariableRatio, 0);
static SwitchOption interfaceVariableRatioYes
(interfaceVariableRatio,
"Yes",
"The branching ratio varies.",
1);
static SwitchOption interfaceVariableRatioNo
(interfaceVariableRatio,
"No",
"The branching ratio does not vary.",
0);
static Switch<ParticleData> interfaceSync
("Synchronized",
"Indicates if the changes to this particle is propagated to "
"its anti-partner or not. Note that setting this switch does not "
"actually synchronize the properties with the anti-partner, "
"it only assures that following changes are propagated. "
"To sync the particle with its anti-particle, use the "
"<interface>Synchronize</interface> command.",
0, 1, false, false,
&ParticleData::setSync, &ParticleData::getSync, 0);
static SwitchOption interfaceSyncYes
(interfaceSync,
"Synchronized",
"Changes to this particle will propagate to its "
"anti-partner",
1);
static SwitchOption interfaceSyncNo
(interfaceSync,
"Not_synchronized",
"Changes to this particle will propagate to its "
"anti-partner",
0);
interfaceSync.setHasDefault(false);
static Command<ParticleData> interfaceSynchronize
("Synchronize",
"Synchronizes this particle so that all its properties "
"correspond to those of its anti-partner",
&ParticleData::doSync, false);
static Reference<ParticleData,MassGenerator> interfaceMassGenerator
("Mass_generator",
"An object derived from the ThePEG::MassGenerator"
"class, which is able to generate a mass for a given "
"particle instance",
&ParticleData::theMassGenerator, false, false, true, true,
&ParticleData::setMassGenerator, 0, 0);
static Reference<ParticleData,WidthGenerator> interfaceWidthGenerator
("Width_generator",
"An object derived from the ThePEG::WidthGenerator class, "
"which is able to calculate the full and partial widths for"
"this particle type and for a given instance of this "
"particle type.",
&ParticleData::theWidthGenerator, false, false, true, true,
&ParticleData::setWidthGenerator, 0, 0);
static RefVector<ParticleData,DecayMode> interfaceDecayModes
("DecayModes",
"The list of decay modes defined for this particle type.",
0, -1, false, false, false, false, 0,
&ParticleData::insDecayModes, &ParticleData::delDecayModes,
&ParticleData::getDecayModes);
static Command<ParticleData> interfaceSelectDecayModes
("SelectDecayModes",
"Only the decay modes which are given as (white-space separated) "
"decay tags will be switched on, all others will be switched off. "
"If no argument or 'none' is given, all decay modes are switched off. "
"If the argument is 'all', all decay modes are switched on.",
&ParticleData::doSelectDecayModes, false);
static Command<ParticleData> interfacePrintDecayModes
("PrintDecayModes",
"Print all decay modes of this particle.",
&ParticleData::doPrintDecayModes, true);
+
+ static Command<ParticleData> interfaceUnsetHardProcessMass
+ ("UnsetHardProcessMass",
+ "Unset a previously set hard process mass.",
+ &ParticleData::doUnsetHardProcessMass, false);
+
+ static Command<ParticleData> interfaceAdjustNominalMass
+ ("AdjustNominalMass",
+ "Unset a previously set hard process mass.",
+ &ParticleData::doAdjustNominalMass, false);
+
+ static Command<ParticleData> interfaceUnsetHardProcessWidth
+ ("UnsetHardProcessWidth",
+ "Unset a previously set hard process width.",
+ &ParticleData::doUnsetHardProcessWidth, false);
+
interfaceStable.rank(14);
interfaceDecayModes.rank(13);
interfaceMass.rank(12);
interfaceWidth.rank(11);
interfaceWidthCut.rank(10);
interfaceCTau.rank(9);
interfaceMassGenerator.rank(8);
interfaceWidthGenerator.rank(7);
interfaceWidthUpCut.rank(-0.1);
interfaceWidthLoCut.rank(-0.1);
}
string ParticleData::doPrintDecayModes(string) {
multimap<double,tDMPtr, std::greater<double> > sorted;
for ( DecaySet::iterator it = decayModes().begin();
it != decayModes().end(); ++it )
sorted.insert(make_pair((**it).brat(), *it));
ostringstream os;
for ( multimap<double,tDMPtr,
std::greater<double> >::iterator it = sorted.begin();
it != sorted.end(); ++it )
os << it->second->tag()
<< (it->second->on()? " ": " (off) ")
<< it->first << endl;
return os.str();
}
string ParticleData::doSelectDecayModes(string args) {
DecaySet on;
while ( !args.empty() ) {
string arg = StringUtils::car(args);
if ( arg == "all" ) {
on = decayModes();
break;
}
if ( arg == "none" ) {
on.clear();
break;
}
string name = arg;
args = StringUtils::cdr(args);
if ( arg.empty() ) continue;
if ( arg[0] != '/' ) arg = fullName() + "/" + arg;
DMPtr dm = Repository::GetPtr<DMPtr>(arg);
if ( !dm ) return "Error: No decay mode with tag '" + name + "' exists.";
on.insert(dm);
}
for ( DecaySet::iterator it = decayModes().begin();
it != decayModes().end(); ++it ) {
if ( on.find(*it) != on.end() ) {
(**it).switchOn();
on.erase(*it);
} else {
(**it).switchOff();
}
}
if ( !on.empty() )
return "Error: decay mode '" + (**on.begin()).tag() + "'was not available.";
return "";
}
void ParticleData::insDecayModes(DMPtr dm, int) {
addDecayMode(dm);
}
void ParticleData::delDecayModes(int i) {
vector<DMPtr> mv = getDecayModes();
if ( i >= 0 && static_cast<unsigned int>(i) < mv.size() ) removeDecayMode(mv[i]);
}
vector<DMPtr> ParticleData::getDecayModes() const {
return vector<DMPtr>(theDecayModes.begin(), theDecayModes.end());
}
ParticleChargeCommand::
ParticleChargeCommand(const ParticleData & pd, string arg) {
theMessage << "Cannot set the charge of particle '" << pd.name()
<< "' to '" << arg << "'.";
severity(warning);
}
void ParticleData::doinit() {
Interfaced::doinit();
if( theMassGenerator ) theMassGenerator->init();
if( theWidthGenerator ) theWidthGenerator->init();
}
void ParticleData::doinitrun() {
Interfaced::doinitrun();
if( theMassGenerator ) theMassGenerator->initrun();
if( theWidthGenerator ) theWidthGenerator->initrun();
}
}
diff --git a/PDT/ParticleData.h b/PDT/ParticleData.h
--- a/PDT/ParticleData.h
+++ b/PDT/ParticleData.h
@@ -1,901 +1,963 @@
// -*- C++ -*-
//
// ParticleData.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_ParticleData_H
#define ThePEG_ParticleData_H
// This is the declaration of the ParticleData class.
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/PDT/PDT.h"
#include "ThePEG/PDT/PID.h"
#include "ThePEG/Vectors/LorentzVector.h"
#include "ThePEG/Vectors/ThreeVector.h"
#include "ThePEG/Interface/Interfaced.h"
#include "ThePEG/Utilities/Selector.h"
#include "ThePEG/PDT/WidthGenerator.h"
#include "ThePEG/PDT/MassGenerator.h"
#include "ThePEG/PDT/DecayMode.fh"
#include "ThePEG/Utilities/ClassTraits.h"
#include "ThePEG/Utilities/ClassDescription.h"
namespace ThePEG {
/**
* ParticleData inherits from InterfacedBase and represents the
* properties of a particle type. It is also able to produce instances
* of this Particle type and, among other things, to decay them.
*
* @see \ref ParticleDataInterfaces "The interfaces"
* defined for ParticleData.
*/
class ParticleData: public Interfaced {
public:
/** The Repository is a friend. */
friend class Repository;
/** The EventGenerator is a friend. */
friend class EventGenerator;
/** DecayMode is a friend. */
friend class DecayMode;
/** A selector of DecayMode objects. */
typedef Selector<tDMPtr> DecaySelector;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* Default constructor.
*/
ParticleData();
/**
* Destructor.
*/
virtual ~ParticleData();
//@}
/** @name The Create methods are special interfaces for ParticleData
classes. */
//@{
/**
* Create a Particle which is its own anti-particle.
*/
static PDPtr Create(PID newId, const string & newPDGName);
/**
* Create a particle - anti particle pair.
*/
static PDPair Create(PID newId, const string & newPDGName, const string & newAntiPDGName);
//@}
public:
/** @name Acces to number and name. */
//@{
/**
* Return the PDG id number.
*/
long id() const { return theId; }
/**
* Return the generic PDG name. Note that this is not really
* standardised.
*/
const string & PDGName() const { return thePDGName; }
/**
* Return the generic PDG name. Note that this is not really
* standardised.
*/
const string & genericName() const { return thePDGName; }
//@}
/** @name Functions used for producing Particle instances. */
//@{
/**
* Produce a particle specifying momentum.
*/
PPtr produceParticle(const Lorentz5Momentum &) const;
/**
* Produce a particle specifying momentum.
*/
PPtr produceParticle(const LorentzMomentum &) const;
/**
* Produce a particle specifying 4-momentum and a mass.
*/
PPtr produceParticle(const LorentzMomentum &, Energy m) const;
/**
* Produce a particle specifying 3-momentum.
*/
PPtr produceParticle(const Momentum3 & pp = Momentum3()) const;
/**
* Produce a particle specifying mass and 3-momentum.
*/
PPtr produceParticle(Energy m, const Momentum3 & pp = Momentum3()) const;
/**
* Produce a particle specifying light-cone momentum components and
* transverse momentum components.
*/
PPtr produceParticle(Energy plus, Energy minus, Energy px, Energy py) const;
/**
* Generate a mass for an instance of this particle type.
*/
Energy generateMass() const;
/**
* Generate a width for an instance of this particle type. Given a
* \a mass of an instance of this particle type, calculate its width.
*/
Energy generateWidth(Energy mass) const;
/**
* Generate a mass for an instance of this particle type. Given a \a
* mass and a \a width of an instance of this particle type,
* generate a life time.
*/
Length generateLifeTime(Energy mass, Energy width) const;
// Given a mass and a width of an instance of this particle type,
// generate a life time.
//@}
/** @name Access the decay modes. */
//@{
/**
* Return the nominal decay selector for this particle. Ie. the
* decay modes weighted by their nominal branching ratios.
*/
const DecaySelector & decaySelector() const { return theDecaySelector; }
/**
* Selects a decay mode randomly according to the branching
* ratios. The nominal branching ratios may be changed for the
* particular Particle instance \a p, iether by an assigned
* WidthGenerator or the respective Decayers.
*/
tDMPtr selectMode(Particle & p) const;
/**
* Access all the decay modes, including those which are
* switched off, or have zero branching ratio
*/
const DecaySet & decayModes() const { return theDecayModes; }
//@}
/**
* Return the nominal mass.
*/
Energy mass() const { return theMass; }
/**
+ * Return the mass to be used when evaluating hard process cross sections.
+ */
+ Energy hardProcessMass() const {
+ return
+ hardProcessMassSet ? theHardProcessMass : mass();
+ }
+
+ /**
* Return the maximum possible mass of this particle type.
*/
Energy massMax() const { return mass() + widthUpCut(); }
/**
* Return the minimum possible mass of this particle type.
*/
Energy massMin() const { return max(mass() - widthLoCut(), ZERO); }
/**
* Return the constituent mass of this particle if relevant. This
* version simply returns the nominal mass.
*/
virtual Energy constituentMass() const { return mass(); }
/**
* Set the width.
*/
Energy width(Energy);
/**
* Get the width. If no width is specified, it is calculated from
* the lifetime.
*/
Energy width() const {
return theWidth >= ZERO ? theWidth :
( theCTau > Length() ? hbarc/theCTau :
( theCTau == Length() ? Constants::MaxEnergy : ZERO ) );
}
/**
* Set the width cut. Both upper and lower cut is set.
*/
Energy widthCut(Energy wci) {
widthUpCut(wci);
return widthLoCut(wci);
}
/**
* Get the width cut.
*/
Energy widthCut() const { return max(widthUpCut(), widthLoCut()); }
/**
* Set the upper width cut.
*/
Energy widthUpCut(Energy);
/**
* Get the upper width cut.
*/
Energy widthUpCut() const {
return theWidthUpCut >= ZERO? theWidthUpCut: Constants::MaxEnergy;
}
/**
* Set the lower width cut.
*/
Energy widthLoCut(Energy);
/**
* Get the lower width cut.
*/
Energy widthLoCut() const {
return theWidthLoCut >= ZERO? theWidthLoCut: Constants::MaxEnergy;
}
/**
* Set the life time cTau.
*/
Length cTau(Length);
/**
* Get the life time cTau cTau. If no life time is specified, it is
* calculated from the width. If the width is also not specified,
* the lifetime is assumed to be zero for ustable particles and
* infinite for stable ones.
*/
Length cTau() const {
return theCTau > Length() ? theCTau :
( theWidth > ZERO ? hbarc/theWidth :
( stable() ? Constants::MaxLength : Length() ) );
}
/**
+ * Return the width to be used when evaluating hard process cross sections.
+ */
+ Energy hardProcessWidth() const {
+ return
+ hardProcessWidthSet ? theHardProcessWidth : width();
+ }
+
+ /**
* Set the charge. The charge should be given
* in units of e/3 using the PDT::Charge enum.
*/
PDT::Charge iCharge(PDT::Charge);
/**
* Get the charge. The charge is returned in standard units and in
* iCharge the charge is returned in units of e/3.
*/
Charge charge() const { return eplus*double(theCharge)/3.0; }
/**
* Get the charge. The charge is returned in units of e/3.
*/
PDT::Charge iCharge() const { return theCharge; }
/**
* Return true if charged.
*/
bool charged() const { return PDT::charged(theCharge); }
/**
* Return true if positively charged.
*/
bool positive() const { return PDT::positive(theCharge); }
/**
* Return true if negatively charged.
*/
bool negative() const { return PDT::negative(theCharge); }
/**
* Set the spin. The spin should be given as 2J+1 (in units of
* hbar/2) using the PDT::Spin enum.
*/
PDT::Spin iSpin(PDT::Spin);
/**
* Get the spin.The spin is returned in standard units.
*/
AngularMomentum spin() const { return hbar_Planck*double(theSpin-1)*0.5; }
/**
* Get the spin. The spin is returned as 2J+1 in units of hbar/2.
*/
PDT::Spin iSpin() const { return theSpin; }
/**
* Set the colour of the particle in units of PDT::Colour.
*/
PDT::Colour iColour(PDT::Colour);
/**
* Get the colour of the particle in units of PDT::Colour.
*/
PDT::Colour iColour() const { return theColour; }
/**
* Return true if coloured.
*/
bool coloured() const { return PDT::coloured(iColour()); }
/**
* Return true if (\a anti) coloured or colour-octet.
*/
bool hasColour(bool anti = false) const {
return anti? hasAntiColour():
( iColour() == PDT::Colour3 || iColour() == PDT::Colour6 ||
iColour() == PDT::Colour8 );
}
/**
* Return true if anti coloured or colour-octet.
*/
bool hasAntiColour() const {
return iColour() == PDT::Colour3bar || iColour() == PDT::Colour6bar ||
iColour() == PDT::Colour8;
}
/**
* Specify if particle is to be considered stable according to \a
* stab.
*/
void stable(bool stab);
/**
* Return true if particle is to be considered stable. If the decay
* table is empty the function always returns true, even if the
* member variable is false.
*/
bool stable() const { return isStable; }
/**
* Get the pointer to the corresponding anti partner.
*/
tPDPtr CC() const { return theAntiPartner; }
/**
* Specify if the anti partner chould be changed automatically when
* this object is changed according to \a sync.
*/
void synchronized(bool sync);
/**
* Return true if the anti partner chould be changed automatically
* when this object is changed.
*/
bool synchronized() const { return syncAnti; }
/**
* If there is an anti-partner, update this object to have correct
* anti-properties.
*/
void synchronize();
/**
* Set the mass generator object.
*/
void massGenerator(tMassGenPtr);
/**
* Get the mass generator object.
*/
tMassGenPtr massGenerator() const { return theMassGenerator; }
/**
* Set the width generator object.
*/
void widthGenerator(tWidthGeneratorPtr);
/**
* Get the width generator object.
*/
tWidthGeneratorPtr widthGenerator() const { return theWidthGenerator; }
/**
* Specify if the branching ratio of the Particle instances should vary with their
* masses.
*/
void variableRatio(bool varRatio);
/**
* Return true if the branching ratio should vary with the mass of the Particle
* instance.
*/
bool variableRatio() const { return theVariableRatio; }
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);
//@}
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;
//@}
/**
* Special clone function used by the Repository. Also makes copies
* the decay modes and the anti-partner if it exists and if
* synchronized() is true.
*/
virtual PDPtr pdclone() const;
/**
* Protected constructor only to be used by subclasses or by the
* Create method.
*/
ParticleData(PID newId, const string & newPDGName);
/**
* Read setup info from a standard stream. The following information
* must be supplied in a white-space separated list: PDG number,
* generic name, default mass (GeV), default width (GeV), width cut
* (GeV), the lifetime ctau (mm), the charge, the colour, the spin,
* stable (true) or not (false). Note that if a minus sign is given
* instead of a generic name, the name of the object will be used
* instead.
*/
virtual void readSetup(istream & is);
/**
* Used by subclasses or by the Create method to setup
* anti-relationship.
*/
static void antiSetup(const PDPair & pap);
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Check sanity of the object during the setup phase.
*/
virtual void doupdate();
/**
* 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();
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
;
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
protected:
/**
* Add a decay mode for this particle.
*/
void addDecayMode(tDMPtr);
/**
* Remove a decay mode for this particle.
*/
void removeDecayMode(tDMPtr);
private:
/**
* Id number according to the STDHEP/PDG standard.
*/
PID theId;
/**
* Name and Id number according to the STDHEP/PDG standard.
*/
string thePDGName;
/**
* Nominal mass.
*/
Energy theMass;
/**
* Width.
*/
Energy theWidth;
/**
+ * The mass to be used when evaluating hard process cross sections.
+ */
+ Energy theHardProcessMass;
+
+ /**
+ * True, if a hard process mass has been set.
+ */
+ bool hardProcessMassSet;
+
+ /**
+ * The width to be used when evaluating hard process cross sections.
+ */
+ Energy theHardProcessWidth;
+
+ /**
+ * True, if a hard process width has been set.
+ */
+ bool hardProcessWidthSet;
+
+ /**
* Upper width cut.
*/
Energy theWidthUpCut;
/**
* Lower width cut.
*/
Energy theWidthLoCut;
/**
* Lifetime.
*/
Length theCTau;
/**
* Three times the charge.
*/
PDT::Charge theCharge;
/**
* 2 times the spin plus one.
*/
PDT::Spin theSpin;
/**
* The colour for this particle.
*/
PDT::Colour theColour;
/**
* A pointer to an object capable to generate a mass for a particle
* of this type.
*/
MassGenPtr theMassGenerator;
/**
* True if the particle is considered stable.
*/
bool isStable;
/**
* A selector of decay modes weighted by the nominal branching
* ratios.
*/
DecaySelector theDecaySelector;
/**
* The set of all decay modes.
*/
DecaySet theDecayModes;
/**
* A pointer to an object capable to generate the branching
* fractions for different decay modes for this particle type. The
* object will be asked to generate branching fractions every time
* the ParticleData object it updated and will modify the branching
* fractions for every particle instance if variableRatio is true.
*/
WidthGeneratorPtr theWidthGenerator;
/**
* Determine whether the branching fractions are allowed to change
* on a particle-by-particle basis.
*/
bool theVariableRatio;
/**
* Pointer to the object corresponding to the antiparticle. Set to
* null if it is its own antiparticle.
*/
tPDPtr theAntiPartner;
/**
* If syncAnti is true all changes to this object will be transfered
* to the antiParticle.
*/
bool syncAnti;
/**
* Helper variable to keep track of the default mass.
*/
Energy theDefMass;
/**
* Helper variable to keep track of the default width.
*/
Energy theDefWidth;
/**
* Helper variable to keep track of the default width cut.
*/
Energy theDefCut;
/**
* Helper variable to keep track of the default lifetime.
*/
Length theDefCTau;
/**
* Helper variable to keep track of the default charge.
*/
PDT::Charge theDefCharge;
/**
* Helper variable to keep track of the default spin.
*/
PDT::Spin theDefSpin;
/**
* Helper variable to keep track of the default colour.
*/
PDT::Colour theDefColour;
/**
* Utility function for the interface.
*/
void setMass(Energy);
/**
* Utility function for the interface.
*/
+ void setHardProcessMass(Energy);
+
+ /**
+ * Reset the hard process mass
+ */
+ string doUnsetHardProcessMass(string);
+
+ /**
+ * Adjust the nominal mass to the hard process mass if a reshuffling
+ * is not desirable.
+ */
+ string doAdjustNominalMass(string);
+
+ /**
+ * Utility function for the interface.
+ */
Energy defMass() const;
/**
* Utility function for the interface.
*/
void setWidth(Energy);
/**
* Utility function for the interface.
*/
+ void setHardProcessWidth(Energy);
+
+ /**
+ * Reset the hard process mass
+ */
+ string doUnsetHardProcessWidth(string);
+
+ /**
+ * Utility function for the interface.
+ */
Energy getWidth() const;
/**
* Utility function for the interface.
*/
Energy defWidth() const;
/**
* Utility function for the interface.
*/
void setCut(Energy);
/**
* Utility function for the interface.
*/
Energy getCut() const;
/**
* Utility function for the interface.
*/
Energy defCut() const;
/**
* Utility function for the interface.
*/
void setUpCut(Energy);
/**
* Utility function for the interface.
*/
Energy getUpCut() const;
/**
* Utility function for the interface.
*/
void setLoCut(Energy);
/**
* Utility function for the interface.
*/
Energy getLoCut() const;
/**
* Utility function for the interface.
*/
void setCTau(Length);
/**
* Utility function for the interface.
*/
Length getCTau() const;
/**
* Utility function for the interface.
*/
Length defCTau() const;
/**
* Utility function for the interface.
*/
void setStable(long);
/**
* Utility function for the interface.
*/
long getStable() const;
/**
* Utility function for the interface.
*/
void setSync(long);
/**
* Utility function for the interface.
*/
long getSync() const;
/**
* Utility function for the interface.
*/
void setVariableRatio(long);
/**
* Utility function for the interface.
*/
long getVariableRatio() const;
/**
* Utility function for the interface.
*/
string doSync(string);
/**
* Utility function for the interface.
*/
void setMassGenerator(MassGenPtr);
/**
* Utility function for the interface.
*/
void setWidthGenerator(WidthGeneratorPtr);
/**
* Utility function for the interface.
*/
void setCharge(int);
/**
* Utility function for the interface.
*/
string ssetCharge(string);
/**
* Utility function for the interface.
*/
int getCharge() const;
/**
* Utility function for the interface.
*/
int defCharge() const;
/**
* Utility function for the interface.
*/
void setSpin(int);
/**
* Utility function for the interface.
*/
int getSpin() const;
/**
* Utility function for the interface.
*/
int defSpin() const;
/**
* Utility function for the interface.
*/
void setColour(long);
/**
* Utility function for the interface.
*/
long getColour() const;
/**
* Utility function for the interface.
*/
long defColour() const;
/**
* Utility function for the interface.
*/
void insDecayModes(DMPtr dm, int);
/**
* Utility function for the interface.
*/
void delDecayModes(int i);
/**
* Utility function for the interface.
*/
vector<DMPtr> getDecayModes() const;
/**
* Utility function for the interface.
*/
string doSelectDecayModes(string);
/**
* Utility function for the interface.
*/
string doPrintDecayModes(string);
/**
* Describe a concrete class with persistent data.
*/
static ClassDescription<ParticleData> initParticleData;
};
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the base classes
* of ParticleData. */
template <>
struct BaseClassTrait<ParticleData,1>: public ClassTraitsType {
/** Typedef of the first base class of ParticleData. */
typedef Interfaced NthBase;
};
/** This template specialization informs ThePEG about the name of the
* ParticleData class. */
template <>
struct ClassTraits<ParticleData>: public ClassTraitsBase<ParticleData> {
/** Return a platform-independent class name */
static string className() { return "ThePEG::ParticleData"; }
};
/** @endcond */
}
#endif /* ThePEG_ParticleData_H */
diff --git a/PDT/StandardMatchers.h b/PDT/StandardMatchers.h
--- a/PDT/StandardMatchers.h
+++ b/PDT/StandardMatchers.h
@@ -1,338 +1,359 @@
// -*- C++ -*-
//
// StandardMatchers.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_StandardMatchers_H
#define ThePEG_StandardMatchers_H
// This is the declaration of the AnyMatcher,
#include "Matcher.h"
#include "ThePEG/PDT/EnumParticles.h"
namespace ThePEG {
/** \file StandardMatchers.h
*
* This file declare a set of standard matcher classes. The
* ChargedMatcher, NegativeMatcher, PositiveMatcher, NeutralMatcher,
* BaryonMatcher, MesonMatcher, DiquarkMatcher, LeptonMatcher,
* LightAntiQuarkMatcher, LightQuarkMatcher and
* StandardQCDPartonMatcher classes can be used by themselves (with
* their static functions) or together with the Matcher class to
* define Interfaced objects of the MatcherBase type to be used in the
* Repository. Suitable typedefs are declared for the latter.
*
* @see Matcher
* @see MatcherBase
*/
/**
* A Matcher class which matches any particle.
*/
struct AnyMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef AnyMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) {
return bool(pd.id());
}
/** A simplified but unique class name. */
static string className() { return "Any"; }
};
/** Gives a MatcherBase class based on AnyMatcher. */
typedef Matcher<AnyMatcher> MatchAny;
/**
* A Matcher class which matches any charged particle.
*/
struct ChargedMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef ChargedMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) {
return PDT::charged(pd.iCharge());
}
/** A simplified but unique class name. */
static string className() { return "Charged"; }
};
/** Gives a MatcherBase class based on ChargedMatcher. */
typedef Matcher<ChargedMatcher> MatchCharged;
struct NegativeMatcher;
/**
* A Matcher class which matches any positively charged particle.
*/
struct PositiveMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef NegativeMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) {
return PDT::positive(pd.iCharge());
}
/** A simplified but unique class name. */
static string className() { return "Positive"; }
};
/** Gives a MatcherBase class based on PositiveMatcher. */
typedef Matcher<PositiveMatcher> MatchPositive;
/**
* A Matcher class which matches any uncharged particle.
*/
struct NeutralMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef NeutralMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) {
return pd.iCharge() == PDT::Charge0;
}
/** A simplified but unique class name. */
static string className() { return "Neutral"; }
};
/** Gives a MatcherBase class based on NeutralMatcher. */
typedef Matcher<NeutralMatcher> MatchNeutral;
/**
* A Matcher class which matches any negatively charged particle.
*/
struct NegativeMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef PositiveMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) {
return PDT::negative(pd.iCharge());
}
/** A simplified but unique class name. */
static string className() { return "Negative"; }
};
/** Gives a MatcherBase class based on NegativeMatcher. */
typedef Matcher<NegativeMatcher> MatchNegative;
/**
* A Matcher class which matches any baryon.
*/
struct BaryonMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef BaryonMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return (id/10)%10 && (id/100)%10 && (id/1000)%10;
}
/** A simplified but unique class name. */
static string className() { return "Baryon"; }
};
/** Gives a MatcherBase class based on BaryonMatcher. */
typedef Matcher<BaryonMatcher> MatchBaryon;
/**
* A Matcher class which matches any meson.
*/
struct MesonMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef MesonMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return (id/10)%10 && (id/100)%10 && (id/1000)%10 == 0;
}
/** A simplified but unique class name. */
static string className() { return "Meson"; }
};
/** Gives a MatcherBase class based on MesonMatcher. */
typedef Matcher<MesonMatcher> MatchMeson;
/**
* A Matcher class which matches any (anti-)diquark.
*/
struct DiquarkMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef DiquarkMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return id/10 && (id/10)%10 == 0 && (id/100)%10 && (id/1000)%10;
}
/** A simplified but unique class name. */
static string className() { return "Diquark"; }
};
/** Gives a MatcherBase class based on DiquarkMatcher. */
typedef Matcher<DiquarkMatcher> MatchDiquark;
/**
* A Matcher class which matches any (anti-)quark.
*/
struct QuarkMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef QuarkMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return id && abs(id) < 10;
}
/** A simplified but unique class name. */
static string className() { return "Quark"; }
};
/** Gives a MatcherBase class based on QuarkMatcher. */
typedef Matcher<QuarkMatcher> MatchQuark;
/**
* A Matcher class which matches any lepton.
*/
struct LeptonMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef LeptonMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return abs(id) > 10 && abs(id) <= 20;
}
/** A simplified but unique class name. */
static string className() { return "Lepton"; }
};
/** Gives a MatcherBase class based on LeptonMatcher. */
typedef Matcher<LeptonMatcher> MatchLepton;
+/**
+ * A Matcher class which matches any neutrino.
+ */
+struct NeutrinoMatcher: public MatcherType {
+ /** Typedef the class matching the complex conjugate particles. */
+ typedef NeutrinoMatcher CC;
+ /** The main static function to check if a given particle type \a pd
+ matches. */
+ static bool Check(const ParticleData & pd) { return Check(pd.id()); }
+ /** The main static function to check if a given particle with type
+ \a id matches. */
+ static bool Check(long id) {
+ return abs(id)-10 >= 2 && abs(id)-10 <= 8 && abs(id)%2 == 0;
+ }
+ /** A simplified but unique class name. */
+ static string className() { return "Neutrino"; }
+};
+
+/** Gives a MatcherBase class based on VectorMesonMatcher. */
+typedef Matcher<NeutrinoMatcher> MatchNeutrino;
+
struct LightAntiQuarkMatcher;
/**
* A Matcher class which matches any light quark (d,u or s).
*/
struct LightQuarkMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef LightAntiQuarkMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return id > 0 && id < 4 ;
}
/** A simplified but unique class name. */
static string className() { return "LightQuark"; }
};
/** Gives a MatcherBase class based on LightQuarkMatcher. */
typedef Matcher<LightQuarkMatcher> MatchLightQuark;
/**
* A Matcher class which matches any light anti-quark
* (\f$\bar{\mbox{d}}\f$,\f$\bar{\mbox{u}}\f$ or
* \f$\bar{\mbox{s}}\f$).
*/
struct LightAntiQuarkMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef LightQuarkMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return id < 0 && id > -4 ;
}
/** A simplified but unique class name. */
static string className() { return "LightAntiQuark"; }
};
/** Gives a MatcherBase class based on LightAntiQuarkMatcher. */
typedef Matcher<LightAntiQuarkMatcher> MatchLightAntiQuark;
/**
* A Matcher class which matches any standard QCD parton, ie. gluons
* and quarks up to bottom.
*/
struct StandardQCDPartonMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef StandardQCDPartonMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return id && ( abs(id) <= 5 || id == ParticleID::g );
}
/** A simplified but unique class name. */
static string className() { return "StandardQCDParton"; }
};
/** Gives a MatcherBase class based on StandardQCDPartonMatcher. */
typedef Matcher<StandardQCDPartonMatcher> MatchStandardQCDParton;
/**
* A Matcher class which matches any pseudo scalar meson.
*/
struct PseudoScalarMesonMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef PseudoScalarMesonMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return ( (abs(id)/1000)%1 == 0 && abs(id) > 100 && abs(id)%10 == 1 ) ||
( id == ParticleID::K_L0 || id == ParticleID::K_S0 );
}
/** A simplified but unique class name. */
static string className() { return "PseudoScalarMeson"; }
};
/** Gives a MatcherBase class based on PseudoScalarMesonMatcher. */
typedef Matcher<PseudoScalarMesonMatcher> MatchPseudoScalarMeson;
/**
* A Matcher class which matches any vector meson.
*/
struct VectorMesonMatcher: public MatcherType {
/** Typedef the class matching the complex conjugate particles. */
typedef VectorMesonMatcher CC;
/** The main static function to check if a given particle type \a pd
matches. */
static bool Check(const ParticleData & pd) { return Check(pd.id()); }
/** The main static function to check if a given particle with type
\a id matches. */
static bool Check(long id) {
return (abs(id)/1000)%1 == 0 && abs(id) > 100 && abs(id)%10 == 3;
}
/** A simplified but unique class name. */
static string className() { return "VectorMeson"; }
};
/** Gives a MatcherBase class based on VectorMesonMatcher. */
typedef Matcher<VectorMesonMatcher> MatchVectorMeson;
}
#endif /* ThePEG_StandardMatchers_H */
diff --git a/Utilities/DynamicLoader.cc b/Utilities/DynamicLoader.cc
--- a/Utilities/DynamicLoader.cc
+++ b/Utilities/DynamicLoader.cc
@@ -1,156 +1,159 @@
// -*- C++ -*-
//
// DynamicLoader.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG 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 DynamicLoader class.
//
// macro is passed in from -D compile flag
#ifndef THEPEG_PKGLIBDIR
#error Makefile.am needs to define THEPEG_PKGLIBDIR
#endif
#include "DynamicLoader.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Config/algorithm.h"
#include "config.h"
#ifdef ThePEG_HAS_DLOPEN
#include <dlfcn.h>
#endif
#include <cstdlib>
#ifdef ThePEG_HAS_FENV
#include <fenv.h>
#endif
using namespace ThePEG;
void DynamicLoader::dlname(string sofile) {
if ( StringUtils::suffix(sofile) == "so" ) {
string lafile = StringUtils::remsuf(sofile) + ".la";
ifstream is(lafile.c_str());
string line;
while ( getline(is, line) ) {
if ( line.find("dlname='") != string::npos ) {
int pos = line.find('\'') + 1;
int l = line.rfind('\'') - pos;
sofile = StringUtils::basename(sofile);
versionMap[sofile] = line.substr(pos, l);
}
}
} else if ( StringUtils::suffix(StringUtils::remsuf(sofile)) == "so" ) {
versionMap[StringUtils::basename(StringUtils::remsuf(sofile))] =
StringUtils::basename(sofile);
}
}
string DynamicLoader::dlnameversion(string libs) {
string ret;
do {
string soname = StringUtils::car(libs);
string dir = StringUtils::dirname(soname);
if ( dir.length() ) dir += '/';
libs = StringUtils::cdr(libs);
if ( versionMap.find(StringUtils::basename(soname)) != versionMap.end() )
ret += dir + versionMap[StringUtils::basename(soname)] + " ";
else
ret += soname + " ";
} while ( libs.length() );
return StringUtils::stripws(ret);
}
bool DynamicLoader::loadcmd(string file) {
#ifdef ThePEG_HAS_DLOPEN
dlname(file);
#ifdef ThePEG_HAS_FENV
int oldfpe = fegetexcept();
#endif
bool ret = dlopen(file.c_str(), RTLD_LAZY|RTLD_GLOBAL) != 0;
#ifdef ThePEG_HAS_FENV
feenableexcept(oldfpe);
#endif
if ( !ret ) lastErrorMessage += string(dlerror()) + string("\n");
return ret;
#else
#error ThePEG can only be run on platforms which support
#error dynamic loading.
return false;
#endif
}
void DynamicLoader::appendPath(string path) {
if ( path[path.size()-1] != '/' ) path += '/';
paths.push_back(path);
apppaths.push_back(path);
}
void DynamicLoader::prependPath(string path) {
if ( path[path.size()-1] != '/' ) path += '/';
paths.insert(paths.begin(), path);
prepaths.push_back(path);
}
bool DynamicLoader::load(string name) {
lastErrorMessage = "";
static set<string> loaded;
if ( loaded.find(name) != loaded.end() ) return true;
loaded.insert(name);
bool success = false;
- if ( name[0] == '/' ) success = loadcmd(name);
+ const string name_dylib = StringUtils::remsuf(name) + ".dylib";
+ if ( name[0] == '/' ) {
+ success = loadcmd(name) || loadcmd(name_dylib);
+ }
else {
for ( unsigned i = 0; i < paths.size(); ++i ) {
string path = paths[i];
if ( path[path.size() - 1] != '/' ) path += '/';
- if ( loadcmd(path + name) ) {
+ if ( loadcmd(path + name) || loadcmd(path + name_dylib) ) {
success = true;
break;
}
}
}
- if ( success || loadcmd(name) ) {
+ if ( success || loadcmd(name) || loadcmd(name_dylib) ) {
lastErrorMessage = "";
return true;
}
loaded.erase(name);
return false;
}
const vector<string> & DynamicLoader::appendedPaths() {
return apppaths;
}
const vector<string> & DynamicLoader::prependedPaths() {
return prepaths;
}
const vector<string> & DynamicLoader::allPaths() {
return paths;
}
vector<string> DynamicLoader::paths = DynamicLoader::defaultPaths();
vector<string> DynamicLoader::prepaths = vector<string>();
vector<string> DynamicLoader::apppaths = vector<string>();
string DynamicLoader::lastErrorMessage;
map<string,string> DynamicLoader::versionMap;
vector<string> DynamicLoader::defaultPaths() {
vector<string> vpaths;
// macro is passed in from -D compile flag
string instpath = THEPEG_PKGLIBDIR;
vpaths.push_back(instpath);
vpaths.push_back(".");
return vpaths;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Dec 21, 2:01 PM (15 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4023053
Default Alt Text
(136 KB)

Event Timeline