diff --git a/EventRecord/Particle.cc b/EventRecord/Particle.cc --- a/EventRecord/Particle.cc +++ b/EventRecord/Particle.cc @@ -1,524 +1,525 @@ // -*- C++ -*- // // Particle.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2017 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined member functions of // the Particle class. // #include "Particle.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/EventRecord/ColourLine.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/EventRecord/ParticleTraits.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include #include #include #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "Particle.tcc" #endif using namespace ThePEG; Particle::ParticleRep::ParticleRep(const ParticleRep & p) : theParents(p.theParents), theChildren(p.theChildren), thePrevious(p.thePrevious), theNext(p.theNext), theBirthStep(p.theBirthStep), theVertex(p.theVertex), theLifeLength(p.theLifeLength), theScale(p.theScale), theVetoScale(p.theVetoScale), theNumber(p.theNumber), theExtraInfo(p.theExtraInfo.size()) { if ( p.theColourInfo ) theColourInfo = dynamic_ptr_cast(p.theColourInfo->clone()); if ( p.theSpinInfo ) theSpinInfo = dynamic_ptr_cast(p.theSpinInfo->clone()); for ( int i = 0, N = p.theExtraInfo.size(); i < N; ++i ) theExtraInfo[i] = p.theExtraInfo[i]->clone(); } Particle::Particle(const Particle & p) - : Base(p), theData(p.theData), theMomentum(p.theMomentum), theRep(p.theRep) { + : Base(p), theData(p.theData), theMomentum(p.theMomentum), + theRep(p.theRep), theStatus(p.theStatus) { if ( p.theRep ) { theRep = new ParticleRep(*p.theRep); theRep->theParents.clear(); } } Particle::~Particle() { if ( theRep ) { if ( colourLine() ) colourLine()->removeColoured(this); if ( antiColourLine() ) antiColourLine()->removeAntiColoured(this); delete theRep; } theRep = 0; theData = cEventPDPtr(); } void Particle::initFull() { if ( theRep ) return; theRep = new ParticleRep; Energy width = data().generateWidth(mass()); if ( width > ZERO ) { Time lifetime = data().generateLifeTime(mass(), width); theRep->theLifeLength.setTau(lifetime); theRep->theLifeLength. setVect((momentum().vect()*(lifetime / max(mass(), Constants::epsilon*GeV)))); theRep->theLifeLength.rescaleEnergy(); } } PPtr Particle::clone() const { return ptr_new(*this); } void Particle::rebind(const EventTranslationMap & trans) { for ( ParticleVector::iterator pit = rep().theChildren.begin(); pit != rep().theChildren.end(); ++pit ) *pit = trans.translate(*pit); for ( tParticleVector::iterator pit = rep().theParents.begin(); pit != rep().theParents.end(); ++pit ) *pit = trans.translate(*pit); rep().thePrevious = trans.translate(rep().thePrevious); rep().theNext = trans.translate(rep().theNext); if ( hasColourInfo() ) colourInfo()->rebind(trans); if ( spinInfo() ) spinInfo()->rebind(trans); rep().theBirthStep = trans.translate(rep().theBirthStep); for ( EIVector::const_iterator ie = rep().theExtraInfo.begin(); ie != rep().theExtraInfo.end(); ++ie ) (**ie).rebind(trans); } tParticleSet Particle::siblings() const { tParticleSet theSiblings; for ( tParticleVector::const_iterator pit = parents().begin(); pit != parents().end(); ++pit ) theSiblings.insert((*pit)->children().begin(), (*pit)->children().end()); theSiblings.erase(const_cast(this)); return theSiblings; } void Particle::colourNeighbour(tPPtr p, bool anti) { tColinePtr line = colourLine(!anti); if ( !line ) line = ColourLine::create(this, !anti); line->addColoured(p, anti); } void Particle::outgoingColour(tPPtr p, bool anti) { tColinePtr line = colourLine(anti); if ( !line ) line = ColourLine::create(this, anti); line->addColoured(p, anti); } tPPtr Particle::incomingColour(bool anti) const { if ( !hasColourInfo() ) return tPPtr(); tColinePtr line = colourLine(anti); if ( !line ) return tPPtr(); for ( int i = 0, N = parents().size(); i < N; ++i ) if ( parents()[i]->hasColourLine(line, anti) ) return parents()[i]; return tPPtr(); } tPPtr Particle::outgoingColour(bool anti) const { if ( !hasColourInfo() ) return tPPtr(); tColinePtr line = colourLine(anti); if ( !line ) return tPPtr(); for ( int i = 0, N = children().size(); i < N; ++i ) if ( children()[i]->hasColourLine(line, anti) ) return children()[i]; return tPPtr(); } LorentzPoint Particle::labVertex() const { LorentzPoint r(rep().theBirthStep && rep().theBirthStep->collision()? vertex() + rep().theBirthStep->collision()->vertex(): vertex()); return r; } void Particle::setLabVertex(const LorentzPoint & p) { rep().theVertex = ( rep().theBirthStep && rep().theBirthStep->collision()? p - rep().theBirthStep->collision()->vertex() : p ); } void Particle::transform(const LorentzRotation & r) { if ( hasRep() && spinInfo() ) spinInfo()->transform(momentum(), r); theMomentum.transform(r); if ( !hasRep() ) return; rep().theVertex.transform(r); rep().theLifeLength.transform(r); } void Particle::deepTransform(const LorentzRotation & r) { transform(r); if ( !theRep ) return; for ( int i = 0, N = children().size(); i < N; ++i ) rep().theChildren[i]->deepTransform(r); if ( rep().theNext ) rep().theNext->deepTransform(r); } void Particle::rotateX(double a) { LorentzRotation r; r.rotateX(a); transform(r); } void Particle::deepRotateX(double a) { LorentzRotation r; r.rotateX(a); deepTransform(r); } void Particle::rotateY(double a) { LorentzRotation r; r.rotateY(a); transform(r); } void Particle::deepRotateY(double a) { LorentzRotation r; r.rotateY(a); deepTransform(r); } void Particle::rotateZ(double a) { LorentzRotation r; r.rotateZ(a); transform(r); } void Particle::deepRotateZ(double a) { LorentzRotation r; r.rotateZ(a); deepTransform(r); } void Particle::rotate(double a, const Axis & axis) { LorentzRotation r; r.rotate(a, axis); transform(r); } void Particle::deepRotate(double a, const Axis & axis) { LorentzRotation r; r.rotate(a, axis); deepTransform(r); } string Particle::outputFormat = "%n3%s10 %i7 %p[,]0 %c(,) %^^0%vv0 %>>0%<>0 %l{,}0\n" " %x10.3%y10.3%z10.3%e10.3%m10.3\n"; int getNumber(string::const_iterator & pos, int def) { if ( !isdigit(*pos) ) return def; def = *pos++ - '0'; while ( isdigit(*pos) ) def = 10*def + *pos++ - '0'; return def; } void writePrecision(ostream & os, string::const_iterator & pos, int defw, int defp, double x) { defw = getNumber(pos, defw); if ( *pos == '.' ) defp = getNumber(++pos, defp); int oldp = os.precision(); os << setprecision(defp) << setw(defw) << x << setprecision(oldp); } void writeStringAdjusted(ostream & os, bool left, int w, string str) { while ( !left && w-- > int(str.size()) ) os << ' '; os << str; while ( left && w-- > int(str.size()) ) os << ' '; } template void writeParticleRanges(ostream & os, const Container & co, char sep, int w) { set cnum; for ( typename Container::const_iterator it = co.begin(); it != co.end(); ++it) cnum.insert((**it).number()); bool elipsis = false; int last = -10; for ( set::iterator it = cnum.begin(); it != cnum.end(); ++it) { int n = *it; int next = 0; set::iterator itn = it; if ( ++itn != cnum.end() ) next = *itn; bool writeit = true; bool writesep = false; if ( elipsis && ( n != last + 1 || n != next - 1 ) ) elipsis = false; else if ( !elipsis && n == last + 1 && n == next -1 ) { os << ".."; elipsis = true; writeit = false; } else if ( elipsis && n == last + 1 && n == next -1 ) writeit = false; else if ( it != cnum.begin() ) writesep = true; if ( writeit ) { if ( writesep ) os << sep; os << setw(w) << n; } last = n; } } ostream & ThePEG::operator<<(ostream & os, const Particle & p) { return p.print(os, p.birthStep()); } ostream & Particle::print(ostream & os, tcStepPtr step) const { if ( !step ) step = birthStep(); tCollPtr coll = step? step->collision(): tCollPtr(); tEventPtr event = coll? coll->event(): tEventPtr(); string::const_iterator pos = Particle::outputFormat.begin(); ios::fmtflags saveflags = os.setf(ios::fixed, ios::floatfield); while ( pos != Particle::outputFormat.end() ) { if ( *pos == '%' && ++pos != Particle::outputFormat.end() ) { bool left = false; if ( *pos == '-' ) { left = true; os.setf(ios::left, ios::adjustfield); ++pos; } else { os.setf(ios::right, ios::adjustfield); } char mark; char open; char close; char sep; int w; string str; string fill; if ( pos == Particle::outputFormat.end() ) break; bool fullColour = false; switch ( *pos ) { case 'n': os << setw(getNumber(++pos, 3)) << number(); break; case 'i': os << setw(getNumber(++pos, 8)) << id(); break; case 's': writeStringAdjusted(os, left, getNumber(++pos, 8), PDGName()); break; case 'x': writePrecision(os, ++pos, 10, 3, momentum().x()/GeV); break; case 'y': writePrecision(os, ++pos, 10, 3, momentum().y()/GeV); break; case 'z': writePrecision(os, ++pos, 10, 3, momentum().z()/GeV); break; case 'e': writePrecision(os, ++pos, 10, 3, momentum().e()/GeV); break; case 'm': writePrecision(os, ++pos, 10, 3, momentum().mass()/GeV); break; case 'P': fullColour = true; [[fallthrough]]; case 'p': open = *++pos; sep = *++pos; close = *++pos; w = getNumber(++pos, 0); if ( parents().empty() ) break; if ( open ) os << open; writeParticleRanges(os, parents(), sep, w); if ( fullColour && hasColourInfo() && ( incomingColour() || incomingAntiColour() ) ) { if ( close ) os << open; if ( incomingColour() ) os << "+" << incomingColour()->number(); if ( incomingAntiColour() ) os << "-" << incomingAntiColour()->number(); if ( close ) os << close; } if ( close ) os << close; break; case 'l': open = *++pos; sep = *++pos; close = *++pos; w = getNumber(++pos, 0); if ( hasColourInfo() && ( colourLine() || antiColourLine() ) && event) { if ( open ) os << open; vector clines = colourInfo()->colourLines(); for ( int i = 0, N = clines.size(); i < N; ++i ) { if ( i > 0 && sep ) os << sep; clines[i]->write(os, event, false); } vector aclines = colourInfo()->antiColourLines(); for ( int i = 0, N = aclines.size(); i < N; ++i ) { if ( ( i > 0 || clines.size() ) && sep ) os << sep; aclines[i]->write(os, event, true); } if ( close ) os << close; } break; case 'C': fullColour = true; [[fallthrough]]; case 'c': open = *++pos; sep = *++pos; close = *++pos; w = getNumber(++pos, 0); if ( children().empty() ) break; if ( open ) os << open; writeParticleRanges(os, children(), sep, w); if ( fullColour && hasColourInfo() && ( outgoingColour() || outgoingAntiColour() ) ) { if ( close ) os << open; if ( outgoingColour() ) os << "+" << outgoingColour()->number(); if ( outgoingAntiColour() ) os << "-" << outgoingAntiColour()->number(); if ( close ) os << close; } if ( close ) os << close; break; case '>': mark = *++pos; w = getNumber(++pos, 0); if ( hasColourInfo() && step && step->colourNeighbour(this) ) { os << setw(w-1) << step->colourNeighbour(this)->number() << mark; } break; case '<': mark = *++pos; w = getNumber(++pos, 0); if ( hasColourInfo() && step && step->antiColourNeighbour(this) ) { int n = step->antiColourNeighbour(this)->number(); ostringstream oss; oss << mark << n; writeStringAdjusted(os, left, w, oss.str()); } break; case 'v': mark = *++pos; w = getNumber(++pos, 0); if ( next() ) { if ( left && mark ) os << mark; os << setw(w) << next()->number(); if ( !left && mark ) os << mark; } break; case '^': mark = *++pos; w = getNumber(++pos, 0); if ( previous() ) { if ( left && mark ) os << mark; os << setw(w) << previous()->number(); if ( !left && mark ) os << mark; } break; case 'd': switch ( *++pos ) { case 'x': writePrecision(os, ++pos, 10, 3, lifeLength().x()/mm); break; case 'y': writePrecision(os, ++pos, 10, 3, lifeLength().y()/mm); break; case 'z': writePrecision(os, ++pos, 10, 3, lifeLength().z()/mm); break; case 't': writePrecision(os, ++pos, 10, 3, lifeLength().e()/mm); break; case 'T': writePrecision(os, ++pos, 10, 3, lifeLength().tau()/mm); break; } break; case 'V': switch ( *++pos ) { case 'x': writePrecision(os, ++pos, 10, 3, vertex().x()/mm); break; case 'y': writePrecision(os, ++pos, 10, 3, vertex().y()/mm); break; case 'z': writePrecision(os, ++pos, 10, 3, vertex().z()/mm); break; case 't': writePrecision(os, ++pos, 10, 3, vertex().e()/mm); break; } break; case 'L': switch ( *++pos ) { case 'x': writePrecision(os, ++pos, 10, 3, labVertex().x()/mm); break; case 'y': writePrecision(os, ++pos, 10, 3, labVertex().y()/mm); break; case 'z': writePrecision(os, ++pos, 10, 3, labVertex().z()/mm); break; case 't': writePrecision(os, ++pos, 10, 3, labVertex().e()/mm); break; } break; default: os << *pos++; } } else { if ( pos != Particle::outputFormat.end() ) os << *pos++; } } os.flags(saveflags); return os; } void Particle::debugme() const { cerr << *this; EventRecordBase::debugme(); } void Particle::persistentOutput(PersistentOStream & os) const { EventConfig::putParticleData(os, theData); - os << ounit(theMomentum, GeV) << bool( theRep != 0 ); + os << ounit(theMomentum, GeV) << theStatus << bool( theRep != 0 ); if ( !theRep ) return; os << rep().theParents << rep().theChildren << rep().thePrevious << rep().theNext << rep().theBirthStep << ounit(rep().theVertex, mm) << ounit(rep().theLifeLength, mm) << ounit(rep().theScale, GeV2) << ounit(rep().theVetoScale, GeV2) << rep().theNumber << rep().theDecayMode << rep().theColourInfo << rep().theSpinInfo << rep().theExtraInfo; } void Particle::persistentInput(PersistentIStream & is, int) { bool readRep; EventConfig::getParticleData(is, theData); - is >> iunit(theMomentum, GeV) >> readRep; + is >> iunit(theMomentum, GeV) >> theStatus >> readRep; if ( !readRep ) return; if ( !hasRep() ) theRep = new ParticleRep; is >> rep().theParents >> rep().theChildren >> rep().thePrevious >> rep().theNext >> rep().theBirthStep >> iunit(rep().theVertex, mm) >> iunit(rep().theLifeLength, mm) >> iunit(rep().theScale, GeV2) >> iunit(rep().theVetoScale, GeV2) >> rep().theNumber >> rep().theDecayMode >> rep().theColourInfo >> rep().theSpinInfo >> rep().theExtraInfo; } ClassDescription Particle::initParticle; void Particle::Init() {} diff --git a/EventRecord/Particle.h b/EventRecord/Particle.h --- a/EventRecord/Particle.h +++ b/EventRecord/Particle.h @@ -1,1180 +1,1195 @@ // -*- C++ -*- // // Particle.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2017 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Particle_H #define ThePEG_Particle_H // This is the decalaration of the Particle class. #include "EventConfig.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/EventRecord/MultiColour.h" #include "ThePEG/EventRecord/SpinInfo.h" #include "ThePEG/PDT/ParticleData.h" namespace ThePEG { /** * The Particle class is used to describe an instance of a * particle. Properties of the corresponding particle type can be * accessed through a pointer to a ParticleData object. * * A Particle object contains pointers to other particles, such as a * list of parents and a list of children. It may also contain a * pointer to the previous or next instance of the same physical * particle if the properties of a given particle has been changed * during the generation. Coloured particles contains pointers to * ColourLine defining the colour connections to other particles. * * The Particle also has a pointer to the Step object where it was * first introduced in the Event. * * When printing a particle the format of the output is governed by * the static outputFormat string. When a particle is sent * to an ostream, the format string is written but with * keys prefixed by the \% character replaced with * infromation about the particle as follows:
\%\% is * replaced by a singel \%
\%C sets a flag so * that subsequent output of children and parents etc. will contain * colour information.
\%n is replaced by the particles * number in a fied ow width
\%s is replaced by the name * of the particle
\%i is replaced by the id number of * the particle type
\%x, \%y, \%z, \%e, \%m is replaced by * the x-, y-, z-, energy- and mass-component of the particles * momentum respectively
\%dx, \%dy, \%dz, \%dt, \%dT is * replaced by the x-, y-, z-, time- and invariant time-component of * the particles lifeLength respectively
\%Vx, \%Vy, \%Vz, * \%Vt is replaced by the x-, y-, z- and time-component of the * creation point relative to the vertex of the * collision.
\%Lx, \%Ly, \%Lz, \%Lt is replaced by the x-, * y-, z- and time-component of the creation point in the current * lab-system.
\%p[,] is replaced by a list (of numbers) * of the particles parents enclosed by [ and ] * and separated by ,, The parent from which the particle * inherits its (anti-) colour is marked by a (-)+
* \%c(,) is replaced by a list (of numbers) of the * particles children enclosed by ( and ) and * separated by ,, The child which inherits the particles * (anti-) colour is marked by a (-)+
\%> is replaced * by the number of the colour neighbor
\%< is * replaced by the number of the anti-colour neighbor
* \%^ is replaced by the number of the previous instance of * the same physical particle
\%v is replaced by the * number of the next instance of the same physical particle.
* \%l{,} is replaced by the indices of the colour lines to * which this particle is connected enclosed by { and * } and separated by ,, The line corresponding * to the (anti-) colour of the particle is prefixed by a (-)+ * * @see Event * @see Collision * @see Step * @see SubProcess * @see Lorentz5Vector * @see ColourLine * @see ColourBase */ class Particle: public EventRecordBase { public: /** Most of the Event classes are friends with each other. */ friend class Event; /** Most of the Event classes are friends with each other. */ friend class Collision; /** Most of the Event classes are friends with each other. */ friend class Step; /** Most of the Event classes are friends with each other. */ friend class SubProcess; /** ParticleData needs to be a friend. */ friend class ParticleData; struct ParticleRep; public: /** * Standard Constructor. Note that the default constructor is * private - there is no particle without a pointer to a * ParticleData object. */ - Particle(tcEventPDPtr newData) : theData(newData), theRep(0) {} + Particle(tcEventPDPtr newData) : theData(newData), theRep(0), theStatus(0) {} /** * Copy constructor. */ Particle(const Particle &); /** * Destructor. */ virtual ~Particle(); //@} /** @name Functions relating to ancestry of particles. */ //@{ /** * Returns true if and only if this particle has decayed. */ bool decayed() const { return hasRep() && !rep().theChildren.empty(); } /** * The list of decay products. */ const ParticleVector & children() const { static const ParticleVector null; return hasRep() ? rep().theChildren : null; } /** * Add a child (the childs parent pointer will be set accordingly). */ void addChild(tPPtr c) { rep().theChildren.push_back(c); (c->rep()).theParents.push_back(this); } /** * Remove the given child from the list of children of this particle * (the corresponding parent pointer of the child will also be * removed). */ void abandonChild(tPPtr child) { removeChild(child); child->removeParent(this); } /** * The list of parent particles. */ const tParticleVector & parents() const { static const tParticleVector null; return hasRep() ? rep().theParents : null; } /** * Return a set of neighboring particles coming from the same decay * as this one. The return value is a newly recalculated set * every time. It must be stored to be used further, do not directly call * e.g. siblings().begin() or siblings().end()! */ tParticleSet siblings() const; /** * Undo the decay of this particle, removing all children (and * grand children ...) from the event record */ void undecay() { if ( hasRep() ) { rep().theChildren.clear(); rep().theNext = tPPtr(); } } /** * If this particle has decayed set the corresponding decay mode. */ void decayMode(tDMPtr dm) { rep().theDecayMode = dm; } /** * If this particle has decayed get the corresponding decay mode. */ tDMPtr decayMode() const { return hasRep() ? rep().theDecayMode : tDMPtr(); } /** * Next instance. Pointer to another instance of the same * physical particle in later steps. */ tPPtr next() const { return hasRep() ? rep().theNext : PPtr(); } /** * Previous instance. Pointer to another instance of the same * physical particle in earlier steps. */ tPPtr previous() const { return hasRep() ? rep().thePrevious : tPPtr(); } /** * Original instance. If there exists another previous instance of * this particle return this instance (recursively). */ tcPPtr original() const { return previous() ? tcPPtr(previous()->original()) : tcPPtr(this); } /** * Original instance. If there exists another previous instance of * this particle return this instance (recursively). */ tPPtr original() { return previous() ? previous()->original() : tPPtr(this); } /** * Final instance. If there exists another subsequent instance of * this particle return this instance (recursively). */ tcPPtr final() const { return next() ? tcPPtr(next()->final()) : tcPPtr(this); } /** * Final instance. If there exists another subsequent instance of * this particle return this instance (recursively). */ tPPtr final() { return next() ? next()->final() : tPPtr(this); } //@} /** @name Relations to the Event and Step. */ //@{ /** * Get the first Step object where this particle occurred. */ tStepPtr birthStep() const { return hasRep() ? rep().theBirthStep : tStepPtr(); } /** * Get the order-number for this particle in the current event. */ int number() const { return hasRep() ? rep().theNumber : 0; } + + /** + * Get the status code of the particle + */ + int status() const { return theStatus; } + + /** + * Set the status code of the particle + */ + void status(int n) { theStatus = n; } //@} /** @name Access the underlying ParticleData object. */ //@{ /** * Access the ParticleData object of this particle type */ const ParticleDataClass & data() const { return *theData; } /** * Access the ParticleData object of this particle type */ tcEventPDPtr dataPtr() const { return theData; } /** * Return the PDG name of this particle. */ const string & PDGName() const { return data().PDGName(); } /** * Return the PDG id number of this particle. */ long id() const { return data().id(); } //@} /** @name Functions to access the momentum. */ //@{ /** * Return the momentum of this particle. */ const Lorentz5Momentum & momentum() const { return theMomentum; } /** * Set the 3-momentum of this particle. The energy is set to be * consistent with the mass. */ void set3Momentum(const Momentum3 & p) { theMomentum.setVect(p); theMomentum.rescaleEnergy(); } /** * Set the momentum of this particle. Afterwards, the underlying * Lorentz5Momentum may have inconsistent mass. */ void setMomentum(const LorentzMomentum & p) { theMomentum = p; } /** * Set the momentum and mass. */ void set5Momentum(const Lorentz5Momentum & p) { theMomentum = p; } /** * Acces the mass of this particle. */ Energy mass() const { return momentum().mass(); } /** * Acces the mass of this particle type. */ Energy nominalMass() const { return data().mass(); } /** * Get the scale at which this particle is considered resolved. */ Energy2 scale() const { return hasRep() ? rep().theScale : -1.0*GeV2; } /** * Set the scale at which this particle is considered resolved. */ void scale(Energy2 q2) { rep().theScale = q2; } /** * Get the scale above which this particle should * not radiate. */ Energy2 vetoScale() const { return hasRep() ? rep().theVetoScale : -1.0*GeV2; } /** * Set the scale above which this particle should * not radiate. */ void vetoScale(Energy2 q2) { rep().theVetoScale = q2; } /** * Return the transverse mass (squared), calculated from the energy * and the longitudinal momentum. */ Energy2 mt2() const { return sqr(momentum().t()) - sqr(momentum().z()); } /** * Return the transverse mass (squared), calculated from the energy * and the longitudinal momentum. */ Energy mt() const { return sqrt(mt2()); } /** * Return the transverse mass (squared), calculated from the mass * and the transverse momentum. */ Energy2 perpmass2() const { return momentum().perp2() + momentum().mass2(); } /** * Return the transverse mass (squared), calculated from the mass * and the transverse momentum. */ Energy perpmass() const { return sqrt(perpmass2()); } /** * Return the (pseudo) rapidity. */ double rapidity() const { return ( Pplus() > ZERO && Pminus() > ZERO )? 0.5*log(Pplus()/Pminus()) : Constants::MaxFloat; } /** * Return the (pseudo) rapidity. */ double eta() const { Energy rho = momentum().rho(); return rho > abs(momentum().z())? 0.5*log((rho+momentum().z())/(rho-momentum().z())) : Constants::MaxFloat; } /** * Return the positive and negative light-cone momenta. */ Energy Pplus() const { return momentum().plus(); } /** * Return the positive and negative light-cone momenta. */ Energy Pminus() const { return momentum().minus(); } //@} /** @name Functions to access the position. */ //@{ /** * The creation vertex of this particle. The point is given * relative to the collision vertex. */ const LorentzPoint & vertex() const { static const LorentzPoint null; return hasRep() ? rep().theVertex : null; } /** * The creation vertex of this particle. The absolute * position in the lab is given. */ LorentzPoint labVertex() const; /** * The decay vertex of this particle. The point is given * relative to the collision vertex. */ LorentzPoint decayVertex() const { return vertex() + lifeLength(); } /** * The decay vertex of this particle. The absolute * position in the lab is given. */ LorentzPoint labDecayVertex() const { return labVertex() + lifeLength(); } /** * The life time/length. Return the Lorentz vector connecting the * creation to the decay vertes. */ const Lorentz5Distance & lifeLength() const { static const Lorentz5Distance null; return hasRep() ? rep().theLifeLength : null; } /** * Set the creation vertex relative to the collision vertex. */ void setVertex(const LorentzPoint & p) { rep().theVertex = p; } /** * Set the creation vertex in the lab frame of this particle. */ void setLabVertex(const LorentzPoint &); /** * Set the life length of this particle. The life time will be * automatically rescaled to be consistent with the invariant * distance. */ void setLifeLength(const Distance & d) { rep().theLifeLength.setVect(d); rep().theLifeLength.rescaleEnergy(); } /** * Set the life time/length of a particle. The invariant distance * may become inconsistent. */ void setLifeLength(const LorentzDistance & d) { rep().theLifeLength = d; } /** * Set the life time/length of a particle. */ void setLifeLength(const Lorentz5Distance & d) { rep().theLifeLength = d; } /** * The invariant life time of this particle. */ Time lifeTime() const { return lifeLength().m(); } //@} /** @name Functions for (Lorentz) transformations. */ //@{ /** * Do Lorentz transformations on this particle. */ void transform(const LorentzRotation & r); /** * Do Lorentz transformations on this particle. \a bx, \a by and \a * bz are the boost vector components. */ void boost(double bx, double by, double bz) { transform(LorentzRotation(Boost(bx, by, bz))); } /** * Do Lorentz transformations on this particle. \a b is the boost * vector. */ void boost(const Boost & b) { transform(LorentzRotation(b)); } /** * Rotate around the x-axis. */ void rotateX(double a); /** * Rotate around the y-axis. */ void rotateY(double a); /** * Rotate around the z-axis. */ void rotateZ(double a); /** * Rotate around the given \a axis. */ void rotate(double a, const Axis & axis); /** * Mirror in the xy-plane. */ void mirror() { theMomentum.setZ(-theMomentum.z()); } /** * Do Lorentz transformations on this particle and its decendants. */ void deepTransform(const LorentzRotation & r); /** * Do Lorentz transformations on this particle and its * decendants. \a bx, \a by and \a bz are the boost vector * components. */ void deepBoost(double bx, double by, double bz) { deepTransform(LorentzRotation(Boost(bx, by, bz))); } /** * Do Lorentz transformations on this particle and its * decendants. \a b is the boost vector. */ void deepBoost(const Boost & b) { deepTransform(LorentzRotation(b)); } /** * Rotate this particle and its decendants around the x-axis. */ void deepRotateX(double a); /** * Rotate this particle and its decendants around the y-axis. */ void deepRotateY(double a); /** * Rotate this particle and its decendants around the z-axis. */ void deepRotateZ(double a); /** * Rotate this particle and its decendants around the given \a axis. */ void deepRotate(double a, const Axis & axis); //@} /** @name Functions controlling possible mass/momentum inconsistencies. */ //@{ /** * Return the relative inconsistency in the mass component. */ double massError() const { return theMomentum.massError(); } /** * Return the relative inconsistency in the energy component. */ double energyError() const { return theMomentum.energyError(); } /** * Return the relative inconsistency in the spatial components. */ double rhoError() const { return theMomentum.rhoError(); } /** * Rescale energy, so that the invariant length/mass of the * LorentzVector agrees with the current one. */ void rescaleEnergy() { theMomentum.rescaleEnergy(); } /** * Rescale spatial component, so that the invariant length/mass of * the LorentzVector agrees with the current one. */ void rescaleRho() { theMomentum.rescaleRho(); } /** * Set the invariant length/mass member, so that it agrees with the * invariant length/mass of the LorentzVector. */ void rescaleMass() { theMomentum.rescaleMass(); } //@} /** @name Acces incormation about colour connections */ //@{ /** * True if this particle has colour information. To determine if * this particle is actually coloured, the coloured(), hasColour() or * hasAntiColour() methods should be used instead. */ bool hasColourInfo() const { return hasRep() && rep().theColourInfo; } /** * Return the colour lines to which this particles anti-colour is * connected. */ tColinePtr antiColourLine() const { return hasColourInfo() ? colourInfo()->antiColourLine() : tColinePtr(); } /** * Return the colour lines to which this particles (\a anti-)colour * is connected. */ tColinePtr colourLine(bool anti = false) const { if ( anti ) return antiColourLine(); return hasColourInfo() ? colourInfo()->colourLine() : tColinePtr(); } /** * Return true if the particle is connected to the given (\a anti-) * colour \a line. */ bool hasColourLine(tcColinePtr line, bool anti = false) const { return hasColourInfo() ? colourInfo()->hasColourLine(line, anti) : false; } /** * Return true if the particle is connected to the given anti-colour * \a line. */ bool hasAntiColourLine(tcColinePtr line) const { return hasColourLine(line, true); } /** * True if this particle type is not a colour singlet. */ bool coloured() const { return data().coloured(); } /** * True if this particle type carries (\a anti-)colour. */ bool hasColour(bool anti = false) const { return data().hasColour(anti); } /** * True if this particle type carries anti-colour. */ bool hasAntiColour() const { return data().hasAntiColour(); } /** * Get the ColourBase object. */ tcCBPtr colourInfo() const { return hasRep() ? rep().theColourInfo : CBPtr(); } /** * Get the ColourBase object. */ tCBPtr colourInfo() { if ( !rep().theColourInfo ) { switch(theData->iColour()) { case PDT::Colour6: case PDT::Colour6bar: rep().theColourInfo = new_ptr(MultiColour()); break; default: rep().theColourInfo = new_ptr(ColourBase()); } } return rep().theColourInfo; } /** * Set the ColourBase object. */ void colourInfo(tCBPtr c) { rep().theColourInfo = c; } /** * Get a pointer to the colour neighbor. Returns a particle in the * range \a first to \a last which colour is connected to the same * line as this particles anti-colour. If \a anti is true return * antiColourNeighbour(). */ template typename std::iterator_traits::value_type colourNeighbour(Iterator first, Iterator last, bool anti = false) const; /** * Get a pointer to the anti-colour neighbor. Returns a particle in * the range \a first to \a last which anti-colour is * connected to the same line as this particles colour. */ template typename std::iterator_traits::value_type antiColourNeighbour(Iterator first, Iterator last) const { return colourNeighbour(first, last, true); } /** * Set the colour neighbor. Connects the given particles colour to * the same colour line as this particles anti-colour. If \a anti is * true call antiColourNeighbour(tPPtr). */ void colourNeighbour(tPPtr, bool anti = false); /** * Set the anti-colour neighbor. Connects the given particles * anti-colour to the same colour line as this particles colour. */ void antiColourNeighbour(tPPtr p) { colourNeighbour(p, true); } /** * Connect colour. Create a colour line connecting to it this * particles colour and the given particles anti-colour. */ void antiColourConnect(tPPtr neighbour) { colourConnect(neighbour, true); } /** * Connect colour. Create a colour line connecting to it this * particles anti-colour and the given particles colour. If \a anti * is true call antiColourConnect(tPPtr). */ void colourConnect(tPPtr neighbour, bool anti = false) { colourNeighbour(neighbour, anti); } /** * Incoming colour. Return the parent particle which colour is * connected to the same colour line as this particle. If \a anti is * true return incomingAntiColour(). */ tPPtr incomingColour(bool anti = false) const; /** * Incoming anti-colour. Return the parent particle which * anti-colour is connected to the same colour line as this * particle. */ tPPtr incomingAntiColour() const { return incomingColour(true); } /** * Set incoming colour. Connect this particles colour to the same * colour line as the given particle. If \a anti * is true call incomingAntiColour(tPPtr). */ void incomingColour(tPPtr p, bool anti = false) { p->outgoingColour(this, anti); } /** * Set incoming anti-colour. Connect this particles anti colour to * the same colour line as the given particle. */ void incomingAntiColour(tPPtr p) { p->outgoingColour(this, true); } /** * Outgoing colour. Return the daughter particle which colour is * connected to the same colour line as this particle. If \a anti is * true return outgoingAntiColour(). */ tPPtr outgoingColour(bool anti = false) const; /** * Outgoing anti-colour. Return the daughter particle which * anti-colour is connected to the same colour line as this * particle. */ tPPtr outgoingAntiColour() const { return outgoingColour(true); } /** * Set outgoing colour. Connect this particles colour to the same * colour line as the given particle. If \a anti * is true call outgoingAntiColour(tPPtr). */ void outgoingColour(tPPtr, bool anti = false); /** * Set outgoing anti-colour. Connect this particles anti-colour to * the same colour line as the given particle. */ void outgoingAntiColour(tPPtr p) { outgoingColour(p, true); } /** * Specify colour flow. Calls outgoingColour(tPPtr,bool). */ void colourFlow(tPPtr child, bool anti = false) { outgoingColour(child, anti); } /** * Specify anticolour flow. Calls outgoingAntiColour(tPPtr,bool). */ void antiColourFlow(tPPtr child) { colourFlow(child, true); } /** * Remove all colour information; */ void resetColour() { if ( hasColourInfo() ) rep().theColourInfo = CBPtr(); } //@} /** @name Functions to access spin. */ //@{ /** * Return the Spin object. */ tcSpinPtr spinInfo() const { return hasRep() ? rep().theSpinInfo : SpinPtr(); } /** * Return the Spin object. */ tSpinPtr spinInfo() { return hasRep() ? rep().theSpinInfo : SpinPtr(); } /** * Set the Spin object. */ void spinInfo(tSpinPtr s) { rep().theSpinInfo = s; } //@} /** @name Accessing user-defined information. */ //@{ /** * Access user-defined information as a vector of EventInfoBase pointers. */ const EIVector & getInfo() const { static const EIVector null; return hasRep() ? rep().theExtraInfo : null; } /** * Access user-defined information as a vector of EventInfoBase pointers. */ EIVector & getInfo() { return rep().theExtraInfo; } //@} public: /** @name Accessing user-defined information. */ //@{ /** * True if this particle has instantiated the object with * information other than type and momentum. */ bool hasRep() const { return theRep; } /** * If this particle has only a type and momentum, instantiate the * rest of the information. */ void initFull(); //@} public: /** @name Input and output functions. */ //@{ /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard function for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); //@} /** * Print particle info to a stream \a os. The \a step is used to * access information about colour neighbors and other struff. */ ostream & print(ostream & os, tcStepPtr step = tcStepPtr()) const; /** * Print a range of particles. */ template static void PrintParticles(ostream & os, Iterator first, Iterator last, tcStepPtr step = tcStepPtr()); /** * Print a container of particles. */ template static inline void PrintParticles(ostream & os, const Cont & c, tcStepPtr step = tcStepPtr()) { PrintParticles(os, c.begin(), c.end(), step); } /** * Standard Init function. @see Base::Init(). */ static void Init(); /** * Specify how to print particles. The format string is analogous to * the one used by eg. the unix 'date' command as described above. */ static string outputFormat; private: /** * Standard clone function. */ virtual PPtr clone() const; /** * Rebind to cloned objects. When an Event is cloned, a shallow * copy is done first, then all Particles etc, are * cloned, and finally this method is used to see to that the * pointers in the cloned Particle points to the cloned objects. */ virtual void rebind(const EventTranslationMap &); /** * Set the order-number for this particle in the current event. */ void number(int n) { rep().theNumber = n; } /** * Remove the given particle from the list of children. */ void removeChild(tPPtr c) { if ( hasRep() ) rep().theChildren.erase(remove(rep().theChildren.begin(), rep().theChildren.end(), c), rep().theChildren.end()); } /** * Remove the given particle from the list of parents. */ void removeParent(tPPtr p) { if ( hasRep() ) rep().theParents.erase(remove(rep().theParents.begin(), rep().theParents.end(), p), rep().theParents.end()); } /** * Set the mass of this particle. */ void mass(Energy m) { theMomentum.setMass(m); } /** * Set the invaiant life time of this particle. */ void lifeTime(Length t) { rep().theLifeLength.setTau(t); } /** * Return a reference to the bulk information of this particle. if * no ParticleRep object exists, one is created. */ ParticleRep & rep() { if ( !hasRep() ) initFull(); return *theRep; } /** * Return a reference to the bulk information of this particle. if * no ParticleRep object exists, we return the default values. */ const ParticleRep & rep() const { static const ParticleRep null; return hasRep() ? *theRep : null; } /** * The pointer to the ParticleData object */ cEventPDPtr theData; /** * The momentum. */ Lorentz5Momentum theMomentum; /** * The rest of the information in this particle is only instantiated * if needed. */ ParticleRep * theRep; + /** + * The status code of the particle + */ + int theStatus; + public: /** * This class is used internally in the Particle class to represent * information besides momentum and type. A corresponding object * will only be instantiated if needed to save memory and time when * temporarily creating particles. */ struct ParticleRep { /** * Default constructor. */ ParticleRep() : theScale(-1.0*GeV2), theVetoScale(-1.0*GeV2), theNumber(0) {} /** * Copy constructor. */ ParticleRep(const ParticleRep &); /** * The pointers to the parents. */ tParticleVector theParents; /** * The pointers to the children. */ ParticleVector theChildren; /** * The pointer to the previous instance. */ tPPtr thePrevious; /** * The pointer to the next instance. */ PPtr theNext; /** * If this particle has decayed this is the pointer to the * corresponding decay mode. */ tDMPtr theDecayMode; /** * The pointer to the first step where this particle occurred. */ tStepPtr theBirthStep; /** * The creation point. */ LorentzPoint theVertex; /** * The life time/length. */ Lorentz5Distance theLifeLength; /** * the resolution scale. */ Energy2 theScale; /** * the veto scale. */ Energy2 theVetoScale; /** * The order-number for this particle in the current event. */ int theNumber; /** * A pointer to the colour information object. */ CBPtr theColourInfo; /** * Spin information */ SpinPtr theSpinInfo; /** * Additional used-defined information. */ EIVector theExtraInfo; }; public: /** * Print out debugging information for this object on std::cerr. To * be called from within a debugger via the debug() function. */ virtual void debugme() const; protected: /** * Private default constructor must only be used by the * PersistentIStream class via the ClassTraits class. */ - Particle() : theRep(0) {} + Particle() : theRep(0), theStatus(0) {} /** * The ClassTraits class must be a friend to be able to * use the private default constructor. */ friend struct ClassTraits; private: /** * Private and non-existent assignment. */ Particle & operator=(const Particle &) = delete; /** * Describe concrete class with persistent data. */ static ClassDescription initParticle; }; /** * Write a Particle object to a stream. */ ostream & operator<<(ostream &, const Particle &); /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base class of Particle. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Collision. */ typedef EventRecordBase NthBase; }; /** This template specialization informs ThePEG about the name of * the Particle class and how to create it. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::Particle"; } /** Create a Particle object. */ static TPtr create() { return TPtr::Create(Particle()); } }; /** @endcond */ } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Particle.tcc" #endif #endif /* ThePEG_Particle_H */ diff --git a/Vectors/HepMCConverter.tcc b/Vectors/HepMCConverter.tcc --- a/Vectors/HepMCConverter.tcc +++ b/Vectors/HepMCConverter.tcc @@ -1,337 +1,337 @@ // -*- C++ -*- // // HepMCConverter.tcc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 1999-2017 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HepMCConverter class. // #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/StandardSelectors.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/PDF/PDF.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Utilities/Throw.h" namespace ThePEG { template typename HepMCConverter::GenEvent * HepMCConverter:: convert(const Event & ev, bool nocopies, Energy eunit, Length lunit) { HepMCConverter converter(ev, nocopies, eunit, lunit); return converter.geneve; } template void HepMCConverter:: convert(const Event & ev, GenEvent & gev, bool nocopies) { HepMCConverter converter(ev, gev, nocopies, Traits::momentumUnit(gev), Traits::lengthUnit(gev)); } template void HepMCConverter:: convert(const Event & ev, GenEvent & gev, bool nocopies, Energy eunit, Length lunit) { HepMCConverter converter(ev, gev, nocopies, eunit, lunit); } template HepMCConverter:: HepMCConverter(const Event & ev, bool nocopies, Energy eunit, Length lunit) : energyUnit(eunit), lengthUnit(lunit) { geneve = Traits::newEvent(ev.number(), ev.weight(), ev.optionalWeights()); init(ev, nocopies); } template HepMCConverter:: HepMCConverter(const Event & ev, GenEvent & gev, bool nocopies, Energy eunit, Length lunit) : energyUnit(eunit), lengthUnit(lunit) { geneve = &gev; Traits::resetEvent(geneve, ev.number(), ev.weight(), ev.optionalWeights()); init(ev, nocopies); } struct ParticleOrderNumberCmp { bool operator()(tcPPtr a, tcPPtr b) const { return a->number() < b->number(); } }; template void HepMCConverter::init(const Event & ev, bool nocopies) { if ( lengthUnit != millimeter && lengthUnit != centimeter ) Throw() << "Length unit used for HepMC::GenEvent was not MM nor CM." << Exception::runerror; if ( energyUnit != GeV && energyUnit != MeV ) Throw() << "Momentum unit used for HepMC::GenEvent was not GEV nor MEV." << Exception::runerror; Traits::setUnits(*geneve, energyUnit, lengthUnit); tcEHPtr eh; if ( ev.primaryCollision() && ( eh = dynamic_ptr_cast(ev.primaryCollision()->handler()) ) ) { // Get general event info if present. Traits::setScaleAndAlphas(*geneve, eh->lastScale(), eh->lastAlphaS(),eh->lastAlphaEM(), energyUnit); } // Extract all particles and order them. tcPVector all; ev.select(back_inserter(all), SelectAll()); stable_sort(all.begin(), all.end(), ParticleOrderNumberCmp()); vertices.reserve(all.size()*2); // Create GenParticle's and map them to the ThePEG particles. for ( int i = 0, N = all.size(); i < N; ++i ) { tcPPtr p = all[i]; if ( nocopies && p->next() ) continue; if ( pmap.find(p) != pmap.end() ) continue; pmap[p] = createParticle(p); if ( !p->children().empty() || p->next() ) { // If the particle has children it should have a decay vertex: vertices.push_back(Vertex()); decv[p] = &vertices.back(); vertices.back().in.insert(p); } if ( !p->parents().empty() || p->previous() || (p->children().empty() && !p->next()) ) { // If the particle has parents it should have a production // vertex. If neither parents or children it should still have a // dummy production vertex. vertices.push_back(Vertex()); prov[p] = &vertices.back(); vertices.back().out.insert(p); } } // Now go through the the particles again, and join the vertices. for ( int i = 0, N = all.size(); i < N; ++i ) { tcPPtr p = all[i]; if ( nocopies ) { if ( p->next() ) continue; for ( int i = 0, N = p->children().size(); i < N; ++i ) join(p, p->children()[i]->final()); tcPPtr pp = p; while ( pp->parents().empty() && pp->previous() ) pp = pp->previous(); for ( int i = 0, N = pp->parents().size(); i < N; ++i ) join(pp->parents()[i]->final(), p); } else { for ( int i = 0, N = p->children().size(); i < N; ++i ) join(p, p->children()[i]); if ( p->next() ) join(p, p->next()); for ( int i = 0, N = p->parents().size(); i < N; ++i ) join(p->parents()[i], p); if ( p->previous() ) join(p->previous(), p); } } // Time to create the GenVertex's for ( typename VertexMap::iterator it = prov.begin(); it != prov.end(); ++it ) if ( !member(vmap, it->second) ) vmap[it->second] = createVertex(it->second); for ( typename VertexMap::iterator it = decv.begin(); it != decv.end(); ++it ) if ( !member(vmap, it->second) ) vmap[it->second] = createVertex(it->second); // Now find the primary signal process vertex defined to be the // decay vertex of the first parton coming into the primary hard // sub-collision. tSubProPtr sub = ev.primarySubProcess(); if ( sub && sub->incoming().first ) { const Vertex * prim = decv[sub->incoming().first]; Traits::setSignalProcessVertex(*geneve, vmap[prim]); vmap.erase(prim); } // Then add the rest of the vertices. for ( typename GenVertexMap::iterator it = vmap.begin(); it != vmap.end(); ++it ) Traits::addVertex(*geneve, it->second); // and the incoming beam particles Traits::setBeamParticles(*geneve,pmap[ev.incoming().first], pmap[ev.incoming().second]); // and the PDF info setPdfInfo(ev); // and the cross section info Traits::setCrossSection(*geneve, eh->integratedXSec()/picobarn, eh->integratedXSecErr()/picobarn); for ( int i = 0, N = all.size(); i < N; ++i ) { tcPPtr p = all[i]; if ( pmap.find(p) == pmap.end() ) continue; GenParticlePtrT gp = pmap[p]; if ( p->hasColourInfo() ) { // Check if the particle is connected to colour lines, in which // case the lines are mapped to an integer and set in the // GenParticle's Flow info. tcColinePtr l; if ( (l = p->colourLine()) ) { if ( !member(flowmap, l) ) flowmap[l] = flowmap.size() + 500; Traits::setColourLine(*gp, 1, flowmap[l]); } if ( (l = p->antiColourLine()) ) { if ( !member(flowmap, l) ) flowmap[l] = flowmap.size() + 500; Traits::setColourLine(*gp, 2, flowmap[l]); } } if ( p->spinInfo() && p->spinInfo()->hasPolarization() ) { DPair pol = p->spinInfo()->polarization(); Traits::setPolarization(*gp, pol.first, pol.second); } } } template typename HepMCConverter::GenParticlePtrT HepMCConverter::createParticle(tcPPtr p) const { int status = 1; size_t nChildren = p->children().size(); if ( nChildren > 0 || p->next() ) status = 11; if ( nChildren > 1 ) { long id = p->data().id(); if ( BaryonMatcher::Check(id) || MesonMatcher::Check(id) || id == ParticleID::muminus || id == ParticleID::muplus || id == ParticleID::tauminus || id == ParticleID::tauplus ) { bool child = false; for(unsigned int ix=0;ixchildren()[ix]->id()==id) { child = true; break; } } if ( !child ) { if(p->data().widthCut()!=ZERO) { if(p->mass() <= p->data().massMax() && p->mass() >= p->data().massMin() ) status = 2; } else { status = 2; } } } } GenParticlePtrT gp = - Traits::newParticle(p->momentum(), p->id(), status, energyUnit); + Traits::newParticle(p->momentum(), p->id(), p->status() ? p->status() : status, energyUnit); if ( p->spinInfo() && p->spinInfo()->hasPolarization() ) { DPair pol = p->spinInfo()->polarization(); Traits::setPolarization(*gp, pol.first, pol.second); } return gp; } template void HepMCConverter::join(tcPPtr parent, tcPPtr child) { Vertex * dec = decv[parent]; Vertex * pro = prov[child]; if ( !pro || !dec ) Throw() << "Found a reference to a ThePEG::Particle which was not in the Event." << Exception::eventerror; if ( pro == dec ) return; while ( !pro->in.empty() ) { dec->in.insert(*(pro->in.begin())); decv[*(pro->in.begin())] = dec; pro->in.erase(pro->in.begin()); } while ( !pro->out.empty() ) { dec->out.insert(*(pro->out.begin())); prov[*(pro->out.begin())] = dec; pro->out.erase(pro->out.begin()); } } template typename HepMCConverter::GenVertexPtrT HepMCConverter::createVertex(Vertex * v) { if ( !v ) Throw() << "Found internal null Vertex." << Exception::abortnow; GenVertexPtrT gv = Traits::newVertex(); // We assume that the vertex position is the average of the decay // vertices of all incoming and the creation vertices of all // outgoing particles in the lab. Note that this will probably not // be useful information for very small distances. LorentzPoint p; for ( tcParticleSet::iterator it = v->in.begin(); it != v->in.end(); ++it ) { p += (**it).labDecayVertex(); Traits::addIncoming(*gv, pmap[*it]); } for ( tcParticleSet::iterator it = v->out.begin(); it != v->out.end(); ++it ) { p += (**it).labVertex(); Traits::addOutgoing(*gv, pmap[*it]); } p /= double(v->in.size() + v->out.size()); Traits::setPosition(*gv, p, lengthUnit); return gv; } template void HepMCConverter::setPdfInfo(const Event & e) { // ids of the partons going into the primary sub process tSubProPtr sub = e.primarySubProcess(); int id1 = sub->incoming().first ->id(); int id2 = sub->incoming().second->id(); // get the event handler tcEHPtr eh = dynamic_ptr_cast(e.handler()); // get the values of x double x1 = eh->lastX1(); double x2 = eh->lastX2(); // get the pdfs pair pdfs; pdfs.first = eh->pdf(sub->incoming().first ); pdfs.second = eh->pdf(sub->incoming().second); // get the scale Energy2 scale = eh->lastScale(); // get the values of the pdfs double xf1 = pdfs.first.xfx(sub->incoming().first->dataPtr(), scale, x1); double xf2 = pdfs.second.xfx(sub->incoming().second->dataPtr(), scale, x2); Traits::setPdfInfo(*geneve, id1, id2, x1, x2, sqrt(scale/GeV2), xf1, xf2); } }