File indexing completed on 2026-08-06 09:24:17
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef HERWIG_PrototypeVertex_H
0010 #define HERWIG_PrototypeVertex_H
0011 #include <stack>
0012 #include "ThePEG/Helicity/Vertex/VertexBase.h"
0013 #include "ThePEG/Persistency/PersistentOStream.h"
0014 #include "ThePEG/Persistency/PersistentIStream.h"
0015 #include "ThePEG/Utilities/EnumIO.h"
0016 #include "NBodyDecayConstructorBase.fh"
0017
0018
0019
0020
0021 namespace Herwig {
0022 using namespace ThePEG;
0023 using Helicity::VertexBasePtr;
0024
0025 class PrototypeVertex;
0026 ThePEG_DECLARE_POINTERS(Herwig::PrototypeVertex,PrototypeVertexPtr);
0027
0028
0029 typedef pair<unsigned int, double> CFPair;
0030
0031
0032
0033
0034
0035 struct ParticleOrdering {
0036
0037
0038
0039
0040
0041 bool operator() (tcPDPtr p1, tcPDPtr p2) const {
0042 return abs(p1->id()) > abs(p2->id()) ||
0043 ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) ||
0044 ( p1->id() == p2->id() && p1->fullName() > p2->fullName() );
0045 }
0046 };
0047
0048
0049
0050
0051 struct VertexOrdering {
0052
0053
0054
0055
0056
0057 bool operator() (const pair< tPDPtr, PrototypeVertexPtr > & p1,
0058 const pair< tPDPtr, PrototypeVertexPtr > & p2) const {
0059 return abs(p1.first->id()) > abs(p2.first->id()) ||
0060 ( abs(p1.first->id()) == abs(p2.first->id()) && p1.first->id() > p2.first->id() ) ||
0061 ( p1.first->id() == p2.first->id() && p1.first->fullName() > p2.first->fullName() );
0062 }
0063 };
0064
0065 typedef multiset<pair< tPDPtr, PrototypeVertexPtr >,VertexOrdering > OrderedVertices;
0066
0067
0068
0069
0070 typedef multiset<PDPtr,ParticleOrdering> OrderedParticles;
0071
0072
0073
0074
0075 class PrototypeVertex : public Base {
0076
0077 public:
0078
0079
0080
0081
0082 PrototypeVertex() : npart(0), possibleOnShell(false) {}
0083
0084
0085
0086
0087 PrototypeVertex(tPDPtr in, OrderedVertices out,
0088 VertexBasePtr v, int n) :
0089 incoming(in), outgoing(out), vertex(v), npart(n),
0090 possibleOnShell(false) {}
0091
0092
0093
0094
0095 tPDPtr incoming;
0096
0097
0098
0099
0100 OrderedVertices outgoing;
0101
0102
0103
0104
0105 VertexBasePtr vertex;
0106
0107
0108
0109
0110 tPrototypeVertexPtr parent;
0111
0112
0113
0114
0115 unsigned int npart;
0116
0117
0118
0119
0120 mutable OrderedParticles outPart;
0121
0122
0123
0124
0125 bool possibleOnShell;
0126
0127
0128
0129
0130 void incrementN(int in) {
0131 npart += in;
0132 if(parent) parent->incrementN(in);
0133 }
0134
0135
0136
0137
0138 Energy incomingMass() {
0139 return incoming->mass();
0140 }
0141
0142
0143
0144
0145 Energy outgoingMass() {
0146 Energy mass(ZERO);
0147 for(OrderedVertices::const_iterator it = outgoing.begin();
0148 it!=outgoing.end();++it) {
0149 mass += it->second ?
0150 it->second->outgoingMass() : it->first->mass();
0151 }
0152 return mass;
0153 }
0154
0155
0156
0157
0158 Energy outgoingConstituentMass() {
0159 Energy mass(ZERO);
0160 for(OrderedVertices::const_iterator it = outgoing.begin();
0161 it!=outgoing.end();++it) {
0162 mass += it->second ?
0163 it->second->outgoingConstituentMass() : it->first->constituentMass();
0164 }
0165 return mass;
0166 }
0167
0168
0169
0170
0171 bool checkExternal(bool first=true) {
0172 if(outPart.empty()) setOutgoing();
0173 if(first&&outPart.find(incoming)!=outPart.end()) return false;
0174 bool output = true;
0175 for(OrderedVertices::const_iterator it = outgoing.begin();
0176 it!=outgoing.end();++it) {
0177 if(it->second&& !it->second->checkExternal(false)) output = false;
0178 }
0179 return output;
0180 }
0181
0182
0183
0184
0185 void setOutgoing() const {
0186 assert(outPart.empty());
0187 for(OrderedVertices::const_iterator it = outgoing.begin();
0188 it!=outgoing.end();++it) {
0189 if(it->second) {
0190 it->second->setOutgoing();
0191 outPart.insert(it->second->outPart.begin(),
0192 it->second->outPart.end());
0193 }
0194 else
0195 outPart.insert(it->first);
0196 }
0197 }
0198
0199
0200
0201
0202 bool canBeOnShell(unsigned int opt,Energy maxMass,bool first);
0203
0204
0205
0206
0207 bool sameDecay(const PrototypeVertex & x) const;
0208
0209
0210
0211
0212 static void createPrototypes(tPDPtr inpart, VertexBasePtr vertex,
0213 std::stack<PrototypeVertexPtr> & prototypes,
0214 NBodyDecayConstructorBasePtr decayCon);
0215
0216
0217
0218
0219 static void expandPrototypes(PrototypeVertexPtr proto, VertexBasePtr vertex,
0220 std::stack<PrototypeVertexPtr> & prototypes,
0221 const set<PDPtr> & excluded,
0222 NBodyDecayConstructorBasePtr decayCon);
0223
0224
0225
0226
0227 static PrototypeVertexPtr replicateTree(PrototypeVertexPtr parent,
0228 PrototypeVertexPtr oldChild,
0229 PrototypeVertexPtr & newChild);
0230
0231 };
0232
0233
0234
0235
0236 inline ostream & operator<<(ostream & os, const PrototypeVertex & diag) {
0237 os << diag.incoming->PDGName() << " -> ";
0238 bool seq=false;
0239 for(OrderedVertices::const_iterator it = diag.outgoing.begin();
0240 it!=diag.outgoing.end();++it) {
0241 os << it->first->PDGName() << " ";
0242 if(it->second) seq = true;
0243 }
0244 os << " decays via "
0245 << diag.vertex->fullName() << " in a "
0246 << diag.npart << "-body decay\n";
0247 if(!seq) return os;
0248 os << "Followed by\n";
0249 for(OrderedVertices::const_iterator it = diag.outgoing.begin();
0250 it!=diag.outgoing.end();++it) {
0251 if(it->second) os << *it->second;
0252 }
0253 return os;
0254 }
0255
0256
0257
0258
0259 inline bool operator==(const PrototypeVertex & x, const PrototypeVertex & y) {
0260 if(x.incoming != y.incoming) return false;
0261 if(x.vertex != y.vertex) return false;
0262 if(x.npart != y.npart) return false;
0263 if(x.outgoing.empty()&&y.outgoing.empty()) return true;
0264 if(x.outgoing.size() != y.outgoing.size()) return false;
0265 OrderedVertices::const_iterator xt = x.outgoing.begin();
0266 OrderedVertices::const_iterator yt = y.outgoing.begin();
0267 while(xt!=x.outgoing.end()) {
0268 if(xt->first != yt->first) return false;
0269
0270 OrderedVertices::const_iterator lxt = x.outgoing.lower_bound(*xt);
0271 OrderedVertices::const_iterator uxt = x.outgoing.upper_bound(*xt);
0272 --uxt;
0273
0274 if(lxt==uxt) {
0275 if(xt->second && yt->second) {
0276 if(*(xt->second)==*(yt->second)) {
0277 ++xt;
0278 ++yt;
0279 continue;
0280 }
0281 else return false;
0282 }
0283 else if(xt->second || yt->second)
0284 return false;
0285 ++xt;
0286 ++yt;
0287 }
0288
0289 else {
0290 ++uxt;
0291 OrderedVertices::const_iterator lyt = y.outgoing.lower_bound(*xt);
0292 OrderedVertices::const_iterator uyt = y.outgoing.upper_bound(*xt);
0293 unsigned int nx=0;
0294 for(OrderedVertices::const_iterator ixt=lxt;ixt!=uxt;++ixt) {++nx;}
0295 unsigned int ny=0;
0296 for(OrderedVertices::const_iterator iyt=lyt;iyt!=uyt;++iyt) {++ny;}
0297 if(nx!=ny) return false;
0298 vector<bool> matched(ny,false);
0299 for(OrderedVertices::const_iterator ixt=lxt;ixt!=uxt;++ixt) {
0300 bool found = false;
0301 unsigned int iy=0;
0302 for(OrderedVertices::const_iterator iyt=lyt;iyt!=uyt;++iyt) {
0303 if(matched[iy]) {
0304 ++iy;
0305 continue;
0306 }
0307 if( (!ixt->second &&!iyt->second) ||
0308 ( ixt->second&&iyt->second &&
0309 *(ixt->second)==*(iyt->second)) ) {
0310 matched[iy] = true;
0311 found = true;
0312 break;
0313 }
0314 ++iy;
0315 }
0316 if(!found) return false;
0317 }
0318 xt=uxt;
0319 yt=uyt;
0320 }
0321 }
0322 return true;
0323 }
0324
0325
0326
0327
0328 struct NBVertex {
0329
0330
0331
0332
0333 NBVertex(PrototypeVertexPtr proto = PrototypeVertexPtr() );
0334
0335
0336
0337
0338 tPDPtr incoming;
0339
0340
0341
0342
0343 mutable OrderedParticles outgoing;
0344
0345
0346
0347
0348 list<pair<PDPtr,NBVertex> > vertices;
0349
0350
0351
0352
0353 VertexBasePtr vertex;
0354 };
0355
0356
0357
0358
0359
0360 struct NBDiagram : public NBVertex {
0361
0362
0363
0364 NBDiagram(PrototypeVertexPtr proto=PrototypeVertexPtr());
0365
0366
0367
0368
0369 vector<unsigned int> channelType;
0370
0371
0372 mutable vector<CFPair> colourFlow;
0373
0374
0375 mutable vector<CFPair> largeNcColourFlow;
0376 };
0377
0378
0379
0380
0381
0382
0383 inline PersistentOStream & operator<<(PersistentOStream & os,
0384 const NBVertex & x) {
0385 os << x.incoming << x.outgoing << x.vertices << x.vertex;
0386 return os;
0387 }
0388
0389
0390
0391
0392
0393
0394 inline PersistentIStream & operator>>(PersistentIStream & is,
0395 NBVertex & x) {
0396 is >> x.incoming >> x.outgoing >> x.vertices >> x.vertex;
0397 return is;
0398 }
0399
0400
0401
0402
0403
0404
0405 inline PersistentOStream & operator<<(PersistentOStream & os,
0406 const NBDiagram & x) {
0407 os << x.incoming << x.channelType << x.outgoing << x.vertices << x.vertex
0408 << x.colourFlow << x.largeNcColourFlow;
0409 return os;
0410 }
0411
0412
0413
0414
0415
0416
0417 inline PersistentIStream & operator>>(PersistentIStream & is,
0418 NBDiagram & x) {
0419 is >> x.incoming >> x.channelType >> x.outgoing >> x.vertices >> x.vertex
0420 >> x.colourFlow >> x.largeNcColourFlow;
0421 return is;
0422 }
0423
0424
0425
0426
0427 inline ostream & operator<<(ostream & os, const NBVertex & vertex) {
0428 os << vertex.incoming->PDGName() << " -> ";
0429 bool seq=false;
0430 for(list<pair<PDPtr,NBVertex> >::const_iterator it=vertex.vertices.begin();
0431 it!=vertex.vertices.end();++it) {
0432 os << it->first->PDGName() << " ";
0433 if(it->second.incoming) seq = true;
0434 }
0435 os << "via vertex " << vertex.vertex->fullName() << "\n";
0436 if(!seq) return os;
0437 os << "Followed by\n";
0438 for(list<pair<PDPtr,NBVertex> >::const_iterator it=vertex.vertices.begin();
0439 it!=vertex.vertices.end();++it) {
0440 if(it->second.incoming) os << it->second;
0441 }
0442 return os;
0443 }
0444
0445
0446
0447
0448 inline ostream & operator<<(ostream & os, const NBDiagram & diag) {
0449 os << diag.incoming->PDGName() << " -> ";
0450 for(OrderedParticles::const_iterator it=diag.outgoing.begin();
0451 it!=diag.outgoing.end();++it) {
0452 os << (**it).PDGName() << " ";
0453 }
0454 os << " has order ";
0455 for(unsigned int ix=0;ix<diag.channelType.size();++ix)
0456 os << diag.channelType[ix] << " ";
0457 os << "\n";
0458 os << "First decay " << diag.incoming->PDGName() << " -> ";
0459 bool seq=false;
0460 for(list<pair<PDPtr,NBVertex> >::const_iterator it=diag.vertices.begin();
0461 it!=diag.vertices.end();++it) {
0462 os << it->first->PDGName() << " ";
0463 if(it->second.incoming) seq = true;
0464 }
0465 os << "via vertex " << diag.vertex->fullName() << "\n";
0466 if(!seq) return os;
0467 os << "Followed by\n";
0468 for(list<pair<PDPtr,NBVertex> >::const_iterator it=diag.vertices.begin();
0469 it!=diag.vertices.end();++it) {
0470 if(it->second.incoming) os << it->second;
0471 }
0472 return os;
0473 }
0474
0475 }
0476
0477 #endif