diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -1,27 +1,28 @@ 0704eccbbae770dd2df2e8145a5dd46e4cb29b66 java-merge 0704eccbbae770dd2df2e8145a5dd46e4cb29b66 pre-cuts-merge 2763da36e168c75a5b48d63a5f44836eb521b343 herwig-2-0-alpha1 337e051dcffc653cd0429988f12806758c183472 release-1-6-1 3f01c180519e15200a4de8e0e9b7f298ab145d57 pre-java-merge 432bd5d28ebdf0c95e737452ac068515c589872f pre-libtool-merge 57f60f2e143afcc16543173ce59601fded4b8247 release-1-7-0 5830e4eb9afe3ba3705341778a40d0fe2dc6567c release-1-8-0 67c66b02adf69f650c77c50d89b698d8ed54c929 release-1-7-2 7e8967c704d1f8a551637a300130587154e9028b LHA-merge 825d126ced6f38223a9b378ba9b09dba4f48751e pre-LHA-merge 8cab12da53be26a852e6a407f53db5e1997fd0b1 release-1-7-1 8d298cf18309cdbded5344990a4955699afff04b cuts-merge b6a8110c61f6226e9a8e0c7f3fa73ec3638bc9c1 herwig-2-0-alpha3 b6a8110c61f6226e9a8e0c7f3fa73ec3638bc9c1 herwig-2-0-beta d063c89add007af8bcff8d8b166576b6b1c091ba release-1-6-0 f4f74476f4db925446c84b54e90c0ef27b82a3d6 libtool-merge d6ba7d425e3ae8b01157223638cbcf0dac939904 release-1-8-1 813a7eb367a9a119998aaf74682a5543bf570da1 release-1-8-2 52eeb52c35cf8b1ceed0e754ef47dd4af282cfa3 release-1-8-3 9ac24d1eb03b6286038402b3420b2520846ce9f0 release-1-9-0 f0ef8fb93d924e1c01a30eeaf172f9fd82d0b4d2 release-1-9-1 2d8e0f74b65ef7f5acdf0128e7280fff535d1f82 release-1-9-2 4cf20ed60ecd8c9016cdaf9e3f6cd0347cee8185 release-2-0-0 7346f289aba9116f5b2327b98adb4b4e8b6a76dc release-2-0-1 16491c05f54af0c4c02cbf40fc3e77120eba8374 release-2-0-2 b08a997136055e39cac6187eeb3c3f84ddc148bc release-2-0-3 +9772c45ac9a165f4c30764e1ba1df43d778d6932 release-2-0-4 diff --git a/Analysis/Makefile.am b/Analysis/Makefile.am --- a/Analysis/Makefile.am +++ b/Analysis/Makefile.am @@ -1,67 +1,67 @@ AIDAWRAPPERS = LWH/AIAnalysisFactory.h LWH/AIAxis.h LWH/AIHistogram1D.h LWH/AIHistogram2D.h \ LWH/AIHistogramFactory.h LWH/AITree.h LWH/AITreeFactory.h \ LWH/AIManagedObject.h LWH/AIDataPoint.h LWH/AIDataPointSet.h \ LWH/AIDataPointSetFactory.h LWH/AIMeasurement.h LWHHEADERS = LWH/AnalysisFactory.h LWH/Axis.h LWH/Tree.h LWH/TreeFactory.h \ LWH/Histogram1D.h LWH/Histogram2D.h LWH/HistogramFactory.h LWH/ManagedObject.h \ LWH/VariAxis.h LWH/DataPoint.h LWH/DataPointSet.h LWH/DataPointSetFactory.h \ LWH/Measurement.h mySOURCES = LWHFactory.cc pkglib_LTLIBRARIES = LWHFactory.la XSecCheck.la ProgressLog.la if HAVE_RIVET DOCFILES = RivetAnalysis.h NLORivetAnalysis.h pkglib_LTLIBRARIES += RivetAnalysis.la RivetAnalysis_la_CPPFLAGS = $(AM_CPPFLAGS) $(RIVETINCLUDE) $(HEPMCINCLUDE) RivetAnalysis_la_LIBADD = $(HEPMCLIBS) $(RIVETLIBS) RivetAnalysis_la_SOURCES = RivetAnalysis.cc NLORivetAnalysis.cc $(INCLUDEFILES) - RivetAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 20:1:0 + RivetAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 20:2:0 else DOCFILES = $(AIDAWRAPPERS) $(LWHHEADERS) endif DOCFILES += LWHFactory.h INCLUDEFILES = $(DOCFILES) LWHINCLUDE = -I$(top_builddir)/include/ThePEG/Analysis/LWH LWHFactory_la_SOURCES = $(mySOURCES) $(INCLUDEFILES) LWHFactory_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) LWHFactory_la_CPPFLAGS = $(AM_CPPFLAGS) $(LWHINCLUDE) XSecCheck_la_SOURCES = XSecCheck.cc XSecCheck.h XSecCheck_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) ProgressLog_la_SOURCES = ProgressLog.cc ProgressLog.h ProgressLog_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) noinst_LTLIBRARIES = libThePEGHist.la libThePEGHist_la_SOURCES = \ FactoryBase.cc FactoryBase.fh FactoryBase.h AIDA_helper.h libThePEGHist_la_CPPFLAGS = $(AM_CPPFLAGS) $(LWHINCLUDE) if HAVE_HEPMC pkglib_LTLIBRARIES += HepMCAnalysis.la - HepMCAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) + HepMCAnalysis_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 20:1:0 HepMCAnalysis_la_SOURCES = HepMCFile.h HepMCFile.cc NLOHepMCFile.h NLOHepMCFile.cc HIHepMCFile.h HIHepMCFile.cc HepMCAnalysis_la_CPPFLAGS = $(AM_CPPFLAGS) $(HEPMCINCLUDE) HepMCAnalysis_la_LIBADD = $(HEPMCLIBS) endif pkglib_LTLIBRARIES += GraphvizPlot.la GraphvizPlot_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) GraphvizPlot_la_SOURCES = GraphvizPlot.h GraphvizPlot.cc LWH.tgz: $(AIDAWRAPPERS) $(LWHHEADERS) tar czf LWH.tgz $(AIDAWRAPPERS) $(LWHHEADERS) include $(top_srcdir)/Config/Makefile.aminclude diff --git a/Config/std.h b/Config/std.h --- a/Config/std.h +++ b/Config/std.h @@ -1,180 +1,185 @@ // -*- C++ -*- // // std.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_std_H #define ThePEG_std_H /** \file * This file introduces a number of std:: classes into * the ThePEG namespace. Also introduces some useful functions for * standard library classes. * * Do not make changes in this file. If you want to use alternatives * to the std:: classes in ThePEG, edit a copy of this * file and include it in an alternative config file which can be * included in the main ThePEG.h config file using the macro * ThePEG_ALTERNATE_CONFIG. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace std { /** @cond TRAITSPECIALIZATIONS */ /** * This specialization of the std::less class is needed in order to be * able use put pointers to type_info objects as keys in maps and * sets. */ template <> struct less : public binary_function { /** * This is the function called when comparing two pointers to * type_info. */ bool operator()(const type_info * x, const type_info * y) const { return x->before(*y); } }; /** @endcond */ } namespace ThePEG { using std::deque; using std::stack; using std::vector; using std::multiset; using std::set; using std::map; using std::list; using std::multimap; using std::pair; using std::make_pair; using std::less; using std::string; using std::type_info; using std::exception; using std::range_error; using std::ios; using std::ostream; using std::istream; using std::ofstream; using std::ifstream; using std::ostringstream; using std::istringstream; using std::cin; using std::cout; using std::cerr; using std::endl; using std::flush; using std::setprecision; using std::setw; using std::swap; using std::min; using std::max; using std::mem_fun; using std::sqrt; //using std::pow; using std::abs; using std::atan2; using std::isfinite; /** Powers - standard or non-standard */ template inline constexpr double pow(double x, ExponentT p) { return std::pow(x,double(p)); } /** Square root of an integer. */ inline double sqrt(int x) { return std::sqrt(double(x)); } +/** factorial */ +inline constexpr long double factorial(unsigned int n) { + return (n < 2) ? 1.0 : n * factorial(n - 1); +} + /** Check if a given object is a part of a container. */ template inline bool member(const Container & c, const Key & k) { return c.find(k) != c.end(); } /** Check if a given object is a part of a vector. */ template inline bool member(const vector & v, const Key & k) { for ( typename vector::const_iterator i = v.begin(); i != v.end(); ++i ) if ( *i == k ) return true; return false; // return find(v.begin(), v.end(), k) != v.end(); } /** Return an insert iterator for a given container. */ template inline std::insert_iterator inserter(Cont & c) { return std::insert_iterator(c, c.end()); } /** Return an insert iterator for a given vector. Overrides the * general version. */ template inline std::back_insert_iterator< vector > inserter(vector & v) { return back_inserter(v); } /** Return an insert iterator for a given vector. Overrides the * general version. */ template inline std::back_insert_iterator< deque > inserter(deque & v) { return back_inserter(v); } /** Stream manipulator setting an ostream to left-adjust its ouput. */ inline ostream& left(ostream& os) { os.setf(ios::left, ios::adjustfield); return os; } /** Stream manipulator setting an ostream to right-adjust its ouput. */ inline ostream& right(ostream& os) { os.setf(ios::right, ios::adjustfield); return os; } } /** Macro for declaring a set. */ #define ThePEG_DECLARE_SET(VALTYPE,NAME) \ /** A set of VALTYPE. */ \ typedef set > NAME /** Macro for declaring a multiset. */ #define ThePEG_DECLARE_MULTISET(VALTYPE,NAME) \ /** A multiset of VALTYPE. */ \ typedef multiset > NAME /** Macro for declaring a map. */ #define ThePEG_DECLARE_MAP(KEYTYPE,VALTYPE,NAME) \ /** A map of VALTYPE indexed by KEYTYPE. */ \ typedef map > NAME #endif /* ThePEG_std_H */ diff --git a/Cuts/Makefile.am b/Cuts/Makefile.am --- a/Cuts/Makefile.am +++ b/Cuts/Makefile.am @@ -1,50 +1,50 @@ mySOURCES = Cuts.cc OneCutBase.cc TwoCutBase.cc MultiCutBase.cc JetFinder.cc FuzzyTheta.cc DOCFILES = Cuts.h OneCutBase.h TwoCutBase.h MultiCutBase.h JetFinder.h FuzzyTheta.h INCLUDEFILES = $(DOCFILES) Cuts.fh OneCutBase.fh \ TwoCutBase.fh MultiCutBase.fh noinst_LTLIBRARIES = libThePEGCuts.la # pkglib_LTLIBRARIES = JetKTClusCuts.la libThePEGCuts_la_SOURCES = $(mySOURCES) $(INCLUDEFILES) pkglib_LTLIBRARIES = SimpleKTCut.la KTClus.la V2LeptonsCut.la SimpleDISCut.la \ KTRapidityCut.la DeltaMeasureCuts.la JetCuts.la SimpleKTCut_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) SimpleKTCut_la_SOURCES = SimpleKTCut.cc SimpleKTCut.h KTRapidityCut_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) KTRapidityCut_la_SOURCES = KTRapidityCut.cc KTRapidityCut.h KTClus_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) KTClus_la_SOURCES = KTClus.cc KTClus.h V2LeptonsCut_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) V2LeptonsCut_la_SOURCES = V2LeptonsCut.cc V2LeptonsCut.h SimpleDISCut_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) SimpleDISCut_la_SOURCES = SimpleDISCut.cc SimpleDISCut.h JetCuts_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) JetCuts_la_SOURCES = \ OneJetCut.h OneJetCut.cc NJetsCut.h NJetsCut.cc \ JetRegion.h JetRegion.cc JetPairRegion.h JetPairRegion.cc \ MultiJetRegion.h MultiJetRegion.cc JetCuts.h JetCuts.cc DeltaMeasureCuts_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) DeltaMeasureCuts_la_SOURCES = DeltaMeasureCuts.cc DeltaMeasureCuts.h if WANT_LIBFASTJET pkglib_LTLIBRARIES += FastJetFinder.la FastJetFinder_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \ -I$(FASTJETPATH) FastJetFinder_la_LIBADD = $(FASTJETLIBS) -FastJetFinder_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) +FastJetFinder_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 21:0:0 FastJetFinder_la_SOURCES = FastJetFinder.cc FastJetFinder.h endif include $(top_srcdir)/Config/Makefile.aminclude diff --git a/EventRecord/Collision.cc b/EventRecord/Collision.cc --- a/EventRecord/Collision.cc +++ b/EventRecord/Collision.cc @@ -1,216 +1,213 @@ // -*- C++ -*- // // Collision.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 member functions of // the Collision class. // #include "Collision.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/EventRecord/SubProcessGroup.h" #include "ThePEG/EventRecord/ParticleTraits.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Debug.h" -#include "ThePEG/Utilities/DIterator.h" #include #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "Collision.tcc" #endif using namespace ThePEG; Collision::~Collision() { for ( int i = 0, N = theSteps.size(); i < N; ++i ) if ( theSteps[i]->collision() == this ) theSteps[i]->theCollision = tCollPtr(); for ( int i = 0, N = theSubProcesses.size(); i < N; ++i ) if ( theSubProcesses[i]->collision() == this ) theSubProcesses[i]->theCollision = tCollPtr(); theIncoming = PPair(); theSteps.clear(); theSubProcesses.clear(); allParticles.clear(); theEvent = tEventPtr(); theHandler = tcEventBasePtr(); } CollPtr Collision::clone() const { return ptr_new(*this); } tStepPtr Collision::newStep(tcEventBasePtr newHandler) { if ( theSteps.empty() ) theSteps.push_back(new_ptr(Step(this))); else theSteps.push_back(new_ptr(Step(*finalStep()))); tStepPtr s = finalStep(); s->handler(newHandler); s->theIntermediates.clear(); s->theSubProcesses.clear(); s->allParticles = s->theParticles; return s; } void Collision::rebind(const EventTranslationMap & trans) { theIncoming.first = trans.translate(theIncoming.first); theIncoming.second = trans.translate(theIncoming.second); theEvent = trans.translate(theEvent); for ( StepVector::iterator sit = theSteps.begin(); sit != theSteps.end(); ++sit ) (*sit = trans.translate(*sit))->rebind(trans); for ( SubProcessVector::iterator spit = theSubProcesses.begin(); spit != theSubProcesses.end(); ++spit ) (*spit = trans.translate(*spit))->rebind(trans); ParticleSet newParticles; for ( ParticleSet::const_iterator pit = allParticles.begin(); pit != allParticles.end(); ++pit ) newParticles.insert(trans.translate(*pit)); allParticles.swap(newParticles); } void Collision::transform(const LorentzRotation & r) { for_each(allParticles, Transformer(r)); } void Collision::addStep(tStepPtr s) { theSteps.push_back(s); s->collision(this); addParticles(s->all().begin(), s->all().end()); if ( event() ) event()->addStep(s); } void Collision::addSubProcess(tSubProPtr p) { theSubProcesses.push_back(p); if ( !p->collision() ) p->theCollision = this; if ( event() ) event()->addSubProcess(p); } void Collision::removeSubProcess(tSubProPtr p) { SubProcessVector::iterator sit = ThePEG::find(theSubProcesses, p); if ( sit == theSubProcesses.end() ) return; theSubProcesses.erase(sit); if ( event() ) event()->removeSubProcess(p); } void Collision::addParticle(tPPtr p) { allParticles.insert(p); if ( event() ) event()->addParticle(p); } void Collision::removeEntry(tPPtr p) { ParticleSet::iterator it = allParticles.find(p); if ( it == allParticles.end() ) return; - for ( DIterator sit = theSteps.begin(); - sit != theSteps.end(); ++sit ) sit->removeEntry(p); + for ( auto & step : theSteps ) step->removeEntry(p); allParticles.erase(it); } void Collision::removeParticle(tPPtr p) { if ( p->next() ) removeParticle(p->next()); while ( !p->children().empty() ) removeParticle(p->children().back()); if ( p->hasRep() ) p->rep().theBirthStep = tStepPtr(); removeEntry(p); } void Collision::removeDecay(tPPtr p) { while ( !p->children().empty() ) removeParticle(p->children().back()); } void Collision::cleanSteps() { for ( StepVector::size_type i = 0; i < theSteps.size(); ++i ) { if ( theSteps[i]->nullStep() ) theSteps.erase(theSteps.begin() + i--); } } void Collision::popStep() { StepPtr last = finalStep(); ParticleVector pv(last->all().begin(), last->all().end()); for ( ParticleVector::iterator pit = pv.begin();pit != pv.end(); ++pit ) if ( (**pit).birthStep() == last ) removeParticle(*pit); theSteps.pop_back(); } tParticleSet Collision::getRemnants() const { tParticleSet ret; tPVector partons; - for ( DIterator i = subProcesses().begin(); - i != subProcesses().end(); ++i ) { + for ( const auto & i : subProcesses() ) { partons.push_back(i->incoming().first->original()); partons.push_back(i->incoming().second->original()); } for ( tPVector::size_type i = 0; i < partons.size(); ++i ) { partons.insert(partons.end(), partons[i]->parents().begin(), partons[i]->parents().end()); tParticleSet siblings = partons[i]->siblings(); ret.insert(siblings.begin(), siblings.end()); } for ( int i = 0, N = partons.size(); i < N; ++i ) ret.erase(partons[i]); return ret; } ostream & ThePEG::operator<<(ostream & os, const Collision & c) { int isub = 0; if ( c.incoming().first || c.incoming().second ) { os << "--- Colliding particles:" << endl; if ( c.incoming().first ) os << *c.incoming().first; if ( c.incoming().second ) os << *c.incoming().second; } for ( unsigned int i = 0; i < c.steps().size(); ++i ) { const Step & s = *c.steps()[i]; for ( SubProcessVector::const_iterator it = s.subProcesses().begin(); it != s.subProcesses().end(); ++it ) { os << string(78, '-') << endl; if ( !isub ) { os << "Primary sub-process"; if ( dynamic_ptr_cast::ptr>(*it) ) os << " group"; ++isub; } else { os << "Secondary sub-process "; if ( dynamic_ptr_cast::ptr>(*it) ) os << "group "; os << isub++; } if ( (**it).handler() ) os << " performed by " << EventConfig::nameHandler((**it).handler()) << endl; os << **it; } os << string(78, '-') << endl << "Step " << i+1; if ( s.handler() ) os << " performed by " << EventConfig::nameHandler(s.handler()); os << endl << s; } if ( ThePEG_DEBUG_ITEM(9) ) { for ( ParticleSet::const_iterator p = c.all().begin(); p != c.all().end(); ++p ) if ( c.isRemnant(*p) ) os << setw(5) << (**p).number(); os << endl; } return os; } void Collision::persistentOutput(PersistentOStream & os) const { os << theIncoming << theSteps << theSubProcesses << theEvent; EventConfig::putHandler(os, theHandler); os << ounit(theVertex, mm); } void Collision::persistentInput(PersistentIStream & is, int) { is >> theIncoming >> theSteps >> theSubProcesses >> theEvent; EventConfig::getHandler(is, theHandler); is >> iunit(theVertex, mm); } ClassDescription Collision::initCollision; void Collision::Init() {} diff --git a/EventRecord/Event.cc b/EventRecord/Event.cc --- a/EventRecord/Event.cc +++ b/EventRecord/Event.cc @@ -1,356 +1,353 @@ // -*- C++ -*- // // Event.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 member functions of // the Event class. // #include "Event.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/EventRecord/ParticleTraits.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" -#include "ThePEG/Utilities/DIterator.h" #include using namespace ThePEG; Event::Event(const PPair & newIncoming, tcEventBasePtr newHandler, string newName, long newNumber, double newWeight) : Named(newName), theIncoming(newIncoming), theHandler(newHandler), theNumber(newNumber), theWeight(newWeight), theParticleNumber(0) { addParticle(incoming().first); addParticle(incoming().second); } Event::Event(const Event & e) : Base(e), Named(e), theIncoming(e.theIncoming), theCollisions(e.theCollisions), allSteps(e.allSteps), allSubProcesses(e.allSubProcesses), allParticles(e.allParticles), theHandler(e.theHandler), theNumber(e.theNumber), theWeight(e.theWeight), theParticleNumber(e.theParticleNumber) {} Event::~Event() { for ( int i = 0, N = theCollisions.size(); i < N; ++i ) if ( theCollisions[i]->event() == this ) theCollisions[i]->theEvent = tEventPtr(); theIncoming = PPair(); theCollisions.clear(); allSteps.clear(); allSubProcesses.clear(); allParticles.clear(); theHandler = tcEventBasePtr(); theColourLines.clear(); theNumber = -1; theWeight = 0.0; } void Event::setInfo(tcEventBasePtr newHandler, string newName, long newNumber, double weight) { theHandler = newHandler; name(newName); theNumber = newNumber; theWeight = weight; } double Event::optionalWeight(const string& name) const { map::const_iterator w = theOptionalWeights.find(name); if ( w == theOptionalWeights.end() ) return 0.; return w->second; } void Event::optionalWeight(const string& name, double value) { theOptionalWeights[name] = value; } tCollPtr Event::newCollision() { theCollisions.push_back(new_ptr(Collision(incoming(), this))); return theCollisions.back(); } tStepPtr Event::newStep() { if ( theCollisions.empty() ) newCollision(); return theCollisions.back()->newStep(); } void Event::addCollision(tCollPtr c) { if ( !c ) return; theCollisions.push_back(c); addParticles(c->all().begin(), c->all().end()); allSubProcesses.insert(c->subProcesses().begin(), c->subProcesses().end()); } void Event::addParticle(tPPtr p) { if ( !p ) return; if ( member(allParticles, p) ) return; allParticles.insert(p); p->number(++theParticleNumber); } void Event::transform(const LorentzRotation & r) { for_each(allParticles, Transformer(r)); } int Event::colourLineIndex(tcColinePtr line) const { ColourLineMap::const_iterator found = theColourLines.find(line); if ( found != theColourLines.end() ) return found->second; int index = theColourLines.size() + 1; theColourLines[line] = index; return index; } void Event::primaryCollision(tCollPtr c) { if ( !c ) return; if ( theCollisions.empty() ) theCollisions.push_back(c); else { if ( theCollisions[0] ) for ( ParticleSet::const_iterator it = theCollisions[0]->all().begin(); it != theCollisions[0]->all().end(); ++it ) allParticles.erase(*it); theCollisions[0] = c; } addParticles(c->all().begin(), c->all().end()); } void Event::removeDecay(tPPtr p) { while ( !p->children().empty() ) removeParticle(p->children().back()); } void Event::removeEntry(tPPtr p) { ParticleSet::iterator it = allParticles.find(p); if ( it == allParticles.end() ) return; - for ( DIterator cit = theCollisions.begin(); - cit != theCollisions.end(); ++cit ) cit->removeEntry(p); + for ( auto & cit : theCollisions ) cit->removeEntry(p); allParticles.erase(it); } void Event::removeParticle(tPPtr p) { if ( p->next() ) removeParticle(p->next()); while ( !p->children().empty() ) removeParticle(p->children().back()); removeEntry(p); } void Event::cleanSteps() { - for ( DIterator cit = theCollisions.begin(); - cit != theCollisions.end(); ++cit ) cit->cleanSteps(); + for ( auto & cit : theCollisions ) cit->cleanSteps(); } EventPtr Event::clone() const { EventPtr newEvent = ptr_new(*this); EventTranslationMap trans; trans[this] = newEvent; for ( CollisionVector::const_iterator cit = theCollisions.begin(); cit != theCollisions.end(); ++cit ) trans[*cit] = (**cit).clone(); for ( SubProcessSet::const_iterator spit = allSubProcesses.begin(); spit != allSubProcesses.end(); ++spit ) trans[*spit] = (**spit).clone(); for ( StepSet::const_iterator sit = allSteps.begin(); sit != allSteps.end(); ++sit ) trans[*sit] = (**sit).clone(); for ( ParticleSet::const_iterator pit = allParticles.begin(); pit != allParticles.end(); ++pit ) trans[*pit] = (**pit).clone(); newEvent->rebind(trans); return newEvent; } void Event::rebind(const EventTranslationMap & trans) { theIncoming.first = trans.translate(theIncoming.first); theIncoming.second = trans.translate(theIncoming.second); for ( CollisionVector::iterator cit = theCollisions.begin(); cit != theCollisions.end(); ++cit ) (*cit = trans.translate(*cit))->rebind(trans); SubProcessSet newSubProcesses; for ( SubProcessSet::const_iterator spit = allSubProcesses.begin(); spit != allSubProcesses.end(); ++spit ) newSubProcesses.insert(trans.translate(*spit)); allSubProcesses.swap(newSubProcesses); StepSet newSteps; for ( StepSet::const_iterator sit = allSteps.begin(); sit != allSteps.end(); ++sit ) newSteps.insert(trans.translate(*sit)); allSteps.swap(newSteps); ParticleSet newParticles; for ( ParticleSet::const_iterator pit = allParticles.begin(); pit != allParticles.end(); ++pit ) newParticles.insert(trans.translate(*pit)); allParticles.swap(newParticles); } ostream & ThePEG::operator<<(ostream & os, const Event & e) { os << string(78, '*') << endl << "Event number " << e.number() << " (id: " << e.name() << ") "; if ( e.handler() ) os << "performed by " << EventConfig::nameHandler(e.handler()); os << endl; for ( unsigned int i = 0; i < e.collisions().size(); ++i ) { os << string(78, '=') << endl; if ( e.collisions().size() != 1 ) { if ( i ) { os << "Secondary Collision " << i; if ( e.collisions()[i]->handler() ) os << " performed by " << EventConfig::nameHandler(e.collisions()[i]->handler()); } else os << "Primary Collision"; } os << endl << *e.collisions()[i]; } return os; } // Helpers for the Graphviz output namespace { static const string header = "digraph test {\nrankdir=LR;\nranksep=1.5;\n"; inline long startnode(tcPPtr p) { return p->parents().empty() ? -p->uniqueId : p->parents()[0]->uniqueId; } inline long endnode(tcPPtr p) { return p->children().empty() ? p->uniqueId : startnode( p->children()[0] ); } static const char * colours[] = { "red", "green", "blue", "orange", "aquamarine", "deeppink", "darkviolet", "darkolivegreen", "cyan" }; struct Vertex { tcParticleSet in; tcParticleSet out; }; typedef map VertexMap; template Lorentz5Momentum sumP(Iter a, Iter b) { Lorentz5Momentum sum; for ( Iter it = a; it != b; ++it ) { sum += (*it)->momentum(); } return sum; } } void ThePEG::Event::printGraphviz() const { ThePEG::printGraphviz(cout, this); } void ThePEG::printGraphviz(ostream & os, tcEventPtr ev) { os << header << "node [width=0.03,height=0.03,shape=point,label=\"\"];\n"; tcParticleSet all; ev->select(inserter(all), SelectAll()); VertexMap vertices; for (tcParticleSet::const_iterator it = all.begin(); it != all.end(); ++it) { tcPPtr p = (*it); long start = startnode(p); long end = endnode(p); vertices[start].out.insert(p); vertices[end ].in .insert(p); os << start << " -> " << end << " [label=\"" << p->number() << ' ' << p->PDGName() << "\\n" << p->momentum().e()/GeV << "\\n" << p->momentum().mass()/GeV << "\""; if ( p->hasColourInfo() && ( p->colourLine() || p->antiColourLine() )) { os << ",penwidth=2,color=\""; const vector & clines = p->colourInfo()->colourLines(); for ( int i = 0, N = clines.size(); i < N; ++i ) { int colindex = ev->colourLineIndex(clines[i]) % 9; if ( i > 0 ) os << ':'; os << colours[colindex]; } const vector & aclines = p->colourInfo()->antiColourLines(); for ( int i = 0, N = aclines.size(); i < N; ++i ) { int colindex = ev->colourLineIndex(aclines[i]) % 9; if ( i > 0 || !clines.empty() ) os << ':'; os << colours[colindex]; } os << '"'; } os << "];\n"; } int label = 0; for ( VertexMap::const_iterator v = vertices.begin(); v != vertices.end(); ++v ) { const long vertexId = v->first; const tcParticleSet & in = v->second.in; const tcParticleSet & out = v->second.out; if ( in.empty() || out.empty() ) continue; Lorentz5Momentum diff = sumP(out.begin(), out.end()) - sumP(in.begin(), in.end()); if ( abs(diff.e()) > 1.0*GeV ) { ++label; std::stringstream tail; tail << " [label=\"" << std::setprecision(4) << abs(diff.e()/GeV) << " GeV\",arrowsize=3,penwidth=5," << "color=\"#ff000010\",fontcolor=\"#ff000010\"];\n"; if ( diff.e() > ZERO ) os << "mom" << label << " -> " << vertexId << tail.str(); else os << vertexId << " -> " << "mom" << label << tail.str(); } } os << '}' << endl; } void Event::debugme() const { cerr << *this; EventRecordBase::debugme(); } void Event::persistentOutput(PersistentOStream & os) const { os << theIncoming << theCollisions << allSteps << allSubProcesses << allParticles << theNumber << theWeight << theOptionalWeights << theParticleNumber; EventConfig::putHandler(os, theHandler); } void Event::persistentInput(PersistentIStream & is, int) { is >> theIncoming >> theCollisions >> allSteps >> allSubProcesses >> allParticles >> theNumber >> theWeight >> theOptionalWeights >> theParticleNumber; EventConfig::getHandler(is, theHandler); } ClassDescription Event::initEvent; void Event::Init() {} diff --git a/EventRecord/RhoDMatrix.h b/EventRecord/RhoDMatrix.h --- a/EventRecord/RhoDMatrix.h +++ b/EventRecord/RhoDMatrix.h @@ -1,145 +1,146 @@ // -*- C++ -*- // // RhoDMatrix.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_RhoDMatrix_H #define ThePEG_RhoDMatrix_H // This is the declaration of the RhoDMatrix class. #include "ThePEG/PDT/PDT.h" #include "ThePEG/Helicity/HelicityDefinitions.h" #include +#include namespace ThePEG { /** * The RhoDMatrix class is designed to implement the storage of the * rho and D matrices which are required for the spin correlation * algorithm. The matrix stores the spin as 2s+1. * * @author Peter Richardson * */ class RhoDMatrix { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor with undefined spin. */ - RhoDMatrix() : _spin(), _ispin() {} + RhoDMatrix() = default; /** * Standard constructor giving the spin as 2s+1. The matrix starts out averaged, * unless the second argument is false, when it is zeroed. */ RhoDMatrix(PDT::Spin inspin, bool average = true) : _spin(inspin), _ispin(abs(int(inspin))) { assert(_ispin <= MAXSPIN); // initialize to average - for(size_t ix=0; ix<_ispin; ++ix) - for(size_t iy=0; iy<_ispin; ++iy) - _matrix[ix][iy] = (average && ix==iy) ? 1./_ispin : 0.; + if ( average ) + for(size_t ix=0; ix<_ispin; ++ix) + _matrix[ix][ix] = 1./_ispin; } //@} public: /** @name Access matrix elements. */ //@{ /** * Return an element of the matrix. */ Complex operator() (size_t ix, size_t iy) const { assert(ix < _ispin); assert(iy < _ispin); return _matrix[ix][iy]; } /** * Set an element of the matrix. */ Complex & operator() (size_t ix, size_t iy) { assert(ix < _ispin); assert(iy < _ispin); return _matrix[ix][iy]; } /** * renormalise the matrix so it has unit trace */ void normalize() { #ifndef NDEBUG static const double epsa=1e-40, epsb=1e-10; #endif Complex norm = 0.; for(size_t ix=0; ix<_ispin; ++ix) norm += _matrix[ix][ix]; assert(norm.real() > epsa); assert(norm.imag()/norm.real() < epsb); double invnorm = 1./norm.real(); for(size_t ix=0; ix<_ispin; ++ix) for(size_t iy=0; iy<_ispin; ++iy) _matrix[ix][iy]*=invnorm; } //@} /** @name Access the spin. */ //@{ /** * Get the spin. The spin is returned as 2J+1 in units of hbar/2. */ PDT::Spin iSpin() const { return _spin; } //@} /** * Output the spin density matrix for debugging purposes. */ friend ostream & operator<<(ostream & os, const RhoDMatrix & rd); private: /** * 2s+1 for the particle. */ PDT::Spin _spin; /** * Storage of 2s+1 for speed. */ size_t _ispin; /** * Spin matrix size */ enum { MAXSPIN = 5 }; /** * Storage for the matrix allowing up to spin 2 particles. */ // Deliberately not using vector<> to avoid calls to 'new' // from this commonly used class. - Complex _matrix[MAXSPIN][MAXSPIN]; + std::array,MAXSPIN> _matrix; }; /** Output operator */ inline ostream & operator<<(ostream & os, const RhoDMatrix & rd) { for (size_t ix = 0; ix < rd._ispin; ++ix) { for (size_t iy = 0; iy < rd._ispin; ++iy) os << rd._matrix[ix][iy] << " "; os << '\n'; } return os; } } #endif /* ThePEG_RhoDMatrix_H */ diff --git a/Handlers/StandardXComb.cc b/Handlers/StandardXComb.cc --- a/Handlers/StandardXComb.cc +++ b/Handlers/StandardXComb.cc @@ -1,818 +1,828 @@ // -*- 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), 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), 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), 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), 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(newHead->subProcessHandler())), 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), 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(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); } bool StandardXComb::setIncomingPartons(tStdXCombPtr labHead) { if ( lastPartons().first ) return true; - - if ( !labHead ) + // If no labHead was given, we need to search the labhead + if ( !labHead ){ labHead = head(); + while ( labHead->head() && labHead->head() != labHead ) { + 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(); if(x1<=0. || x2 <= 0. ) return false; lastX1X2(make_pair(x1,x2)); lastY((lastPartons().first->momentum()+ lastPartons().second->momentum()).rapidity()); return true; } void StandardXComb::fill(const PPair& newParticles, const PPair& newPartons, const vector& 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 outmomenta(meMomenta().begin()+2,meMomenta().end()); Boost tocm = (meMomenta()[0]+meMomenta()[1]).findBoostToCM(); if ( tocm.mag2() > Constants::epsilon ) { for ( vector::iterator p = outmomenta.begin(); p != outmomenta.end(); ++p ) { p->boost(tocm); } } for ( vector::iterator p = outmomenta.begin(); p != outmomenta.end(); ++p ) if ( !std::isfinite(double(p->x()/GeV)) || !std::isfinite(double(p->y()/GeV)) || !std::isfinite(double(p->z()/GeV)) || !std::isfinite(double(p->t()/GeV)) ) throw Exception() << "Event momenta contain an invalid entry: " << (*p)/GeV << Exception::runerror; 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; theExternalDiagram = tcDiagPtr(); 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()); + partonBinInstances().first->scale(lastScale()); + partonBinInstances().second->scale(lastScale()); + 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 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 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(); + const bool isCKKW=CKKWHandler() && matrixElement()->maxMultCKKW() > 0 && + matrixElement()->maxMultCKKW() > matrixElement()->minMultCKKW(); + + if(!isCKKW) + 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() ) { + if ( isCKKW ) { 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::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()))); if ( !theExternalDiagram ) 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); lastCentralScale(lastProjector()->lastCentralScale()); lastShowerScale(lastProjector()->lastShowerScale()); 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; if ( eventHandler().cascadeHandler() ) { if ( eventHandler().cascadeHandler()->isReshuffling() ) return; } for ( cPDVector::const_iterator p = mePartonData().begin() + 2; p != mePartonData().end(); ++p ) { theNeedsReshuffling |= ( (**p).mass() != (**p).hardProcessMass() ); } } double StandardXComb::reshuffleEquation(double k, const vector >& coeffs, Energy2 Q2) const { double res = 0.; for ( vector >::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 >& 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& pout) const { Lorentz5Momentum Q(ZERO,ZERO,ZERO,ZERO); for ( vector::const_iterator p = pout.begin(); p != pout.end(); ++p ) Q += *p; if ( Q.m2() <= ZERO ) throw Veto(); LorentzVector Qhat = Q/sqrt(Q.m2()); vector pQhat; vector > coeffs; vector::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::iterator px = pout.begin(); vector::const_iterator pQ = pQhat.begin(); vector >::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 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 << theExternalDiagram << theMEInfo << theLastRandomNumbers << theMEPartonData << theLastPDFWeight << ounit(theLastCrossSection,nanobarn) << theLastJacobian << theLastME2 << theLastPreweight << ounit(theLastMECrossSection,nanobarn) << theLastMEPDFWeight << theLastMECouplings << theHead << theProjectors << theProjector << theKinematicsGenerated << checkedCuts << passedCuts << theCutWeight << theNeedsReshuffling; } void StandardXComb::persistentInput(PersistentIStream & is, int) { is >> theSubProcessHandler >> theME >> theStats >> theDiagrams >> isMirror >> theNDim >> partonDims >> theLastDiagramIndex >> theExternalDiagram >> theMEInfo >> theLastRandomNumbers >> theMEPartonData >> theLastPDFWeight >> iunit(theLastCrossSection,nanobarn) >> theLastJacobian >> theLastME2 >> theLastPreweight >> iunit(theLastMECrossSection,nanobarn) >> theLastMEPDFWeight >> theLastMECouplings >> theHead >> theProjectors >> theProjector >> theKinematicsGenerated >> checkedCuts >> passedCuts >> theCutWeight >> theNeedsReshuffling; } ClassDescription StandardXComb::initStandardXComb; diff --git a/Helicity/FermionSpinInfo.h b/Helicity/FermionSpinInfo.h --- a/Helicity/FermionSpinInfo.h +++ b/Helicity/FermionSpinInfo.h @@ -1,211 +1,209 @@ // -*- C++ -*- // // FermionSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_FermionSpinInfo_H #define ThePEG_FermionSpinInfo_H // This is the declaration of the FermionSpinInfo class. #include "ThePEG/EventRecord/SpinInfo.h" #include "ThePEG/Helicity/LorentzSpinor.h" #include "FermionSpinInfo.fh" +#include namespace ThePEG { namespace Helicity { /** * The FermionSpinInfo class inherits from the SpinInfo class and * implements the storage of the basis vectors for a spin-1/2 * particle. The basis states are the u-spinors for a particle and * the v-spinors for an antiparticle. The barred spinors can be * obtained from these. * * These basis states should be set by either matrixelements or * decayers which are capable of generating spin correlation * information. * * The basis states in the rest frame of the particles can then be * accessed by decayers to produce the correct correlations. * * N.B. in our convention 0 is the \f$-\frac12\f$ helicity state and * 1 is the \f$+\frac12\f$ helicity state. * * @author Peter Richardson */ class FermionSpinInfo: public SpinInfo { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ - FermionSpinInfo() : SpinInfo(PDT::Spin1Half), _productionstates(2), - _currentstates(2), _decaystates(2), - _decaycalc(false) {} + FermionSpinInfo() + : SpinInfo(PDT::Spin1Half), _decaycalc(false) {} /** * Standard Constructor. * @param p the production momentum. * @param time true if the particle is time-like. */ FermionSpinInfo(const Lorentz5Momentum & p, bool time) - : SpinInfo(PDT::Spin1Half, p, time), - _productionstates(2), _currentstates(2), _decaystates(2), - _decaycalc(false) {} + : SpinInfo(PDT::Spin1Half, p, time), _decaycalc(false) {} //@} public: /** @name Set and get methods for the basis state. */ //@{ /** * Set the basis state, this is production state. * @param hel the helicity (0 or 1 as described above.) * @param in the LorentzSpinor for the given helicity. */ void setBasisState(unsigned int hel, const LorentzSpinor & in) const { assert(hel<2); _productionstates[hel] = in; _currentstates [hel] = in; } /** * Set the basis state for the decay. * @param hel the helicity (0 or 1 as described above.) * @param in the LorentzSpinor for the given helicity. */ void setDecayState(unsigned int hel, const LorentzSpinor & in) const { assert(hel<2); _decaycalc = true; _decaystates[hel] = in; } /** * Get the basis state for the production for the given helicity, \a * hel (which is 0 or 1 as described above.) */ const LorentzSpinor & getProductionBasisState(unsigned int hel) const { assert(hel<2); return _productionstates[hel]; } /** * Get the current basis state for the given helicity, \a * hel (which is 0 or 1 as described above.) */ const LorentzSpinor & getCurrentBasisState(unsigned int hel) const { assert(hel<2); return _currentstates[hel]; } /** * Get the basis state for the decay for the given helicity, \a hel * (which is 0 or 1 as described above.) */ const LorentzSpinor & getDecayBasisState(unsigned int hel) const { assert(hel<2); if(!_decaycalc) { for(unsigned int ix=0;ix<2;++ix) _decaystates[ix]=_currentstates[ix]; _decaycalc=true; } return _decaystates[hel]; } //@} /** * Perform a lorentz rotation of the spin information */ virtual void transform(const LorentzMomentum &,const LorentzRotation &); public: /** * Standard Init function. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initFermionSpinInfo; /** * Private and non-existent assignment operator. */ FermionSpinInfo & operator=(const FermionSpinInfo &); private: /** * basis states in the frame in which the particle was produced */ - mutable vector > _productionstates; + mutable std::array,2> _productionstates; /** * basis states in the current frame of the particle */ - mutable vector > _currentstates; + mutable std::array,2> _currentstates; /** * basis states in the frame in which the particle decays */ - mutable vector > _decaystates; + mutable std::array,2> _decaystates; /** * True if the decay state has been set. */ mutable bool _decaycalc; }; } } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * FermionSpinInfo. */ template <> struct BaseClassTrait : public ClassTraitsType { /** Typedef of the base class of FermionSpinInfo. */ typedef ThePEG::SpinInfo NthBase; }; /** * This template specialization informs ThePEG about the name of the * FermionSpinInfo class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::Helicity::FermionSpinInfo"; } }; /** @endcond */ } #endif /* ThePEG_FermionSpinInfo_H */ diff --git a/Helicity/HelicityDefinitions.h b/Helicity/HelicityDefinitions.h --- a/Helicity/HelicityDefinitions.h +++ b/Helicity/HelicityDefinitions.h @@ -1,54 +1,54 @@ // -*- C++ -*- // // HelicityDefinitions.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_HelicityDefinitions_H #define THEPEG_HelicityDefinitions_H // This is the declaration of the HelicityDefinitions class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Exception.h" /** \file HelicityDefinitions.h * * This file contains enumerations used by LorentzSpinor and * LorentzSpinorBar classes. * * @see LorentzSpinor * * @author Peter Richardson */ namespace ThePEG { /** * The Helicity namespace contains classes for spin representation * classes in ThePEG. */ namespace Helicity { /** * Enumeration to specify spinor type. */ -enum SpinorType { - u_spinortype, /**< u spinor. */ - v_spinortype, /**< v spinor. */ - unknown_spinortype /**< Undefined spinor type. */ +enum class SpinorType { + u, /**< u spinor. */ + v, /**< v spinor. */ + unknown /**< Undefined spinor type. */ }; /** @cond EXCEPTIONCLASSES */ /** Exception class used by Helicity classes to signal a logical error. */ class HelicityLogicalError: public Exception {}; /** Exception class used by Helicity classes to signal a inconsistencies. */ class HelicityConsistencyError: public Exception {}; /** @endcond */ } } #endif /* THEPEG_HelicityDefinitions_H */ diff --git a/Helicity/LorentzRSSpinor.h b/Helicity/LorentzRSSpinor.h --- a/Helicity/LorentzRSSpinor.h +++ b/Helicity/LorentzRSSpinor.h @@ -1,414 +1,409 @@ // -*- C++ -*- // // LorentzRSSpinor.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_LorentzRSSpinor_H #define ThePEG_LorentzRSSpinor_H #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Vectors/ThreeVector.h" #include "HelicityDefinitions.h" #include "LorentzRSSpinor.fh" #include "LorentzRSSpinorBar.h" #include "LorentzSpinorBar.h" #include "LorentzSpinor.h" #include "LorentzPolarizationVector.h" namespace ThePEG{ namespace Helicity{ /** * The LorentzRSSpinor class is designed to store a Rarita-Schwinger * spinor for a spin-3/2 particle. In addition to storing the * components of the spinor information is stored on the type of * spinor, for example u or v type. * * At the moment only one choice of the Dirac matrix representation * is supported. For high-energy calculations the choice made by the * HELAS collaboration is more efficient for numerical * calculations. In this representation * * \f[ * \gamma_{i=1,2,3}=\left(\begin{array}{cc} * 0 & \sigma_i \\ * -\sigma_i & 0 * \end{array}\right) * \quad * \gamma_0=\left(\begin{array}{cc} * 0 & 1 \\ * 1 & 0 * \end{array}\right) * \quad * \gamma_5=\left(\begin{array}{cc} * -1 & 0 \\ * 0 & 1 * \end{array}\right) * \f] * * The type of the spinor is also stored using the SpinorType - * enumeration. There are three types supported u_spinortype, - * v_spinortype, unknown_spinortype. This information is intended + * enumeration. There are three types supported SpinorType::u, + * SpinorType::v, SpinorType::unknown. This information is intended * mainly for use in the case of Majorana particles where matrix * elements can be calculated with either u or v type spinors and * knowledge of which was used will be needed in order to give the - * correct correlations. The unknown_spinortypee is intended for + * correct correlations. The SpinorType::unknowne is intended for * cases where either the spinor for an off-shell line in a matrix * element calculation or the information is genuinely unknown. * * The LorentzRSSpinorBar class is also provided to store the barred * spinor. * * * @see HelicityDefinitions * @see LorentzRSSpinorBar * * \author Peter Richardson * */ template class LorentzRSSpinor { public: /** @name Standard constructors. */ //@{ /** * Default zero constructor, optionally specifying \a t, the type. */ - LorentzRSSpinor(SpinorType t = unknown_spinortype) : _type(t) { - for(unsigned int ix=0;ix<4;++ix) - for(unsigned int iy=0;iy<4;++iy) - _spin[ix][iy]=Value(); - } + LorentzRSSpinor(SpinorType t = SpinorType::unknown) : _type(t), _spin() {} /** * Constructor with complex numbers specifying the components, * optionally specifying \a t, the type. */ LorentzRSSpinor(complex a1, complex b1, complex c1, complex d1, complex a2, complex b2, complex c2, complex d2, complex a3, complex b3, complex c3, complex d3, complex a4, complex b4, complex c4, complex d4, - SpinorType t=unknown_spinortype) - : _type(t) { - _spin[0][0]=a1;_spin[1][0]=a2;_spin[2][0]=a3;_spin[3][0]=a4; - _spin[0][1]=b1;_spin[1][1]=b2;_spin[2][1]=b3;_spin[3][1]=b4; - _spin[0][2]=c1;_spin[1][2]=c2;_spin[2][2]=c3;_spin[3][2]=c4; - _spin[0][3]=d1;_spin[1][3]=d2;_spin[2][3]=d3;_spin[3][3]=d4; - } + SpinorType t=SpinorType::unknown) + : _type(t), _spin{{ {{a1,b1,c1,d1}}, + {{a2,b2,c2,d2}}, + {{a3,b3,c3,d3}}, + {{a4,b4,c4,d4}} + }} {} //@} /** @name Access the components. */ //@{ /** * Subscript operator to return spinor components */ complex operator()(int i, int j) const { assert( i >= 0 && i <= 3 && j>=0 && j<=3); return _spin[i][j]; } /** * Set components by index */ complex & operator () (int i, int j) { assert( i >= 0 && i <= 3 && j>=0 && j<=3); return _spin[i][j]; } /** * Get first spinor component for the x vector */ complex xs1() const {return _spin[0][0];} /** * Get second spinor component for the x vector */ complex xs2() const {return _spin[0][1];} /** * Get third spinor component for the x vector */ complex xs3() const {return _spin[0][2];} /** * Get fourth spinor component for the x vector */ complex xs4() const {return _spin[0][3];} /** * Get first spinor component for the y vector */ complex ys1() const {return _spin[1][0];} /** * Get second spinor component for the y vector */ complex ys2() const {return _spin[1][1];} /** * Get third spinor component for the y vector */ complex ys3() const {return _spin[1][2];} /** * Get fourth spinor component for the y vector */ complex ys4() const {return _spin[1][3];} /** * Get first spinor component for the z vector */ complex zs1() const {return _spin[2][0];} /** * Get second spinor component for the z vector */ complex zs2() const {return _spin[2][1];} /** * Get third spinor component for the z vector */ complex zs3() const {return _spin[2][2];} /** * Get fourth spinor component for the z vector */ complex zs4() const {return _spin[2][3];} /** * Get first spinor component for the t vector */ complex ts1() const {return _spin[3][0];} /** * Get second spinor component for the t vector */ complex ts2() const {return _spin[3][1];} /** * Get third spinor component for the t vector */ complex ts3() const {return _spin[3][2];} /** * Get fourth spinor component for the t vector */ complex ts4() const {return _spin[3][3];} /** * Set first spinor component for the x vector */ void setXS1(complex in) {_spin[0][0]=in;} /** * Set second spinor component for the x vector */ void setXS2(complex in) {_spin[0][1]=in;} /** * Set third spinor component for the x vector */ void setXS3(complex in) {_spin[0][2]=in;} /** * Set fourth spinor component for the x vector */ void setXS4(complex in) {_spin[0][3]=in;} /** * Set first spinor component for the y vector */ void setYS1(complex in) {_spin[1][0]=in;} /** * Set second spinor component for the y vector */ void setYS2(complex in) {_spin[1][1]=in;} /** * Set third spinor component for the y vector */ void setYS3(complex in) {_spin[1][2]=in;} /** * Set fourth spinor component for the y vector */ void setYS4(complex in) {_spin[1][3]=in;} /** * Set first spinor component for the z vector */ void setZS1(complex in) {_spin[2][0]=in;} /** * Set second spinor component for the z vector */ void setZS2(complex in) {_spin[2][1]=in;} /** * Set third spinor component for the z vector */ void setZS3(complex in) {_spin[2][2]=in;} /** * Set fourth spinor component for the z vector */ void setZS4(complex in) {_spin[2][3]=in;} /** * Set first spinor component for the t vector */ void setTS1(complex in) {_spin[3][0]=in;} /** * Set second spinor component for the t vector */ void setTS2(complex in) {_spin[3][1]=in;} /** * Set third spinor component for the t vector */ void setTS3(complex in) {_spin[3][2]=in;} /** * Set fourth spinor component for the t vector */ void setTS4(complex in) {_spin[3][3]=in;} //@} /** @name Arithmetic operators. */ //@{ /** * dot product with a polarization vector */ LorentzSpinor dot(const LorentzPolarizationVector & vec) const { LorentzSpinor output(_type); complex temp; unsigned int ix; for(ix=0;ix<4;++ix) { temp = _spin[3][ix]*vec.t(); temp -= _spin[0][ix]*vec.x(); temp -= _spin[1][ix]*vec.y(); temp -= _spin[2][ix]*vec.z(); output[ix]=temp; } return output; } /** * dot product with a 4-vector */ LorentzSpinor dot(const LorentzMomentum & invec) const { LorentzSpinor output(_type); complex temp; LorentzVector vec = UnitRemoval::InvE * invec; unsigned int ix; for(ix=0;ix<4;++ix) { temp = - ( _spin[0][ix]*vec.x() + _spin[1][ix]*vec.y()+ _spin[2][ix]*vec.z() ) + _spin[3][ix]*vec.t(); output[ix]=temp; } return output; } //@} /** @name Transformations. */ //@{ /** * return the barred spinor */ LorentzRSSpinorBar bar() const; /** * Standard Lorentz boost specifying the components of the beta vector. */ LorentzRSSpinor & boost(double,double,double); /** * Standard Lorentz boost specifying the beta vector. */ LorentzRSSpinor & boost(const Boost &); /** * General transform */ LorentzRSSpinor & transform(const LorentzRotation &); //@} /** @name Functions related to type. */ //@{ /** * Return the type of the spinor. */ SpinorType Type() const {return _type;} //@} /** * Scalar product \f$\bar{f}^\alpha(c_LP_L+c_RP_R)f_\alpha\f$for general couplings * @param fbar The barred spinor * @param left The left-handed coupling, \f$c_L\f$. * @param right The right-handed coupling, \f$c_R\f$. */ template complex::MulT> generalScalar(LorentzRSSpinorBar& fbar, Complex left, Complex right) { complex::MulT> output; unsigned int iz; output = left*(fbar(3,0)*_spin[3][0]+fbar(3,1)*_spin[3][1]) +right*(fbar(3,2)*_spin[3][2]+fbar(3,3)*_spin[3][3]); for(iz=0;iz<3;++iz) { output -= left*(fbar(iz,0)*_spin[iz][0]+fbar(iz,1)*_spin[iz][1]) +right*(fbar(iz,2)*_spin[iz][2]+fbar(iz,3)*_spin[iz][3]); } return output; } /** * Current \f$\bar{f}(c_LP_L+c_RP_R)f^\alpha\f$ for general couplings. * @param fbar The barred spinor * @param left The left-handed coupling, \f$c_L\f$. * @param right The right-handed coupling, \f$c_R\f$. */ template LorentzVector::MulT> > generalCurrent(LorentzSpinorBar& fbar, Complex left, Complex right) { typedef complex::MulT> ResultT; ResultT output[4]; for(size_t iz=0;iz<4;++iz) output[iz]= left*(fbar.s1()*_spin[iz][0]+fbar.s2()*_spin[iz][1]) +right*(fbar.s3()*_spin[iz][2]+fbar.s4()*_spin[iz][3]); return LorentzVector(output[0],output[1],output[2],output[3]); } private: /** * Type of spinor */ SpinorType _type; /** * Storage of the components. */ - complex _spin[4][4]; + std::array,4>,4> _spin; }; } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzRSSpinor.tcc" #endif #endif diff --git a/Helicity/LorentzRSSpinorBar.h b/Helicity/LorentzRSSpinorBar.h --- a/Helicity/LorentzRSSpinorBar.h +++ b/Helicity/LorentzRSSpinorBar.h @@ -1,351 +1,346 @@ // -*- C++ -*- // // LorentzRSSpinorBar.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_LorentzRSSpinorBar_H #define ThePEG_LorentzRSSpinorBar_H // This is the declaration of the LorentzRSSpinorBar class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Vectors/ThreeVector.h" #include "HelicityDefinitions.h" #include "LorentzRSSpinor.fh" #include "LorentzRSSpinorBar.fh" #include "LorentzSpinorBar.h" #include "LorentzSpinor.h" #include "LorentzPolarizationVector.h" namespace ThePEG { namespace Helicity { /** * The LorentzRSSpinorBar class implements the storage of a * barred Lorentz Rarita-Schwinger Spinor for a spin-3/2 particle. * The design is based on that of the * LorentzRSSpinor class and the details of the implemented * are discussed in more detail in the header file for that class. * * @see LorentzRSSpinor * * \author Peter Richardson * */ template class LorentzRSSpinorBar { public: /** @name Standard constructors. */ //@{ /** * Default zero constructor, optionally specifying \a t, the type. */ - LorentzRSSpinorBar(SpinorType t = unknown_spinortype) : _type(t) { - for(unsigned int ix=0;ix<4;++ix) - for(unsigned int iy=0;iy<4;++iy) - _spin[ix][iy]=Value(); - } + LorentzRSSpinorBar(SpinorType t = SpinorType::unknown) : _type(t), _spin() {} /** * Constructor with complex numbers specifying the components, * optionally specifying \a t, the type. */ LorentzRSSpinorBar(complex a1,complex b1, complex c1,complex d1, complex a2,complex b2, complex c2,complex d2, complex a3,complex b3, complex c3,complex d3, complex a4,complex b4, complex c4,complex d4, - SpinorType t=unknown_spinortype) - : _type(t) { - _spin[0][0]=a1;_spin[1][0]=a2;_spin[2][0]=a3;_spin[3][0]=a4; - _spin[0][1]=b1;_spin[1][1]=b2;_spin[2][1]=b3;_spin[3][1]=b4; - _spin[0][2]=c1;_spin[1][2]=c2;_spin[2][2]=c3;_spin[3][2]=c4; - _spin[0][3]=d1;_spin[1][3]=d2;_spin[2][3]=d3;_spin[3][3]=d4; - } + SpinorType t=SpinorType::unknown) + : _type(t), _spin{{ {{a1,b1,c1,d1}}, + {{a2,b2,c2,d2}}, + {{a3,b3,c3,d3}}, + {{a4,b4,c4,d4}} + }} {} //@} /** @name Access the components. */ //@{ /** * Subscript operator to return spinor components */ complex operator()(int i, int j) const { assert( i >= 0 && i <= 3 && j>=0 && j<=3 ); return _spin[i][j]; } /** * Set components by index */ complex & operator () (int i, int j) { assert( i >= 0 && i <= 3 && j>=0 && j<=3 ); return _spin[i][j]; } /** * Get first spinor component for the x vector */ complex xs1() const {return _spin[0][0];} /** * Get second spinor component for the x vector */ complex xs2() const {return _spin[0][1];} /** * Get third spinor component for the x vector */ complex xs3() const {return _spin[0][2];} /** * Get fourth spinor component for the x vector */ complex xs4() const {return _spin[0][3];} /** * Get first spinor component for the y vector */ complex ys1() const {return _spin[1][0];} /** * Get second spinor component for the y vector */ complex ys2() const {return _spin[1][1];} /** * Get third spinor component for the y vector */ complex ys3() const {return _spin[1][2];} /** * Get fourth spinor component for the y vector */ complex ys4() const {return _spin[1][3];} /** * Get first spinor component for the z vector */ complex zs1() const {return _spin[2][0];} /** * Get second spinor component for the z vector */ complex zs2() const {return _spin[2][1];} /** * Get third spinor component for the z vector */ complex zs3() const {return _spin[2][2];} /** * Get fourth spinor component for the z vector */ complex zs4() const {return _spin[2][3];} /** * Get first spinor component for the t vector */ complex ts1() const {return _spin[3][0];} /** * Get second spinor component for the t vector */ complex ts2() const {return _spin[3][1];} /** * Get third spinor component for the t vector */ complex ts3() const {return _spin[3][2];} /** * Get fourth spinor component for the t vector */ complex ts4() const {return _spin[3][3];} /** * Set first spinor component for the x vector */ void setXS1(complex in) {_spin[0][0]=in;} /** * Set second spinor component for the x vector */ void setXS2(complex in) {_spin[0][1]=in;} /** * Set third spinor component for the x vector */ void setXS3(complex in) {_spin[0][2]=in;} /** * Set fourth spinor component for the x vector */ void setXS4(complex in) {_spin[0][3]=in;} /** * Set first spinor component for the y vector */ void setYS1(complex in) {_spin[1][0]=in;} /** * Set second spinor component for the y vector */ void setYS2(complex in) {_spin[1][1]=in;} /** * Set third spinor component for the y vector */ void setYS3(complex in) {_spin[1][2]=in;} /** * Set fourth spinor component for the y vector */ void setYS4(complex in) {_spin[1][3]=in;} /** * Set first spinor component for the z vector */ void setZS1(complex in) {_spin[2][0]=in;} /** * Set second spinor component for the z vector */ void setZS2(complex in) {_spin[2][1]=in;} /** * Set third spinor component for the z vector */ void setZS3(complex in) {_spin[2][2]=in;} /** * Set fourth spinor component for the z vector */ void setZS4(complex in) {_spin[2][3]=in;} /** * Set first spinor component for the t vector */ void setTS1(complex in) {_spin[3][0]=in;} /** * Set second spinor component for the t vector */ void setTS2(complex in) {_spin[3][1]=in;} /** * Set third spinor component for the t vector */ void setTS3(complex in) {_spin[3][2]=in;} /** * Set fourth spinor component for the t vector */ void setTS4(complex in ) {_spin[3][3]=in;} //@} /** @name Arithmetic operators. */ //@{ /** * dot product with a polarization vector */ LorentzSpinorBar dot(const LorentzPolarizationVector & vec) const { LorentzSpinorBar output(_type); for(unsigned int ix=0;ix<4;++ix) { output[ix]=_spin[3][ix]*vec.t()-_spin[0][ix]*vec.x() -_spin[1][ix]*vec.y()-_spin[2][ix]*vec.z(); } return output; } /** * dot product with a 4-momentum */ LorentzSpinorBar dot(const LorentzMomentum & invec) const { LorentzSpinorBar output(_type); LorentzVector vec = UnitRemoval::InvE * invec; unsigned int ix; for(ix=0;ix<4;++ix) { output[ix]=_spin[3][ix]*vec.t()-_spin[0][ix]*vec.x() -_spin[1][ix]*vec.y()-_spin[2][ix]*vec.z(); } return output; } //@} /** @name Transformations. */ //@{ /** * return the barred spinor */ LorentzRSSpinor bar() const; /** * Standard Lorentz boost specifying the components of the beta vector. */ LorentzRSSpinorBar & boost(double,double,double); /** * Standard Lorentz boost specifying the beta vector. */ LorentzRSSpinorBar & boost(const Boost &); /** * General transform */ LorentzRSSpinorBar & transform(const LorentzRotation &); //@} /** @name Functions related to type. */ //@{ /** * Return the type of the spinor. */ SpinorType Type() const {return _type;} //@} /** * Current \f$\bar{f}^\alpha(c_LP_L+c_RP_R)f\f$ for general couplings. * @param f The unbarred spinor * @param left The left-handed coupling, \f$c_L\f$. * @param right The right-handed coupling, \f$c_R\f$. */ template LorentzVector::MulT> > generalCurrent(LorentzSpinor& f, Complex left, Complex right) { typedef complex::MulT> ResultT; ResultT output[4]; unsigned int iz; for(iz=0;iz<4;++iz){ output[iz]= left*(_spin[iz][0]*f.s1()+_spin[iz][1]*f.s2()) +right*(_spin[iz][2]*f.s3()+_spin[iz][3]*f.s4()); } return LorentzVector(output[0],output[1], output[2],output[3]); } private: /** * Type of spinor. */ SpinorType _type; /** * Storage of the components. */ - complex _spin[4][4]; + std::array,4>,4> _spin; }; } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzRSSpinorBar.tcc" #endif #endif diff --git a/Helicity/LorentzSpinor.h b/Helicity/LorentzSpinor.h --- a/Helicity/LorentzSpinor.h +++ b/Helicity/LorentzSpinor.h @@ -1,500 +1,494 @@ // -*- C++ -*- // // LorentzSpinor.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_LorentzSpinor_H #define ThePEG_LorentzSpinor_H // This is the declaration of the LorentzSpinor class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/Vectors/ThreeVector.h" #include "HelicityDefinitions.h" #include "LorentzSpinor.fh" #include "LorentzSpinorBar.h" #include "LorentzPolarizationVector.h" #include "LorentzTensor.h" +#include namespace ThePEG{ namespace Helicity{ /** * The LorentzSpinor class is designed to store a spinor. In addition * to storing the components of the spinor, information is stored on * the representation of the type of spinor, for example u or v type. * * At the moment only one choice of the Dirac matrix representation * is supported. For high-energy calculations the choice made by the * HELAS collaboration is more efficient for numerical * calculations. In this representation * * \f[ * \gamma_{i=1,2,3}=\left(\begin{array}{cc} * 0 & \sigma_i \\ * -\sigma_i & 0 * \end{array}\right) * \quad * \gamma_0=\left(\begin{array}{cc} * 0 & 1 \\ * 1 & 0 * \end{array}\right) * \quad * \gamma_5=\left(\begin{array}{cc} * -1 & 0 \\ * 0 & 1 * \end{array}\right) * \f] * * The type of the spinor is also stored using the SpinorType - * enumeration. There are three types supported u_spinortype, - * v_spinortype, unknown_spinortype. This information is intended + * enumeration. There are three types supported SpinorType::u, + * SpinorType::v, SpinorType::unknown. This information is intended * mainly for use in the case of Majorana particles where matrix * elements can be calculated with either u or v type spinors and * knowledge of which was used will be needed in order to give the - * correct correlations. The unknown_spinortypee is intended for + * correct correlations. The SpinorType::unknowne is intended for * cases where either the spinor for an off-shell line in a matrix * element calculation or the information is genuinely unknown. * * The LorentzSpinorBar class is also provided to store the barred * spinor. * * @see LorentzSpinorBar * * @author Peter Richardson * */ template class LorentzSpinor { public: /** @name Standard constructors. */ //@{ /** * Default zero constructor, optionally specifying \a t, the type. */ - LorentzSpinor(SpinorType t = unknown_spinortype) : _type(t) { - for(unsigned int ix=0;ix<4;++ix) _spin[ix]=Value(); - } + LorentzSpinor(SpinorType t = SpinorType::unknown) : _type(t), _spin() {} /** * Constructor with complex numbers specifying the components, * optionally specifying \a s, the type. */ LorentzSpinor(complex a,complex b, complex c,complex d, - SpinorType s = unknown_spinortype) : _type(s) { - _spin[0]=a; - _spin[1]=b; - _spin[2]=c; - _spin[3]=d; - } + SpinorType s = SpinorType::unknown) : _type(s), _spin{{a,b,c,d}} {} //@} /** @name Access the components. */ //@{ /** * Subscript operator to return spinor components */ complex operator[](int i) const { assert( i >= 0 && i <= 3 ); return _spin[i]; } /** * Subscript operator to return spinor components */ complex operator()(int i) const { assert( i >= 0 && i <= 3 ); return _spin[i]; } /** * Set components by index. */ complex & operator()(int i) { assert( i >= 0 && i <= 3 ); return _spin[i]; } /** * Set components by index. */ complex & operator[](int i) { assert( i >= 0 && i <= 3 ); return _spin[i]; } /** * Get first component. */ complex s1() const {return _spin[0];} /** * Get second component. */ complex s2() const {return _spin[1];} /** * Get third component. */ complex s3() const {return _spin[2];} /** * Get fourth component. */ complex s4() const {return _spin[3];} /** * Set first component. */ void setS1(complex in) {_spin[0]=in;} /** * Set second component. */ void setS2(complex in) {_spin[1]=in;} /** * Set third component. */ void setS3(complex in) {_spin[2]=in;} /** * Set fourth component. */ void setS4(complex in) {_spin[3]=in;} //@} /** @name Transformations. */ //@{ /** * Return the barred spinor */ LorentzSpinorBar bar() const; /** * Return the conjugated spinor \f$u_c=C\bar{u}^T\f$. This operation * transforms u-spinors to v-spinors and vice-versa and is required when * dealing with majorana particles. */ LorentzSpinor conjugate() const; /** * Standard Lorentz boost specifying the components of the beta vector. */ LorentzSpinor & boost(double,double,double); /** * Standard Lorentz boost specifying the beta vector. */ LorentzSpinor & boost(const Boost &); /** * General Lorentz transformation */ LorentzSpinor & transform(const SpinHalfLorentzRotation & ); /** * General Lorentz transformation */ LorentzSpinor & transform(const LorentzRotation & r) { transform(r.half()); return *this; } //@} /** @name Functions related to type. */ //@{ /** * Return the type of the spinor. */ SpinorType Type() const {return _type;} //@} /** * @name Functions to apply the projection operator */ //@{ /** * Apply \f$p\!\!\!\!\!\not\,\,\,+m\f$ */ template LorentzSpinor::MulT> projectionOperator(const LorentzVector & p, const ValueB & m) const { typedef typename BinaryOpTraits::MulT ResultT; LorentzSpinor spin; static const Complex ii(0.,1.); complex p0pp3=p.t()+p.z(); complex p0mp3=p.t()-p.z(); complex p1pp2=p.x()+ii*p.y(); complex p1mp2=p.x()-ii*p.y(); spin.setS1(m*s1()+p0mp3*s3()-p1mp2*s4()); spin.setS2(m*s2()+p0pp3*s4()-p1pp2*s3()); spin.setS3(m*s3()+p0pp3*s1()+p1mp2*s2()); spin.setS4(m*s4()+p0mp3*s2()+p1pp2*s1()); return spin; } /** * Apply \f$g^LP_L+g^RP_R\f$ */ LorentzSpinor helicityProjectionOperator(const Complex & gL, const Complex & gR) const { LorentzSpinor spin; spin.setS1(gL*s1()); spin.setS2(gL*s2()); spin.setS3(gR*s3()); spin.setS4(gR*s4()); return spin; } //@} /** @name Functions to calculate certain currents. */ //@{ /** * Apply \f$p\!\!\!\!\!\not\f$ */ template LorentzSpinor::MulT> slash(const LorentzVector & p) const { typedef typename BinaryOpTraits::MulT ResultT; LorentzSpinor spin; static const Complex ii(0.,1.); complex p0pp3=p.t()+p.z(); complex p0mp3=p.t()-p.z(); complex p1pp2=p.x()+ii*p.y(); complex p1mp2=p.x()-ii*p.y(); spin.setS1(p0mp3*s3()-p1mp2*s4()); spin.setS2(p0pp3*s4()-p1pp2*s3()); spin.setS3(p0pp3*s1()+p1mp2*s2()); spin.setS4(p0mp3*s2()+p1pp2*s1()); return spin; } /** * Apply \f$p\!\!\!\!\!\not\f$ */ template LorentzSpinor::MulT> slash(const LorentzVector > & p) const { typedef typename BinaryOpTraits::MulT ResultT; LorentzSpinor spin; static const Complex ii(0.,1.); complex p0pp3=p.t()+p.z(); complex p0mp3=p.t()-p.z(); complex p1pp2=p.x()+ii*p.y(); complex p1mp2=p.x()-ii*p.y(); spin.setS1(p0mp3*s3()-p1mp2*s4()); spin.setS2(p0pp3*s4()-p1pp2*s3()); spin.setS3(p0pp3*s1()+p1mp2*s2()); spin.setS4(p0mp3*s2()+p1pp2*s1()); return spin; } /** * Calculate the left-handed current \f$\bar{f}\gamma^\mu P_Lf\f$. * @param fb The barred spinor. */ template LorentzVector::MulT> > leftCurrent(const LorentzSpinorBar& fb) const { typedef complex::MulT> ResultT; LorentzVector vec; Complex ii(0.,1.); ResultT p1(fb.s3()*s2()),p2(fb.s4()*s1()); vec.setX( -(p1+p2) ); vec.setY( ii*(p1-p2) ); p1 = fb.s3()*s1();p2 = fb.s4()*s2(); vec.setZ( -(p1-p2) ); vec.setT( (p1+p2) ); return vec; } /** * Calculate the right-handed current \f$\bar{f}\gamma^\mu P_Rf\f$. * @param fb The barred spinor. */ template LorentzVector::MulT> > rightCurrent(const LorentzSpinorBar& fb) const { typedef complex::MulT> ResultT; LorentzVector vec; Complex ii(0.,1.); ResultT p1(fb.s1()*s4()),p2(fb.s2()*s3()); vec.setX( (p1+p2)); vec.setY( -ii*(p1-p2)); p1 = fb.s1()*s3();p2 = fb.s2()*s4(); vec.setZ( (p1-p2)); vec.setT( (p1+p2)); return vec; } /** * Calculate the vector current \f$\bar{f}\gamma^\mu f\f$ * @param fb The barred spinor. */ template LorentzVector::MulT> > vectorCurrent(const LorentzSpinorBar& fb) const { typedef complex::MulT> ResultT; LorentzVector vec; Complex ii(0.,1.); ResultT s1s4(fb.s1()*s4()),s2s3(fb.s2()*s3()), s3s2(fb.s3()*s2()),s4s1(fb.s4()*s1()), s1s3(fb.s1()*s3()),s2s4(fb.s2()*s4()), s3s1(fb.s3()*s1()),s4s2(fb.s4()*s2()); vec.setX( s1s4+s2s3-s3s2-s4s1 ); vec.setY( -ii*(s1s4-s2s3-s3s2+s4s1)); vec.setZ( s1s3-s2s4-s3s1+s4s2 ); vec.setT( s1s3+s2s4+s3s1+s4s2); return vec; } /** * Calculate a general current with arbitary left and right couplings, * i.e. \f$\bar{f}\gamma^\mu(c_lP_L+c_RP_R)f\f$ * @param fb The barred spinor. * @param left The left coupling, \f$c_L\f$. * @param right The right coupling, \f$c_R\f$. */ template LorentzVector::MulT> > generalCurrent(const LorentzSpinorBar& fb, Complex left, Complex right) const { typedef complex::MulT> ResultT; LorentzVector vec; Complex ii(0.,1.); ResultT p1(fb.s3()*s2()),p2(fb.s4()*s1()); vec.setX( -left*(p1+p2)); vec.setY( ii*left*(p1-p2)); p1 = fb.s3()*s1();p2 = fb.s4()*s2(); vec.setZ( -left*(p1-p2)); vec.setT( left*(p1+p2)); p1=fb.s1()*s4();p2=fb.s2()*s3(); vec.setX(vec.x()+right*(p1+p2)); vec.setY(vec.y()-ii*right*(p1-p2)); p1 = fb.s1()*s3();p2 = fb.s2()*s4(); vec.setZ(vec.z()+right*(p1-p2)); vec.setT(vec.t()+right*(p1+p2)); return vec; } //@} /** @name Functions to calculate certain scalars. */ //@{ /** * Calculate the left-handed scalar \f$\bar{f}P_Lf\f$. * @param fb The barred spinor. */ template complex::MulT> leftScalar(const LorentzSpinorBar& fb) const { return fb.s1()*s1()+fb.s2()*s2(); } /** * Calculate the right-handed scalar \f$\bar{f}P_Rf\f$. * @param fb The barred spinor. */ template complex::MulT> rightScalar(const LorentzSpinorBar& fb) const { return fb.s3()*s3()+fb.s4()*s4(); } /** * Calculate the scalar \f$\bar{f}f\f$. * @param fb The barred spinor. */ template complex::MulT> scalar(const LorentzSpinorBar& fb) const { return fb.s1()*s1()+fb.s2()*s2()+fb.s3()*s3()+fb.s4()*s4(); } /** * Calculate the pseudoscalar \f$\bar{f}\gamma_5f\f$. * @param fb The barred spinor. */ template complex::MulT> pseudoScalar(const LorentzSpinorBar& fb) const { return -fb.s1()*s1()-fb.s2()*s2()+fb.s3()*s3()+fb.s4()*s4(); } /** * Calculate a general scalar product with arbitary left and right couplings, * i.e. \f$\bar{f}c_lP_L+c_RP_Rf\f$ * @param fb The barred spinor. * @param left The left coupling, \f$c_L\f$. * @param right The right coupling, \f$c_R\f$. */ template complex::MulT> generalScalar(const LorentzSpinorBar& fb, Complex left, Complex right) const { return left*(fb.s1()*s1()+fb.s2()*s2()) + right*(fb.s3()*s3()+fb.s4()*s4()); } //@} /** * Calculate the product with \f$\sigma^{\mu\nu}\f$, i.e. * \f$\bar{f}\sigma^{\mu\nu}f\f$ */ template LorentzTensor::MulT> sigma(const LorentzSpinorBar& fb) const { typedef typename BinaryOpTraits::MulT ResultT; LorentzTensor output; complex s11(fb.s1()*s1()),s22(fb.s2()*s2()), s33(fb.s3()*s3()),s44(fb.s4()*s4()), s12(fb.s1()*s2()),s21(fb.s2()*s1()), s34(fb.s3()*s4()),s43(fb.s4()*s3()); Complex ii(0.,1.); complex zero; zero = ZERO; output.setTT( zero ); output.setTX(-ii*( s12+s21-s34-s43)); output.setTY( -s12+s21+s34-s43 ); output.setTZ(-ii*( s11-s22-s33+s44)); output.setXT( -output.tx() ); output.setXX( zero ); output.setXY( s11-s22+s33-s44 ); output.setXZ(-ii*(-s12+s21-s34+s43)); output.setYT( -output.ty() ); output.setYX( -output.xy() ); output.setYY( zero ); output.setYZ( s12+s21+s34+s43 ); output.setZT( -output.tz() ); output.setZX( -output.xz() ); output.setZY( -output.yz() ); output.setZZ( zero ); return output; } private: /** * Type of spinor */ SpinorType _type; /** * Storage of the components. */ - complex _spin[4]; + std::array,4> _spin; }; } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzSpinor.tcc" #endif #endif diff --git a/Helicity/LorentzSpinor.tcc b/Helicity/LorentzSpinor.tcc --- a/Helicity/LorentzSpinor.tcc +++ b/Helicity/LorentzSpinor.tcc @@ -1,112 +1,112 @@ // -*- C++ -*- // // LorentzSpinor.tcc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 member // functions of the LorentzSpinor class. // // Author: Peter Richardson // #include "LorentzSpinor.h" #include "LorentzSpinorBar.h" using namespace ThePEG; using namespace ThePEG::Helicity; // return the barred spinor template LorentzSpinorBar LorentzSpinor::bar() const { complex output[4]; // HELAS output[0] = conj(_spin[2]); output[1] = conj(_spin[3]); output[2] = conj(_spin[0]); output[3] = conj(_spin[1]); return LorentzSpinorBar(output[0],output[1],output[2],output[3],_type); } // boost the spinor template LorentzSpinor & LorentzSpinor::boost(double bx,double by,double bz) { // work out beta and chi double beta=sqrt(bx*bx+by*by+bz*bz); double chi = atanh(beta); double sinhchi = sinh(0.5*chi)/beta, coshchi = cosh(0.5*chi); // calculate the new spinor complex out[4]; Complex ii(0.,1.); Complex nxminy=bx-ii*by; Complex nxpiny=bx+ii*by; out[0] = coshchi*_spin[0]+sinhchi*(-bz*_spin[0]-nxminy*_spin[1]); out[1] = coshchi*_spin[1]+sinhchi*(+bz*_spin[1]-nxpiny*_spin[0]); out[2] = coshchi*_spin[2]+sinhchi*(+bz*_spin[2]+nxminy*_spin[3]); out[3] = coshchi*_spin[3]+sinhchi*(-bz*_spin[3]+nxpiny*_spin[2]); for(unsigned int ix=0;ix<4;++ix) _spin[ix]=out[ix]; return *this; } // boost the spinor template LorentzSpinor & LorentzSpinor::boost(const Boost & boostv) { double beta = boostv.mag(); double bx=boostv.x(),by=boostv.y(),bz=boostv.z(); double chi = atanh(beta); double sinhchi = sinh(0.5*chi)/beta, coshchi = cosh(0.5*chi); complex out[4]; Complex ii(0.,1.); Complex nxminy=bx-ii*by; Complex nxpiny=bx+ii*by; out[0] = coshchi*_spin[0]+sinhchi*(-bz*_spin[0]-nxminy*_spin[1]); out[1] = coshchi*_spin[1]+sinhchi*(+bz*_spin[1]-nxpiny*_spin[0]); out[2] = coshchi*_spin[2]+sinhchi*(+bz*_spin[2]+nxminy*_spin[3]); out[3] = coshchi*_spin[3]+sinhchi*(-bz*_spin[3]+nxpiny*_spin[2]); for(unsigned int ix=0;ix<4;++ix) _spin[ix]=out[ix]; return *this; } // general transform template LorentzSpinor & LorentzSpinor:: transform(const SpinHalfLorentzRotation & r) { unsigned int ix,iy; complex out[4]; for(ix=0;ix<4;++ix) { out[ix]=complex(); for(iy=0;iy<4;++iy) out[ix]+=r(ix,iy)*_spin[iy]; } for(ix=0;ix<4;++ix) _spin[ix]=out[ix]; return *this; } // conjugation template LorentzSpinor LorentzSpinor::conjugate() const { SpinorType new_type; switch(_type) { - case u_spinortype: - new_type=v_spinortype; + case SpinorType::u: + new_type=SpinorType::v; break; - case v_spinortype: - new_type=u_spinortype; + case SpinorType::v: + new_type=SpinorType::u; break; - case unknown_spinortype: + case SpinorType::unknown: default: - new_type=unknown_spinortype; + new_type=SpinorType::unknown; break; } return LorentzSpinor( conj(_spin[3]), -conj(_spin[2]), -conj(_spin[1]), +conj(_spin[0]), new_type); } diff --git a/Helicity/LorentzSpinorBar.h b/Helicity/LorentzSpinorBar.h --- a/Helicity/LorentzSpinorBar.h +++ b/Helicity/LorentzSpinorBar.h @@ -1,240 +1,233 @@ // -*- C++ -*- // // LorentzSpinorBar.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_LorentzSpinorBar_H #define ThePEG_LorentzSpinorBar_H // This is the declaration of the LorentzSpinorBar class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/Vectors/ThreeVector.h" #include "HelicityDefinitions.h" #include "LorentzSpinor.fh" #include "LorentzSpinorBar.fh" namespace ThePEG { namespace Helicity { /** * The LorentzSpinorBar class implements the storage of a barred * LorentzSpinor. The design is based on that of the LorentzSpinor * class where the details of the implemented are discussed in more * detail. * * @see LorentzSpinor * * @author Peter Richardson */ template class LorentzSpinorBar { public: /** @name Standard constructors. */ //@{ /** * Default zero constructor, optionally specifying \a t, the type */ - LorentzSpinorBar(SpinorType t = unknown_spinortype) : _type(t) { - for(unsigned int ix=0;ix<4;++ix) _spin[ix]=Value(); - } + LorentzSpinorBar(SpinorType t = SpinorType::unknown) : _type(t), _spin() {} /** * Constructor with complex numbers specifying the components, * optionally specifying \a t, the type */ LorentzSpinorBar(complex a, complex b, complex c, complex d, - SpinorType t = unknown_spinortype) - : _type(t) { - _spin[0]=a; - _spin[1]=b; - _spin[2]=c; - _spin[3]=d; - } + SpinorType t = SpinorType::unknown) + : _type(t), _spin{{a,b,c,d}} {} //@} /** @name Access the components. */ //@{ /** * Subscript operator to return spinor components */ complex operator[](int i) const { assert( i>= 0 && i <= 3 ); return _spin[i]; } /** * Subscript operator to return spinor components */ complex operator()(int i) const { assert( i>= 0 && i <= 3 ); return _spin[i]; } /** * Set components by index. */ complex & operator()(int i) { assert( i>= 0 && i <= 3 ); return _spin[i]; } /** * Set components by index. */ complex & operator[](int i) { assert( i>= 0 && i <= 3 ); return _spin[i]; } /** * Get first component. */ complex s1() const {return _spin[0];} /** * Get second component. */ complex s2() const {return _spin[1];} /** * Get third component. */ complex s3() const {return _spin[2];} /** * Get fourth component. */ complex s4() const {return _spin[3];} /** * Set first component. */ void setS1(complex in) {_spin[0]=in;} /** * Set second component. */ void setS2(complex in) {_spin[1]=in;} /** * Set third component. */ void setS3(complex in) {_spin[2]=in;} /** * Set fourth component. */ void setS4(complex in) {_spin[3]=in;} //@} /** @name Transformations. */ //@{ /** * Return the barred spinor */ LorentzSpinor bar() const; /** * Return the conjugated spinor \f$u_c=C\bar{u}^T\f$. This operation * transforms u-spinors to v-spinors and vice-versa and is required when * dealing with majorana particles. */ LorentzSpinorBar conjugate() const; /** * Standard Lorentz boost specifying the components of the beta vector. */ LorentzSpinorBar & boost(double,double,double); /** * Standard Lorentz boost specifying the beta vector. */ LorentzSpinorBar & boost(const Boost &); /** * General Lorentz transformation */ LorentzSpinorBar & transform(const SpinHalfLorentzRotation &) ; /** * General Lorentz transformation */ LorentzSpinorBar & transform(const LorentzRotation & r) { transform(r.half()); return *this; } //@} /** @name Functions related to type. */ //@{ /** * Return the type of the spinor. */ SpinorType Type() const {return _type;} //@} /** * @name Functions to apply the projection operator */ //@{ /** * Apply \f$p\!\!\!\!\!\not\,\,\,+m\f$ */ template LorentzSpinorBar::MulT> projectionOperator(const LorentzVector & p, const ValueB & m) const { typedef typename BinaryOpTraits::MulT ResultT; LorentzSpinorBar spin; static const Complex ii(0.,1.); complex p0pp3=p.t()+p.z(); complex p0mp3=p.t()-p.z(); complex p1pp2=p.x()+ii*p.y(); complex p1mp2=p.x()-ii*p.y(); spin.setS1(m*s1()+p0pp3*s3()+p1pp2*s4()); spin.setS2(m*s2()+p0mp3*s4()+p1mp2*s3()); spin.setS3(m*s3()+p0mp3*s1()-p1pp2*s2()); spin.setS4(m*s4()+p0pp3*s2()-p1mp2*s1()); return spin; } /** * Apply \f$g^LP_L+g^RP_R\f$ */ LorentzSpinorBar helicityProjectionOperator(const Complex & gL, const Complex & gR) const { LorentzSpinorBar spin; spin.setS1(gL*s1()); spin.setS2(gL*s2()); spin.setS3(gR*s3()); spin.setS4(gR*s4()); return spin; } //@} private: /** * Type of spinor */ SpinorType _type; /** * Storage of the components. */ - complex _spin[4]; + std::array,4> _spin; }; } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzSpinorBar.tcc" #endif #endif diff --git a/Helicity/LorentzSpinorBar.tcc b/Helicity/LorentzSpinorBar.tcc --- a/Helicity/LorentzSpinorBar.tcc +++ b/Helicity/LorentzSpinorBar.tcc @@ -1,109 +1,109 @@ // -*- C++ -*- // // LorentzSpinorBar.tcc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 member // functions of the LorentzSpinorBar class. // // Author: Peter Richardson // #include "LorentzSpinorBar.h" #include "LorentzSpinor.h" using namespace ThePEG; using namespace ThePEG::Helicity; // return the unbarred spinor template LorentzSpinor LorentzSpinorBar::bar() const { complex output[4]; // HELAS output[0] = conj(_spin[2]); output[1] = conj(_spin[3]); output[2] = conj(_spin[0]); output[3] = conj(_spin[1]); return LorentzSpinor(output[0],output[1],output[2],output[3],_type); } template LorentzSpinorBar & LorentzSpinorBar::boost(double bx,double by,double bz) { // work out beta and chi double beta=sqrt(bx*bx+by*by+bz*bz); double chi = atanh(beta); double sinhchi = sinh(0.5*chi)/beta, coshchi = cosh(0.5*chi); // calculate the new spinor complex out[4]; Complex ii(0.,1.); Complex nxminy=bx-ii*by; Complex nxpiny=bx+ii*by; out[0] = coshchi*_spin[0]+sinhchi*(-bz*_spin[0]-nxpiny*_spin[1]); out[1] = coshchi*_spin[1]+sinhchi*(+bz*_spin[1]-nxminy*_spin[0]); out[2] = coshchi*_spin[2]+sinhchi*(+bz*_spin[2]+nxpiny*_spin[3]); out[3] = coshchi*_spin[3]+sinhchi*(-bz*_spin[3]+nxminy*_spin[2]); for(unsigned int ix=0;ix<4;++ix){_spin[ix]=out[ix];} return *this; } template LorentzSpinorBar & LorentzSpinorBar::boost(const Boost & boostv) { double beta = boostv.mag(); double bx=boostv.x(),by=boostv.y(),bz=boostv.z(); double chi = atanh(beta); double sinhchi = sinh(0.5*chi)/beta, coshchi = cosh(0.5*chi); complex out[4]; Complex ii(0.,1.); Complex nxminy=bx-ii*by; Complex nxpiny=bx+ii*by; out[0] = coshchi*_spin[0]+sinhchi*(-bz*_spin[0]-nxpiny*_spin[1]); out[1] = coshchi*_spin[1]+sinhchi*(+bz*_spin[1]-nxminy*_spin[0]); out[2] = coshchi*_spin[2]+sinhchi*(+bz*_spin[2]+nxpiny*_spin[3]); out[3] = coshchi*_spin[3]+sinhchi*(-bz*_spin[3]+nxminy*_spin[2]); for(unsigned int ix=0;ix<4;++ix){_spin[ix]=out[ix];} return *this; } // general transform template LorentzSpinorBar & LorentzSpinorBar::transform(const SpinHalfLorentzRotation & r) { unsigned int ix,iy; SpinHalfLorentzRotation t(r.inverse()); complex out[4]; for(ix=0;ix<4;++ix) { out[ix]=complex(); for(iy=0;iy<4;++iy){out[ix]+=_spin[iy]*t(iy,ix);} } for(ix=0;ix<4;++ix){_spin[ix]=out[ix];} return *this; } // conjugation template LorentzSpinorBar LorentzSpinorBar::conjugate() const { SpinorType new_type; switch(_type) { - case u_spinortype: - new_type=v_spinortype; + case SpinorType::u: + new_type=SpinorType::v; break; - case v_spinortype: - new_type=u_spinortype; + case SpinorType::v: + new_type=SpinorType::u; break; - case unknown_spinortype: + case SpinorType::unknown: default: - new_type=unknown_spinortype; + new_type=SpinorType::unknown; break; } return LorentzSpinorBar(-conj(_spin[3]),+conj(_spin[2]), +conj(_spin[1]),-conj(_spin[0]),new_type); } diff --git a/Helicity/LorentzTensor.h b/Helicity/LorentzTensor.h --- a/Helicity/LorentzTensor.h +++ b/Helicity/LorentzTensor.h @@ -1,511 +1,505 @@ // -*- C++ -*- // // LorentzTensor.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_LorentzTensor_H #define ThePEG_LorentzTensor_H // This is the declaration of the LorentzTensor class. #include "ThePEG/Config/ThePEG.h" #include "LorentzPolarizationVector.h" namespace ThePEG { namespace Helicity { // compiler magic needs these pre-declarations to make friend templates work template class LorentzTensor; /** * The LorentzTensor class is designed to implement the storage of a * complex tensor to be used to representation the wavefunction of a * spin-2 particle. * * At the moment it only implements the storage of the tensor * components but it is envisaged that it will be extended to include * boost methods etc. * * @author Peter Richardson * */ template class LorentzTensor { public: /** @name Standard constructors and destructors. */ //@{ /** * Default zero constructor. */ - LorentzTensor() { - for(unsigned int ix=0;ix<4;++ix) - for(unsigned int iy=0;iy<4;++iy) - _tensor[ix][iy]=Value(); - } + LorentzTensor() = default; /** * Constructor specifyign all components. */ LorentzTensor(complex xx, complex xy, complex xz, complex xt, complex yx, complex yy, complex yz, complex yt, complex zx, complex zy, complex zz, complex zt, complex tx, complex ty, - complex tz, complex tt){ - _tensor[0][0]=xx;_tensor[0][1]=xy;_tensor[0][2]=xz;_tensor[0][3]=xt; - _tensor[1][0]=yx;_tensor[1][1]=yy;_tensor[1][2]=yz;_tensor[1][3]=yt; - _tensor[2][0]=zx;_tensor[2][1]=zy;_tensor[2][2]=zz;_tensor[2][3]=zt; - _tensor[3][0]=tx;_tensor[3][1]=ty;_tensor[3][2]=tz;_tensor[3][3]=tt; - } - + complex tz, complex tt) + : _tensor{{ {{xx,xy,xz,xt}}, + {{yx,yy,yz,yt}}, + {{zx,zy,zz,zt}}, + {{tx,ty,tz,tt}} }} {} /** * Constructor in terms of two polarization vectors. */ LorentzTensor(const LorentzPolarizationVector & p, const LorentzPolarizationVector & q) { setXX(p.x() * q.x()); setYX(p.y() * q.x()); setZX(p.z() * q.x()); setTX(p.t() * q.x()); setXY(p.x() * q.y()); setYY(p.y() * q.y()); setZY(p.z() * q.y()); setTY(p.t() * q.y()); setXZ(p.x() * q.z()); setYZ(p.y() * q.z()); setZZ(p.z() * q.z()); setTZ(p.t() * q.z()); setXT(p.x() * q.t()); setYT(p.y() * q.t()); setZT(p.z() * q.t()); setTT(p.t() * q.t()); } //@} /** @name Access individual components. */ //@{ /** * Get x,x component. */ complex xx() const {return _tensor[0][0];} /** * Get y,x component. */ complex yx() const {return _tensor[1][0];} /** * Get z,x component. */ complex zx() const {return _tensor[2][0];} /** * Get t,x component. */ complex tx() const {return _tensor[3][0];} /** * Get x,y component. */ complex xy() const {return _tensor[0][1];} /** * Get y,y component. */ complex yy() const {return _tensor[1][1];} /** * Get z,y component. */ complex zy() const {return _tensor[2][1];} /** * Get t,y component. */ complex ty() const {return _tensor[3][1];} /** * Get x,z component. */ complex xz() const {return _tensor[0][2];} /** * Get y,z component. */ complex yz() const {return _tensor[1][2];} /** * Get z,z component. */ complex zz() const {return _tensor[2][2];} /** * Get t,z component. */ complex tz() const {return _tensor[3][2];} /** * Get x,t component. */ complex xt() const {return _tensor[0][3];} /** * Get y,t component. */ complex yt() const {return _tensor[1][3];} /** * Get z,t component. */ complex zt() const {return _tensor[2][3];} /** * Get t,t component. */ complex tt() const {return _tensor[3][3];} /** * Set x,x component. */ void setXX(complex a) {_tensor[0][0]=a;} /** * Set y,x component. */ void setYX(complex a) {_tensor[1][0]=a;} /** * Set z,x component. */ void setZX(complex a) {_tensor[2][0]=a;} /** * Set t,x component. */ void setTX(complex a) {_tensor[3][0]=a;} /** * Set x,y component. */ void setXY(complex a) {_tensor[0][1]=a;} /** * Set y,y component. */ void setYY(complex a) {_tensor[1][1]=a;} /** * Set z,y component. */ void setZY(complex a) {_tensor[2][1]=a;} /** * Set t,y component. */ void setTY(complex a) {_tensor[3][1]=a;} /** * Set x,z component. */ void setXZ(complex a) {_tensor[0][2]=a;} /** * Set y,z component. */ void setYZ(complex a) {_tensor[1][2]=a;} /** * Set z,z component. */ void setZZ(complex a) {_tensor[2][2]=a;} /** * Set t,z component. */ void setTZ(complex a) {_tensor[3][2]=a;} /** * Set x,t component. */ void setXT(complex a) {_tensor[0][3]=a;} /** * Set y,t component. */ void setYT(complex a) {_tensor[1][3]=a;} /** * Set z,t component. */ void setZT(complex a) {_tensor[2][3]=a;} /** * Set t,t component. */ void setTT(complex a) {_tensor[3][3]=a;} /** * Get components by indices. */ complex operator () (int i, int j) const { assert( i>=0 && i<=3 && j>=0 && j<=3); return _tensor[i][j]; } /** * Set components by indices. */ complex & operator () (int i, int j) { assert( i>=0 && i<=3 && j>=0 && j<=3); return _tensor[i][j]; } //@} /** @name Transformations. */ //@{ /** * Standard Lorentz boost specifying the components of the beta vector. */ LorentzTensor & boost(double,double,double); /** * Standard Lorentz boost specifying the beta vector. */ LorentzTensor & boost(const Boost & b) { return boost(b.x(), b.y(), b.z()); } /** * General Lorentz transformation */ LorentzTensor & transform(const SpinOneLorentzRotation & r){ unsigned int ix,iy,ixa,iya; LorentzTensor output; complex temp; for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { temp=complex(); for(ixa=0;ixa<4;++ixa) { for(iya=0;iya<4;++iya) temp+=r(ix,ixa)*r(iy,iya)*(*this)(ixa,iya); } output(ix,iy)=temp; } } *this=output; return *this; } /** * Return the complex conjugate. */ LorentzTensor conjugate() { return LorentzTensor(conj(xx()), conj(xy()), conj(xz()), conj(xt()), conj(yx()), conj(yy()), conj(yz()), conj(yt()), conj(zx()), conj(zy()), conj(zz()), conj(zt()), conj(tx()), conj(ty()), conj(tz()), conj(tt())); } //@} /** @name Arithmetic operators. */ //@{ /** * Scaling with a complex number */ LorentzTensor operator*=(Complex a) { for(int ix=0;ix<4;++ix) for(int iy=0;iy<4;++iy) _tensor[ix][iy]*=a; return *this; } /** * Scalar product with other tensor */ template friend complex::MulT> operator*(const LorentzTensor & t, const LorentzTensor & u); /** * Addition. */ LorentzTensor operator+(const LorentzTensor & in) const { return LorentzTensor(xx()+in.xx(),xy()+in.xy(),xz()+in.xz(),xt()+in.xt(), yx()+in.yx(),yy()+in.yy(),yz()+in.yz(),yt()+in.yt(), zx()+in.zx(),zy()+in.zy(),zz()+in.zz(),zt()+in.zt(), tx()+in.tx(),ty()+in.ty(),tz()+in.tz(),tt()+in.tt()); } /** * Subtraction. */ LorentzTensor operator-(const LorentzTensor & in) const { return LorentzTensor(xx()-in.xx(),xy()-in.xy(),xz()-in.xz(),xt()-in.xt(), yx()-in.yx(),yy()-in.yy(),yz()-in.yz(),yt()-in.yt(), zx()-in.zx(),zy()-in.zy(),zz()-in.zz(),zt()-in.zt(), tx()-in.tx(),ty()-in.ty(),tz()-in.tz(),tt()-in.tt()); } /** * Trace */ complex trace() const { return _tensor[3][3]-_tensor[0][0]-_tensor[1][1]-_tensor[2][2]; } //@} /** * Various dot products */ //@{ /** * First index dot product with polarization vector */ LorentzVector > preDot (const LorentzPolarizationVector & vec) const { LorentzVector > output; output.setX(vec.t()*_tensor[3][0]-vec.x()*_tensor[0][0]- vec.y()*_tensor[1][0]-vec.z()*_tensor[2][0]); output.setY(vec.t()*_tensor[3][1]-vec.x()*_tensor[0][1]- vec.y()*_tensor[1][1]-vec.z()*_tensor[2][1]); output.setZ(vec.t()*_tensor[3][2]-vec.x()*_tensor[0][2]- vec.y()*_tensor[1][2]-vec.z()*_tensor[2][2]); output.setT(vec.t()*_tensor[3][3]-vec.x()*_tensor[0][3]- vec.y()*_tensor[1][3]-vec.z()*_tensor[2][3]); return output; } /** * Second index dot product with polarization vector */ LorentzVector > postDot(const LorentzPolarizationVector & vec) const { LorentzVector > output; output.setX(vec.t()*_tensor[0][3]-vec.x()*_tensor[0][0]- vec.y()*_tensor[0][1]-vec.z()*_tensor[0][2]); output.setY(vec.t()*_tensor[1][3]-vec.x()*_tensor[1][0]- vec.y()*_tensor[1][1]-vec.z()*_tensor[1][2]); output.setZ(vec.t()*_tensor[2][3]-vec.x()*_tensor[2][0]- vec.y()*_tensor[2][1]-vec.z()*_tensor[2][2]); output.setT(vec.t()*_tensor[3][3]-vec.x()*_tensor[3][0]- vec.y()*_tensor[3][1]-vec.z()*_tensor[3][2]); return output; } /** * First index dot product with momentum */ LorentzVector::MulT> > preDot (const Lorentz5Momentum & vec) const { LorentzVector::MulT> > output; output.setX(vec.t()*_tensor[3][0]-vec.x()*_tensor[0][0]- vec.y()*_tensor[1][0]-vec.z()*_tensor[2][0]); output.setY(vec.t()*_tensor[3][1]-vec.x()*_tensor[0][1]- vec.y()*_tensor[1][1]-vec.z()*_tensor[2][1]); output.setZ(vec.t()*_tensor[3][2]-vec.x()*_tensor[0][2]- vec.y()*_tensor[1][2]-vec.z()*_tensor[2][2]); output.setT(vec.t()*_tensor[3][3]-vec.x()*_tensor[0][3]- vec.y()*_tensor[1][3]-vec.z()*_tensor[2][3]); return output; } /** * Second index dot product with momentum */ LorentzVector::MulT> > postDot(const Lorentz5Momentum & vec) const { LorentzVector::MulT> > output; output.setX(vec.t()*_tensor[0][3]-vec.x()*_tensor[0][0]- vec.y()*_tensor[0][1]-vec.z()*_tensor[0][2]); output.setY(vec.t()*_tensor[1][3]-vec.x()*_tensor[1][0]- vec.y()*_tensor[1][1]-vec.z()*_tensor[1][2]); output.setZ(vec.t()*_tensor[2][3]-vec.x()*_tensor[2][0]- vec.y()*_tensor[2][1]-vec.z()*_tensor[2][2]); output.setT(vec.t()*_tensor[3][3]-vec.x()*_tensor[3][0]- vec.y()*_tensor[3][1]-vec.z()*_tensor[3][2]); return output; } //@} private: /** * The components. */ - complex _tensor[4][4]; + std::array,4>,4> _tensor; }; /** * Multiplication by a complex number. */ template inline LorentzTensor::MulT> operator*(complex a, const LorentzTensor & t) { return LorentzTensor::MulT> (a*t.xx(), a*t.xy(), a*t.xz(), a*t.xt(), a*t.yx(), a*t.yy(), a*t.yz(), a*t.yt(), a*t.zx(), a*t.zy(), a*t.zz(), a*t.zt(), a*t.tx(), a*t.ty(), a*t.tz(), a*t.tt()); } /** * Multiply a LorentzVector by a LorentzTensor. */ template inline LorentzVector,U>::MulT> operator*(const LorentzVector & invec, const LorentzTensor & inten) { LorentzVector,U>::MulT> outvec; outvec.setX(invec.t()*inten(3,0)-invec.x()*inten(0,0) -invec.y()*inten(1,0)-invec.z()*inten(2,0)); outvec.setY(invec.t()*inten(3,1)-invec.x()*inten(0,1) -invec.y()*inten(1,1)-invec.z()*inten(2,1)); outvec.setZ(invec.t()*inten(3,2)-invec.x()*inten(0,2) -invec.y()*inten(1,2)-invec.z()*inten(2,2)); outvec.setT(invec.t()*inten(3,3)-invec.x()*inten(0,3) -invec.y()*inten(1,3)-invec.z()*inten(2,3)); return outvec; } /** * Multiply a LorentzTensor by a LorentzVector. */ template inline LorentzVector,U>::MulT> operator*(const LorentzTensor & inten, const LorentzVector & invec){ LorentzVector,U>::MulT> outvec; outvec.setX(invec.t()*inten(0,3)-invec.x()*inten(0,0) -invec.y()*inten(0,1)-invec.z()*inten(0,2)); outvec.setY(invec.t()*inten(1,3)-invec.x()*inten(1,0) -invec.y()*inten(1,1)-invec.z()*inten(1,2)); outvec.setZ(invec.t()*inten(2,3)-invec.x()*inten(2,0) -invec.y()*inten(2,1)-invec.z()*inten(2,2)); outvec.setT(invec.t()*inten(3,3)-invec.x()*inten(3,0) -invec.y()*inten(3,1)-invec.z()*inten(3,2)); return outvec; } /** * Multiply a LorentzTensor by a LorentzTensor */ template inline complex::MulT> operator*(const LorentzTensor & t, const LorentzTensor & u) { typedef complex::MulT> RetT; RetT output=RetT(),temp; for(unsigned int ix=0;ix<4;++ix) { temp = t._tensor[ix][3]*u._tensor[ix][3]; for(unsigned int iy=0;iy<3;++iy) { temp+= t._tensor[ix][iy]*u._tensor[ix][iy]; } if(ix<3) output-=temp; else output+=temp; } return output; } } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzTensor.tcc" #endif #endif diff --git a/Helicity/RSFermionSpinInfo.h b/Helicity/RSFermionSpinInfo.h --- a/Helicity/RSFermionSpinInfo.h +++ b/Helicity/RSFermionSpinInfo.h @@ -1,207 +1,204 @@ // -*- C++ -*- // // RSFermionSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_RSFermionSpinInfo_H #define THEPEG_RSFermionSpinInfo_H // This is the declaration of the RSFermionSpinInfo class. #include "ThePEG/EventRecord/SpinInfo.h" #include "ThePEG/Helicity/LorentzRSSpinor.h" #include "RSFermionSpinInfo.fh" +#include namespace ThePEG { namespace Helicity { /** * The RSFermionSpinInfo class inherits from the SpinInfo class and * implements the storage of the basis vector for a spin-3/2 particle. * The basis states are the vector u spinors for a particle and the vector * v-spinors for an antiparticle. The barred spinors can be obtained from these. * * These basis states should be set by either the matrixelements or decayers * which are capable of generating spin correlation information. * * The basis states in the rest frame of the particles can then be accessed by * the decayers to produce the correct correlations. * * N.B. in our convention 0 is the \f$-\frac32\f$ helicity state, * 1 is the \f$-\frac12\f$ helicity state, * 2 is the \f$+\frac12\f$ helicity state, * 3 is the \f$+\frac32\f$ helicity state. * * @see SpinInfo * * \author Peter Richardson * */ class RSFermionSpinInfo: public SpinInfo { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ - RSFermionSpinInfo() : SpinInfo(PDT::Spin3Half), _productionstates(4), - _decaystates(4), _currentstates(4), - _decaycalc(false) {} + RSFermionSpinInfo() : SpinInfo(PDT::Spin3Half), _decaycalc(false) {} /** * Standard Constructor. * @param p the production momentum. * @param time true if the particle is time-like. */ RSFermionSpinInfo(const Lorentz5Momentum & p,bool time) - : SpinInfo(PDT::Spin3Half, p, time), - _productionstates(4), _decaystates(4), _currentstates(4), - _decaycalc(false) {} + : SpinInfo(PDT::Spin3Half, p, time), _decaycalc(false) {} //@} public: /** @name Set and get methods for the basis state. */ //@{ /** * Set the basis state, this is production state. * @param hel the helicity (0,1,2,3 as described above.) * @param in the LorentzRSSpinor for the given helicity. */ void setBasisState(unsigned int hel, const LorentzRSSpinor & in) const { assert(hel<4); _productionstates[hel] = in; _currentstates [hel] = in; } /** * Set the basis state for the decay. * @param hel the helicity (0,1,2,3 as described above.) * @param in the LorentzRSSpinor for the given helicity. */ void setDecayState(unsigned int hel, const LorentzRSSpinor & in) const { assert(hel<4); _decaycalc = true; _decaystates[hel] = in; } /** * Get the basis state for the production for the given helicity, \a * hel (0,1,2,3 as described above.) */ const LorentzRSSpinor & getProductionBasisState(unsigned int hel) const { assert(hel<4); return _productionstates[hel]; } /** * Get the basis state for the decay for the given helicity, \a hel * (0,1,2,3 as described above.) */ const LorentzRSSpinor & getDecayBasisState(unsigned int hel) const { assert(hel<4); if(!_decaycalc) { for(unsigned int ix=0;ix<4;++ix) _decaystates[ix]=_currentstates[ix]; _decaycalc=true; } return _decaystates[hel]; } /** * Perform a lorentz rotation of the spin information */ virtual void transform(const LorentzMomentum &,const LorentzRotation &); //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initRSFermionSpinInfo; /** * Private and non-existent assignment operator. */ RSFermionSpinInfo & operator=(const RSFermionSpinInfo &); private: /** * Basis states in the frame in which the particle was produced. */ - mutable vector > _productionstates; + mutable std::array,4> _productionstates; /** * Basis states in the frame in which the particle decays. */ - mutable vector > _decaystates; + mutable std::array,4> _decaystates; /** * Basis states in the current frame of the particle */ - mutable vector > _currentstates; + mutable std::array,4> _currentstates; /** * True if the decay state has been set. */ mutable bool _decaycalc; }; } } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * The following template specialization informs ThePEG about the * base class of RSFermionSpinInfo. */ template <> struct BaseClassTrait { /** Typedef of the base class of RSFermionSpinInfo. */ typedef ThePEG::SpinInfo NthBase; }; /** * The following template specialization informs ThePEG about the * name of this class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::Helicity::RSFermionSpinInfo"; } }; /** @endcond */ } #endif /* THEPEG_RSFermionSpinInfo_H */ diff --git a/Helicity/TensorSpinInfo.h b/Helicity/TensorSpinInfo.h --- a/Helicity/TensorSpinInfo.h +++ b/Helicity/TensorSpinInfo.h @@ -1,205 +1,202 @@ // -*- C++ -*- // // TensorSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_TensorSpinInfo_H #define THEPEG_TensorSpinInfo_H // This is the declaration of the TensorSpinInfo class. #include "ThePEG/EventRecord/SpinInfo.h" #include "ThePEG/Helicity/LorentzTensor.h" #include "TensorSpinInfo.fh" // #include "TensorSpinInfo.xh" +#include namespace ThePEG { namespace Helicity { /** * The TensorSpinInfo class is the implementation of the spin * information for tensor particles. It inherits from the SpinInfo * class and implements the storage of the basis tensors. * * These basis states should be set by either matrix elements or * decayers which are capable of generating spin correlation * information. * * The basis states in the rest frame of the particles can then be * accessed by decayers to produce the correct correlation. * * N.B. in our convention 0 is the \f$-2\f$ helicity state, * 1 is the \f$-1\f$ helicity state, * 2 is the \f$0\f$ helicity state, * 3 is the \f$+1\f$ helicity state and * 4 is the \f$+2\f$ helicity state. * * @author Peter Richardson * */ class TensorSpinInfo: public SpinInfo { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ - TensorSpinInfo() : SpinInfo(PDT::Spin2),_productionstates(5), - _decaystates(5), _currentstates(5), - _decaycalc(false) {} + TensorSpinInfo() : SpinInfo(PDT::Spin2), _decaycalc(false) {} /** * Standard Constructor. * @param p the production momentum. * @param time true if the particle is time-like. */ - TensorSpinInfo(const Lorentz5Momentum & p,bool time) - : SpinInfo(PDT::Spin2, p, time), - _productionstates(5), _decaystates(5), _currentstates(5), - _decaycalc(false) {} + TensorSpinInfo(const Lorentz5Momentum & p, bool time) + : SpinInfo(PDT::Spin2, p, time), _decaycalc(false) {} //@} public: /** @name Access the basis states. */ //@{ /** * Set the basis state, this is production state. * @param hel the helicity (0,1,2,3,4 as described above.) * @param in the LorentzTensor for the given helicity. */ void setBasisState(unsigned int hel, LorentzTensor in) const { assert(hel<5); _productionstates[hel]=in; _currentstates [hel]=in; } /** * Set the basis state for the decay. * @param hel the helicity (0,1,2,3,4 as described above.) * @param in the LorentzTensor for the given helicity. */ void setDecayState(unsigned int hel, LorentzTensor in) const { assert(hel<5); _decaycalc = true; _decaystates[hel] = in; } /** * Get the basis state for the production for the given helicity, \a * hel (0,1,2,3,4 as described above.) */ const LorentzTensor & getProductionBasisState(unsigned int hel) const { assert(hel<5); return _productionstates[hel]; } /** * Get the basis state for the decay for the given helicity, \a hel * (0,1,2,3,4 as described above.) */ const LorentzTensor & getDecayBasisState(unsigned int hel) const { assert(hel<5); if(!_decaycalc) { for(unsigned int ix=0;ix<5;++ix) _decaystates[ix]=_currentstates[ix].conjugate(); _decaycalc=true; } return _decaystates[hel]; } //@} /** * Perform a lorentz rotation of the spin information */ virtual void transform(const LorentzMomentum &,const LorentzRotation &); public: /** * Standard Init function. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initTensorSpinInfo; /** * Private and non-existent assignment operator. */ TensorSpinInfo & operator=(const TensorSpinInfo &); private: /** * Basis states in the frame in which the particle was produced. */ - mutable vector > _productionstates; + mutable std::array,5> _productionstates; /** * Basis states in the frame in which the particle decays. */ - mutable vector > _decaystates; + mutable std::array,5> _decaystates; /** * Basis states in the current frame of the particle */ - mutable vector > _currentstates; + mutable std::array,5> _currentstates; /** * True if the decay state has been set. */ mutable bool _decaycalc; }; } } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * TensorSpinInfo. */ template <> struct BaseClassTrait : public ClassTraitsType { /** Typedef of the base class of ScalarSpinInfo. */ typedef ThePEG::SpinInfo NthBase; }; /** * This template specialization informs ThePEG about the name of the * TensorSpinInfo class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::Helicity::TensorSpinInfo"; } }; /** @endcond */ } #endif /* THEPEG_TensorSpinInfo_H */ diff --git a/Helicity/VectorSpinInfo.h b/Helicity/VectorSpinInfo.h --- a/Helicity/VectorSpinInfo.h +++ b/Helicity/VectorSpinInfo.h @@ -1,205 +1,201 @@ // -*- C++ -*- // // VectorSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_VectorSpinInfo_H #define THEPEG_VectorSpinInfo_H // This is the declaration of the VectorSpinInfo class. #include "ThePEG/EventRecord/SpinInfo.h" #include "ThePEG/Helicity/LorentzPolarizationVector.h" #include "VectorSpinInfo.fh" namespace ThePEG { namespace Helicity { /** * The VectorSpinInfo class is the implementation of the spin * information for vector particles. It inherits from the SpinInfo * class and implements the storage of the basis vectors. * * These basis states should be set by either matrixelements or * decayers which are capable of generating spin correlation * information. * * The basis states in the rest frame of the particles can then be * accessed by decayers to produce the correct correlation. * * N.B. in our convention 0 is the \f$-1\f$ helicity state, * 1 is the \f$0\f$ helicity state and * 2 is the \f$+1\f$ helicity state. * * @author Peter Richardson * */ class VectorSpinInfo: public SpinInfo { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ - VectorSpinInfo() : SpinInfo(PDT::Spin1), _productionstates(3), - _decaystates(3), _currentstates(3), - _decaycalc(false) {} + VectorSpinInfo() : SpinInfo(PDT::Spin1), _decaycalc(false) {} /** * Standard Constructor. * @param p the production momentum. * @param time true if the particle is time-like. */ VectorSpinInfo(const Lorentz5Momentum & p, bool time) - : SpinInfo(PDT::Spin1, p, time), - _productionstates(3), _decaystates(3), _currentstates(3), - _decaycalc(false) {} + : SpinInfo(PDT::Spin1, p, time), _decaycalc(false) {} //@} public: /** @name Set and get methods for the basis state. */ //@{ /** * Set the basis state, this is production state. * @param hel the helicity (0,1,2 as described above.) * @param in the LorentzPolarizationVector for the given helicity. */ void setBasisState(unsigned int hel, const LorentzPolarizationVector & in) const { assert(hel<3); _productionstates[hel] = in; _currentstates [hel] = in; } /** * Set the basis state for the decay. * @param hel the helicity (0,1,2 as described above.) * @param in the LorentzPolarizationVector for the given helicity. */ void setDecayState(unsigned int hel, const LorentzPolarizationVector & in) const { assert(hel<3); _decaycalc = true; _decaystates[hel] = in;; } /** * Get the basis state for the production for the given helicity, \a * hel (0,1,2 as described above.) */ const LorentzPolarizationVector & getProductionBasisState(unsigned int hel) const { assert(hel<3); return _productionstates[hel]; } /** * Get the basis state for the decay for the given helicity, \a hel * (0,1,2 as described above.) */ const LorentzPolarizationVector & getDecayBasisState(unsigned int hel) const { assert(hel<3); if(!_decaycalc) { for(unsigned int ix=0;ix<3;++ix) _decaystates[ix]=_currentstates[ix].conjugate(); _decaycalc=true; } // return the basis function return _decaystates[hel]; } //@} /** * Perform a Lorentz rotation of the spin information */ virtual void transform(const LorentzMomentum &,const LorentzRotation & ); public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initVectorSpinInfo; /** * Private and non-existent assignment operator. */ VectorSpinInfo & operator=(const VectorSpinInfo &); private: /** * Basis states in the frame in which the particle was produced. */ - mutable vector _productionstates; + mutable std::array _productionstates; /** * Basis states in the frame in which the particle decays. */ - mutable vector _decaystates; + mutable std::array _decaystates; /** * Basis states in the current frame of the particle */ - mutable vector _currentstates; + mutable std::array _currentstates; /** * True if the decay state has been set. */ mutable bool _decaycalc; }; } } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * VectorSpinInfo. */ template <> struct BaseClassTrait : public ClassTraitsType { /** Typedef of the base class of VectorSpinInfo. */ typedef ThePEG::SpinInfo NthBase; }; /** * This template specialization informs ThePEG about the name of the * VectorSpinInfo class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::Helicity::VectorSpinInfo"; } }; /** @endcond */ } #endif /* THEPEG_VectorSpinInfo_H */ diff --git a/Helicity/Vertex/Vector/FFVVertex.cc b/Helicity/Vertex/Vector/FFVVertex.cc --- a/Helicity/Vertex/Vector/FFVVertex.cc +++ b/Helicity/Vertex/Vector/FFVVertex.cc @@ -1,473 +1,473 @@ // -*- C++ -*- // // FFVVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 FFVVertex class. // #include "FFVVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; using namespace Helicity; // Definition of the static class description member AbstractNoPIOClassDescription FFVVertex::initFFVVertex; void FFVVertex::Init() { static ClassDocumentation documentation ("The FFVVertex class implements the helicity amplitude" "calculations for a fermion-fantifermion gauge boson vertex. Any " "implementation of such a vertex should inherit from in and implement" " the virtual setCoupling member to calculate the coupling"); } // evalulate the full vertex Complex FFVVertex::evaluate(Energy2 q2, const SpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, const VectorWaveFunction & vec) { // first calculate the couplings if(kinematics()) calculateKinematics(sp.momentum(),sbar.momentum(),vec.momentum()); setCoupling(q2,sp.particle(),sbar.particle(),vec.particle()); Complex ii(0.,1.); // useful combinations of the polarization vector components Complex e0p3=vec.t()+vec.z(); Complex e0m3=vec.t()-vec.z(); Complex e1p2=vec.x()+ii*vec.y(); Complex e1m2=vec.x()-ii*vec.y(); Complex vertex(0.); if(_left!=0.) { vertex += _left*(+sbar.s3()*(sp.s1()*e0p3+sp.s2()*e1m2) +sbar.s4()*(sp.s1()*e1p2+sp.s2()*e0m3)); } // then the right piece (often not needed eg W vertex) if(_right!=0.) { vertex += _right*(+sbar.s1()*(sp.s3()*e0m3-sp.s4()*e1m2) -sbar.s2()*(sp.s3()*e1p2-sp.s4()*e0p3)); } vertex*=ii; return vertex*norm(); } // evaluate an off-shell spinor SpinorWaveFunction FFVVertex::evaluate(Energy2 q2, int iopt,tcPDPtr out, const SpinorWaveFunction & sp, const VectorWaveFunction &vec, complex mass, complex width) { // extract the pointers to the particle data objects tcPDPtr Psp=sp.particle(); tcPDPtr Pvec=vec.particle(); // work out the momentum of the off-shell particle Lorentz5Momentum pout = sp.momentum()+vec.momentum(); // first calculate the couplings if(kinematics()) calculateKinematics(sp.momentum(),pout,vec.momentum()); setCoupling(q2,Psp,out,Pvec); Complex ii(0.,1.); // now evaluate the contribution // polarization components Complex e0p3 = vec.t() + vec.z(); Complex e0m3 = vec.t() - vec.z(); Complex e1p2 = vec.x()+ii*vec.y(); Complex e1m2 = vec.x()-ii*vec.y(); // overall factor Energy2 p2 = pout.m2(); Complex fact=-normPropagator(iopt,p2,out,mass,width); // momentum components if(mass.real() < ZERO) mass = iopt==5 ? ZERO : out->mass(); complex p1p2 = pout.x()+ii*pout.y(); complex p1m2 = pout.x()-ii*pout.y(); // complex nos for for the spinor Complex s1(0.),s2(0.),s3(0.),s4(0.); LorentzSpinor spt =sp .wave(); complex p0p3=pout.e() + pout.z(); complex p0m3=pout.e() - pout.z(); // left piece if(_left!=0.) { Complex a3=_left*fact*( spt.s1()*e0p3+spt.s2()*e1m2); Complex a4=_left*fact*( spt.s1()*e1p2+spt.s2()*e0m3); s1 +=UnitRemoval::InvE * (p0m3*a3-p1m2*a4); s2 +=UnitRemoval::InvE * (-p1p2*a3+p0p3*a4); s3 +=UnitRemoval::InvE * a3*mass; s4 +=UnitRemoval::InvE * a4*mass; } // right piece if(_right!=0.) { Complex a1=_right*fact*( spt.s3()*e0m3-spt.s4()*e1m2); Complex a2=_right*fact*(-spt.s3()*e1p2+spt.s4()*e0p3); s1 +=UnitRemoval::InvE * a1*mass; s2 +=UnitRemoval::InvE * a2*mass; s3 +=UnitRemoval::InvE * (p0p3*a1+p1m2*a2); s4 +=UnitRemoval::InvE * (p1p2*a1+p0m3*a2); } // return the wavefunction return SpinorWaveFunction(pout,out,s1,s2,s3,s4); } // evaluate an off-shell SpinorBar SpinorBarWaveFunction FFVVertex::evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorBarWaveFunction & sbar, const VectorWaveFunction & vec, complex mass, complex width) { // work out the momentum of the off-shell particle Lorentz5Momentum pout = sbar.momentum()+vec.momentum(); // first calculate the couplings if(kinematics()) calculateKinematics(pout,sbar.momentum(),vec.momentum()); setCoupling(q2,out,sbar.particle(),vec.particle()); Complex ii(0.,1.); // now evaluate the contribution // polarization components Complex e0p3=vec.t() + vec.z(); Complex e0m3=vec.t() - vec.z(); Complex e1p2=vec.x()+ii*vec.y(); Complex e1m2=vec.x()-ii*vec.y(); // overall factor Energy2 p2 = pout.m2(); Complex fact=-normPropagator(iopt,p2,out,mass,width); // momentum components if(mass.real() < ZERO) mass = (iopt==5) ? ZERO : out->mass(); complex p1p2=pout.x()+ii*pout.y(); complex p1m2=pout.x()-ii*pout.y(); // complex numbers for the spinor Complex s1(0.),s2(0.),s3(0.),s4(0.); LorentzSpinorBar sbart=sbar.wave(); Energy p0p3=pout.e() + pout.z(); Energy p0m3=pout.e() - pout.z(); // left piece if(_left!=0.) { Complex a1 = _left*fact*( sbart.s3()*e0p3+sbart.s4()*e1p2); Complex a2 = _left*fact*( sbart.s3()*e1m2+sbart.s4()*e0m3); s1 += UnitRemoval::InvE*a1*mass; s2 += UnitRemoval::InvE*a2*mass; s3 += UnitRemoval::InvE*(-p0m3*a1+p1p2*a2); s4 += UnitRemoval::InvE*(+p1m2*a1-p0p3*a2); } // right piece if(_right!=0.) { Complex a3 = _right*fact*( sbart.s1()*e0m3-sbart.s2()*e1p2); Complex a4 = _right*fact*(-sbart.s1()*e1m2+sbart.s2()*e0p3); s1 += UnitRemoval::InvE*(-p0p3*a3-p1p2*a4); s2 += UnitRemoval::InvE*(-p1m2*a3-p0m3*a4); s3 += UnitRemoval::InvE*a3*mass; s4 += UnitRemoval::InvE*a4*mass; } return SpinorBarWaveFunction(pout,out,s1,s2,s3,s4); } // off-shell vector VectorWaveFunction FFVVertex::evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, complex mass, complex width) { // work out the momentum of the off-shell particle Lorentz5Momentum pout = sbar.momentum()+sp.momentum(); // first calculate the couplings if(kinematics()) calculateKinematics(sp.momentum(),sbar.momentum(),pout); setCoupling(q2,sp.particle(),sbar.particle(),out); Complex ii(0.,1.); // overall factor Energy2 p2 = pout.m2(); Complex fact = normPropagator(iopt,p2,out,mass,width); // momentum components if(mass.real() < ZERO) mass = (iopt==5) ? ZERO : out->mass(); complex mass2 = sqr(mass); // the vector for the fermion-antifermion Complex vec[4]; // left coupling if(_left!=0.) { vec[0] = -_left*(sbar.s3()*sp.s2()+sbar.s4()*sp.s1()); vec[1] = ii*_left*(sbar.s3()*sp.s2()-sbar.s4()*sp.s1()); vec[2] = -_left*(sbar.s3()*sp.s1()-sbar.s4()*sp.s2()); vec[3] = _left*(sbar.s3()*sp.s1()+sbar.s4()*sp.s2()); } // right coupling if(_right!=0.) { vec[0] += +_right*(sbar.s1()*sp.s4()+sbar.s2()*sp.s3()); vec[1] += -ii*_right*(sbar.s1()*sp.s4()-sbar.s2()*sp.s3()); vec[2] += +_right*(sbar.s1()*sp.s3()-sbar.s2()*sp.s4()); vec[3] += +_right*(sbar.s1()*sp.s3()+sbar.s2()*sp.s4()); } // massless boson if(mass.real()==ZERO) { for(int ix=0;ix<4;++ix){vec[ix]*=fact;} } // massive boson else { complex dot = ( pout.e() *vec[3] -pout.x()*vec[0] -pout.y()*vec[1] -pout.z()*vec[2])/mass2; vec[0]=fact*(vec[0]-dot*pout.x()); vec[1]=fact*(vec[1]-dot*pout.y()); vec[2]=fact*(vec[2]-dot*pout.z()); vec[3]=fact*(vec[3]-dot*pout.e()); } return VectorWaveFunction(pout,out,vec[0],vec[1],vec[2],vec[3]); } SpinorWaveFunction FFVVertex::evaluateSmall(Energy2 q2,int iopt, tcPDPtr out, const SpinorWaveFunction & sp, const VectorWaveFunction & vec, unsigned int fhel, unsigned int vhel, double ctheta, double phi, double stheta, bool includeEikonal, SmallAngleDirection direction, Energy mass, Energy) { assert(fhel <= 1); assert( vhel == 0 || vhel == 2 ); SpinorWaveFunction output; // first calculate the couplings setCoupling(q2,sp.particle(),out,vec.particle()); Complex ii(0.,1.); if(mass < ZERO) mass = iopt==5 ? ZERO : out->mass(); Lorentz5Momentum pout = sp.momentum()+vec.momentum(); assert(sp.direction()!=intermediate); // helicity of the boson double lam = double(vhel)-1.; // energy of the boson Energy Eg = abs(vec.momentum().e()); // energy of the fermion Energy Ef = abs(sp .momentum().e()); // energy fraction of photon double x = Eg/Ef; // velocity of the fermon double beta = sqrt(1.-sqr(mass/Ef)); // dimensionless versions of the variables double dm = mass*UnitRemoval::InvE; double dEf = Ef*UnitRemoval::InvE; double rE = sqrt(.5*dEf); // calculation of propagator accurate as beta->1 and theta -> 0 Energy2 dot = 2.*Ef*Eg*(sqr(mass/Ef)/(1.+beta)*ctheta + sqr(stheta)/(1.+ctheta) ); Complex fact= norm()*(0.5*left()+0.5*right())*UnitRemoval::E2/dot; // phase factor Complex ephig = cos(phi )+ii*sin(phi ); // calculation of the spinor Complex s1(0.),s2(0.),s3(0.),s4(0.); // u-type spinor - if(sp.wave().Type()==u_spinortype) { + if(sp.wave().Type()==SpinorType::u) { // fermion along +z if(direction==PostiveZDirection) { if(fhel==0) { s1 = +x*rE*dEf*sqrt(1.+beta)/ephig*(1.+lam)*sqr(stheta)/(1.+ctheta); s2 =-rE*dEf*sqrt(1.+beta)*stheta* (+x*(1.+lam)-(includeEikonal ? 2.*beta*lam : 0. )); s3 = +x*rE*dm/ephig*(lam-1.)*(1.+ctheta)/sqrt(1.+beta); s4 = +rE*dm/sqrt(1.+beta)*stheta* (-x*(1.-lam)+(includeEikonal ? 2.*beta*lam : 0. )); } else if(fhel==1) { s1 = +rE*dm/sqrt(1.+beta)*stheta* (+x*(1.+lam)+(includeEikonal ? 2.*beta*lam : 0. )); s2 = -x*rE*dm*ephig*(lam+1.)*(1.+ctheta)/sqrt(1.+beta); s3 = -rE*dEf*sqrt(1.+beta)*stheta* (-x*(1.-lam)-(includeEikonal ? 2.*beta*lam : 0. )); s4 = -x*rE*dEf*sqrt(1.+beta)*ephig*(lam-1.)*sqr(stheta)/(1.+ctheta); } } // fermion along -z else { if(fhel==0) { s1 = -rE*dEf*sqrt(1.+beta)*stheta* (+x*(1.+lam)-(includeEikonal ? 2.*beta*lam : 0. )); s2 = -x*rE*dEf*sqrt(1.+beta)/ephig*(1.+lam)*sqr(stheta)/(1.+ctheta); s3 = rE*dm/sqrt(1.+beta)*stheta* (-x*(1.-lam)+(includeEikonal ? 2.*beta*lam : 0. )); s4 = -x*rE*dm/ephig*(-1.+lam)*(1.+ctheta)/sqrt(1.+beta); } else if(fhel==1) { s1 =-x*rE*dm*ephig*(1.+lam)*(1.+ctheta)/sqrt(1.+beta); s2 =-rE*dm/sqrt(1.+beta)*stheta* ( x*(1.+lam) + (includeEikonal ? 2.*beta*lam : 0. )); s3 = x*rE*dEf*sqrt(1.+beta)*ephig*(1.-lam)*sqr(stheta)/(1.+ctheta); s4 =-rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.-lam) + (includeEikonal ? 2.*beta*lam : 0. )); } } } // v-type spinor - else if(sp.wave().Type()==v_spinortype) { + else if(sp.wave().Type()==SpinorType::v) { // fermion along +z if(direction==PostiveZDirection) { if(fhel==0) { s1 = rE*dm/sqrt(1.+beta)*stheta* (-x*(1.+lam) + ( includeEikonal ? 2.*beta*lam : 0. )); s2 = x*rE*dm*ephig*(lam+1.)*(1.+ctheta)/sqrt(1.+beta); s3 = rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.-lam) - ( includeEikonal ? 2.*beta*lam : 0. )); s4 = x*rE*dEf*sqrt(1.+beta)*ephig*(1.-lam)*sqr(stheta)/(1.+ctheta); } else if(fhel==1) { s1 = x*rE*dEf*sqrt(1.+beta)/ephig*(1.+lam)*sqr(stheta)/(1.+ctheta); s2 =-rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.+lam) + (includeEikonal ? 2.*beta*lam : 0.)); s3 = x*rE*dm/ephig*(1.-lam)*(1.+ctheta)/sqrt(1.+beta); s4 = rE*dm/sqrt(1.+beta)*stheta* ( x*(1.-lam) + (includeEikonal ? 2.*beta*lam : 0. )); } } // fermion aling -z else { if(fhel==0) { s1 = x*rE*dm*ephig*(1.+lam)*(1.+ctheta)/sqrt(1.+beta); s2 = rE*dm/sqrt(1.+beta)*stheta* ( x*(1.+lam) - ( includeEikonal ? 2.*beta*lam : 0. )); s3 = x*rE*dEf*sqrt(1.+beta)*ephig*(1.-lam)*sqr(stheta) / (1.+ctheta); s4 =-rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.-lam) - ( includeEikonal ? 2.*beta*lam : 0. )); } else if(fhel==1) { s1 =-rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.+lam) + ( includeEikonal ? 2.*beta*lam : 0. )); s2 =-x*rE*dEf*sqrt(1.+beta)/ephig*(1.+lam)*sqr(stheta)/(1.+ctheta); s3 = rE*dm/sqrt(1.+beta)*stheta* ( x*(1.-lam) + ( includeEikonal ? 2.*beta*lam : 0. )); s4 =-x*rE*dm/ephig*(1.-lam)*(1.+ctheta)/sqrt(1.+beta); } } } s1 *= -fact; s2 *= -fact; s3 *= -fact; s4 *= -fact; return SpinorWaveFunction(pout,out,s1,s2,s3,s4); } SpinorBarWaveFunction FFVVertex::evaluateSmall(Energy2 q2,int iopt, tcPDPtr out, const SpinorBarWaveFunction & sbar, const VectorWaveFunction & vec, unsigned int fhel, unsigned int vhel, double ctheta, double phi, double stheta, bool includeEikonal, SmallAngleDirection direction, Energy mass, Energy) { assert(fhel <= 1); assert( vhel == 0 || vhel == 2 ); SpinorBarWaveFunction output; // first calculate the couplings setCoupling(q2,out,sbar.particle(),vec.particle()); Complex ii(0.,1.); if(mass < ZERO) mass = iopt==5 ? ZERO : out->mass(); Lorentz5Momentum pout = sbar.momentum()+vec.momentum(); assert(sbar.direction()!=intermediate); // helicity of the boson double lam = double(vhel)-1.; // energies and velocities Energy Ef = abs(sbar.momentum().e()); Energy Eg = abs(vec .momentum().e()); double x = Eg/Ef; double beta = sqrt(1.-sqr(mass/Ef)); // calculation of propagator accurate as beta->1 and theta -> 0 Energy2 dot = 2.*Ef*Eg*(sqr(mass/Ef)/(1.+beta)*ctheta + sqr(stheta)/(1.+ctheta) ); Complex fact= norm()*(0.5*left()+0.5*right())*UnitRemoval::E2/dot; // calculation of the spinor Complex s1(0.),s2(0.),s3(0.),s4(0.); Complex ephig = cos(phi )+ii*sin(phi ); double dm = mass*UnitRemoval::InvE; double dEf = Ef*UnitRemoval::InvE; double rE = sqrt(.5*dEf); // u-type spinor - if(sbar.wave().Type()==u_spinortype) { + if(sbar.wave().Type()==SpinorType::u) { // fermion along +z if(direction==PostiveZDirection) { if(fhel==0) { s1 = x*rE*dm*ephig*(1.+lam)*(1.+ctheta)/sqrt(1.+beta); s2 = rE*dm/sqrt(1.+beta)*stheta* (+x*(1.+lam) - (includeEikonal ? 2.*beta*lam : 0. )); s3 = -x*rE*dEf*sqrt(1.+beta)*ephig*(1.-lam)*sqr(stheta)/(1.+ctheta); s4 = rE*dEf*sqrt(1.+beta)*stheta* (+x*(1.-lam) - (includeEikonal ? 2.*beta*lam : 0. )); } else if(fhel==1) { s1 = -rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.+lam) + (includeEikonal ? 2.*beta*lam : 0. )); s2 = -x*rE*dEf*sqrt(1.+beta)/ephig*(lam+1.)*sqr(stheta)/(1.+ctheta); s3 =-rE*dm/sqrt(1.+beta)*stheta* ( x*(1.-lam) + (includeEikonal ? 2.*beta*lam : 0. )); s4 = -x*rE*dm/ephig*(lam-1.)*(1.+ctheta)/sqrt(1.+beta); s4 = rE*dm*(1.+ctheta)/ephig*x*(1.-lam)/sqrt(1.+beta); } } // fermion aling -z else { if(fhel==0) { s1 = rE*dm/sqrt(1.+beta)*stheta* (+x*(1.+lam) - (includeEikonal ? 2.*beta*lam : 0. )); s2 = -x*rE*dm*ephig*(1.+lam)*(1.+ctheta)/sqrt(1.+beta); s3 = rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.-lam) - (includeEikonal ? 2.*beta*lam : 0. )); s4 = -x*rE*dEf*sqrt(1.+beta)*ephig*(lam-1.)*sqr(stheta)/(1.+ctheta); } else if(fhel==1) { s1 = -x*rE*dEf*sqrt(1.+beta)/ephig*(1.+lam)*sqr(stheta)/(1.+ctheta); s2 = rE*dEf*sqrt(1.+beta)*stheta* (+x*(1.+lam) + (includeEikonal ? 2.*beta*lam : 0. )); s3 =-x*rE*dm/ephig*(lam-1.)*(1.+ctheta)/sqrt(1.+beta); s4 = rE*dm/sqrt(1.+beta)*stheta* ( x*(1.-lam) + (includeEikonal ? 2.*beta*lam : 0. )); } } } // v-type spinor - else if(sbar.wave().Type()==v_spinortype) { + else if(sbar.wave().Type()==SpinorType::v) { // anti fermion along +z if(direction==PostiveZDirection) { if(fhel==0) { s1 = -rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.+lam) - (includeEikonal ? 2.*beta*lam : 0. )); s2 = -x*rE*dEf*sqrt(1.+beta)/ephig*(1.+lam)*sqr(stheta)/(1.+ctheta); s3 = rE*dm/sqrt(1.+beta)*stheta* ( x*(1.-lam) - (includeEikonal ? 2.*beta*lam : 0. )); s4 =-x*rE*dm/ephig*(1.-lam)*(1.+ctheta)/sqrt(1.+beta); } else if(fhel==1) { s1 =-x*rE*dm*ephig*(1.+lam)*(1.+ctheta)/sqrt(1.+beta); s2 =-rE*dm/sqrt(1.+beta)*stheta* ( x*(1.+lam) + (includeEikonal ? 2.*beta*lam : 0. )); s3 =-x*rE*dEf*sqrt(1.+beta)*ephig*(1.-lam)*sqr(stheta)/(1.+ctheta); s4 = rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.-lam) + (includeEikonal ? 2.*beta*lam : 0. )); } } // anti fermion aling -z else { if(fhel==0) { s1 = -x*rE*dEf*sqrt(1.+beta)/ephig*(1.+lam)*sqr(stheta)/(1.+ctheta); s2 = rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.+lam) - (includeEikonal ? 2.*beta*lam : 0. )); s3 = x*rE*dm/ephig*(-1.+lam)*(1.+ctheta)/sqrt(1.+beta); s4 =-rE*dm/sqrt(1.+beta)*stheta* (+x*(1.-lam) - (includeEikonal ? 2.*beta*lam : 0. )); } else if(fhel==1) { s1 =-rE*dm/sqrt(1.+beta)*stheta* ( x*(1.+lam) + (includeEikonal ? 2.*beta*lam : 0. )); s2 = x*rE*dm*ephig*(lam+1.)*(1.+ctheta)/sqrt(1.+beta); s3 = rE*dEf*sqrt(1.+beta)*stheta* ( x*(1.-lam) + (includeEikonal ? 2.*beta*lam : 0. )); s4 =-x*rE*dEf*sqrt(1.+beta)*ephig*(lam-1.)*sqr(stheta)/(1.+ctheta); } } } s1 *= -fact; s2 *= -fact; s3 *= -fact; s4 *= -fact; return SpinorBarWaveFunction(pout,out,s1,s2,s3,s4); } diff --git a/Helicity/Vertex/VertexBase.cc b/Helicity/Vertex/VertexBase.cc --- a/Helicity/Vertex/VertexBase.cc +++ b/Helicity/Vertex/VertexBase.cc @@ -1,332 +1,311 @@ // -*- C++ -*- // // VertexBase.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 VertexBase class. // #include "VertexBase.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/Rebinder.h" #include #include #include using namespace ThePEG; using namespace ThePEG::Helicity; VertexBase::VertexBase(VertexType::T name, bool kine) : _npoint(1), _norm(0), _calckinematics(kine), - _kine(5,vector(5)), _theName(name), + _kine(), _theName(name), _ordergEM(0), _ordergS(0), _coupopt(0), _gs(sqrt(4.*Constants::pi*0.3)), _ee(sqrt(4.*Constants::pi/137.04)), _sw(sqrt(0.232)) { assert ( name != VertexType::UNDEFINED ); // Count number of lines from length of 'name' while ( name /= 10 ) ++_npoint; } // setup the lists of particles // should only be called from child class constructors void VertexBase::addToList(long ida, long idb, long idc, long idd) { - if ( idd == 0 ) { - const long id[] = { ida, idb, idc }; - addToList(vector(id,id+3)); - } - else { - const long id[] = { ida, idb, idc, idd }; - addToList(vector(id,id+4)); - } + if ( idd == 0 ) addToList({ ida, idb, idc }); + else addToList({ ida, idb, idc, idd }); } void VertexBase::addToList(const vector & ids) { assert( ids.size() == _npoint ); vector tmp; int chargeSum = 0; - for (vector::const_iterator it = ids.begin(); - it != ids.end(); ++it) { - tPDPtr p = getParticleData(*it); + for ( auto id : ids ) { + tPDPtr p = getParticleData(id); if ( !p ) return; // needed e.g. to deal with chi_5 in MSSM tmp.push_back(p); chargeSum += p->iCharge(); } assert( tmp.size() == _npoint ); if ( chargeSum != 0 ) { cerr << "Problem with the addToList() calls in " << fullName() << ":\n" << "Vertex particles "; copy (ids.begin(), ids.end(), std::ostream_iterator(cerr," ")); cerr << "have non-zero electric charge " << chargeSum << "/3.\n"; assert( false ); } _particles.push_back(tmp); } void VertexBase::doinit() { Interfaced::doinit(); // set up the incoming and outgoing particles if ( !_outpart.empty() || !_inpart.empty() ) return; - for ( unsigned int ix=0; ix<_particles.size(); ++ix ) { - for ( vector::const_iterator it = _particles[ix].begin(); - it != _particles[ix].end(); ++it ) { - tPDPtr p = *it; + for ( const auto & pvec : _particles ) { + for ( tPDPtr p : pvec ) { assert( p ); - assert ( p->id() == getParticleData(p->id())->id() ); tPDPtr cc = p->CC(); _inpart.insert( cc ? cc : p ); _outpart.insert(p); } } // check the couplings if(Debug::level>1&&_npoint!=2+_ordergEM+_ordergS) generator()->log() << fullName() << " has inconsistent number of " << "external particles and coupling order\nQED = " << _ordergEM << " QCD = " << _ordergS << " for" << " a perturbative interaction. Either it's an" << " effective vertex or something is wrong.\n"; assert(_npoint<=2+_ordergEM+_ordergS); } void VertexBase::persistentOutput(PersistentOStream & os) const { os << _npoint << _inpart << _outpart << _particles << _calckinematics << _coupopt << _gs << _ee << _sw; } void VertexBase::persistentInput(PersistentIStream & is, int) { is >> _npoint >> _inpart >> _outpart >> _particles >> _calckinematics >> _coupopt >> _gs >> _ee >> _sw; } // Static variable needed for the type description system in ThePEG. DescribeAbstractClass describeThePEGVertexBase("ThePEG::VertexBase", ""); void VertexBase::Init() { static Switch interfaceCalculateKinematics ("CalculateKinematics", "Calculate kinematic invariants at the vertices. This is" " mainly needed for loop vertices.", &VertexBase::_calckinematics, false, false, false); static SwitchOption interfaceCalculateKinematicsCalculate (interfaceCalculateKinematics, "Calculate", "Calculate the kinematics", true); static SwitchOption interfaceCalculateKinematicsNoKinematics (interfaceCalculateKinematics, "NoKinematics", "Do not calculate the kinematics", false); static ClassDocumentation documentation ("The VertexBase class is designed to be the base class" "of all vertices."); static Switch interfaceCoupling ("Coupling", "Treatment of the running couplings", &VertexBase::_coupopt, 0, false, false); static SwitchOption interfaceCouplingRunning (interfaceCoupling, "Running", "Use the running couplings from the StandardModel object", 0); static SwitchOption interfaceCouplingFixedSM (interfaceCoupling, "FixedSM", "Use the fixed values from the StandardModel object", 1); static SwitchOption interfaceCouplingFixedLocal (interfaceCoupling, "FixedLocal", "Use the local fixed values", 2); static Parameter interfaceStrongCoupling ("StrongCoupling", "The fixed value of the strong coupling to use", &VertexBase::_gs, sqrt(4.*Constants::pi*0.3), 0.0, 10.0, false, false, Interface::limited); static Parameter interfaceElectroMagneticCoupling ("ElectroMagneticCoupling", "The fixed value of the electromagnetic coupling to use", &VertexBase::_ee, sqrt(4.*Constants::pi/128.91), 0.0, 10.0, false, false, Interface::limited); static Parameter interfaceSinThetaW ("SinThetaW", "The fixed value of sin theta_W to use", &VertexBase::_sw, sqrt(0.232), 0.0, 10.0, false, false, Interface::limited); } // find particles with a given id vector VertexBase::search(unsigned int iloc,long idd) const { assert( iloc < _npoint ); vector out; - for(unsigned int ix=0; ix<_particles.size(); ++ix) { - bool found = _particles[ix][iloc]->id() == idd; + for(const auto & pvec : _particles ) { + bool found = pvec[iloc]->id() == idd; if(found) { - for(unsigned int iy=0;iy<_particles[ix].size();++iy) { - out.push_back(_particles[ix][iy]->id()); + for( tcPDPtr p : pvec ) { + out.push_back(p->id()); } } } return out; } // find particles with a given id vector VertexBase::search(unsigned int iloc,tcPDPtr idd) const { assert( iloc < _npoint ); vector out; - for(unsigned int ix=0; ix<_particles.size(); ++ix) { - bool found = _particles[ix][iloc] == idd; - if(found) { - for(unsigned int iy=0;iy<_particles[ix].size();++iy) { - out.push_back(_particles[ix][iy]); - } + for(const auto & pvec : _particles) { + if(pvec[iloc] == idd) { + out.insert(out.end(),pvec.begin(), pvec.end()); } } return out; } // check a given combination is allowed for a three point vertex bool VertexBase::allowed(long ida, long idb, long idc, long idd) const { assert( ( _npoint==3 && idd == 0 ) || _npoint == 4 ); vector out = search(0,ida); for ( size_t ix = 0; ix < out.size(); ix += _npoint ) { if ( out[ix+1] == idb && out[ix+2] == idc && ( idd == 0 || out[ix+3] == idd ) ) { return true; } } return false; } // output the information ostream & ThePEG::Helicity::operator<<(ostream & os, const VertexBase & in) { os << "Information on Vertex" << endl; os << "This is an " << in._npoint << " vertex\n"; os << string( in._calckinematics ? "The kinematic invariants are calculated" : "The kinematics invariants are not calculated" ) << "\n"; os << " Particles allowed for this Vertex\n"; for(unsigned int ix=0;ixPDGName() << " "; } os << '\n'; } return os; } // calculate the propagator for a diagram Complex VertexBase::propagator(int iopt, Energy2 p2,tcPDPtr part, complex mass, complex width) { if(mass.real() < ZERO) mass = part->mass(); const complex mass2 = sqr(mass); if(width.real() < ZERO) { const tcWidthGeneratorPtr widthgen = part->widthGenerator(); width = widthgen && (iopt==2 || iopt==6 ) ? widthgen->width(*part,sqrt(p2)) : part->width(); } const Complex ii(0.,1.); complex masswidth; if(iopt==5) { return Complex(UnitRemoval::E2/p2); } else if(iopt==4) { return 1.0; } else if(p2 < ZERO) { if(iopt!=7) masswidth = ZERO; else masswidth = ii * mass * width; } else { switch (iopt) { case 1: case 2: case 7: masswidth = ii * mass * width; break; case 3: masswidth = ZERO; break; case 6: masswidth = ii * mass2 * width / sqrt(p2); return Complex(UnitRemoval::E2 * (mass2/p2) / (p2-mass2+masswidth)); default: assert( false ); return -999.999; } } return Complex(UnitRemoval::E2/(p2-mass2+masswidth)); } void VertexBase::rebind(const TranslationMap & trans) { - vector >::iterator cit; - vector::iterator cjt; - for (cit = _particles.begin(); cit != _particles.end(); ++cit) { - for (cjt = cit->begin(); cjt != cit->end(); ++cjt) { + for (auto cit = _particles.begin(); cit != _particles.end(); ++cit) { + for (auto cjt = cit->begin(); cjt != cit->end(); ++cjt) { *cjt = trans.translate(*cjt); } } - set::iterator it; set newinpart; - for (it = _inpart.begin(); it != _inpart.end(); ++it) { + for (auto it = _inpart.begin(); it != _inpart.end(); ++it) { newinpart.insert(trans.translate(*it)); } _inpart = newinpart; set newoutpart; - for (it = _outpart.begin(); it != _outpart.end(); ++it) { + for (auto it = _outpart.begin(); it != _outpart.end(); ++it) { newoutpart.insert(trans.translate(*it)); } _outpart = newoutpart; Interfaced::rebind(trans); } IVector VertexBase::getReferences() { IVector ret = Interfaced::getReferences(); - vector >::iterator cit; - vector::iterator cjt; - for (cit = _particles.begin(); cit != _particles.end(); ++cit) { - for (cjt = cit->begin(); cjt != cit->end(); ++cjt) { + for (auto cit = _particles.begin(); cit != _particles.end(); ++cit) { + for (auto cjt = cit->begin(); cjt != cit->end(); ++cjt) { ret.push_back(*cjt); } } - set::iterator it; - for (it = _inpart.begin(); - it != _inpart.end(); ++it) { + for (auto it = _inpart.begin(); it != _inpart.end(); ++it) { ret.push_back(*it); } - for (it = _outpart.begin(); - it != _outpart.end(); ++it) { + for (auto it = _outpart.begin(); it != _outpart.end(); ++it) { ret.push_back(*it); } return ret; } diff --git a/Helicity/Vertex/VertexBase.h b/Helicity/Vertex/VertexBase.h --- a/Helicity/Vertex/VertexBase.h +++ b/Helicity/Vertex/VertexBase.h @@ -1,535 +1,536 @@ // -*- C++ -*- // // VertexBase.h is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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_VertexBase_H #define ThePEG_VertexBase_H // // This is the declaration of the VertexBase class. #include #include #include #include #include "ThePEG/StandardModel/StandardModelBase.h" #include "VertexBase.fh" +#include + namespace ThePEG { namespace Helicity { /** * Namespace for naming of vertices. Each child class should extend this * with its own spin configuration. */ namespace VertexType { typedef unsigned T; /** * Undefined Enum for the Lorentz structures */ const T UNDEFINED = 0; } /** \ingroup Helicity * * The VertexBase class is the base class for all helicity amplitude * vertices. In implements the storage of the particles * which are allowed to interact at the vertex and some simple functions * which are often needed by the classes which implement the specific * vertices. * * In practice little use is made of this information and it is mainly * included for future extensions. It can also be used at the development * and debugging stage. * */ class VertexBase : public Interfaced { /** * The output operator is a friend to avoid the data being public. */ friend ostream & operator<<(ostream &, const VertexBase &); public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor for \f$n\f$-point vertices. * @param name The type of vertex * @param kine Whether the kinematic invariants should be calculated. */ VertexBase(VertexType::T name, bool kine=false); //@} 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 interfaces. */ static void Init(); public: /** * Access to the particle information */ //@{ /** * Number of different particle combinations allowed. */ unsigned int size() const { return _particles.size(); } public: /** * Is a particle allowed as an incoming particle? * @param p The ParticleData pointer */ bool isIncoming(tPDPtr p) const { return _inpart.find(p) != _inpart.end(); } /** * Is a particle allowed as an outgoing particle? * @param p The ParticleData pointer */ bool isOutgoing(tPDPtr p) const { return _outpart.find(p) != _outpart.end(); } /** * Get the list of incoming particles. */ const set & incoming() const { return _inpart; } /** * Get the list of outgoing particles. */ const set & outgoing() const { return _outpart; } /** * Get the coupling. */ Complex norm() const { return _norm; } /** * Function to search the list. * @param ilist Which list to search * @param id The PDG code to look for. */ vector search(unsigned int ilist,long id) const; /** * Function to search the list. * @param ilist Which list to search * @param id The particle to look for. */ vector search(unsigned int ilist,tcPDPtr id) const; /** * Is a given combination allowed. * @param id1 PDG code of the first particle. * @param id2 PDG code of the second particle. * @param id3 PDG code of the third particle. * @param id4 PDG code of the fourth particle. */ bool allowed(long id1, long id2, long id3, long id4 = 0) const; /** * Get name of Vertex */ VertexType::T getName() const { return _theName; } /** * Get number of lines on Vertex */ unsigned int getNpoint() const { return _npoint; } /** * Get the order in \f$g_EM\f$ */ unsigned int orderInGem() const { return _ordergEM; } /** * Get the order in \f$g_s\f$ */ unsigned int orderInGs() const { return _ordergS; } //@} public: /** * @name Calculation of the strong, electromagnetic and weak couplings */ //@{ /** * Strong coupling */ double strongCoupling(Energy2 q2) const { if(_coupopt==0) { double val = 4.0*Constants::pi*generator()->standardModel()->alphaS(q2); assert(val>=0.); return sqrt(val); } else if(_coupopt==1) return sqrt(4.0*Constants::pi*generator()->standardModel()->alphaS()); else return _gs; } /** * Electromagnetic coupling */ double electroMagneticCoupling(Energy2 q2) const { if(_coupopt==0) return sqrt(4.0*Constants::pi*generator()->standardModel()->alphaEMME(q2)); else if(_coupopt==1) return sqrt(4.0*Constants::pi*generator()->standardModel()->alphaEMMZ()); else return _ee; } /** * Weak coupling */ double weakCoupling(Energy2 q2) const { if( _coupopt == 0 ) return sqrt(4.0*Constants::pi*generator()->standardModel()->alphaEMME(q2)/ generator()->standardModel()->sin2ThetaW()); else if( _coupopt == 1 ) return sqrt(4.0*Constants::pi*generator()->standardModel()->alphaEMMZ()/ generator()->standardModel()->sin2ThetaW()); else return _ee/_sw; } double sin2ThetaW() const { if( _coupopt == 0 || _coupopt == 1) return generator()->standardModel()->sin2ThetaW(); else return sqr(_sw); } //@} public: /** * Set coupling methods */ //@{ /** * Calculate the couplings for a three point interaction. * This method is virtual and must be implemented in * classes inheriting from this. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param part1 The ParticleData pointer for the first particle. * @param part2 The ParticleData pointer for the second particle. * @param part3 The ParticleData pointer for the third particle. */ virtual void setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3)=0; /** * Calculate the couplings for a four point interaction. * This method is virtual and must be implemented in * classes inheriting from this. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param part1 The ParticleData pointer for the first particle. * @param part2 The ParticleData pointer for the second particle. * @param part3 The ParticleData pointer for the third particle. * @param part4 The ParticleData pointer for the fourth particle. */ virtual void setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2,tcPDPtr part3, tcPDPtr part4)=0; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * 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(); //@} protected: /** * Members to set-up the particles */ //@{ /** * Set up the lists of outer particles for the vertex. * @param ids A vector of PDG codes for the particles. */ void addToList(const vector & ids); /** * Set up the lists of outer particles for the three-/four-point vertex. * For small vertices, this form is much easier to use. * @param ida The PDG codes for the first set of particles. * @param idb The PDG codes for the second set of particles. * @param idc The PDG codes for the third set of particles. * @param idd The PDG codes for the fourth set of particles. */ void addToList(long ida, long idb, long idc, long idd = 0); //@} protected: /** * Members for the amplitude calculations */ //@{ /** * Set the coupling. * @param coup The coupling. */ void norm(const Complex & coup) { _norm = coup; } /** * Calculate the propagator for a diagram. * @param iopt The option for the Breit-Wigner shape * @param q2 The scale * @param part The ParticleData pointer for the off-shell particle. * @param mass The mass if not to be taken from the ParticleData object * @param width The width if not to be taken from the ParticleData object */ virtual Complex propagator(int iopt, Energy2 q2,tcPDPtr part, complex mass=-GeV, complex width=-GeV); /** * Calculate propagator multiplied by coupling. * @param iopt The option for the Breit-Wigner shape * @param q2 The scale * @param part The ParticleData pointer for the off-shell particle. * @param mass The mass if not to be taken from the ParticleData object * @param width The width if not to be taken from the ParticleData object */ Complex normPropagator(int iopt, Energy2 q2,tcPDPtr part, complex mass=-GeV, complex width=-GeV) { return _norm*propagator(iopt,q2,part,mass,width); } //@} public: /** @name Kinematic invariants for loop diagrams */ //@{ /** * Whether or not to calculate the kinematics invariants */ bool kinematics() const { return _calckinematics; } /** * Set whether or not to calculate the kinematics invariants */ void kinematics(bool kine ) { _calckinematics=kine; } /** * Calculate the kinematics for a 3-point vertex */ void calculateKinematics(const Lorentz5Momentum & p0, const Lorentz5Momentum & p1, const Lorentz5Momentum & p2) { _kine[0][0]=p0*p0; _kine[1][1]=p1*p1; _kine[2][2]=p2*p2; _kine[0][1]=p0*p1;_kine[1][0]=_kine[0][1]; _kine[0][2]=p0*p2;_kine[2][0]=_kine[0][2]; _kine[1][2]=p1*p2;_kine[2][1]=_kine[1][2]; } /** * Calculate the kinematics for a 4-point vertex */ void calculateKinematics(const Lorentz5Momentum & p0, const Lorentz5Momentum & p1, const Lorentz5Momentum & p2, const Lorentz5Momentum & p3) { _kine[0][0]=p0*p0; _kine[1][1]=p1*p1; _kine[2][2]=p2*p2; _kine[3][3]=p3*p3; _kine[0][1]=p0*p1;_kine[1][0]=_kine[0][1]; _kine[0][2]=p0*p2;_kine[2][0]=_kine[0][2]; _kine[0][3]=p0*p3;_kine[3][0]=_kine[0][3]; _kine[1][2]=p1*p2;_kine[2][1]=_kine[1][2]; _kine[1][3]=p1*p3;_kine[3][1]=_kine[1][3]; _kine[2][3]=p2*p3;_kine[3][2]=_kine[2][3]; } /** * Calculate the kinematics for a n-point vertex */ void calculateKinematics(const vector & p) { - unsigned int ix,iy; - for(ix=0;ix initVertexBase; /** * Private and non-existent assignment operator. */ VertexBase & operator=(const VertexBase &); private: /** * Storage of the particles. */ //@{ /** * Particles interacting at the vertex */ vector > _particles; /** * Number of particles at the vertex */ unsigned int _npoint; /** * ParticleData pointers for the allowed incoming particles. */ set _inpart; /** * ParticleData pointers for the allowed outgoing particles. */ set _outpart; //@} /** * The overall coupling. */ Complex _norm; /** * Whether or not to calculate the kinematic invariants for the vertex */ bool _calckinematics; /** * Kinematica quantities needed for loop vertices */ - vector > _kine; + std::array,5> _kine; /** * Name of vertex */ VertexType::T _theName; /** * Order of vertex in \f$g_EM\f$ */ unsigned int _ordergEM; /** * Order of vertex in \f$g_s\f$ */ unsigned int _ordergS; /** * option for the coupling */ unsigned int _coupopt; /** * Fixed value of strong coupling to use */ double _gs; /** * Fixed value of the electromagentic coupling to use */ double _ee; /** * Fixed value of \f$\sin\theta_W\f$ to use */ double _sw; }; /** * Output the information on the vertex. */ ostream & operator<<(ostream &, const VertexBase &); } } #endif /* ThePEG_VertexBase_H */ diff --git a/Helicity/WaveFunction/RSSpinorBarWaveFunction.cc b/Helicity/WaveFunction/RSSpinorBarWaveFunction.cc --- a/Helicity/WaveFunction/RSSpinorBarWaveFunction.cc +++ b/Helicity/WaveFunction/RSSpinorBarWaveFunction.cc @@ -1,330 +1,330 @@ // -*- C++ -*- // // RSSpinorBarWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 RSSpinorBarWaveFunction class. // #include "RSSpinorBarWaveFunction.h" using namespace ThePEG; using namespace ThePEG::Helicity; // calculate the Wavefunction void RSSpinorBarWaveFunction::calculateWaveFunction(unsigned int ihel) { Complex ii(0.,1.); LorentzRSSpinorBar news; - if(direction()==incoming) news=LorentzRSSpinorBar(u_spinortype); - else news=LorentzRSSpinorBar(v_spinortype); + if(direction()==incoming) news=LorentzRSSpinorBar(SpinorType::u); + else news=LorentzRSSpinorBar(SpinorType::v); unsigned int ix,iy; assert(direction()!=intermediate); assert(ihel<=3); // only two valid helicities in massless case assert( mass()>ZERO || (ihel == 0 || ihel == 3 ) ); // extract the momentum components // compute the normal spinors to construct the RS spinor Complex hel_wf[2][2]; if(direction()==incoming) { // the + spinor hel_wf[0][0] = 0.; hel_wf[0][1] = 1.; // the - spinor hel_wf[1][0] = 1.; hel_wf[1][1] = 0.; } else { // the + spinor hel_wf[0][0] = 1.; hel_wf[0][1] = 0.; // the - spinor hel_wf[1][0] = 0.; hel_wf[1][1] = 1.; } double fact = direction()==incoming ? 1. : -1.; Energy pmm=mass(),pee=fact*e(); Energy pabs = sqrt(sqr(px())+sqr(py())+sqr(pz())); SqrtEnergy eplusp = sqrt(pee+pabs); SqrtEnergy eminusp = ( pmm == ZERO ) ? ZERO : pmm/eplusp; SqrtEnergy upper[2],lower[2]; if(direction()==incoming) { upper[0] = eminusp; lower[0] =-eplusp ; upper[1] =-eplusp ; lower[1] = eminusp; } else { upper[0] = eplusp ; lower[0] = eminusp; upper[1] = eminusp; lower[1] = eplusp ; } // now construct the spinors complex spinor[2][4]; for(ix=0;ix<2;++ix) { spinor[ix][0] = upper[ix]*hel_wf[ix][0]; spinor[ix][1] = upper[ix]*hel_wf[ix][1]; spinor[ix][2] = lower[ix]*hel_wf[ix][0]; spinor[ix][3] = lower[ix]*hel_wf[ix][1]; } // compute the polarization vectors to construct the RS spinor Complex vec[3][4]; double ort = sqrt(0.5); double r1 = ( pmm == ZERO ) ? 0. : double(pee /pmm); double r2 = ( pmm == ZERO ) ? 0. : double(pabs/pmm); if(direction()==incoming) { vec[0][0] = ort; vec[0][1] = ort*ii; vec[0][2] = 0.; vec[0][3] = 0.; vec[1][0] = 0.; vec[1][1] = 0.; vec[1][2] =-r1; vec[1][3] =-r2; vec[2][0] =-ort; vec[2][1] = ort*ii; vec[2][2] = 0.; vec[2][3] = 0.; } else { vec[0][0] =-ort; vec[0][1] = ort*ii; vec[0][2] = 0.; vec[0][3] = 0.; vec[1][0] = 0.; vec[1][1] = 0.; vec[1][2] = r1; vec[1][3] = r2; vec[2][0] = ort; vec[2][1] = ort*ii; vec[2][2] = 0.; vec[2][3] = 0.; } // now we can put the bits together to compute the RS spinor double or3(sqrt(1./3.)),tor3(sqrt(2./3.)); if(ihel==3) { for(ix=0;ix<4;++ix) for(iy=0;iy<4;++iy) news(ix,iy)=UnitRemoval::InvSqrtE*vec[0][ix]*spinor[0][iy]; } else if(ihel==2) { for(ix=0;ix<4;++ix) for(iy=0;iy<4;++iy) news(ix,iy)=UnitRemoval::InvSqrtE* (or3*vec[0][ix]*spinor[1][iy]+tor3*vec[1][ix]*spinor[0][iy]); } else if(ihel==1) { for(ix=0;ix<4;++ix) for(iy=0;iy<4;++iy) news(ix,iy)=UnitRemoval::InvSqrtE* (or3*vec[2][ix]*spinor[0][iy]+tor3*vec[1][ix]*spinor[1][iy]); } else if(ihel==0) { for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { news(ix,iy)=UnitRemoval::InvSqrtE*(vec[2][ix]*spinor[1][iy]); } } } // spinor is currently along the z axis, rotate so in right direction if(pabs/pmm>1e-8) { Axis axis; axis.setX(fact*momentum().x()/pabs); axis.setY(fact*momentum().y()/pabs); axis.setZ(fact*momentum().z()/pabs); double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if(sinth>1e-8) { LorentzRotation rot; rot.setRotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); _wf = news.transform(rot); } else if (axis.z()<0.) { LorentzRotation rot; rot.setRotateX(Constants::pi); _wf = news.transform(rot); } else { _wf = news; } } else { _wf=news; } } void RSSpinorBarWaveFunction:: calculateWaveFunctions(vector > & waves, tPPtr particle,Direction dir) { tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(4); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<4;++ix) waves[ix] = inspin->getProductionBasisState(ix).bar(); } else { inspin->decay(); for(unsigned int ix=0;ix<4;++ix) waves[ix] = inspin->getDecayBasisState(ix).bar(); } } // do the calculation else { assert(!particle->spinInfo()); RSSpinorBarWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<4;++ix) { wave.reset(ix); waves[ix] = wave.dimensionedWf(); } } } void RSSpinorBarWaveFunction:: calculateWaveFunctions(vector & waves, tPPtr particle,Direction dir) { tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(4); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<4;++ix) waves[ix] = RSSpinorBarWaveFunction(particle, inspin->getProductionBasisState(ix).bar(), dir); } else { inspin->decay(); for(unsigned int ix=0;ix<4;++ix) waves[ix] = RSSpinorBarWaveFunction(particle, inspin->getDecayBasisState(ix).bar(), dir); } } // do the calculation else { assert(!particle->spinInfo()); RSSpinorBarWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<4;++ix) { wave.reset(ix); waves[ix] = wave; } } } void RSSpinorBarWaveFunction:: calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction dir) { tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(4); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<4;++ix) waves[ix] = inspin->getProductionBasisState(ix).bar(); rho = RhoDMatrix(PDT::Spin3Half); } else { inspin->decay(); for(unsigned int ix=0;ix<4;++ix) waves[ix] = inspin->getDecayBasisState(ix).bar(); rho = inspin->rhoMatrix(); } } // do the calculation else { assert(!particle->spinInfo()); RSSpinorBarWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<4;++ix) { wave.reset(ix); waves[ix] = wave.dimensionedWf(); } rho = RhoDMatrix(PDT::Spin3Half); } } void RSSpinorBarWaveFunction:: calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction dir) { tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(4); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<4;++ix) waves[ix] = RSSpinorBarWaveFunction(particle, inspin->getProductionBasisState(ix).bar(), dir); rho = RhoDMatrix(PDT::Spin3Half); } else { inspin->decay(); for(unsigned int ix=0;ix<4;++ix) waves[ix] = RSSpinorBarWaveFunction(particle, inspin->getDecayBasisState(ix).bar(), dir); rho = inspin->rhoMatrix(); } } // do the calculation else { assert(!particle->spinInfo()); RSSpinorBarWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<4;++ix) { wave.reset(ix); waves[ix] = wave; } rho = RhoDMatrix(PDT::Spin3Half); } } void RSSpinorBarWaveFunction:: constructSpinInfo(const vector > & waves, tPPtr particle,Direction dir, bool time) { assert(waves.size()==4); tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<4;++ix) if(dir==outgoing) inspin->setBasisState(ix,waves[ix].bar()); else inspin->setDecayState(ix,waves[ix].bar()); } else { RSFermionSpinPtr temp = new_ptr(RSFermionSpinInfo(particle->momentum(),time)); particle->spinInfo(temp); for(unsigned int ix=0;ix<4;++ix) if(dir==outgoing) temp->setBasisState(ix,waves[ix].bar()); else temp->setDecayState(ix,waves[ix].bar()); } } void RSSpinorBarWaveFunction:: constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time) { assert(waves.size()==4); tRSFermionSpinPtr inspin = !part->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(part->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<4;++ix) if (dir==outgoing) inspin->setBasisState(ix,waves[ix].dimensionedWf().bar()); else inspin->setDecayState(ix,waves[ix].dimensionedWf().bar()); } else { RSFermionSpinPtr temp = new_ptr(RSFermionSpinInfo(part->momentum(),time)); part->spinInfo(temp); for(unsigned int ix=0;ix<4;++ix) if(dir==outgoing) temp->setBasisState(ix,waves[ix].dimensionedWf().bar()); else temp->setDecayState(ix,waves[ix].dimensionedWf().bar()); } } diff --git a/Helicity/WaveFunction/RSSpinorWaveFunction.cc b/Helicity/WaveFunction/RSSpinorWaveFunction.cc --- a/Helicity/WaveFunction/RSSpinorWaveFunction.cc +++ b/Helicity/WaveFunction/RSSpinorWaveFunction.cc @@ -1,328 +1,328 @@ // -*- C++ -*- // // RSSpinorWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 RSSpinorWaveFunction class. // #include "RSSpinorWaveFunction.h" using namespace ThePEG; using namespace ThePEG::Helicity; // calculate the Wavefunction void RSSpinorWaveFunction::calculateWaveFunction(unsigned int ihel) { LorentzRSSpinor news; if(direction()==incoming) - news=LorentzRSSpinor(u_spinortype); + news=LorentzRSSpinor(SpinorType::u); else - news=LorentzRSSpinor(v_spinortype); + news=LorentzRSSpinor(SpinorType::v); unsigned int ix,iy; // check helicity and type assert(direction()!=intermediate); assert(ihel<=3); // massive // only two valid helicities in massless case assert( mass()>ZERO || ( ihel == 0 || ihel==3 ) ); // extract the momentum components // compute the normal spinors to construct the RS spinor Complex hel_wf[2][2]; if(direction()==incoming) { // the + spinor hel_wf[0][0] = 1.; hel_wf[0][1] = 0.; // the - spinor hel_wf[1][0] = 0.; hel_wf[1][1] = 1.; } else { // the + spinor hel_wf[0][0] = 0.; hel_wf[0][1] = 1.; // the - spinor hel_wf[1][0] = 1.; hel_wf[1][1] = 0.; } // prefactors double fact = direction()==incoming ? 1. : -1.; Energy pmm=mass(),pee=fact*e(); Energy pabs = sqrt(sqr(px())+sqr(py())+sqr(pz())); SqrtEnergy eplusp = sqrt(pee+pabs); SqrtEnergy eminusp = ( pmm == ZERO ) ? ZERO : pmm/eplusp; SqrtEnergy upper[2],lower[2]; if(direction()==incoming) { upper[0] = eminusp; lower[0] = eplusp ; upper[1] = eplusp ; lower[1] = eminusp; } else { upper[0] =-eplusp ; lower[0] = eminusp; upper[1] = eminusp; lower[1] =-eplusp ; } // now construct the spinors complex spinor[2][4]; for(ix=0;ix<2;++ix) { spinor[ix][0] = upper[ix]*hel_wf[ix][0]; spinor[ix][1] = upper[ix]*hel_wf[ix][1]; spinor[ix][2] = lower[ix]*hel_wf[ix][0]; spinor[ix][3] = lower[ix]*hel_wf[ix][1]; } // compute the polarization vectors to construct the RS spinor Complex vec[3][4],ii(0.,1.); double ort = sqrt(0.5); double r1 = ( pmm == ZERO ) ? 0. : double(pee /pmm); double r2 = ( pmm == ZERO ) ? 0. : double(pabs/pmm); if(direction()==incoming) { vec[0][0] =-ort; vec[0][1] =-ort*ii; vec[0][2] = 0.; vec[0][3] = 0.; vec[1][0] = 0.; vec[1][1] = 0.; vec[1][2] = r1; vec[1][3] = r2; vec[2][0] = ort; vec[2][1] =-ort*ii; vec[2][2] = 0.; vec[2][3] = 0.; } else { vec[0][0] = ort; vec[0][1] =-ort*ii; vec[0][2] = 0.; vec[0][3] = 0.; vec[1][0] = 0.; vec[1][1] = 0.; vec[1][2] =-r1; vec[1][3] =-r2; vec[2][0] =-ort; vec[2][1] =-ort*ii; vec[2][2] = 0.; vec[2][3] = 0.; } // now we can put the bits together to compute the RS spinor double or3(sqrt(1./3.)),tor3(sqrt(2./3.)); if(ihel==3) { for(ix=0;ix<4;++ix) for(iy=0;iy<4;++iy) news(ix,iy)=UnitRemoval::InvSqrtE*vec[0][ix]*spinor[0][iy]; } else if(ihel==2) { for(ix=0;ix<4;++ix) for(iy=0;iy<4;++iy) news(ix,iy)=UnitRemoval::InvSqrtE* (or3*vec[0][ix]*spinor[1][iy]+tor3*vec[1][ix]*spinor[0][iy]); } else if(ihel==1) { for(ix=0;ix<4;++ix) for(iy=0;iy<4;++iy) news(ix,iy)=UnitRemoval::InvSqrtE* (or3*vec[2][ix]*spinor[0][iy]+tor3*vec[1][ix]*spinor[1][iy]); } else if(ihel==0) { for(ix=0;ix<4;++ix) for(iy=0;iy<4;++iy) news(ix,iy)=UnitRemoval::InvSqrtE*vec[2][ix]*spinor[1][iy]; } // spinor is currently along the z axis, rotate so in right direction if(pabs/pmm>1e-8) { Axis axis; axis.setX(fact*momentum().x()/pabs); axis.setY(fact*momentum().y()/pabs); axis.setZ(fact*momentum().z()/pabs); double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); if(sinth>1e-8) { LorentzRotation rot; rot.setRotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); _wf= news.transform(rot); } else if (axis.z()<0.) { LorentzRotation rot; rot.setRotateX(Constants::pi); _wf= news.transform(rot); } else { _wf = news; } } else { _wf=news; } } void RSSpinorWaveFunction:: calculateWaveFunctions(vector > & waves, tPPtr particle,Direction dir) { tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(4); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<4;++ix) waves[ix] = inspin->getProductionBasisState(ix); } else { inspin->decay(); for(unsigned int ix=0;ix<4;++ix) waves[ix] = inspin->getDecayBasisState(ix); } } // do the calculation else { assert(!particle->spinInfo()); RSSpinorWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<4;++ix) { wave.reset(ix); waves[ix] = wave.dimensionedWf(); } } } void RSSpinorWaveFunction:: calculateWaveFunctions(vector & waves, tPPtr particle,Direction dir) { tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(4); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<4;++ix) waves[ix] = RSSpinorWaveFunction(particle, inspin->getProductionBasisState(ix),dir); } else { inspin->decay(); for(unsigned int ix=0;ix<4;++ix) waves[ix] = RSSpinorWaveFunction(particle, inspin->getDecayBasisState(ix),dir); } } // do the calculation else { assert(!particle->spinInfo()); RSSpinorWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<4;++ix) { wave.reset(ix); waves[ix] = wave; } } } void RSSpinorWaveFunction:: calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction dir) { tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(4); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<4;++ix) waves[ix] = inspin->getProductionBasisState(ix); rho = RhoDMatrix(PDT::Spin3Half); } else { inspin->decay(); for(unsigned int ix=0;ix<4;++ix) waves[ix] = inspin->getDecayBasisState(ix); rho = inspin->rhoMatrix(); } } // do the calculation else { assert(!particle->spinInfo()); RSSpinorWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<4;++ix) { wave.reset(ix); waves[ix] = wave.dimensionedWf(); } rho = RhoDMatrix(PDT::Spin3Half); } } void RSSpinorWaveFunction:: calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction dir) { tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(4); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<4;++ix) waves[ix] = RSSpinorWaveFunction(particle, inspin->getProductionBasisState(ix),dir); rho = RhoDMatrix(PDT::Spin3Half); } else { inspin->decay(); for(unsigned int ix=0;ix<4;++ix) waves[ix] = RSSpinorWaveFunction(particle, inspin->getDecayBasisState(ix),dir); rho = inspin->rhoMatrix(); } } // do the calculation else { assert(!particle->spinInfo()); RSSpinorWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<4;++ix) { wave.reset(ix); waves[ix] = wave; } rho = RhoDMatrix(PDT::Spin3Half); } } void RSSpinorWaveFunction:: constructSpinInfo(const vector > & waves, tPPtr particle,Direction dir,bool time) { assert(waves.size()==4); tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<4;++ix) if(dir==outgoing) inspin->setBasisState(ix,waves[ix]); else inspin->setDecayState(ix,waves[ix]); } else { RSFermionSpinPtr temp = new_ptr(RSFermionSpinInfo(particle->momentum(),time)); particle->spinInfo(temp); for(unsigned int ix=0;ix<4;++ix) if(dir==outgoing) temp->setBasisState(ix,waves[ix]); else temp->setDecayState(ix,waves[ix]); } } void RSSpinorWaveFunction:: constructSpinInfo(const vector & waves, tPPtr particle,Direction dir,bool time) { assert(waves.size()==4); tRSFermionSpinPtr inspin = !particle->spinInfo() ? tRSFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<4;++ix) if(dir==outgoing) inspin->setBasisState(ix,waves[ix].dimensionedWf()); else inspin->setDecayState(ix,waves[ix].dimensionedWf()); } else { RSFermionSpinPtr temp = new_ptr(RSFermionSpinInfo(particle->momentum(),time)); particle->spinInfo(temp); for(unsigned int ix=0;ix<4;++ix) if(dir==outgoing) temp->setBasisState(ix,waves[ix].dimensionedWf()); else temp->setDecayState(ix,waves[ix].dimensionedWf()); } } diff --git a/Helicity/WaveFunction/SpinorBarWaveFunction.cc b/Helicity/WaveFunction/SpinorBarWaveFunction.cc --- a/Helicity/WaveFunction/SpinorBarWaveFunction.cc +++ b/Helicity/WaveFunction/SpinorBarWaveFunction.cc @@ -1,340 +1,343 @@ // -*- C++ -*- // // SpinorBarWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 SpinorBarWaveFunction class. // // Author: Peter Richardson // #include "SpinorBarWaveFunction.h" #include "SpinorWaveFunction.h" using namespace ThePEG; using namespace Helicity; // calculate the Wavefunction void SpinorBarWaveFunction::calculateWaveFunction(unsigned int ihel) { Direction dir=direction(); if(dir==intermediate) ThePEG::Helicity::HelicityConsistencyError() << "In SpinorBarWaveFunction::calcluateWaveFunction " << "particle must be incoming or outgoing not intermediate" << Exception::abortnow; // check ihelicity is O.K. if(ihel>1) ThePEG::Helicity::HelicityConsistencyError() << "Invalid Helicity = " << ihel << " requested for SpinorBar" << Exception::abortnow; // extract the momentum components double fact = dir==incoming ? 1. : -1.; Energy ppx=fact*px(),ppy=fact*py(),ppz=fact*pz(),pee=fact*e(),pmm=mass(); // define and calculate some kinematic quantities Energy2 ptran2 = ppx*ppx+ppy*ppy; Energy pabs = sqrt(ptran2+ppz*ppz); Energy ptran = sqrt(ptran2); // first need to evalulate the 2-component helicity spinors // this is the same regardless of which definition of the spinors // we are using Complex hel_wf[2]; // compute the + spinor for + helicty particles and - helicity antiparticles if((dir==outgoing && ihel== 1) || (dir==incoming && ihel==0)) { // no transverse momentum if(ptran==ZERO) { if(ppz>=ZERO) { hel_wf[0] = 1; hel_wf[1] = 0; } else { hel_wf[0] = 0; hel_wf[1] = 1; } } else { InvSqrtEnergy denominator = 1./sqrt(2.*pabs); SqrtEnergy rtppluspz = (ppz>=ZERO) ? sqrt(pabs+ppz) : ptran/sqrt(pabs-ppz); hel_wf[0] = denominator*rtppluspz; hel_wf[1] = denominator/rtppluspz*complex(ppx,-ppy); } } // compute the - spinor for - helicty particles and + helicity antiparticles else { // no transverse momentum if(ptran==ZERO) { if(ppz>=ZERO) { hel_wf[0] = 0; hel_wf[1] = 1; } // transverse momentum else { hel_wf[0] = -1; hel_wf[1] = 0; } } else { InvSqrtEnergy denominator = 1./sqrt(2.*pabs); SqrtEnergy rtppluspz = (ppz>=ZERO) ? sqrt(pabs+ppz) : ptran/sqrt(pabs-ppz); hel_wf[0] = denominator/rtppluspz*complex(-ppx,-ppy); hel_wf[1] = denominator*rtppluspz; } } SqrtEnergy upper, lower; SqrtEnergy eplusp = sqrt(max(pee+pabs,ZERO)); SqrtEnergy eminusp = ( pmm!=ZERO ) ? pmm/eplusp : ZERO; // set up the coefficients for the different cases if(dir==outgoing) { if(ihel==1) { upper = eplusp; lower = eminusp; } else { upper = eminusp; lower = eplusp; } } else { if(ihel==1) { upper = eminusp; lower = -eplusp; } else { upper =-eplusp; lower = eminusp; } } // now finally we can construct the spinors - _wf = LorentzSpinorBar((dir==incoming) ? v_spinortype : u_spinortype); + _wf = LorentzSpinorBar((dir==incoming) ? SpinorType::v : SpinorType::u); _wf[0] = upper*hel_wf[0]*UnitRemoval::InvSqrtE; _wf[1] = upper*hel_wf[1]*UnitRemoval::InvSqrtE; _wf[2] = lower*hel_wf[0]*UnitRemoval::InvSqrtE; _wf[3] = lower*hel_wf[1]*UnitRemoval::InvSqrtE; } void SpinorBarWaveFunction::conjugate() { _wf=_wf.conjugate(); } SpinorWaveFunction SpinorBarWaveFunction::bar() { Lorentz5Momentum p = momentum(); if(direction()==outgoing) p *= -1.; tcPDPtr ptemp = particle(); if(direction()==incoming&&particle()->CC()) ptemp = particle()->CC(); return SpinorWaveFunction(p,ptemp,_wf.bar(),direction()); } void SpinorBarWaveFunction:: calculateWaveFunctions(vector > & waves, tPPtr particle,Direction dir) { tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(2); // spin info object exists if(inspin) { if(dir==outgoing) { waves[0] = inspin->getProductionBasisState(0).bar(); waves[1] = inspin->getProductionBasisState(1).bar(); } else { inspin->decay(); - if( (particle->id()>0&&inspin->getDecayBasisState(0).Type()!=u_spinortype) || - (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=v_spinortype)) { + if( (particle->id()>0&&inspin->getDecayBasisState(0).Type()!=SpinorType::u) || + (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=SpinorType::v)) { waves[0] = inspin->getDecayBasisState(0).conjugate().bar(); waves[1] = inspin->getDecayBasisState(1).conjugate().bar(); } else { waves[0] = inspin->getDecayBasisState(0).bar(); waves[1] = inspin->getDecayBasisState(1).bar(); } } } // do the calculation else { assert(!particle->spinInfo()); SpinorBarWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); waves[ix] = wave.dimensionedWave(); } } } void SpinorBarWaveFunction:: calculateWaveFunctions(vector & waves, tPPtr particle,Direction dir) { tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(2); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorBarWaveFunction(particle, inspin->getProductionBasisState(ix).bar(), dir); } else { inspin->decay(); - if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=u_spinortype) || - (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=v_spinortype)) { + if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=SpinorType::u) || + (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=SpinorType::v)) { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorBarWaveFunction(particle, inspin->getDecayBasisState(ix).conjugate().bar(),dir); } else { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorBarWaveFunction(particle, inspin->getDecayBasisState(ix).bar(),dir); } } } // do the calculation else { assert(!particle->spinInfo()); SpinorBarWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); waves[ix] = wave; } } } void SpinorBarWaveFunction:: calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction dir) { tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(2); // spin info object exists if(inspin) { if(dir==outgoing) { waves[0] = inspin->getProductionBasisState(0).bar(); waves[1] = inspin->getProductionBasisState(1).bar(); rho = RhoDMatrix(PDT::Spin1Half); } else { inspin->decay(); - if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=u_spinortype) || - (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=v_spinortype)) { + if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=SpinorType::u) || + (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=SpinorType::v)) { waves[0] = inspin->getDecayBasisState(0).conjugate().bar(); waves[1] = inspin->getDecayBasisState(1).conjugate().bar(); } else { waves[0] = inspin->getDecayBasisState(0).bar(); waves[1] = inspin->getDecayBasisState(1).bar(); } rho = inspin->rhoMatrix(); } } // do the calculation else { assert(!particle->spinInfo()); SpinorBarWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); waves[ix] = wave.dimensionedWave(); } rho = RhoDMatrix(PDT::Spin1Half); } } void SpinorBarWaveFunction:: calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction dir) { tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(2); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorBarWaveFunction(particle, inspin->getProductionBasisState(ix).bar(), dir); rho = RhoDMatrix(PDT::Spin1Half); } else { inspin->decay(); - if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=u_spinortype) || - (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=v_spinortype)) { + if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=SpinorType::u) || + (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=SpinorType::v)) { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorBarWaveFunction(particle, inspin->getDecayBasisState(ix).conjugate().bar(),dir); } else { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorBarWaveFunction(particle, inspin->getDecayBasisState(ix).bar(),dir); } rho = inspin->rhoMatrix(); } } // do the calculation else { assert(!particle->spinInfo()); SpinorBarWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); waves[ix] = wave; } rho = RhoDMatrix(PDT::Spin1Half); } } void SpinorBarWaveFunction:: constructSpinInfo(const vector > & waves, tPPtr part,Direction dir, bool time) { assert(waves.size()==2); tFermionSpinPtr inspin = !part->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(part->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<2;++ix) { - if(( dir == outgoing && time) || + if(( dir == outgoing && time) || ( dir == incoming && !time)) inspin->setBasisState(ix,waves[ix].bar()); else inspin->setDecayState(ix,waves[ix].bar()); } } else { FermionSpinPtr temp = new_ptr(FermionSpinInfo(part->momentum(),time)); part->spinInfo(temp); for(unsigned int ix=0;ix<2;++ix) { - if(( dir == outgoing && time) || + if(( dir == outgoing && time) || ( dir == incoming && !time)) temp->setBasisState(ix,waves[ix].bar()); else temp->setDecayState(ix,waves[ix].bar()); } } } void SpinorBarWaveFunction:: constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time) { assert(waves.size()==2); tFermionSpinPtr inspin = !part->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(part->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<2;++ix) - if (dir==outgoing) inspin->setBasisState(ix,waves[ix].dimensionedWf().bar()); - else inspin->setDecayState(ix,waves[ix].dimensionedWf().bar()); + if(( dir == outgoing && time) || + ( dir == incoming && !time)) + inspin->setBasisState(ix,waves[ix].dimensionedWf().bar()); + else + inspin->setDecayState(ix,waves[ix].dimensionedWf().bar()); } else { FermionSpinPtr temp = new_ptr(FermionSpinInfo(part->momentum(),time)); part->spinInfo(temp); for(unsigned int ix=0;ix<2;++ix) { - if(( dir == outgoing && time) || + if(( dir == outgoing && time) || ( dir == incoming && !time)) temp->setBasisState(ix,waves[ix].dimensionedWf().bar()); else temp->setDecayState(ix,waves[ix].dimensionedWf().bar()); } } } diff --git a/Helicity/WaveFunction/SpinorWaveFunction.cc b/Helicity/WaveFunction/SpinorWaveFunction.cc --- a/Helicity/WaveFunction/SpinorWaveFunction.cc +++ b/Helicity/WaveFunction/SpinorWaveFunction.cc @@ -1,340 +1,340 @@ // -*- C++ -*- // // SpinorWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 SpinorWaveFunction class. // // Author: Peter Richardson // #include "SpinorWaveFunction.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "SpinorBarWaveFunction.h" using namespace ThePEG; using namespace Helicity; // calculate the Wavefunction void SpinorWaveFunction::calculateWaveFunction(unsigned int ihel) { // check helicity is O.K. Direction dir = direction(); if(dir==intermediate) throw ThePEG::Helicity::HelicityConsistencyError() << "In SpinorWaveFunction::calcluateWaveFunction " << "particle must be incoming or outgoing not intermediate" << Exception::abortnow; if(ihel>1) throw ThePEG::Helicity::HelicityConsistencyError() << "Invalid Helicity = " << ihel << " requested for Spinor" << Exception::abortnow; // extract the momentum components double fact=-1.; if(dir==incoming){fact=1.;} Energy ppx=fact*px(),ppy=fact*py(),ppz=fact*pz(),pee=fact*e(),pmm=mass(); // define and calculate some kinematic quantities Energy2 ptran2 = ppx*ppx+ppy*ppy; Energy pabs = sqrt(ptran2+ppz*ppz); Energy ptran = sqrt(ptran2); // first need to evalulate the 2-component helicity spinors // this is the same regardless of which definition of the spinors // we are using complex hel_wf[2]; // compute the + spinor for + helicty particles and - helicity antiparticles if((dir==incoming && ihel== 1) || (dir==outgoing && ihel==0)) { // no transverse momentum if(ptran==ZERO) { if(ppz>=ZERO) { hel_wf[0] = 1; hel_wf[1] = 0; } else { hel_wf[0] = 0; hel_wf[1] = 1; } } else { InvSqrtEnergy denominator = 1./sqrt(2.*pabs); SqrtEnergy rtppluspz = (ppz>=ZERO) ? sqrt(pabs+ppz) : ptran/sqrt(pabs-ppz); hel_wf[0] = denominator*rtppluspz; hel_wf[1] = denominator/rtppluspz*complex(ppx,ppy); } } // compute the - spinor for - helicty particles and + helicity antiparticles else { // no transverse momentum if(ptran==ZERO) { if(ppz>=ZERO) { hel_wf[0] = 0; hel_wf[1] = 1; } // transverse momentum else { hel_wf[0] = -1; hel_wf[1] = 0; } } else { InvSqrtEnergy denominator = 1./sqrt(2.*pabs); SqrtEnergy rtppluspz = (ppz>=ZERO) ? sqrt(pabs+ppz) : ptran/sqrt(pabs-ppz); hel_wf[0] = denominator/rtppluspz*complex(-ppx,ppy); hel_wf[1] = denominator*rtppluspz; } } SqrtEnergy upper,lower; SqrtEnergy eplusp = sqrt(max(pee+pabs,ZERO)); SqrtEnergy eminusp = ( pmm != ZERO ) ? pmm/eplusp : ZERO; // set up the coefficients for the different cases if(dir==incoming) { if(ihel==1) { upper = eminusp; lower = eplusp; } else { upper = eplusp; lower = eminusp; } } else { if(ihel==1) { upper = -eplusp; lower = eminusp; } else { upper = eminusp; lower =-eplusp; } } // now finally we can construct the spinors - _wf = LorentzSpinor( (dir==incoming) ? u_spinortype : v_spinortype); + _wf = LorentzSpinor( (dir==incoming) ? SpinorType::u : SpinorType::v); _wf[0]=upper*hel_wf[0]*UnitRemoval::InvSqrtE; _wf[1]=upper*hel_wf[1]*UnitRemoval::InvSqrtE; _wf[2]=lower*hel_wf[0]*UnitRemoval::InvSqrtE; _wf[3]=lower*hel_wf[1]*UnitRemoval::InvSqrtE; } SpinorBarWaveFunction SpinorWaveFunction::bar() { Lorentz5Momentum p = momentum(); if(direction()==outgoing) p *= -1.; tcPDPtr ptemp = particle(); if(direction()==incoming&&particle()->CC()) ptemp = particle()->CC(); return SpinorBarWaveFunction(p,ptemp,_wf.bar(),direction()); } void SpinorWaveFunction:: calculateWaveFunctions(vector > & waves, tPPtr particle,Direction dir) { tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(2); // spin info object exists if(inspin) { if(dir==outgoing) { waves[0] = inspin->getProductionBasisState(0); waves[1] = inspin->getProductionBasisState(1); } else { inspin->decay(); - if( (particle->id()>0&&inspin->getDecayBasisState(0).Type()!=u_spinortype) || - (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=v_spinortype)) { + if( (particle->id()>0&&inspin->getDecayBasisState(0).Type()!=SpinorType::u) || + (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=SpinorType::v)) { waves[0] = inspin->getDecayBasisState(0).conjugate(); waves[1] = inspin->getDecayBasisState(1).conjugate(); } else { waves[0] = inspin->getDecayBasisState(0); waves[1] = inspin->getDecayBasisState(1); } } } // do the calculation else { assert(!particle->spinInfo()); SpinorWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); waves[ix] = wave.dimensionedWave(); } } } void SpinorWaveFunction:: calculateWaveFunctions(vector & waves, tPPtr particle,Direction dir) { tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(2); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorWaveFunction(particle, inspin->getProductionBasisState(ix),dir); } else { inspin->decay(); - if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=u_spinortype) || - (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=v_spinortype)) { + if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=SpinorType::u) || + (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=SpinorType::v)) { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorWaveFunction(particle, inspin->getDecayBasisState(ix).conjugate(),dir); } else { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorWaveFunction(particle, inspin->getDecayBasisState(ix),dir); } } } // do the calculation else { assert(!particle->spinInfo()); SpinorWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); waves[ix] = wave; } } } void SpinorWaveFunction:: calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction dir) { tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(2); // spin info object exists if(inspin) { if(dir==outgoing) { waves[0] = inspin->getProductionBasisState(0); waves[1] = inspin->getProductionBasisState(1); rho = RhoDMatrix(PDT::Spin1Half); } else { inspin->decay(); - if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=u_spinortype) || - (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=v_spinortype)) { + if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=SpinorType::u) || + (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=SpinorType::v)) { waves[0] = inspin->getDecayBasisState(0).conjugate(); waves[1] = inspin->getDecayBasisState(1).conjugate(); } else { waves[0] = inspin->getDecayBasisState(0); waves[1] = inspin->getDecayBasisState(1); } rho = inspin->rhoMatrix(); } } // do the calculation else { assert(!particle->spinInfo()); SpinorWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); waves[ix] = wave.dimensionedWave(); } rho = RhoDMatrix(PDT::Spin1Half); } } void SpinorWaveFunction:: calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction dir) { tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(2); // spin info object exists if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorWaveFunction(particle, inspin->getProductionBasisState(ix),dir); rho = RhoDMatrix(PDT::Spin1Half); } else { inspin->decay(); - if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=u_spinortype) || - (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=v_spinortype)) { + if((particle->id()>0&&inspin->getDecayBasisState(0).Type()!=SpinorType::u) || + (particle->id()<0&&inspin->getDecayBasisState(0).Type()!=SpinorType::v)) { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorWaveFunction(particle, inspin->getDecayBasisState(ix).conjugate(),dir); } else { for(unsigned int ix=0;ix<2;++ix) waves[ix] = SpinorWaveFunction(particle, inspin->getDecayBasisState(ix),dir); } rho = inspin->rhoMatrix(); } } // do the calculation else { assert(!particle->spinInfo()); SpinorWaveFunction wave(particle->momentum(),particle->dataPtr(),dir); for(unsigned int ix=0;ix<2;++ix) { wave.reset(ix); waves[ix] = wave; } rho = RhoDMatrix(PDT::Spin1Half); } } void SpinorWaveFunction:: constructSpinInfo(const vector > & waves, tPPtr particle,Direction dir,bool time) { assert(waves.size()==2); tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<2;++ix) { if(( dir == outgoing && time) || ( dir == incoming && !time)) inspin->setBasisState(ix,waves[ix]); else inspin->setDecayState(ix,waves[ix]); } } else { FermionSpinPtr temp = new_ptr(FermionSpinInfo(particle->momentum(),time)); particle->spinInfo(temp); for(unsigned int ix=0;ix<2;++ix) { if(( dir == outgoing && time) || ( dir == incoming && !time)) temp->setBasisState(ix,waves[ix]); else temp->setDecayState(ix,waves[ix]); } } } void SpinorWaveFunction:: constructSpinInfo(const vector & waves, tPPtr particle,Direction dir,bool time) { assert(waves.size()==2); tFermionSpinPtr inspin = !particle->spinInfo() ? tFermionSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<2;++ix) { if(( dir == outgoing && time) || ( dir == incoming && !time)) inspin->setBasisState(ix,waves[ix].dimensionedWf()); else inspin->setDecayState(ix,waves[ix].dimensionedWf()); } } else { FermionSpinPtr temp = new_ptr(FermionSpinInfo(particle->momentum(),time)); particle->spinInfo(temp); for(unsigned int ix=0;ix<2;++ix) { if(( dir == outgoing && time) || ( dir == incoming && !time)) temp->setBasisState(ix,waves[ix].dimensionedWf()); else temp->setDecayState(ix,waves[ix].dimensionedWf()); } } } diff --git a/Helicity/WaveFunction/VectorWaveFunction.cc b/Helicity/WaveFunction/VectorWaveFunction.cc --- a/Helicity/WaveFunction/VectorWaveFunction.cc +++ b/Helicity/WaveFunction/VectorWaveFunction.cc @@ -1,294 +1,306 @@ // -*- C++ -*- // // VectorWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation // Copyright (C) 2003-2011 Peter Richardson, 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 VectorWaveFunction class. // // Author: Peter Richardson // #include "VectorWaveFunction.h" using namespace ThePEG; using namespace ThePEG::Helicity; // calculate the Wavefunction void VectorWaveFunction::calculateWaveFunction(unsigned int ihel,VectorPhase vphase) { Direction dir=direction(); if(dir==intermediate) throw ThePEG::Helicity::HelicityConsistencyError() << "In VectorWaveFunction::calcluateWaveFunction " << "particle must be incoming or outgoing not intermediate" << Exception::abortnow; // check a valid helicity combination if(ihel==0 || ihel==2||(ihel==1&&mass()>ZERO)) { int jhel=ihel-1; // extract the momentum components double fact=-1.; if(dir==incoming){fact=1.;} Energy ppx=fact*px(),ppy=fact*py(),ppz=fact*pz(),pee=fact*e(),pmm=mass(); // calculate some kinematic quantites; Energy2 pt2 = ppx*ppx+ppy*ppy; Energy pabs = sqrt(pt2+ppz*ppz); Energy pt = sqrt(pt2); // overall phase of the vector Complex phase; if(vphase==vector_phase) { if(pt==ZERO || ihel==1) phase = 1.; else if(ihel==0) phase = Complex(ppx/pt,-fact*ppy/pt); else phase = Complex(ppx/pt, fact*ppy/pt); } else phase = 1.; if(ihel!=1) phase = phase/sqrt(2.); // first the +/-1 helicity states if(ihel!=1) { // first the no pt case if(pt==ZERO) { double sgnz; sgnz = ppz(jhel)*phase); _wf.setY(sgnz*phase*complex(0,-fact)); _wf.setZ(0.); _wf.setT(0.); } else { InvEnergy opabs=1./pabs; InvEnergy opt =1./pt; _wf.setX(phase*complex(-jhel*ppz*ppx*opabs*opt, fact*ppy*opt)); _wf.setY(phase*complex(-jhel*ppz*ppy*opabs*opt,-fact*ppx*opt)); _wf.setZ(double(jhel*pt*opabs)*phase); _wf.setT(0.); } } // 0 component for massive vectors else { if(pabs==ZERO) { _wf.setX(0.); _wf.setY(0.); _wf.setZ(1.); _wf.setT(0.); } else { InvEnergy empabs=pee/pmm/pabs; _wf.setX(double(empabs*ppx)); _wf.setY(double(empabs*ppy)); _wf.setZ(double(empabs*ppz)); _wf.setT(double(pabs/pmm)); } } } // special return the momentum as a check of gauge invariance else if(ihel==10) { _wf.setX(double(px()/MeV)); _wf.setY(double(py()/MeV)); _wf.setZ(double(pz()/MeV)); _wf.setT(double(e()/MeV)); } // issue warning and return zero else { ThePEG::Helicity::HelicityConsistencyError() << "Invalid Helicity = " << ihel << " requested for Vector " << particle()->PDGName() << Exception::abortnow; _wf.setX(0.);_wf.setY(0.);_wf.setZ(0.);_wf.setT(0.); } } void VectorWaveFunction:: calculateWaveFunctions(vector & waves, tPPtr particle,Direction dir,bool massless, VectorPhase phase) { tVectorSpinPtr inspin = !particle->spinInfo() ? tVectorSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(3); if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<3;++ix) waves[ix]=inspin->getProductionBasisState(ix); } else { inspin->decay(); for(unsigned int ix=0;ix<3;++ix) waves[ix]=inspin->getDecayBasisState(ix); } } else { assert(!particle->spinInfo()); VectorWaveFunction wave(particle->momentum(),particle->dataPtr(),0, dir,phase); for(unsigned int ix=0;ix<3;++ix) { if(massless&&ix==1) { waves[ix] = LorentzPolarizationVector(); } else { if(ix!=0) wave.reset(ix); waves[ix] = wave.wave(); } } } } void VectorWaveFunction:: calculateWaveFunctions(vector & waves, tPPtr particle, Direction dir, bool massless, VectorPhase phase) { tVectorSpinPtr inspin = !particle->spinInfo() ? tVectorSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(3); if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<3;++ix) waves[ix]=VectorWaveFunction(particle->momentum(), particle->dataPtr(), inspin->getProductionBasisState(ix),dir); } else { inspin->decay(); for(unsigned int ix=0;ix<3;++ix) waves[ix]=VectorWaveFunction(particle->momentum(), particle->dataPtr(), inspin->getDecayBasisState(ix),dir); } } else { assert(!particle->spinInfo()); VectorWaveFunction wave(particle->momentum(),particle->dataPtr(),0, dir,phase); for(unsigned int ix=0;ix<3;++ix) { if(massless&&ix==1) { waves[ix] = VectorWaveFunction(particle->momentum(), particle->dataPtr(),dir); } else { if(ix!=0) wave.reset(ix); waves[ix] = wave; } } } } void VectorWaveFunction:: calculateWaveFunctions(vector & waves, RhoDMatrix & rho,tPPtr particle, Direction dir,bool massless, VectorPhase phase) { tVectorSpinPtr inspin = !particle->spinInfo() ? tVectorSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(3); if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<3;++ix) waves[ix]=inspin->getProductionBasisState(ix); rho = RhoDMatrix(PDT::Spin1); } else { inspin->decay(); for(unsigned int ix=0;ix<3;++ix) waves[ix]=inspin->getDecayBasisState(ix); rho = inspin->rhoMatrix(); } } else { assert(!particle->spinInfo()); VectorWaveFunction wave(particle->momentum(),particle->dataPtr(),0, dir,phase); for(unsigned int ix=0;ix<3;++ix) { if(massless&&ix==1) { waves[ix] = LorentzPolarizationVector(); } else { if(ix!=0) wave.reset(ix); waves[ix] = wave.wave(); } } rho = RhoDMatrix(PDT::Spin1); } } void VectorWaveFunction:: calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle, Direction dir,bool massless, VectorPhase phase) { tVectorSpinPtr inspin = !particle->spinInfo() ? tVectorSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(3); if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<3;++ix) waves[ix]=VectorWaveFunction(particle->momentum(), particle->dataPtr(), inspin->getProductionBasisState(ix),dir); rho = RhoDMatrix(PDT::Spin1); } else { inspin->decay(); for(unsigned int ix=0;ix<3;++ix) waves[ix]=VectorWaveFunction(particle->momentum(), particle->dataPtr(), inspin->getDecayBasisState(ix),dir); rho = inspin->rhoMatrix(); } } else { assert(!particle->spinInfo()); VectorWaveFunction wave(particle->momentum(),particle->dataPtr(),0, dir,phase); for(unsigned int ix=0;ix<3;++ix) { if(massless&&ix==1) { waves[ix] = VectorWaveFunction(particle->momentum(), particle->dataPtr(),dir); } else { if(ix!=0) wave.reset(ix); waves[ix] = wave; } } rho = RhoDMatrix(PDT::Spin1); } } void VectorWaveFunction:: constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time,bool ) { assert(waves.size()==3); tVectorSpinPtr inspin = !part->spinInfo() ? tVectorSpinPtr() : dynamic_ptr_cast(part->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<3;++ix) - if(dir==outgoing) inspin->setBasisState(ix,waves[ix]); - else inspin->setDecayState(ix,waves[ix]); + if(( dir == outgoing && time) || + ( dir == incoming && !time)) + inspin->setBasisState(ix,waves[ix]); + else + inspin->setDecayState(ix,waves[ix]); } else { VectorSpinPtr temp = new_ptr(VectorSpinInfo(part->momentum(),time)); part->spinInfo(temp); for(unsigned int ix=0;ix<3;++ix) - if(dir==outgoing) temp->setBasisState(ix,waves[ix]); - else temp->setDecayState(ix,waves[ix]); + if(( dir == outgoing && time) || + ( dir == incoming && !time)) + temp->setBasisState(ix,waves[ix]); + else + temp->setDecayState(ix,waves[ix]); } } void VectorWaveFunction:: constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time,bool ) { assert(waves.size()==3); tVectorSpinPtr inspin = !part->spinInfo() ? tVectorSpinPtr() : dynamic_ptr_cast(part->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<3;++ix) - if(dir==outgoing) inspin->setBasisState(ix,waves[ix].wave()); - else inspin->setDecayState(ix,waves[ix].wave()); + if(( dir == outgoing && time) || + ( dir == incoming && !time)) + inspin->setBasisState(ix,waves[ix].wave()); + else + inspin->setDecayState(ix,waves[ix].wave()); } else { VectorSpinPtr temp = new_ptr(VectorSpinInfo(part->momentum(),time)); part->spinInfo(temp); for(unsigned int ix=0;ix<3;++ix) - if(dir==outgoing) temp->setBasisState(ix,waves[ix].wave()); - else temp->setDecayState(ix,waves[ix].wave()); + if(( dir == outgoing && time) || + ( dir == incoming && !time)) + temp->setBasisState(ix,waves[ix].wave()); + else + temp->setDecayState(ix,waves[ix].wave()); } } diff --git a/LesHouches/LesHouchesEventHandler.cc b/LesHouches/LesHouchesEventHandler.cc --- a/LesHouches/LesHouchesEventHandler.cc +++ b/LesHouches/LesHouchesEventHandler.cc @@ -1,587 +1,621 @@ // -*- C++ -*- // // LesHouchesEventHandler.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 LesHouchesEventHandler class. // #include "LesHouchesEventHandler.h" #include "LesHouchesReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Handlers/LuminosityFunction.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/Utilities/LoopGuard.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; LesHouchesEventHandler::~LesHouchesEventHandler() {} IBPtr LesHouchesEventHandler::clone() const { return new_ptr(*this); } IBPtr LesHouchesEventHandler::fullclone() const { return new_ptr(*this); } void LesHouchesEventHandler::doinit() { EventHandler::doinit(); for ( int i = 0, N = readers().size(); i < N; ++i ) { readers()[i]->init(); } ntries = 0; } void LesHouchesEventHandler::initialize() { if ( lumiFnPtr() ) Repository::clog() << "The LuminosityFunction '" << lumiFnPtr()->name() << "' assigned to the LesHouchesEventHandler '" << name() << "' will not be active in this run. Instead the incoming " << "particles will be determined by the used LesHouchesReader objects.\n" << Exception::warning; if ( readers().empty() ) throw LesHouchesInitError() << "No readers were defined for the LesHouchesEventHandler '" << name() << "'" << Exception::warning; // Go through all the readers and collect information about cross // sections and processes. typedef map ProcessMap; ProcessMap processes; PDPair incoming; Energy MaxEA = ZERO; Energy MaxEB = ZERO; weightnames.clear(); for ( int i = 0, N = readers().size(); i < N; ++i ) { LesHouchesReader & reader = *readers()[i]; reader.initialize(*this); if ( i == 0 ) weightnames = reader.optWeightsNamesFunc(); else if ( reader.optWeightsNamesFunc() != weightnames ) throw LesHouchesInitError() << "the optional weights names for the LesHouchesEventHandler do not match '" << name() << "'" << Exception::warning; // Check that the incoming particles are consistent between the // readers. if ( !incoming.first ) { incoming.first = getParticleData(reader.heprup.IDBMUP.first); if ( !incoming.first ) Throw() << "Unknown beam PID " << reader.heprup.IDBMUP.first << ". Have you created a matching BeamParticle object?" << Exception::runerror; } if ( !incoming.second ) { incoming.second = getParticleData(reader.heprup.IDBMUP.second); if ( !incoming.second ) Throw() << "Unknown beam PID " << reader.heprup.IDBMUP.first << ". Have you created a matching BeamParticle object?" << Exception::runerror; } if ( incoming.first->id() != reader.heprup.IDBMUP.first || incoming.second->id() != reader.heprup.IDBMUP.second ) Repository::clog() << "The different LesHouchesReader objects in the " << "LesHouchesEventHandler '" << name() << "' have different " << "types of colliding particles." << Exception::warning; MaxEA = max(MaxEA, reader.heprup.EBMUP.first*GeV); MaxEB = max(MaxEB, reader.heprup.EBMUP.second*GeV); // Check that the weighting of the events in the different readers // is consistent with the ones requested for this event // handler. Also collect the sum of the maximum weights. if ( reader.negativeWeights() && weightOption() > 0 ) throw LesHouchesInitError() << "The reader '" << reader.name() << "' contains negatively weighted events, " << "which is not allowed for the LesHouchesEventHandler '" << name() << "'." << Exception::warning; // Check that we do not have the same process numbers in different // readers. for ( int ip = 0; ip < reader.heprup.NPRUP; ++ip ) { if ( reader.heprup.LPRUP[ip] ) { ProcessMap::iterator pit = processes.find(reader.heprup.LPRUP[ip]); if ( pit == processes.end() ) processes[reader.heprup.LPRUP[ip]] = readers()[i]; else if ( warnPNum ) { Throw() << "In the LesHouchesEventHandler '" << name() << "', both the '" << pit->second->name() << "' and '" << reader.name() << "' contains sub-process number " << pit->first << ". This process may be double-counted in this run." << Exception::warning; } } } selector().insert(reader.stats.maxXSec(), i); } stats.maxXSec(selector().sum()); histStats.maxXSec(selector().sum()); for (map::iterator it= opt.begin(); it!=opt.end(); ++it) { (it->second).stats.maxXSec(selector().sum()); (it->second).histStats.maxXSec(selector().sum()); } // Check that we have any cross section at all. if ( stats.maxXSec() <= ZERO ) throw LesHouchesInitError() << "The sum of the cross sections of the readers in the " << "LesHouchesEventHandler '" << name() << "' was zero." << Exception::warning; // We now create a LuminosityFunction object to inform others about // the energy of the beam. theIncoming = incoming; lumiFn(new_ptr(LuminosityFunction(MaxEA, MaxEB))); } void LesHouchesEventHandler::doinitrun() { EventHandler::doinitrun(); stats.reset(); histStats.reset(); weightnames.clear(); for ( int i = 0, N = readers().size(); i < N; ++i ) { readers()[i]->initrun(); LesHouchesReader & reader = *readers()[i]; reader.initialize(*this); if ( i == 0 ) weightnames = reader.optWeightsNamesFunc(); else if ( reader.optWeightsNamesFunc() != weightnames ) throw LesHouchesInitError() << "the optional weights names for the LesHouchesEventHandler do not match '" << name() << "'" << Exception::warning; } for(unsigned int ww = 0; ww < weightnames.size(); ++ww) { const OptWeight optweight = { XSecStat(), ZERO, XSecStat() }; opt.insert(make_pair(weightnames[ww], optweight)); } ntries = 0; } EventPtr LesHouchesEventHandler::generateEvent() { LoopGuard loopGuard(*this, maxLoop()); while ( true ) { loopGuard(); currentReader(readers()[selector().select(UseRandom::current())]); skipEvents(); currentReader()->reset(); double weight = currentReader()->getEvent(); if ( weightOption() == unitweight && weight < 0.0 ) weight = 0.0; if ( weightOption() == unitweight || weightOption() == unitnegweight ) { CrossSection newmax = selector().reweight(weight); if ( newmax > CrossSection() ) increaseMaxXSec(newmax); } select(weight/currentReader()->preweight); histStats.select(weight); if ( !weighted() ) { if ( weightOption() == unitweight || weightOption() == unitnegweight ) { if ( !rndbool(abs(weight)) ) continue; weight = Math::sign(1.0, weight); } else if ( weight == 0.0 ) continue; } else if ( weight == 0.0 ) continue; accept(); // Divide by the bias introduced by the preweights in the reader. weight /= currentReader()->preweight; try { theLastXComb = currentReader()->getXComb(); + // fact for weight normalization + const double fact = + theNormWeight ? + double(selector().sum()/picobarn) : 1.; + currentEvent(new_ptr(Event(lastParticles(), this, generator()->runName(), - generator()->currentEventNumber(), weight))); + generator()->currentEventNumber(), weight*fact ))); currentEvent()->optionalWeights() = currentReader()->optionalEventWeights(); + // normalize the optional weights + for(map::iterator it = currentEvent()->optionalWeights().begin(); + it!=currentEvent()->optionalWeights().end();++it) + it->second *= fact; performCollision(); if ( !currentCollision() ) throw Veto(); return currentEvent(); } catch (Veto) { reject(weight); } catch (Stop) { } catch (Exception &) { reject(weight); throw; } } } void LesHouchesEventHandler::skipEvents() { if ( weightOption() == 2 || weightOption() == -2 ) return; //does it make sense to skip events if we are using varying weights? // Don't do this for readers which seem to generate events on the fly. if ( currentReader()->active() || currentReader()->NEvents() <= 0 ) return; // Estimate the fration of the total events available from // currentReader() which will be requested. double frac = currentReader()->stats.maxXSec()/stats.maxXSec(); if ( stats.accepted() > 0 ) frac *= double(stats.attempts())/double(stats.accepted()); else frac *= double(stats.attempts() + 1); double xscan = generator()->N()*frac/currentReader()->NEvents(); // Estimate the number of times we need to go through the events for // the currentReader(), and how many events on average we need to // skip for each attempted event to go through the file an integer // number of times. double nscan = ceil(xscan); double meanskip = nscan/xscan - 1.0; // Skip an average numer of steps with a Poissonian distribution. currentReader()-> skip(UseRandom::rndPoisson(meanskip)%currentReader()->NEvents()); } void LesHouchesEventHandler::select(double weight) { stats.select(weight); currentReader()->select(weight); for (map::const_iterator it = currentReader()->optionalEventWeights().begin(); it != currentReader()->optionalEventWeights().end(); ++it) { const double w = it->second; OptWeight & o = opt[it->first]; o.histStats.select(w); o.stats.select(w); } } tCollPtr LesHouchesEventHandler::performCollision() { lastExtractor()->select(lastXCombPtr()); if ( CKKWHandler() ) CKKWHandler()->setXComb(lastXCombPtr()); currentCollision(new_ptr(Collision(lastParticles(), currentEvent(), this))); if ( currentEvent() ) currentEvent()->addCollision(currentCollision()); currentStep(new_ptr(Step(currentCollision(), this))); currentCollision()->addStep(currentStep()); currentStep()->addSubProcess(currentReader()->getSubProcess()); lastExtractor()->constructRemnants(lastXCombPtr()->partonBinInstances(), subProcess(), currentStep()); if ( !currentReader()->cuts().passCuts(*currentCollision()) ) throw Veto(); initGroups(); if ( ThePEG_DEBUG_ITEM(1) ) { if ( currentEvent() ) generator()->logfile() << *currentEvent(); else generator()->logfile() << *currentCollision(); } return continueCollision(); } EventPtr LesHouchesEventHandler::continueEvent() { try { continueCollision(); } catch (Veto) { - reject(currentEvent()->weight()); + const double fact = + theNormWeight ? + double(selector().sum()/picobarn) : 1.; + reject(currentEvent()->weight()/fact); } catch (Stop) { } catch (Exception &) { - reject(currentEvent()->weight()); + const double fact = + theNormWeight ? + double(selector().sum()/picobarn) : 1.; + reject(currentEvent()->weight()/fact); throw; } return currentEvent(); } void LesHouchesEventHandler::dofinish() { EventHandler::dofinish(); if ( selector().compensating() ) generator()->log() << "Warning: The run was ended while the LesHouchesEventHandler '" << name() << "' was still trying to compensate for weights larger than 1. " << "The cross section estimates may therefore be statistically " << "inaccurate." << endl; } void LesHouchesEventHandler::statistics(ostream & os) const { if ( statLevel() == 0 ) return; string line = "=======================================" "=======================================\n"; if ( stats.accepted() <= 0 ) { os << line << "No events generated by event handler '" << name() << "'." << endl; return; } os << line << "Statistics for Les Houches event handler \'" << name() << "\':\n" << " " << "generated number of Cross-section\n" << " " << " events attempts (nb)\n"; os << line << "Total:" << setw(42) << stats.accepted() << setw(13) << stats.attempts() << setw(17) << ouniterr(stats.xSec(), stats.xSecErr(), nanobarn) << endl << line; if ( statLevel() == 1 ) return; if ( statLevel() == 2 ) { os << "Per Les Houches Reader breakdown:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { LesHouchesReader & reader = *readers()[i]; string n = reader.name(); n.resize(37, ' '); os << n << setw(11) << reader.stats.accepted() << setw(13) << reader.stats.attempts() << setw(17) << ouniterr(reader.stats.xSec(), reader.stats.xSecErr(), nanobarn) << endl; } os << line; } else { os << "Per Les Houches Reader (and process #) breakdown:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { LesHouchesReader & reader = *readers()[i]; string n = reader.name() + " (all)"; n.resize(37, ' '); os << n << setw(11) << reader.stats.accepted() << setw(13) << reader.stats.attempts() << setw(17) << ouniterr(reader.stats.xSec(), reader.stats.xSecErr(), nanobarn) << endl; CrossSection xsectot = reader.stats.xSec(); if ( xsectot != ZERO ) xsectot /= reader.stats.sumWeights(); typedef LesHouchesReader::StatMap::const_iterator const_iterator; for ( const_iterator i = reader.statmap.begin(); i != reader.statmap.end(); ++i ) { ostringstream ss; ss << reader.name() << " (" << i->first << ")"; string n = ss.str(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted() << setw(13) << i->second.attempts() << setw(17) << ouniterr(i->second.sumWeights()*xsectot, sqrt(i->second.sumWeights2())*xsectot, nanobarn) << endl; } os << line; } } string warn = "Warning: Result may be statistically incorrect since\n" " the following LesHouchesReaders were oversampled:\n"; for ( int i = 0, N = readers().size(); i < N; ++i ) { LesHouchesReader & reader = *readers()[i]; if ( reader.NEvents() > 0 && reader.stats.attempts() > reader.NEvents() ) { os << warn; warn = ""; os << "'" << reader.name() << "' (by a factor " << double(reader.stats.attempts())/double(reader.NEvents()) << ")" << endl; } } } void LesHouchesEventHandler::increaseMaxXSec(CrossSection maxxsec) { stats.maxXSec(selector().sum()); histStats.maxXSec(selector().sum()); currentReader()->increaseMaxXSec(maxxsec); } void LesHouchesEventHandler::accept() { ntries++; stats.accept(); histStats.accept(); currentReader()->accept(); for (map::iterator it = opt.begin(); it!=opt.end(); ++it) { OptWeight & tmp = it->second; tmp.histStats.accept(); tmp.stats.accept(); } } void LesHouchesEventHandler::reject(double w) { ntries++; stats.reject(w); histStats.reject(w); currentReader()->reject(w); for (map::const_iterator it = currentReader()->optionalEventWeights().begin(); it != currentReader()->optionalEventWeights().end(); ++it) { const double w = it->second; OptWeight & o = opt[it->first]; o.histStats.reject(w); o.stats.reject(w); } } const map & LesHouchesEventHandler::optintegratedXSecMap() const { static map result; result.clear(); for ( map::const_iterator it= opt.begin(); it!=opt.end(); ++it ) { result[it->first] = ( it->second.stats.sumWeights() / it->second.stats.attempts() ) * picobarn; } return result; } CrossSection LesHouchesEventHandler::histogramScale() const { return histStats.xSec()/histStats.sumWeights(); } CrossSection LesHouchesEventHandler::integratedXSec() const { return histStats.xSec(); } CrossSection LesHouchesEventHandler::integratedXSecErr() const { return histStats.xSecErr(); } int LesHouchesEventHandler::ntriesinternal() const { return stats.attempts(); } void LesHouchesEventHandler::persistentOutput(PersistentOStream & os) const { os << stats << histStats << theReaders << theSelector - << oenum(theWeightOption) << theUnitTolerance << theCurrentReader << warnPNum; + << oenum(theWeightOption) << theUnitTolerance << theCurrentReader << warnPNum + << theNormWeight; } void LesHouchesEventHandler::persistentInput(PersistentIStream & is, int) { is >> stats >> histStats >> theReaders >> theSelector - >> ienum(theWeightOption) >> theUnitTolerance >> theCurrentReader >> warnPNum; + >> ienum(theWeightOption) >> theUnitTolerance >> theCurrentReader >> warnPNum + >> theNormWeight; } ClassDescription LesHouchesEventHandler::initLesHouchesEventHandler; // Definition of the static class description member. void LesHouchesEventHandler::setUnitTolerance(double x) { theUnitTolerance = x; selector().tolerance(unitTolerance()); } void LesHouchesEventHandler::Init() { static ClassDocumentation documentation ("This is the main class administrating the selection of hard " "subprocesses from a set of ThePEG::LesHouchesReader objects."); static RefVector interfaceLesHouchesReaders ("LesHouchesReaders", "Objects capable of reading events from an event file or an " "external matrix element generator.", &LesHouchesEventHandler::theReaders, -1, false, false, true, false, false); static Switch interfaceWeightOption ("WeightOption", "The different ways to weight events in the Les Houches event handler. " "Whether weighted or not and whether or not negative weights are allowed.", &LesHouchesEventHandler::theWeightOption, unitweight, true, false); static SwitchOption interfaceWeightOptionUnitWeight (interfaceWeightOption, "UnitWeight", "All events have unit weight.", unitweight); static SwitchOption interfaceWeightOptionNegUnitWeight (interfaceWeightOption, "NegUnitWeight", "All events have weight +1 or maybe -1.", unitnegweight); static SwitchOption interfaceWeightOptionVarWeight (interfaceWeightOption, "VarWeight", "Events may have varying but positive weights.", varweight); static SwitchOption interfaceWeightOptionVarNegWeight (interfaceWeightOption, "VarNegWeight", "Events may have varying weights, both positive and negative.", varnegweight); static Switch interfaceWarnPNum ("WarnPNum", "Warn if the same process number is used in more than one " "LesHouchesReader.", &LesHouchesEventHandler::warnPNum, true, true, false); static SwitchOption interfaceWarnPNumWarning (interfaceWarnPNum, "Warning", "Give a warning message.", true); static SwitchOption interfaceWarnPNumNoWarning (interfaceWarnPNum, "NoWarning", "Don't give a warning message.", false); static Parameter interfaceUnitTolerance ("UnitTolerance", "If the WeightOption is set to unit weight, do not start compensating unless the a weight is found to be this much larger than unity.", &LesHouchesEventHandler::theUnitTolerance, 1.0e-6, 0.0, 0, true, false, Interface::lowerlim, &LesHouchesEventHandler::setUnitTolerance, (double(LesHouchesEventHandler::*)()const)(0), (double(LesHouchesEventHandler::*)()const)(0), (double(LesHouchesEventHandler::*)()const)(0), (double(LesHouchesEventHandler::*)()const)(0)); + + static Switch interfaceWeightNormalization + ("WeightNormalization", + "How to normalize the output weights", + &LesHouchesEventHandler::theNormWeight, 0, false, false); + static SwitchOption interfaceWeightNormalizationUnit + (interfaceWeightNormalization, + "Normalized", + "Standard normalization, i.e. +/- for unweighted events", + 0); + static SwitchOption interfaceWeightNormalizationCrossSection + (interfaceWeightNormalization, + "CrossSection", + "Normalize the weights to the max cross section in pb", + 1); + + interfaceLesHouchesReaders.rank(10); interfaceWeightOption.rank(9); } diff --git a/LesHouches/LesHouchesEventHandler.h b/LesHouches/LesHouchesEventHandler.h --- a/LesHouches/LesHouchesEventHandler.h +++ b/LesHouches/LesHouchesEventHandler.h @@ -1,470 +1,474 @@ // -*- C++ -*- // // LesHouchesEventHandler.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_LesHouchesEventHandler_H #define THEPEG_LesHouchesEventHandler_H // // This is the declaration of the LesHouchesEventHandler class. // #include "ThePEG/Handlers/EventHandler.h" #include "LesHouchesEventHandler.fh" #include "LesHouchesReader.fh" #include "ThePEG/Utilities/CompSelector.h" #include "ThePEG/Utilities/XSecStat.h" namespace ThePEG { /** * The LesHouchesEventHandler inherits from the general EventHandler * class and administers the reading of events generated by external * matrix element generator programs according to the Les Houches * accord. * * The class has a list of LesHouchesReaders which * typically are connected to files with event data produced by * external matrix element generator programs. When an event is * requested by LesHouchesEventHandler, one of the readers are chosen, * an event is read in and then passed to the different * StepHandler defined in the underlying * EventHandler class. * * @see \ref LesHouchesEventHandlerInterfaces "The interfaces" * defined for LesHouchesEventHandler. */ class LesHouchesEventHandler: public EventHandler { public: /** * A vector of LesHouchesReader objects. */ typedef vector ReaderVector; /** * A selector of readers. */ typedef CompSelector ReaderSelector; /** * Enumerate the weighting options. */ enum WeightOpt { unitweight = 1, /**< All events have unit weight. */ unitnegweight = -1, /**< All events have wight +/- 1. */ varweight = 2, /**< Varying positive weights. */ varnegweight = -2 /**< Varying positive or negative weights. */ }; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ LesHouchesEventHandler() - : theWeightOption(unitweight), theUnitTolerance(1.0e-6), warnPNum(true) + : theWeightOption(unitweight), theUnitTolerance(1.0e-6), warnPNum(true), + theNormWeight(0) { selector().tolerance(unitTolerance()); } /** * The destructor. */ virtual ~LesHouchesEventHandler(); //@} public: /** @name Initialization and finalization functions. */ //@{ /** * Initialize this event handler and all related objects needed to * generate events. */ virtual void initialize(); /** * Write out accumulated statistics about intergrated cross sections * and stuff. */ virtual void statistics(ostream &) const; /** * Histogram scale. A histogram bin which has been filled with the * weights associated with the Event objects should be scaled by * this factor to give the correct cross section. */ virtual CrossSection histogramScale() const; /** * The estimated total integrated cross section of the processes * generated in this run. * @return 0 if no integrated cross section could be estimated. */ virtual CrossSection integratedXSec() const; /** * The number of attempts inside the statistics object */ virtual int ntriesinternal() const; /** * The estimated error in the total integrated cross section of the * processes generated in this run. * @return 0 if no integrated cross section error could be estimated. */ virtual CrossSection integratedXSecErr() const; /** * Map to aid the calculation of the optional weights' integrated cross section */ virtual const map & optintegratedXSecMap() const; //@} /** @name Functions used for the actual generation */ //@{ /** * Generate an event. */ virtual EventPtr generateEvent(); /** * Create the Event and Collision objects. Used by the * generateEvent() function. */ virtual tCollPtr performCollision(); /** * Continue generating an event if the generation has been stopped * before finishing. */ virtual EventPtr continueEvent(); //@} /** @name Functions to manipulate statistics. */ //@{ /** * An event has been selected. Signal that an event has been * selected with the given \a weight. If unit weights are requested, * the event will be accepted with that weight. This also takes care * of the statistics collection of the selected reader object. */ void select(double weight); /** * Accept the current event, taking care of the statistics * collection of the corresponding reader objects. */ void accept(); /** * Reject the current event, taking care of the statistics * collection of the corresponding reader objects. */ void reject(double weight); /** * Increase the overestimated cross section for the selected reader. */ void increaseMaxXSec(CrossSection maxxsec); /** * Skip some events. To ensure a reader file is scanned an even * number of times, skip a number of events for the selected reader. */ void skipEvents(); //@} /** @name Simple access functions. */ //@{ /** * The way weights are to be treated. */ WeightOpt weightOption() const { return theWeightOption; } /** * If the weight option is set to unit weight, do not start * compensating unless the weight is this much larger than unity. */ double unitTolerance() const { return theUnitTolerance; } /** * Access the list of readers. */ const ReaderVector & readers() const { return theReaders; } /** * The selector to choose readers according to their overestimated * cross section. */ const ReaderSelector & selector() const { return theSelector; } /** * The currently selected reader object. */ tLesHouchesReaderPtr currentReader() const { return theCurrentReader; } /** * Set the currently selected reader object. */ void currentReader(tLesHouchesReaderPtr x) { theCurrentReader = x; } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); /** * The currently selected reader object. */ tLesHouchesReaderPtr theCurrentReader; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} protected: /** * Access the list of readers. */ ReaderVector & readers() { return theReaders; } /** * The selector to choose readers according to their overestimated * cross section. */ ReaderSelector & selector() { return theSelector; } /** * Helper function for the interface; */ void setUnitTolerance(double); /** * Collect statistics for this event handler. */ XSecStat stats; /** * Collect statistics for this event handler. To be used for * histogram scaling. */ XSecStat histStats; /** * The weight identifiers for the events */ vector weightnames; /** * Collect statistics for this event handler's optional weights. */ struct OptWeight { /** * Collect statistics for the optional weights */ XSecStat stats; /** * Calculate the cross section for the optional weights */ CrossSection xs; /** * Collect statistics for this event handler's optional weights. To be used for * histogram scaling. */ XSecStat histStats; }; /** Map statistics to weight name strings */ map opt; /** * Counter for the number of tries for the purpose of statistics */ int ntries; /** * Return the optional weights' statistics */ const map & optWeights() const { return opt; } private: /** * The list of readers. */ ReaderVector theReaders; /** * The selector to choose readers according to their overestimated * cross section. */ ReaderSelector theSelector; /** * The way weights are to be treated. */ WeightOpt theWeightOption; /** * If the weight option is set to unit weight, do not start * compensating unless the weight is this much larger than unity. */ double theUnitTolerance; /** * Warn if the same process number is used in more than one * LesHouchesReader. */ bool warnPNum; - + /** + * How to normalize the weights + */ + unsigned int theNormWeight; public: /** @cond EXCEPTIONCLASSES */ /** * Exception class used if no readers were assigned. */ class LesHouchesInitError: public InitException {}; /** * Exception class used if the same process number is used by more * than ne reader. */ class LesHouchesPNumException: public InitException {}; /** @endcond */ private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initLesHouchesEventHandler; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ LesHouchesEventHandler & operator=(const LesHouchesEventHandler &); }; } // CLASSDOC OFF #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of LesHouchesEventHandler. */ template <> struct BaseClassTrait { /** Typedef of the first base class of LesHouchesEventHandler. */ typedef EventHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the LesHouchesEventHandler class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::LesHouchesEventHandler"; } /** Return the name of the shared library be loaded to get access to * the LesHouchesEventHandler class and every other class it uses * (except the base class). */ static string library() { return "LesHouches.so"; } }; /** @endcond */ } #endif /* THEPEG_LesHouchesEventHandler_H */ diff --git a/LesHouches/LesHouchesReader.cc b/LesHouches/LesHouchesReader.cc --- a/LesHouches/LesHouchesReader.cc +++ b/LesHouches/LesHouchesReader.cc @@ -1,1587 +1,1592 @@ // -*- C++ -*- // // LesHouchesReader.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 LesHouchesReader class. // #include "LesHouchesReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "config.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/PDF/NoPDF.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/EventRecord/TmpTransform.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "LesHouchesEventHandler.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" using namespace ThePEG; LesHouchesReader::LesHouchesReader(bool active) : theNEvents(0), position(0), reopened(0), theMaxScan(-1), scanning(false), isActive(active), theCacheFileName(""), doCutEarly(true), preweight(1.0), reweightPDF(false), doInitPDFs(false), theMaxMultCKKW(0), theMinMultCKKW(0), lastweight(1.0), maxFactor(1.0), optionalnpLO(0), optionalnpNLO(0), weightScale(1.0*picobarn), skipping(false), theMomentumTreatment(0), useWeightWarnings(true),theReOpenAllowed(true), theIncludeSpin(true) {} LesHouchesReader::LesHouchesReader(const LesHouchesReader & x) : HandlerBase(x), LastXCombInfo<>(x), heprup(x.heprup), hepeup(x.hepeup), inData(x.inData), inPDF(x.inPDF), outPDF(x.outPDF), thePartonExtractor(x.thePartonExtractor), thePartonBins(x.thePartonBins), theXCombs(x.theXCombs), theCuts(x.theCuts), theNEvents(x.theNEvents), position(x.position), reopened(x.reopened), theMaxScan(x.theMaxScan), scanning(false), isActive(x.isActive), theCacheFileName(x.theCacheFileName), doCutEarly(x.doCutEarly), stats(x.stats), statmap(x.statmap), thePartonBinInstances(x.thePartonBinInstances), reweights(x.reweights), preweights(x.preweights), preweight(x.preweight), reweightPDF(x.reweightPDF), doInitPDFs(x.doInitPDFs), theMaxMultCKKW(x.theMaxMultCKKW), theMinMultCKKW(x.theMinMultCKKW), lastweight(x.lastweight), maxFactor(x.maxFactor), weightScale(x.weightScale), xSecWeights(x.xSecWeights), maxWeights(x.maxWeights), skipping(x.skipping), theMomentumTreatment(x.theMomentumTreatment), useWeightWarnings(x.useWeightWarnings), theReOpenAllowed(x.theReOpenAllowed), theIncludeSpin(x.theIncludeSpin) {} LesHouchesReader::~LesHouchesReader() {} void LesHouchesReader::doinitrun() { HandlerBase::doinitrun(); stats.reset(); for ( StatMap::iterator i = statmap.begin(); i != statmap.end(); ++i ) i->second.reset(); open(); if ( cacheFileName().length() ) openReadCacheFile(); position = 0; reopened = 0; } bool LesHouchesReader::preInitialize() const { if ( HandlerBase::preInitialize() ) return true; if ( doInitPDFs && ! ( inPDF.first && inPDF.second ) ) return true; return false; } void LesHouchesReader::doinit() { HandlerBase::doinit(); open(); close(); if ( !heprup.IDBMUP.first || !heprup.IDBMUP.second ) Throw() << "No information about incoming particles were found in " << "LesHouchesReader '" << name() << "'." << Exception::warning; inData = make_pair(getParticleData(heprup.IDBMUP.first), getParticleData(heprup.IDBMUP.second)); if ( heprup.EBMUP.first <= 0.0 || heprup.EBMUP.second <= 0.0 ) Throw() << "No information about the energy of incoming particles were found in " << "LesHouchesReader '" << name() << "'." << Exception::warning; if ( doInitPDFs && ! ( inPDF.first && inPDF.second ) ) { initPDFs(); if ( ! ( inPDF.first && inPDF.second ) ) Throw() << "LesHouchesReader '" << name() << "' could not create PDFBase objects in pre-initialization." << Exception::warning; } else if ( !inPDF.first || !inPDF.second ) Throw() << "No information about the PDFs of incoming particles were found in " << "LesHouchesReader '" << name() << "'." << Exception::warning; } void LesHouchesReader::initPDFs() { if ( inPDF.first && inPDF.second ) return; string remhname; if ( heprup.PDFSUP.first && !inPDF.first) { inPDF.first = dynamic_ptr_cast (generator()->preinitCreate("ThePEG::LHAPDF", fullName() + "/PDFA", "ThePEGLHAPDF.so")); if ( !inPDF.first ) { Throw() << "LesHouchesReader '" << name() << "' could not use information " << "about the PDFs used because the LHAPDF library was not properly " "defined." << Exception::warning; return; } remhname = fullName() + "/DummyRemH"; generator()->preinitCreate("ThePEG::NoRemnants", remhname); generator()->preinitInterface(inPDF.first, "RemnantHandler", "set", remhname); if ( heprup.PDFGUP.first > 0 && heprup.PDFGUP.first < 10 ) { ostringstream os; os << heprup.PDFGUP.first << " " << heprup.PDFSUP.first; generator()->preinitInterface(inPDF.first, "PDFLIBNumbers", "set", os.str()); } else { ostringstream os; os << heprup.PDFGUP.first*1000 + heprup.PDFSUP.first; generator()->preinitInterface(inPDF.first, "PDFNumber", "set", os.str()); } generator()->preinitInterface(inPDF.first, "RangeException", "newdef", "Freeze"); } if ( heprup.PDFSUP.second && !inPDF.second) { inPDF.second = dynamic_ptr_cast (generator()->preinitCreate("ThePEG::LHAPDF", fullName() + "/PDFB", "ThePEGLHAPDF.so")); if ( !inPDF.second ) { Throw() << "LesHouchesReader '" << name() << "' could not use information " << "about the PDFs used because the LHAPDF library was not properly " "defined." << Exception::warning; return; } if ( remhname == "" ) { remhname = fullName() + "/DummyRemH"; generator()->preinitCreate("ThePEG::NoRemnants", remhname); } generator()->preinitInterface(inPDF.second, "RemnantHandler", "set", remhname); if ( heprup.PDFGUP.second > 0 && heprup.PDFGUP.second < 10 ) { ostringstream os; os << heprup.PDFGUP.second << " " << heprup.PDFSUP.second; generator()->preinitInterface(inPDF.second, "PDFLIBNumbers", "set", os.str()); } else { ostringstream os; os << heprup.PDFGUP.second*1000 + heprup.PDFSUP.second; generator()->preinitInterface(inPDF.second, "PDFNumber", "set", os.str()); } generator()->preinitInterface(inPDF.second, "RangeException", "newdef", "Freeze"); } if ( ! ( inPDF.first && inPDF.second ) ) Throw() << "LesHouchesReader '" << name() << "' could not find information about the PDFs used." << Exception::warning; } void LesHouchesReader::initialize(LesHouchesEventHandler & eh) { Energy2 Smax = ZERO; double Y = 0.0; if ( !theCuts ) { theCuts = eh.cuts(); if ( !theCuts ) Throw() << "No Cuts object was assigned to the LesHouchesReader '" << name() << "' nor was one\nassigned to the controlling " << "LesHouchesEventHandler '" << eh.name() << "'.\nAt least one of them " << "needs to have a Cuts object." << Exception::runerror; Smax = cuts().SMax(); Y = cuts().Y(); } theCKKW = eh.CKKWHandler(); if ( !partonExtractor() ) { thePartonExtractor = eh.partonExtractor(); if ( !partonExtractor() ) Throw() << "No PartonExtractor object was assigned to the LesHouchesReader '" << name() << "' nor was one\nassigned to the controlling " << "LesHouchesEventHandler '" << eh.name() << "'.\nAt least one of them " << "needs to have a PartonExtractor object." << Exception::runerror; } open(); Energy emax = 2.0*sqrt(heprup.EBMUP.first*heprup.EBMUP.second)*GeV; theCuts->initialize(sqr(emax), 0.5*log(heprup.EBMUP.first/heprup.EBMUP.second)); if ( Smax > ZERO && ( Smax != cuts().SMax() || Y != cuts().Y() ) ) Throw() << "The LesHouchesReader '" << name() << "' uses the same Cuts object " << "as another LesHouchesReader which has not got the same energies of " << "the colliding particles. For the generation to work properly " << "different LesHouchesReader object with different colliding particles " << "must be assigned different (although possibly identical) Cuts " << "objects." << Exception::warning; thePartonBins = partonExtractor()->getPartons(emax, inData, cuts()); for ( int i = 0, N = partonBins().size(); i < N; ++i ) { theXCombs[partonBins()[i]] = new_ptr(XComb(emax, inData, &eh, partonExtractor(), CKKWHandler(), partonBins()[i], theCuts)); partonExtractor()->nDims(partonBins()[i]); } outPDF = make_pair(partonExtractor()->getPDF(inData.first), partonExtractor()->getPDF(inData.second)); close(); if ( !heprup.IDWTUP && useWeightWarnings ) Throw() << "No information about the weighting scheme was found. The events " << "produced by LesHouchesReader " << name() << " may not be sampled correctly." << Exception::warning; if ( abs(heprup.IDWTUP) > 1 && !eh.weighted() && useWeightWarnings ) Throw() << "LesHouchesReader " << name() << " has the IDWTUP flag set to " << heprup.IDWTUP << " which is not supported by this reader, the " << "produced events may not be sampled correctly. It is up to " << "sub-classes of LesHouchesReader to correctly convert to match IDWTUP " << "+/- 1. Will try to make intelligent guesses to get " << "correct statistics.\nIn most cases this should be sufficient. " << "Unset WeightWarnings to avoid this message," << "or set Weighted to on." << Exception::warning; if ( heprup.IDWTUP != eh.weightOption() && abs(heprup.IDWTUP) < 3 && useWeightWarnings ) Throw() << "LesHouchesReader " << name() << " has the IDWTUP flag set to " << heprup.IDWTUP << ", which does not correspond\nto the weight option " << eh.weightOption() << " set in " << "the LesHouchesEventHandler " << eh.name() << ".\n\n" << "Use the following handler setting instead:\n" << " set " << eh.name() << ":WeightOption " << heprup.IDWTUP << "\nWill try to make intelligent guesses to get " << "correct statistics. In most cases this should be sufficient. " << "Unset WeightWarnings to avoid this message" << Exception::warning; scan(); initStat(); } long LesHouchesReader::scan() { open(); // Shall we write the events to a cache file for fast reading? If so // we write to a temporary file if the caches events should be // randomized. if ( cacheFileName().length() ) openWriteCacheFile(); // Keep track of the number of events scanned. long neve = 0; long cuteve = 0; bool negw = false; // If the open() has not already gotten information about subprocesses // and cross sections we have to scan through the events. if ( !heprup.NPRUP || cacheFile() || abs(heprup.IDWTUP) != 1 ) { // why scan if IDWTUP != 1? HoldFlag<> isScanning(scanning); double oldsum = 0.0; vector lprup; vector newmax; vector oldeve; vector neweve; vector sumlprup; vector sumsqlprup; vector nscanned; for ( int i = 0; ( maxScan() < 0 || i < maxScan() ) && readEvent(); ++i ) { if ( !checkPartonBin() ) Throw() << "Found event in LesHouchesReader '" << name() << "' which cannot be handeled by the assigned PartonExtractor '" << partonExtractor()->name() << "'." << Exception::runerror; vector::iterator idit = find(lprup.begin(), lprup.end(), hepeup.IDPRUP); int id = lprup.size(); if ( idit == lprup.end() ) { lprup.push_back(hepeup.IDPRUP); newmax.push_back(0.0); neweve.push_back(0); oldeve.push_back(0); sumlprup.push_back(0.); sumsqlprup.push_back(0.); nscanned.push_back(0); } else { id = idit - lprup.begin(); } ++neve; ++oldeve[id]; oldsum += hepeup.XWGTUP; sumlprup[id] += hepeup.XWGTUP; sumsqlprup[id] += sqr(hepeup.XWGTUP); ++nscanned[id]; if ( cacheFile() ) { if ( eventWeight() == 0.0 ) { ++cuteve; continue; } cacheEvent(); } ++neweve[id]; newmax[id] = max(newmax[id], abs(eventWeight())); if ( eventWeight() < 0.0 ) negw = true; } //end of scanning events xSecWeights.resize(oldeve.size(), 1.0); for ( int i = 0, N = oldeve.size(); i < N; ++i ) if ( oldeve[i] ) xSecWeights[i] = double(neweve[i])/double(oldeve[i]); if ( maxScan() < 0 || neve > NEvents() ) NEvents(neve - cuteve); if ( lprup.size() == heprup.LPRUP.size() ) { for ( int id = 0, N = lprup.size(); id < N; ++id ) { vector::iterator idit = find(heprup.LPRUP.begin(), heprup.LPRUP.end(), hepeup.IDPRUP); if ( idit == heprup.LPRUP.end() ) { Throw() << "When scanning events, the LesHouschesReader '" << name() << "' found undeclared processes." << Exception::warning; heprup.NPRUP = 0; break; } int idh = idit - heprup.LPRUP.begin(); heprup.XMAXUP[idh] = newmax[id]; } } if ( heprup.NPRUP == 0 ) { // No heprup block was supplied or something went wrong. heprup.NPRUP = lprup.size(); heprup.LPRUP.resize(lprup.size()); heprup.XMAXUP.resize(lprup.size()); for ( int id = 0, N = lprup.size(); id < N; ++id ) { heprup.LPRUP[id] = lprup[id]; heprup.XMAXUP[id] = newmax[id]; } } if ( abs(heprup.IDWTUP) != 1 ) { // Try to fix things if abs(heprup.IDWTUP) != 1. double sumxsec = 0.0; if(abs(heprup.IDWTUP)==3) { for ( int id = 0; id < heprup.NPRUP; ++id ) sumxsec += heprup.XSECUP[id]; } else { for ( int id = 0; id < heprup.NPRUP; ++id ) { //set the cross section directly from the event weights read heprup.XSECUP[id] = sumlprup[id]/nscanned[id]; heprup.XERRUP[id] = (sumsqlprup[id]/nscanned[id] - sqr(sumlprup[id]/nscanned[id])) / nscanned[id]; if(heprup.XERRUP[id] < 0.) { if( heprup.XERRUP[id]/(sumsqlprup[id]/nscanned[id])>-1e-10) heprup.XERRUP[id] = 0.; else { Throw() << "Negative error when scanning events in LesHouschesReader '" << name() << Exception::warning; heprup.XERRUP[id] = 0.; } } heprup.XERRUP[id] = sqrt( heprup.XERRUP[id] ); heprup.XMAXUP[id] = newmax[id]; sumxsec += heprup.XSECUP[id]; } } weightScale = picobarn*neve*sumxsec/oldsum; } } if ( cacheFile() ) closeCacheFile(); if ( negw ) heprup.IDWTUP = min(-abs(heprup.IDWTUP), -1); return neve; } void LesHouchesReader::setWeightScale(long) {} void LesHouchesReader::initStat() { stats.reset(); statmap.clear(); if ( heprup.NPRUP <= 0 ) return; double sumx = 0.0; xSecWeights.resize(heprup.NPRUP, 1.0); maxWeights.clear(); for ( int ip = 0; ip < heprup.NPRUP; ++ip ) { sumx = max(heprup.XMAXUP[ip]*xSecWeights[ip], sumx); statmap[heprup.LPRUP[ip]] = XSecStat(heprup.XMAXUP[ip]*weightScale*xSecWeights[ip]); maxWeights[heprup.LPRUP[ip]] = heprup.XMAXUP[ip]; } stats.maxXSec(sumx*weightScale); maxFactor = 1.0; } void LesHouchesReader::increaseMaxXSec(CrossSection maxxsec) { for ( int i = 0; i < heprup.NPRUP; ++i ) statmap[heprup.LPRUP[i]].maxXSec(statmap[heprup.LPRUP[i]].maxXSec()* maxxsec/stats.maxXSec()); maxFactor *= maxxsec/stats.maxXSec(); stats.maxXSec(maxxsec); } tXCombPtr LesHouchesReader::getXComb() { if ( lastXCombPtr() ) return lastXCombPtr(); fillEvent(); connectMothers(); tcPBPair sel = createPartonBinInstances(); tXCombPtr lastXC = xCombs()[sel]; // clean up the old XComb object before switching to a new one if ( theLastXComb && theLastXComb != lastXC ) theLastXComb->clean(); theLastXComb = lastXC; lastXCombPtr()->subProcess(SubProPtr()); lastXCombPtr()->setPartonBinInstances(partonBinInstances(), sqr(hepeup.SCALUP)*GeV2); lastXCombPtr()->lastAlphaS(hepeup.AQCDUP); lastXCombPtr()->lastAlphaEM(hepeup.AQEDUP); return lastXCombPtr(); } tSubProPtr LesHouchesReader::getSubProcess() { getXComb(); if ( subProcess() ) return subProcess(); lastXCombPtr()->subProcess(new_ptr(SubProcess(lastPartons(), tCollPtr(), this))); subProcess()->setOutgoing(outgoing().begin(), outgoing().end()); subProcess()->setIntermediates(intermediates().begin(), intermediates().end()); return subProcess(); } void LesHouchesReader::fillEvent() { if ( !particleIndex.empty() ) return; particleIndex.clear(); colourIndex.clear(); colourIndex(0, tColinePtr()); createParticles(); createBeams(); } void LesHouchesReader::reopen() { // If we didn't know how many events there were, we know now. if ( NEvents() <= 0 ) NEvents(position); ++reopened; // How large fraction of the events have we actually used? And how // large will we have used if we go through the file again? double frac = double(stats.attempts())/double(NEvents()); if ( frac*double(reopened + 1)/double(reopened) > 1.0 && NEvents() - stats.attempts() < generator()->N() - generator()->currentEventNumber() ) { if(theReOpenAllowed) generator()->logWarning(LesHouchesReopenWarning() << "Reopening LesHouchesReader '" << name() << "' after accessing " << stats.attempts() << " events out of " << NEvents() << Exception::warning); else throw LesHouchesReopenWarning() << "More events requested than available in LesHouchesReader " << name() << Exception::runerror; } if ( cacheFile() ) { closeCacheFile(); openReadCacheFile(); if ( !uncacheEvent() ) Throw() << "Could not reopen LesHouchesReader '" << name() << "'." << Exception::runerror; } else { close(); open(); if ( !readEvent() ) Throw() << "Could not reopen LesHouchesReader '" << name() << "'." << Exception::runerror; } } void LesHouchesReader::reset() { particleIndex.clear(); colourIndex.clear(); if ( theLastXComb ) theLastXComb->clean(); theLastXComb = tXCombPtr(); } bool LesHouchesReader::readEvent() { reset(); if ( !doReadEvent() ) return false; // If we are just skipping event we do not need to reweight or do // anything fancy. if ( skipping ) { return true; } if ( cacheFile() && !scanning ) { return true; } // Reweight according to the re- and pre-weights objects in the // LesHouchesReader base class. lastweight = reweight(); if ( !reweightPDF && !cutEarly() ) return true; // We should try to reweight the PDFs or make early cuts here. fillEvent(); double x1 = incoming().first->momentum().plus()/ beams().first->momentum().plus(); if ( reweightPDF && inPDF.first && outPDF.first && inPDF.first != outPDF.first ) { if ( hepeup.XPDWUP.first <= 0.0 ) hepeup.XPDWUP.first = inPDF.first->xfx(inData.first, incoming().first->dataPtr(), sqr(hepeup.SCALUP*GeV), x1); double xf = outPDF.first->xfx(inData.first, incoming().first->dataPtr(), sqr(hepeup.SCALUP*GeV), x1); lastweight *= xf/hepeup.XPDWUP.first; hepeup.XPDWUP.first = xf; } double x2 = incoming().second->momentum().minus()/ beams().second->momentum().minus(); if ( reweightPDF && inPDF.second && outPDF.second && inPDF.second != outPDF.second ) { if ( hepeup.XPDWUP.second <= 0.0 ) hepeup.XPDWUP.second = inPDF.second->xfx(inData.second, incoming().second->dataPtr(), sqr(hepeup.SCALUP*GeV), x2); double xf = outPDF.second->xfx(inData.second, incoming().second->dataPtr(), sqr(hepeup.SCALUP*GeV), x2); lastweight *= xf/hepeup.XPDWUP.second; hepeup.XPDWUP.second = xf; } if ( cutEarly() ) { if ( !cuts().initSubProcess((incoming().first->momentum() + incoming().second->momentum()).m2(), 0.5*log(x1/x2)) ) lastweight = 0.0; tSubProPtr sub = getSubProcess(); TmpTransform tmp(sub, Utilities::getBoostToCM(sub->incoming())); if ( !cuts().passCuts(*sub) ) lastweight = 0.0; } return true; } double LesHouchesReader::getEvent() { if ( cacheFile() ) { if ( !uncacheEvent() ) reopen(); } else { if ( !readEvent() ) reopen(); } ++position; double max = maxWeights[hepeup.IDPRUP]*maxFactor; - return max != 0.0? eventWeight()/max: 0.0; + // normalize all the weights to the max weight + for(map::iterator it=optionalWeights.begin(); + it!=optionalWeights.end();++it) { + it->second = (max != 0.0) ? it->second/max : 0.0; + } + return (max != 0.0) ? eventWeight()/max : 0.0; } void LesHouchesReader::skip(long n) { HoldFlag<> skipflag(skipping); while ( n-- ) getEvent(); } double LesHouchesReader::reweight() { preweight = 1.0; if ( reweights.empty() && preweights.empty() && !( CKKWHandler() && maxMultCKKW() > 0 && maxMultCKKW() > minMultCKKW() ) ) return 1.0; fillEvent(); getSubProcess(); for ( int i = 0, N = preweights.size(); i < N; ++i ) { preweights[i]->setXComb(lastXCombPtr()); preweight *= preweights[i]->weight(); } double weight = preweight; for ( int i = 0, N = reweights.size(); i < N; ++i ) { reweights[i]->setXComb(lastXCombPtr()); weight *= reweights[i]->weight(); } // If we are caching events we do not want to do CKKW reweighting. if ( cacheFile() ) return weight; if ( CKKWHandler() && maxMultCKKW() > 0 && maxMultCKKW() > minMultCKKW() ) { CKKWHandler()->setXComb(lastXCombPtr()); weight *= CKKWHandler()->reweightCKKW(minMultCKKW(), maxMultCKKW()); } return weight; } bool LesHouchesReader::checkPartonBin() { // First find the positions of the incoming partons. pair< vector, vector > inc; for ( int i = 0; i < hepeup.NUP; ++i ) { if ( hepeup.ISTUP[i] == -9 ) { if ( inc.first.empty() ) inc.first.push_back(i); else if ( inc.second.empty() ) inc.second.push_back(i); } else if ( hepeup.ISTUP[i] == -1 ) { if ( inc.first.size() && hepeup.MOTHUP[i].first == inc.first.back() + 1 ) inc.first.push_back(i); else if ( inc.second.size() && hepeup.MOTHUP[i].first == inc.second.back() + 1 ) inc.second.push_back(i); else if ( inc.first.empty() ) { inc.first.push_back(-1); inc.first.push_back(i); } else if ( inc.second.empty() ) { inc.second.push_back(-1); inc.second.push_back(i); } else if ( inc.first.size() <= inc.second.size() ) inc.first.push_back(i); else inc.second.push_back(i); } } // Now store the corresponding id numbers pair< vector, vector > ids; ids.first.push_back(inc.first[0] < 0? heprup.IDBMUP.first: hepeup.IDUP[inc.first[0]]); for ( int i = 1, N = inc.first.size(); i < N; ++i ) ids.first.push_back(hepeup.IDUP[inc.first[i]]); ids.second.push_back(inc.second[0] < 0? heprup.IDBMUP.second: hepeup.IDUP[inc.second[0]]); for ( int i = 1, N = inc.second.size(); i < N; ++i ) ids.second.push_back(hepeup.IDUP[inc.second[i]]); // Find the correct pair of parton bins. PBPair pbp; for ( int i = 0, N = partonBins().size(); i < N; ++i ) { tcPBPtr curr = partonBins()[i].first; int icurr = inc.first.size() - 1; while ( curr && icurr >= 0 ) { if ( curr->parton()->id () != ids.first[icurr] ) break; curr = curr->incoming(); --icurr; } if(!(!partonBins()[i].first->incoming() && !partonBins()[i].first->particle() && partonBins()[i].first->parton()->id () == ids.first[0] && ( inc.first.size()==1 || (inc.first.size()==2 && ids.first[0]==ids.first[1]))) && ( curr || icurr >= 0 ) ) continue; curr = partonBins()[i].second; icurr = inc.second.size() - 1; while ( curr && icurr >= 0 ) { if ( curr->parton()->id () != ids.second[icurr] ) break; curr = curr->incoming(); --icurr; } if(!(!partonBins()[i].second->incoming() && !partonBins()[i].second->particle() && partonBins()[i].second->parton()->id () == ids.second[0] && ( inc.second.size()==1 || (inc.second.size()==2 && ids.second[0]==ids.second[1]))) && ( curr || icurr >= 0 ) ) continue; pbp = partonBins()[i]; } // If we are only checking we return here. return ( pbp.first && pbp.second ); } namespace { bool recursionNotNull(tcPBPtr bin, tcPPtr p) { while ( bin && p ) { if ( p->dataPtr() != bin->parton() ) break; bin = bin->incoming(); p = p->parents().size()? p->parents()[0]: tPPtr(); } return bin || p; } } tcPBPair LesHouchesReader::createPartonBinInstances() { tcPBPair sel; for ( int i = 0, N = partonBins().size(); i < N; ++i ) { tcPBPtr bin = partonBins()[i].first; tcPPtr p = incoming().first; if ( recursionNotNull(bin,p) ) continue; bin = partonBins()[i].second; p = incoming().second; if ( recursionNotNull(bin,p) ) continue; sel = partonBins()[i]; break; } if ( !sel.first || !sel.second ) Throw() << "Could not find appropriate PartonBin objects for event produced by " << "LesHouchesReader '" << name() << "'." << Exception::runerror; Direction<0> dir(true); thePartonBinInstances.first = new_ptr(PartonBinInstance(incoming().first, sel.first, -sqr(hepeup.SCALUP*GeV))); if ( thePartonBinInstances.first->xi() > 1.00001 ) { Throw() << "Found an event with momentum fraction larger than unity (x1=" << thePartonBinInstances.first->xi() << "). The event will be skipped." << Exception::warning; throw Veto(); } dir.reverse(); thePartonBinInstances.second = new_ptr(PartonBinInstance(incoming().second, sel.second, -sqr(hepeup.SCALUP*GeV))); if ( thePartonBinInstances.second->xi() > 1.00001 ) { Throw() << "Found an event with momentum fraction larger than unity (x2=" << thePartonBinInstances.second->xi() << "). The event will be skipped." << Exception::warning; throw Veto(); } return sel; } void LesHouchesReader::createParticles() { theBeams = PPair(); theIncoming = PPair(); theOutgoing = PVector(); theIntermediates = PVector(); for ( int i = 0, N = hepeup.IDUP.size(); i < N; ++i ) { if ( !hepeup.IDUP[i] ) continue; Lorentz5Momentum mom(hepeup.PUP[i][0]*GeV, hepeup.PUP[i][1]*GeV, hepeup.PUP[i][2]*GeV, hepeup.PUP[i][3]*GeV, hepeup.PUP[i][4]*GeV); // cout << hepeup.PUP[i][0] << " " << hepeup.PUP[i][1] << " " << hepeup.PUP[i][2] << " " << hepeup.PUP[i][3] << " " << hepeup.PUP[i][4] << endl; if(theMomentumTreatment == 1) mom.rescaleEnergy(); else if(theMomentumTreatment == 2) mom.rescaleMass(); // cout << hepeup.PUP[i][0] << " " << hepeup.PUP[i][1] << " " << hepeup.PUP[i][2] << " " << hepeup.PUP[i][3] << " " << hepeup.PUP[i][4] << endl; PDPtr pd = getParticleData(hepeup.IDUP[i]); if (!pd) { Throw() << "LesHouchesReader '" << name() << "' found unknown particle ID " << hepeup.IDUP[i] << " in Les Houches common block structure.\n" << "You need to define the new particle in an input file.\n" << Exception::runerror; } if ( ! pd->coloured() && ( hepeup.ICOLUP[i].first != 0 || hepeup.ICOLUP[i].second != 0 ) ) { Throw() << "LesHouchesReader " << name() << ": " << pd->PDGName() << " is not a coloured particle.\nIt should not have " << "(anti-)colour lines " << hepeup.ICOLUP[i].first << ' ' << hepeup.ICOLUP[i].second << " set; the event file needs to be fixed." << Exception::runerror; } PPtr p = pd->produceParticle(mom); if(hepeup.ICOLUP[i].first>=0 && hepeup.ICOLUP[i].second >=0) { tColinePtr c = colourIndex(hepeup.ICOLUP[i].first); if ( c ) { c->addColoured(p); } c = colourIndex(hepeup.ICOLUP[i].second); if ( c ) c->addAntiColoured(p); } else { tColinePtr c1 = colourIndex(abs(hepeup.ICOLUP[i].first )); tColinePtr c2 = colourIndex(abs(hepeup.ICOLUP[i].second)); if(pd->hasColour()) { c1->addColouredIndexed(p,1); c2->addColouredIndexed(p,2); } else { c1->addAntiColouredIndexed(p,1); c2->addAntiColouredIndexed(p,2); } } particleIndex(i + 1, p); switch ( hepeup.ISTUP[i] ) { case -9: if ( !theBeams.first ) theBeams.first = p; else if ( !theBeams.second ) theBeams.second = p; else Throw() << "To many incoming beam particles in the LesHouchesReader '" << name() << "'." << Exception::runerror; break; case -1: if ( !theIncoming.first ) theIncoming.first = p; else if ( !theIncoming.second ) theIncoming.second = p; else if ( particleIndex(theIncoming.first) == hepeup.MOTHUP[i].first ) theIncoming.first = p; else if ( particleIndex(theIncoming.second) == hepeup.MOTHUP[i].first ) theIncoming.second = p; else Throw() << "To many incoming particles to hard subprocess in the " << "LesHouchesReader '" << name() << "'." << Exception::runerror; p->scale(sqr(hepeup.SCALUP*GeV)); break; case 1: theOutgoing.push_back(p); p->scale(sqr(hepeup.SCALUP*GeV)); break; case -2: case 2: case 3: theIntermediates.push_back(p); break; default: Throw() << "Unknown status code (" << hepeup.ISTUP[i] << ") in the LesHouchesReader '" << name() << "'." << Exception::runerror; } // value 9 is defined as "Unknown or unpolarized particles" double spinup = hepeup.SPINUP[i]; if ( abs(spinup - 9) < 1.0e-3 ) spinup = 0.; if ( spinup < -1. || spinup > 1. ) { Throw() << "Polarization must be between -1 and 1, not " << spinup << " as found in the " << "LesHouches event file.\nThe event file needs to be fixed." << Exception::runerror; } if( theIncludeSpin && abs(pd->id()) == ParticleID::tauminus && spinup !=0) { if(pd->iSpin() == PDT::Spin1Half ) { vector wave; Helicity::SpinorWaveFunction(wave,p,Helicity::outgoing,true); RhoDMatrix rho(pd->iSpin(),true); rho(0,0) = 0.5*(1.-spinup); rho(1,1) = 0.5*(1.+spinup); p->spinInfo()->rhoMatrix() = rho; p->spinInfo()-> DMatrix() = rho; } } } // check the colour flows, and if necessary create any sources/sinks // hard process // get the particles in the hard process PVector external; for ( int i = 0, N = hepeup.IDUP.size(); i < N; ++i ) { unsigned int moth; switch ( hepeup.ISTUP[i] ) { case -1: external.push_back(particleIndex.find(i+1)); break; case 1: case 2: case 3: moth = hepeup.MOTHUP[i].first; if(moth!=0 && (hepeup.ISTUP[moth]==-1||hepeup.ISTUP[moth]==-2|| hepeup.ISTUP[moth]==-9)) external.push_back(particleIndex.find(i+1)); moth = hepeup.MOTHUP[i].second; if(moth!=0 && (hepeup.ISTUP[moth]==-1||hepeup.ISTUP[moth]==-2|| hepeup.ISTUP[moth]==-9)) external.push_back(particleIndex.find(i+1)); break; case -2: case -9: default: break; } } // check the incoming/outgoing lines match vector unMatchedColour,unMatchedAntiColour; for(unsigned int ix=0;ix col = external[ix]->colourInfo()-> colourLines(); vector anti = external[ix]->colourInfo()->antiColourLines(); if(hepeup.ISTUP[particleIndex(external[ix])-1]<0) swap(col,anti); if(!col.empty()) { for(unsigned int ic1=0;ic1 col2; if(hepeup.ISTUP[particleIndex(external[iy])-1]<0) { if(external[iy]->colourInfo()->colourLines().empty()) continue; col2 = external[iy]->colourInfo()->colourLines(); } else if(hepeup.ISTUP[particleIndex(external[iy])-1]>0) { if(external[iy]->colourInfo()->antiColourLines().empty()) continue; col2 = external[iy]->colourInfo()->antiColourLines(); } for(unsigned int ic2=0;ic2(col[ic1])); } } if(!anti.empty()) { for(unsigned int ic1=0;ic1 anti2; if(hepeup.ISTUP[particleIndex(external[iy])-1]<0) { if(external[iy]->colourInfo()->colourLines().empty()) continue; anti2 = external[iy]->colourInfo()->antiColourLines(); } else if(hepeup.ISTUP[particleIndex(external[iy])-1]>0) { if(external[iy]->colourInfo()->antiColourLines().empty()) continue; anti2 = external[iy]->colourInfo()->colourLines(); } for(unsigned int ic2=0;ic2(anti[ic1])); } } } // might have source/sink if( unMatchedColour.size() + unMatchedAntiColour.size() != 0) { if(unMatchedColour.size() == 3 ) { unMatchedColour[0]->setSourceNeighbours(unMatchedColour[1], unMatchedColour[2]); } else if(unMatchedColour.size() != 0 && ThePEG_DEBUG_LEVEL) { Throw() << "LesHouchesReader '" << name() << "' found inconsistent colour " << "flow in Les Houches common block structure for hard process.\n" << hepeup << Exception::runerror; } if(unMatchedAntiColour.size() == 3 ) { unMatchedAntiColour[0]->setSinkNeighbours(unMatchedAntiColour[1], unMatchedAntiColour[2]); } else if(unMatchedAntiColour.size() != 0 && ThePEG_DEBUG_LEVEL) { Throw() << "LesHouchesReader '" << name() << "' found inconsistent colour " << "flow in Les Houches common block structure for hard process.\n" << hepeup << Exception::runerror; } } // any subsequent decays for ( int i = 0, N = hepeup.IDUP.size(); i < N; ++i ) { if(hepeup.ISTUP[i] !=2 && hepeup.ISTUP[i] !=3) continue; PVector external; external.push_back(particleIndex.find(i+1)); for ( int j = 0; j < N; ++j ) { if(hepeup.MOTHUP[j].first==i+1|| hepeup.MOTHUP[j].second==i+1) external.push_back(particleIndex.find(j+1)); } // check the incoming/outgoing lines match vector unMatchedColour,unMatchedAntiColour; for(unsigned int ix=0;ix col = external[ix]->colourInfo()-> colourLines(); vector anti = external[ix]->colourInfo()->antiColourLines(); if(ix==0) swap(col,anti); if(!col.empty()) { for(unsigned int ic1=0;ic1 col2; if(iy==0) { if(external[iy]->colourInfo()->colourLines().empty()) continue; col2 = external[iy]->colourInfo()->colourLines(); } else { if(external[iy]->colourInfo()->antiColourLines().empty()) continue; col2 = external[iy]->colourInfo()->antiColourLines(); } for(unsigned int ic2=0;ic2(col[ic1])); } } if(!anti.empty()) { for(unsigned int ic1=0;ic1 anti2; if(iy==0) { if(external[iy]->colourInfo()->antiColourLines().empty()) continue; anti2 = external[iy]->colourInfo()->antiColourLines(); } else { if(external[iy]->colourInfo()->colourLines().empty()) continue; anti2 = external[iy]->colourInfo()->colourLines(); } for(unsigned int ic2=0;ic2(anti[ic1])); } } } // might have source/sink if( unMatchedColour.size() + unMatchedAntiColour.size() != 0) { if(unMatchedColour.size() == 3 ) { unMatchedColour[0]->setSourceNeighbours(unMatchedColour[1], unMatchedColour[2]); } else if(unMatchedColour.size() != 0 && ThePEG_DEBUG_LEVEL) { Throw() << "LesHouchesReader '" << name() << "' found inconsistent colour " << "flow in Les Houches common block structure for decay of \n" << *external[0] << "\n" << hepeup << Exception::runerror; } if(unMatchedAntiColour.size() == 3 ) { unMatchedAntiColour[0]->setSinkNeighbours(unMatchedAntiColour[1], unMatchedAntiColour[2]); } else if(unMatchedAntiColour.size() != 0 && ThePEG_DEBUG_LEVEL) { Throw() << "LesHouchesReader '" << name() << "' found inconsistent colour " << "flow in Les Houches common block structure for decay of\n" << *external[0] << "\n" << hepeup << Exception::runerror; } } } } void LesHouchesReader::createBeams() { if ( !theBeams.first && dynamic_ptr_cast::tcp>(inPDF.first) ) { theBeams.first = theIncoming.first; } else if ( !theBeams.first ) { theBeams.first = getParticleData(heprup.IDBMUP.first)->produceParticle(); double m = theBeams.first->mass()/GeV; theBeams.first->set5Momentum (Lorentz5Momentum(ZERO, ZERO, sqrt(sqr(heprup.EBMUP.first) - sqr(m))*GeV, heprup.EBMUP.first*GeV, m*GeV)); hepeup.IDUP.push_back(heprup.IDBMUP.first); hepeup.ISTUP.push_back(-9); hepeup.MOTHUP.push_back(make_pair(0, 0)); hepeup.ICOLUP.push_back(make_pair(0, 0)); hepeup.VTIMUP.push_back(0.0); hepeup.SPINUP.push_back(0.0); particleIndex(hepeup.IDUP.size(), theBeams.first); hepeup.MOTHUP[particleIndex(theIncoming.first) - 1].first = hepeup.IDUP.size(); } if ( !theBeams.second && dynamic_ptr_cast::tcp>(inPDF.second) ) { theBeams.second = theIncoming.second; } else if ( !theBeams.second ) { theBeams.second = getParticleData(heprup.IDBMUP.second)->produceParticle(); double m = theBeams.second->mass()/GeV; theBeams.second->set5Momentum (Lorentz5Momentum(ZERO, ZERO, -sqrt(sqr(heprup.EBMUP.second) - sqr(m))*GeV, heprup.EBMUP.second*GeV, m*GeV)); hepeup.IDUP.push_back(heprup.IDBMUP.second); hepeup.ISTUP.push_back(-9); hepeup.MOTHUP.push_back(make_pair(0, 0)); hepeup.ICOLUP.push_back(make_pair(0, 0)); hepeup.VTIMUP.push_back(0.0); hepeup.SPINUP.push_back(0.0); particleIndex(hepeup.IDUP.size(), theBeams.second); hepeup.MOTHUP[particleIndex(theIncoming.second) - 1].first = hepeup.IDUP.size(); } } void LesHouchesReader::connectMothers() { const ObjectIndexer & pi = particleIndex; for ( int i = 0, N = hepeup.IDUP.size(); i < N; ++i ) { if ( pi(hepeup.MOTHUP[i].first) ) pi(hepeup.MOTHUP[i].first)->addChild(pi(i + 1)); if ( pi(hepeup.MOTHUP[i].second) && hepeup.MOTHUP[i].second != hepeup.MOTHUP[i].first ) pi(hepeup.MOTHUP[i].second)->addChild(pi(i + 1)); } } void LesHouchesReader::openReadCacheFile() { if ( cacheFile() ) closeCacheFile(); cacheFile().open(cacheFileName(), "r"); position = 0; } void LesHouchesReader::openWriteCacheFile() { if ( cacheFile() ) closeCacheFile(); cacheFile().open(cacheFileName(), "w"); } void LesHouchesReader::closeCacheFile() { cacheFile().close(); } void LesHouchesReader::cacheEvent() const { static vector buff; cacheFile().write(&hepeup.NUP, sizeof(hepeup.NUP)); buff.resize(eventSize(hepeup.NUP)); char * pos = &buff[0]; pos = mwrite(pos, hepeup.IDPRUP); pos = mwrite(pos, hepeup.XWGTUP); pos = mwrite(pos, hepeup.XPDWUP); pos = mwrite(pos, hepeup.SCALUP); pos = mwrite(pos, hepeup.AQEDUP); pos = mwrite(pos, hepeup.AQCDUP); pos = mwrite(pos, hepeup.IDUP[0], hepeup.NUP); pos = mwrite(pos, hepeup.ISTUP[0], hepeup.NUP); pos = mwrite(pos, hepeup.MOTHUP[0], hepeup.NUP); pos = mwrite(pos, hepeup.ICOLUP[0], hepeup.NUP); for ( int i = 0; i < hepeup.NUP; ++i ) pos = mwrite(pos, hepeup.PUP[i][0], 5); pos = mwrite(pos, hepeup.VTIMUP[0], hepeup.NUP); pos = mwrite(pos, hepeup.SPINUP[0], hepeup.NUP); pos = mwrite(pos, lastweight); pos = mwrite(pos, optionalWeights); for(size_t ff = 0; ff < optionalWeightsNames.size(); ff++) { pos = mwrite(pos, optionalWeightsNames[ff]); } pos = mwrite(pos, optionalnpLO); pos = mwrite(pos, optionalnpNLO); pos = mwrite(pos, preweight); cacheFile().write(&buff[0], buff.size(), 1); } bool LesHouchesReader::uncacheEvent() { reset(); static vector buff; if ( cacheFile().read(&hepeup.NUP, sizeof(hepeup.NUP)) != 1 ) return false; buff.resize(eventSize(hepeup.NUP)); if ( cacheFile().read(&buff[0], buff.size()) != 1 ) return false; const char * pos = &buff[0]; pos = mread(pos, hepeup.IDPRUP); pos = mread(pos, hepeup.XWGTUP); pos = mread(pos, hepeup.XPDWUP); pos = mread(pos, hepeup.SCALUP); pos = mread(pos, hepeup.AQEDUP); pos = mread(pos, hepeup.AQCDUP); hepeup.IDUP.resize(hepeup.NUP); pos = mread(pos, hepeup.IDUP[0], hepeup.NUP); hepeup.ISTUP.resize(hepeup.NUP); pos = mread(pos, hepeup.ISTUP[0], hepeup.NUP); hepeup.MOTHUP.resize(hepeup.NUP); pos = mread(pos, hepeup.MOTHUP[0], hepeup.NUP); hepeup.ICOLUP.resize(hepeup.NUP); pos = mread(pos, hepeup.ICOLUP[0], hepeup.NUP); hepeup.PUP.resize(hepeup.NUP, vector(5)); for ( int i = 0; i < hepeup.NUP; ++i ) pos = mread(pos, hepeup.PUP[i][0], 5); hepeup.VTIMUP.resize(hepeup.NUP); pos = mread(pos, hepeup.VTIMUP[0], hepeup.NUP); hepeup.SPINUP.resize(hepeup.NUP); pos = mread(pos, hepeup.SPINUP[0], hepeup.NUP); pos = mread(pos, lastweight); pos = mread(pos, optionalWeights); for(size_t ff = 0; ff < optionalWeightsNames.size(); ff++) { pos = mread(pos, optionalWeightsNames[ff]); } pos = mread(pos, optionalnpLO); pos = mread(pos, optionalnpNLO); pos = mread(pos, preweight); // If we are skipping, we do not have to do anything else. if ( skipping ) return true; if ( CKKWHandler() && maxMultCKKW() > 0 && maxMultCKKW() > minMultCKKW() ) { // The cached event has not been submitted to CKKW reweighting, so // we do that now. fillEvent(); getSubProcess(); CKKWHandler()->setXComb(lastXCombPtr()); lastweight *= CKKWHandler()->reweightCKKW(minMultCKKW(), maxMultCKKW()); } return true; } void LesHouchesReader::persistentOutput(PersistentOStream & os) const { os << heprup.IDBMUP << heprup.EBMUP << heprup.PDFGUP << heprup.PDFSUP << heprup.IDWTUP << heprup.NPRUP << heprup.XSECUP << heprup.XERRUP << heprup.XMAXUP << heprup.LPRUP << hepeup.NUP << hepeup.IDPRUP << hepeup.XWGTUP << hepeup.XPDWUP << hepeup.SCALUP << hepeup.AQEDUP << hepeup.AQCDUP << hepeup.IDUP << hepeup.ISTUP << hepeup.MOTHUP << hepeup.ICOLUP << hepeup.PUP << hepeup.VTIMUP << hepeup.SPINUP << inData << inPDF << outPDF << thePartonExtractor << theCKKW << thePartonBins << theXCombs << theCuts << theNEvents << position << reopened << theMaxScan << isActive << theCacheFileName << doCutEarly << stats << statmap << thePartonBinInstances << theBeams << theIncoming << theOutgoing << theIntermediates << reweights << preweights << preweight << reweightPDF << doInitPDFs << theLastXComb << theMaxMultCKKW << theMinMultCKKW << lastweight << optionalWeights << optionalnpLO << optionalnpNLO << maxFactor << ounit(weightScale, picobarn) << xSecWeights << maxWeights << theMomentumTreatment << useWeightWarnings << theReOpenAllowed << theIncludeSpin; } void LesHouchesReader::persistentInput(PersistentIStream & is, int) { if ( cacheFile() ) closeCacheFile(); is >> heprup.IDBMUP >> heprup.EBMUP >> heprup.PDFGUP >> heprup.PDFSUP >> heprup.IDWTUP >> heprup.NPRUP >> heprup.XSECUP >> heprup.XERRUP >> heprup.XMAXUP >> heprup.LPRUP >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP >> hepeup.XPDWUP >> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP >> hepeup.IDUP >> hepeup.ISTUP >> hepeup.MOTHUP >> hepeup.ICOLUP >> hepeup.PUP >> hepeup.VTIMUP >> hepeup.SPINUP >> inData >> inPDF >> outPDF >> thePartonExtractor >> theCKKW >> thePartonBins >> theXCombs >> theCuts >> theNEvents >> position >> reopened >> theMaxScan >> isActive >> theCacheFileName >> doCutEarly >> stats >> statmap >> thePartonBinInstances >> theBeams >> theIncoming >> theOutgoing >> theIntermediates >> reweights >> preweights >> preweight >> reweightPDF >> doInitPDFs >> theLastXComb >> theMaxMultCKKW >> theMinMultCKKW >> lastweight >> optionalWeights >> optionalnpLO >> optionalnpNLO >> maxFactor >> iunit(weightScale, picobarn) >> xSecWeights >> maxWeights >> theMomentumTreatment >> useWeightWarnings >> theReOpenAllowed >> theIncludeSpin; } AbstractClassDescription LesHouchesReader::initLesHouchesReader; // Definition of the static class description member. void LesHouchesReader::setBeamA(long id) { heprup.IDBMUP.first = id; } long LesHouchesReader::getBeamA() const { return heprup.IDBMUP.first; } void LesHouchesReader::setBeamB(long id) { heprup.IDBMUP.second = id; } long LesHouchesReader::getBeamB() const { return heprup.IDBMUP.second; } void LesHouchesReader::setEBeamA(Energy e) { heprup.EBMUP.first = e/GeV; } Energy LesHouchesReader::getEBeamA() const { return heprup.EBMUP.first*GeV; } void LesHouchesReader::setEBeamB(Energy e) { heprup.EBMUP.second = e/GeV; } Energy LesHouchesReader::getEBeamB() const { return heprup.EBMUP.second*GeV; } void LesHouchesReader::setPDFA(PDFPtr pdf) { inPDF.first = pdf; } PDFPtr LesHouchesReader::getPDFA() const { return inPDF.first; } void LesHouchesReader::setPDFB(PDFPtr pdf) { inPDF.second = pdf; } PDFPtr LesHouchesReader::getPDFB() const { return inPDF.second; } void LesHouchesReader::Init() { static ClassDocumentation documentation ("ThePEG::LesHouchesReader is an abstract base class to be used " "for objects which reads event files or streams from matrix element " "generators."); static Parameter interfaceBeamA ("BeamA", "The PDG id of the incoming particle along the positive z-axis. " "If zero the corresponding information is to be deduced from the " "event stream/file.", 0, 0, 0, 0, true, false, false, &LesHouchesReader::setBeamA, &LesHouchesReader::getBeamA, 0, 0, 0); static Parameter interfaceBeamB ("BeamB", "The PDG id of the incoming particle along the negative z-axis. " "If zero the corresponding information is to be deduced from the " "event stream/file.", 0, 0, 0, 0, true, false, false, &LesHouchesReader::setBeamB, &LesHouchesReader::getBeamB, 0, 0, 0); static Parameter interfaceEBeamA ("EBeamA", "The energy of the incoming particle along the positive z-axis. " "If zero the corresponding information is to be deduced from the " "event stream/file.", 0, GeV, ZERO, ZERO, 1000000000.0*GeV, true, false, true, &LesHouchesReader::setEBeamA, &LesHouchesReader::getEBeamA, 0, 0, 0); static Parameter interfaceEBeamB ("EBeamB", "The energy of the incoming particle along the negative z-axis. " "If zero the corresponding information is to be deduced from the " "event stream/file.", 0, GeV, ZERO, ZERO, 1000000000.0*GeV, true, false, true, &LesHouchesReader::setEBeamB, &LesHouchesReader::getEBeamB, 0, 0, 0); static Reference interfacePDFA ("PDFA", "The PDF used for incoming particle along the positive z-axis. " "If null the corresponding information is to be deduced from the " "event stream/file.", 0, true, false, true, true, false, &LesHouchesReader::setPDFA, &LesHouchesReader::getPDFA, 0); static Reference interfacePDFB ("PDFB", "The PDF used for incoming particle along the negative z-axis. " "If null the corresponding information is to be deduced from the " "event stream/file.", 0, true, false, true, true, false, &LesHouchesReader::setPDFB, &LesHouchesReader::getPDFB, 0); static Parameter interfaceMaxScan ("MaxScan", "The maximum number of events to scan to obtain information about " "processes and cross section in the intialization.", &LesHouchesReader::theMaxScan, -1, 0, 0, true, false, false); static Parameter interfaceCacheFileName ("CacheFileName", "Name of file used to cache the events from the reader in a fast-readable " "form. If empty, no cache file will be generated.", &LesHouchesReader::theCacheFileName, "", true, false); interfaceCacheFileName.fileType(); static Switch interfaceCutEarly ("CutEarly", "Determines whether to apply cuts to events before converting to " "ThePEG format.", &LesHouchesReader::doCutEarly, true, true, false); static SwitchOption interfaceCutEarlyYes (interfaceCutEarly, "Yes", "Event are cut before converted.", true); static SwitchOption interfaceCutEarlyNo (interfaceCutEarly, "No", "Events are not cut before converted.", false); static Reference interfacePartonExtractor ("PartonExtractor", "The PartonExtractor object used to construct remnants. If no object is " "provided the LesHouchesEventHandler object must provide one instead.", &LesHouchesReader::thePartonExtractor, true, false, true, true, false); static Reference interfaceCuts ("Cuts", "The Cuts object to be used for this reader. Note that these " "must not be looser cuts than those used in the actual generation. " "If no object is provided the LesHouchesEventHandler object must " "provide one instead.", &LesHouchesReader::theCuts, true, false, true, true, false); static RefVector interfaceReweights ("Reweights", "A list of ThePEG::ReweightBase objects to modify this the weight of " "this reader.", &LesHouchesReader::reweights, 0, false, false, true, false); static RefVector interfacePreweights ("Preweights", "A list of ThePEG::ReweightBase objects to bias the phase space for this " "reader without influencing the actual cross section.", &LesHouchesReader::preweights, 0, false, false, true, false); static Switch interfaceReweightPDF ("ReweightPDF", "If the PDFs used in the generation for this reader is different " "from the ones assumed by the associated PartonExtractor object, " "should the events be reweighted to fit the latter?", &LesHouchesReader::reweightPDF, false, true, false); static SwitchOption interfaceReweightPDFNo (interfaceReweightPDF, "No", "The event weights are kept as they are.", false); static SwitchOption interfaceReweightPDFYes (interfaceReweightPDF, "Yes", "The events are reweighted.", true); static Switch interfaceInitPDFs ("InitPDFs", "If no PDFs were specified in PDFA or " "PDFBfor this reader, try to extract the " "information from the event file and assign the relevant PDFBase" "objects when the reader is initialized.", &LesHouchesReader::doInitPDFs, false, true, false); static SwitchOption interfaceInitPDFsYes (interfaceInitPDFs, "Yes", "Extract PDFs during initialization.", true); static SwitchOption interfaceInitPDFsNo (interfaceInitPDFs, "No", "Do not extract PDFs during initialization.", false); static Parameter interfaceMaxMultCKKW ("MaxMultCKKW", "If this reader is to be used (possibly together with others) for CKKW-" "reweighting and veto, this should give the multiplicity of outgoing " "particles in the highest multiplicity matrix element in the group. " "If set to zero, no CKKW procedure should be applied.", &LesHouchesReader::theMaxMultCKKW, 0, 0, 0, true, false, Interface::lowerlim); static Parameter interfaceMinMultCKKW ("MinMultCKKW", "If this reader is to be used (possibly together with others) for CKKW-" "reweighting and veto, this should give the multiplicity of outgoing " "particles in the lowest multiplicity matrix element in the group. If " "larger or equal to MaxMultCKKW, no CKKW " "procedure should be applied.", &LesHouchesReader::theMinMultCKKW, 0, 0, 0, true, false, Interface::lowerlim); static Switch interfaceMomentumTreatment ("MomentumTreatment", "Treatment of the momenta supplied by the interface", &LesHouchesReader::theMomentumTreatment, 0, false, false); static SwitchOption interfaceMomentumTreatmentAccept (interfaceMomentumTreatment, "Accept", "Just accept the momenta given", 0); static SwitchOption interfaceMomentumTreatmentRescaleEnergy (interfaceMomentumTreatment, "RescaleEnergy", "Rescale the energy supplied so it is consistent with the mass", 1); static SwitchOption interfaceMomentumTreatmentRescaleMass (interfaceMomentumTreatment, "RescaleMass", "Rescale the mass supplied so it is consistent with the" " energy and momentum", 2); static Switch interfaceWeightWarnings ("WeightWarnings", "Determines if warnings about possible weight incompatibilities should " "be issued when this reader is initialized.", &LesHouchesReader::useWeightWarnings, true, true, false); static SwitchOption interfaceWeightWarningsWarnAboutWeights (interfaceWeightWarnings, "WarnAboutWeights", "Warn about possible incompatibilities with the weight option in the " "Les Houches common block and the requested weight treatment.", true); static SwitchOption interfaceWeightWarningsDontWarnAboutWeights (interfaceWeightWarnings, "DontWarnAboutWeights", "Do not warn about possible incompatibilities with the weight option " "in the Les Houches common block and the requested weight treatment.", false); static Switch interfaceAllowedTopReOpen ("AllowedToReOpen", "Can the file be reopened if more events are requested than the file contains?", &LesHouchesReader::theReOpenAllowed, true, false, false); static SwitchOption interfaceAllowedTopReOpenYes (interfaceAllowedTopReOpen, "Yes", "Allowed to reopen the file", true); static SwitchOption interfaceAllowedTopReOpenNo (interfaceAllowedTopReOpen, "No", "Not allowed to reopen the file", false); static Switch interfaceIncludeSpin ("IncludeSpin", "Use the spin information present in the event file, for tau leptons" " only as this is the only case which makes any sense", &LesHouchesReader::theIncludeSpin, true, false, false); static SwitchOption interfaceIncludeSpinYes (interfaceIncludeSpin, "Yes", "Use the spin information", true); static SwitchOption interfaceIncludeSpinNo (interfaceIncludeSpin, "No", "Don't use the spin information", false); interfaceCuts.rank(8); interfacePartonExtractor.rank(7); interfaceBeamA.rank(5); interfaceBeamB.rank(4); interfaceEBeamA.rank(3); interfaceEBeamB.rank(2); interfaceMaxMultCKKW.rank(1.5); interfaceMinMultCKKW.rank(1.0); interfaceBeamA.setHasDefault(false); interfaceBeamB.setHasDefault(false); interfaceEBeamA.setHasDefault(false); interfaceEBeamB.setHasDefault(false); interfaceMaxMultCKKW.setHasDefault(false); interfaceMinMultCKKW.setHasDefault(false); } namespace ThePEG { ostream & operator<<(ostream & os, const HEPEUP & h) { os << "\n" << " " << setw(4) << h.NUP << " " << setw(6) << h.IDPRUP << " " << setw(14) << h.XWGTUP << " " << setw(14) << h.SCALUP << " " << setw(14) << h.AQEDUP << " " << setw(14) << h.AQCDUP << "\n"; for ( int i = 0; i < h.NUP; ++i ) os << " " << setw(8) << h.IDUP[i] << " " << setw(2) << h.ISTUP[i] << " " << setw(4) << h.MOTHUP[i].first << " " << setw(4) << h.MOTHUP[i].second << " " << setw(4) << h.ICOLUP[i].first << " " << setw(4) << h.ICOLUP[i].second << " " << setw(14) << h.PUP[i][0] << " " << setw(14) << h.PUP[i][1] << " " << setw(14) << h.PUP[i][2] << " " << setw(14) << h.PUP[i][3] << " " << setw(14) << h.PUP[i][4] << " " << setw(1) << h.VTIMUP[i] << " " << setw(1) << h.SPINUP[i] << std::endl; os << "" << std::endl; return os; } } diff --git a/LesHouches/Makefile.am b/LesHouches/Makefile.am --- a/LesHouches/Makefile.am +++ b/LesHouches/Makefile.am @@ -1,26 +1,27 @@ mySOURCES = LesHouchesReader.cc LesHouchesFileReader.cc \ LesHouchesEventHandler.cc DOCFILES = LesHouchesReader.h LesHouchesFileReader.h \ LesHouchesEventHandler.h LesHouches.h INCLUDEFILES = $(DOCFILES) LesHouchesReader.fh \ LesHouchesFileReader.fh \ LesHouchesEventHandler.fh pkglib_LTLIBRARIES = LesHouches.la MadGraphReader.la # Version info should be updated if any interface or persistent I/O # function is changed MadGraphReader_la_LDFLAGS = $(AM_LDFLAGS) -module $(LIBTOOLVERSIONINFO) -MadGraphReader_la_SOURCES = MadGraphReader.cc MadGraphReader.h \ - MadGraphOneCut.cc MadGraphOneCut.h \ - MadGraphTwoCut.cc MadGraphTwoCut.h +MadGraphReader_la_SOURCES = \ +MadGraphReader.cc MadGraphReader.h \ +MadGraphOneCut.cc MadGraphOneCut.h \ +MadGraphTwoCut.cc MadGraphTwoCut.h # Version info should be updated if any interface or persistent I/O # function is changed -LesHouches_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 21:0:0 +LesHouches_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 22:0:0 LesHouches_la_SOURCES = $(mySOURCES) $(INCLUDEFILES) include $(top_srcdir)/Config/Makefile.aminclude diff --git a/MatrixElement/BlobMEBase.cc b/MatrixElement/BlobMEBase.cc --- a/MatrixElement/BlobMEBase.cc +++ b/MatrixElement/BlobMEBase.cc @@ -1,89 +1,102 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the BlobMEBase class. // #include "BlobMEBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace ThePEG; BlobMEBase::BlobMEBase() {} BlobMEBase::~BlobMEBase() {} #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/BlobDiagram.h" -string BlobMEBase::ColourConnection::write(size_t& sourceCount) const { - assert(members.size() >= 2); +string BlobMEBase::ColourConnection::write(size_t& sourceCount, + bool sink) const { string res; - for ( auto it = members.begin(); it != members.end(); ++it ) - res += std::to_string(*it) + " "; - if ( members.size() > 2 || - ( members.size() == 2 && members[0]*members[1] > 0 ) ) { - res += ": " + std::to_string(sourceCount); - ++sourceCount; + if ( members.size() == 2 ) { + // standard connection + for ( auto it = members.begin(); it != members.end(); ++it ) + res += std::to_string(*it) + " "; + } else if ( members.size() == 3 ) { + // source or sink + for ( auto it = members.begin(); it != members.end(); ++it ) { + res += std::to_string(*it) + " " + (sink ? "-":"") + std::to_string(sourceCount); + if ( std::next(it) != members.end() ) + res += ", "; + } + sourceCount += 1; + } else { + // not handled + throw Exception() << "BlobMEBase::ColourConnection::write: Invalid colour connection information." + << Exception::runerror; } return res; } void BlobMEBase::getDiagrams() const { - map proc = processes(); + multimap proc = processes(); int id = 1; for ( auto it = proc.begin(); it != proc.end(); ++it, ++id ) { BlobDiagram diag(id,it->first.first,it->first.second); for ( auto pit = it->second.begin(); pit != it->second.end(); ++pit ) diag.operator,(*pit); add(new_ptr(diag)); } } Selector BlobMEBase::diagrams(const DiagramVector & diags) const { assert(diags.size()==1); Selector sel; sel.insert(1.0, 0); return sel; } Selector BlobMEBase::colourGeometries(tcDiagPtr diag) const { auto connections = colourConnections(); ostringstream clines; - size_t sourceCount = diag->partons().size(); + size_t sourceCount = diag->partons().size() + 1; for ( auto it = connections.begin(); it != connections.end(); ++it ) { - clines << it->write(sourceCount); + bool sink = (it->members.size()==3 && + (-it->members[0] > diag->nIncoming() || + it->members[0] < diag->nIncoming() ) ); + clines << it->write(sourceCount,sink); auto nit = it; ++nit; if ( nit != connections.end() ) clines << ","; } theColourLines.reset(clines.str()); Selector sel; sel.insert(1.0,&theColourLines); return sel; } CrossSection BlobMEBase::dSigHatDR() const { if ( !lastXCombPtr()->willPassCuts() ) return ZERO; return (sqr(hbarc)/(2.*lastSHat())) * jacobian() * me2(); } AbstractNoPIOClassDescription BlobMEBase::initBlobMEBase; void BlobMEBase::Init() { static ClassDocumentation documentation ("BlobMEBase is the base class for matrix elements producing blobs."); } diff --git a/MatrixElement/BlobMEBase.h b/MatrixElement/BlobMEBase.h --- a/MatrixElement/BlobMEBase.h +++ b/MatrixElement/BlobMEBase.h @@ -1,181 +1,181 @@ // -*- C++ -*- #ifndef ThePEG_BlobMEBase_H #define ThePEG_BlobMEBase_H // // This is the declaration of the BlobMEBase class. // #include "ThePEG/MatrixElement/MEBase.h" namespace ThePEG { /** * Here is the documentation of the BlobMEBase class. * * @see \ref BlobMEBaseInterfaces "The interfaces" * defined for BlobMEBase. */ class BlobMEBase: public MEBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ BlobMEBase(); /** * The destructor. */ virtual ~BlobMEBase(); //@} public: /** * Helper struct to represent colour connections. */ struct ColourConnection { /** * The members of the colour connection */ vector members; /** * Add a leg's colour to the connection */ void addColour(int leg) { members.push_back(leg+1); } /** * Add a leg's anti-colour to the connection */ void addAntiColour(int leg) { members.push_back(-leg-1); } /** * Write out the connection to the colour lines string */ - string write(size_t& sourceCount) const; + string write(size_t& sourceCount, bool sink) const; }; /** @name Virtual functions required by the MEBase class. */ //@{ /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; /** * Return the matrix element squared differential in the variables * given by the last call to generateKinematics(). */ virtual CrossSection dSigHatDR() const; //@} /** * Return the possible processes this matrix element will be able to handle, * as a map incoming to outgoing; it is assumed that the number of outgoing * partons does not vary. */ - virtual map processes() const = 0; + virtual multimap processes() const = 0; /** * Return the colour connections for the process. */ virtual list colourConnections() const = 0; public: /** * Describe an abstract base class without persistent data. */ static AbstractNoPIOClassDescription initBlobMEBase; /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ BlobMEBase & operator=(const BlobMEBase &); /** * The colour lines object used as a proxy to connect colours in * BlobDiagram::construct */ mutable ColourLines theColourLines; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * BlobMEBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of BlobMEBase. */ typedef MEBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * BlobMEBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::BlobMEBase"; } }; /** @endcond */ } #endif /* ThePEG_BlobMEBase_H */ diff --git a/MatrixElement/ColourLines.cc b/MatrixElement/ColourLines.cc --- a/MatrixElement/ColourLines.cc +++ b/MatrixElement/ColourLines.cc @@ -1,143 +1,142 @@ // -*- C++ -*- // // ColourLines.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 ColourLines class. // #include "ColourLines.h" #include "ColourLines.xh" #include "ThePEG/EventRecord/ColourLine.h" #include "ThePEG/EventRecord/MultiColour.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/StringUtils.h" using namespace ThePEG; ColourLines::ColourLines(string s) { reset(s); } void ColourLines::reset(string s) { theLines.clear(); while ( true ) { string line = StringUtils::car(s, ","); line = StringUtils::stripws(line); Line l; while (line!="") { string loc = StringUtils::car(line); string first = StringUtils::car(loc,":"); string second = StringUtils::cdr(loc,":"); if(second!="") { int i; istringstream is(first); is >> i; int j; istringstream is2(second); is2 >> j; l.push_back(make_pair(i,j)); } else { int i; istringstream is(first); is >> i; l.push_back(make_pair(i,0)); } line = StringUtils::cdr(line); }; if ( l.empty() ) return; theLines.push_back(l); s = StringUtils::cdr(s, ","); } } void ColourLines::connect(const tPVector & partons) const { VertexVector sinks; VertexVector sources; long np = partons.size(); // Create each line and connect the specified partons to them. Save // all lines coming from a source or ending in a sink. for ( LineVector::size_type il = 0; il < theLines.size(); ++il ) { const Line & line = theLines[il]; ColinePtr cline = new_ptr(ColourLine()); for ( Line::size_type i = 0; i < line.size(); ++i ) { if ( line[i].first > np ) { // this is a colour source. int is = line[i].first - np; sources.resize(is); sources[is - 1].push_back(cline); } else if ( -line[i].first > np ) { // this is a colour sink. int is = -line[i].first - np; - sources.resize(is); - sources[is - 1].push_back(cline); + sinks.resize(is); + sinks[is - 1].push_back(cline); } else if ( line[i].first > 0 ) { // This is a coloured particle. if ( !partons[line[i].first - 1]->hasColour() ) throw ColourGeometryException(partons, line); if(line[i].second==0) { cline->addColoured(partons[line[i].first - 1]); } else { Ptr::pointer colour = dynamic_ptr_cast::pointer>(partons[line[i].first - 1]->colourInfo()); assert(colour); colour->colourLine(cline,line[i].second); } } else { if ( !partons[-line[i].first - 1]->hasAntiColour() ) throw ColourGeometryException(partons, line); if(line[i].second==0) { cline->addAntiColoured(partons[-line[i].first - 1]); } else { Ptr::pointer colour = dynamic_ptr_cast::pointer>(partons[-line[i].first - 1]->colourInfo()); assert(colour); colour->antiColourLine(cline,line[i].second); } } } } - // Now connect up all lines steming from sources. for ( VertexVector::size_type i = 0; i < sources.size(); ++i ) { if ( sources[i].empty() ) continue; if ( sources[i].size() != 3 ) throw ColourGeometryException(partons, vector >() ); sources[i][0]->setSourceNeighbours(sources[i][1], sources[i][2]); } // Now connect up all lines ending in sinks. for ( VertexVector::size_type i = 0; i < sinks.size(); ++i ) { if ( sinks[i].empty() ) continue; if ( sinks[i].size() != 3 ) throw ColourGeometryException(partons, vector >()); sinks[i][0]->setSinkNeighbours(sinks[i][1], sinks[i][2]); } } ColourGeometryException:: ColourGeometryException(const tPVector & p, const vector > & c) { if ( c.empty() ) theMessage << "The number of colour lines steming from one colour source " << "or ending in one colour sink was not equal to three.\n"; else { theMessage << "Cannot connect the following partons:\n"; for ( unsigned i = 0; i < p.size(); ++i ) theMessage << " " << p[i]->PDGName(); theMessage << "\n to the following colour line:\n"; for ( unsigned i = 0; i < c.size(); ++i ) theMessage << " (" << c[i].first << "," << c[i].second << ") "; theMessage << endl; } severity(maybeabort); } diff --git a/MatrixElement/Tree2toNDiagram.cc b/MatrixElement/Tree2toNDiagram.cc --- a/MatrixElement/Tree2toNDiagram.cc +++ b/MatrixElement/Tree2toNDiagram.cc @@ -1,436 +1,454 @@ // -*- 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 pout(xc.meMomenta().begin() + 2, xc.meMomenta().end()); 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 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 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 Tree2toNDiagram::children(int ii) const { pair 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 > 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::tcptr cmp = dynamic_ptr_cast::tcptr>( diag ); if ( !cmp ) return false; + if ( cmp->nSpace() != nSpace() ) + return false; return equals(cmp) && external() == cmp->external(); } bool Tree2toNDiagram::isSame (tcDiagPtr diag, map& remap) const { Ptr::tcptr cmp = dynamic_ptr_cast::tcptr>( diag ); if ( !cmp ) return false; + if ( cmp->nSpace() != nSpace() ) + return false; remap.clear(); remap[0] = 0; return equals(cmp,remap); } bool Tree2toNDiagram::equals(Ptr::tcptr diag, int start, int startCmp) const { - if ( start < 0 && startCmp < 0 ) - return true; + // one leg ended externally while the other still has children left + if ( start < 0 || startCmp < 0 ) + return false; + // no match, if the legs are not the same if ( allPartons()[start] != diag->allPartons()[startCmp] ) return false; pair ch = children(start); pair chCmp = diag->children(startCmp); + // start and startCmp are matching external legs + if ( ch.first < 0 && chCmp.first < 0 ) { + return true; + } + + // check the first combination of children bool match = equals(diag,ch.first,chCmp.first) && equals(diag,ch.second,chCmp.second); - // also try swapped legs on same vertex + // also try swapped legs on same vertex for time-like legs if ( !match && start > nSpace() - 1 ) match = equals(diag,ch.first,chCmp.second) && equals(diag,ch.second,chCmp.first); return match; } bool Tree2toNDiagram::equals(Ptr::tcptr diag, map& remap, int start, int startCmp) const { - if ( start < 0 && startCmp < 0 ) - return true; + // one leg ended externally while the other still has children left + if ( start < 0 || startCmp < 0 ) + return false; + // no match, if the legs are not the same if ( allPartons()[start] != diag->allPartons()[startCmp] ) return false; pair ch = children(start); pair chCmp = diag->children(startCmp); + // start and startCmp are matching external legs, which require remapping of + // external labels if ( ch.first < 0 && chCmp.first < 0 ) { remap[externalId(start)] = diag->externalId(startCmp); + return true; } + // check the first combination of children bool match = equals(diag,remap,ch.first,chCmp.first) && equals(diag,remap,ch.second,chCmp.second); - // also try swapped legs on same vertex + // also try swapped legs on same vertex for time-like legs if ( !match && start > nSpace() - 1 ) 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& 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::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 remove; size_type theNSpaceBackup = theNSpace; int theNOutgoingBackup = theNOutgoing; int nextOrigBackup = nextOrig; cPDVector thePartonsBackup = thePartons; vector 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::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 swapDiagIds(p,diagramId(npos)); swap(thePartons[swapDiagIds.first],thePartons[swapDiagIds.second]); swap(theParents[swapDiagIds.first],theParents[swapDiagIds.second]); for ( map::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::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::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/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -1,912 +1,931 @@ ThePEG News -*- outline -*- =============================== Numbered bugs can be found at http://projects.hepforge.org/herwig/trac/ticket/NN where NN is the bug number. The latest version of ThePEG can be found at http://www.thep.lu.se/ThePEG or at http:///projects.hepforge.org/herwig/versions +* ThePEG-2.0.4 release: 2016-10-25 + +** Default weight explicitly labelled + The nominal event weight is now labelled "Default" and is always the + first weight to be inserted into HepMC. + (Note that HepMC 2.06.09 may not preserve this ordering.) + +** LesHouches event weights handling + There are now two options for the treatment of optional weights + coming in from a Les Houches file, available through + "LesHouchesEventHandler:WeightNormalization". Either they are + normalized to the "Default" weight ("Normalized"), or they are given + as cross-sections in pb ("CrossSection"). The default behaviour + is "Normalized". + +** JetFinder in Cuts objects writes information + The selected JetFinder is explicitly listed in the debug output + + * ThePEG-2.0.3 release: 2016-07-21 ** LesHouches reader Removed FxFx-specific weights from default output ** FuzzyTheta cut Fixed missing division by width ** NaN check for incoming momenta from ME providers ** Build system Compatibility with gcc-6, improved configure macros. * ThePEG-2.0.2 release: 2016-04-27 ** LesHouches reader Fixed cross-section issue for LH event files using weight scheme 3 * ThePEG-2.0.1 release: 2016-02-17 ** Electroweak scheme fixes Schemes 2 and 5 now set GF, scheme 7 calculates mw correctly. ** New ParVector 'clear' command ** More visible version information The version number of ThePEG is written into the log file. ** Rivet exception handling Any exceptions from Rivet/YODA are converted into warning exceptions. This can invalidate plots, please check the logfile. ** Rapidity limits fixed in FuzzyTheta cuts ** Doxygen updated to version 1.8 ** Java interface fixed * ThePEG-2.0.0 release: 2015-12-04 ** Improvements for NLO A number of improvements and bug fixes have been made in the course of (Herwig 7) NLO development. ** Improvements for spin correlations A number of improvements have been made to handle spin correlations in the parton shower. ** Setup file mechanism An isolated event generator can now be modified prior to generating events by providing an additional input file; also support for re-initalizing isolated event generators has been added in this course to support Herwig 7's parallel integration modes. ** Handling of weighted LHE events The handling of LHE events with variable weight (codes 3 and 4) has now been enabled, along with the full handling of multiple event weights down to the HepMC output. ** LHAPDF6 handling A problem in initializing LHAPDF6 has been fixed. ** Heavy ion collisions A dedicated HepMC interface for heavy ion collisions has been introduced. ** First steps for unit testing Unit testing has been introduced for a number of components based on boost's unittesting framework. They are only enabled, when configured --with-boost . * ThePEG-1.9.2 release: 2014-07-07 ** Better support for LHAPDF 6 The LHAPDF interface now determines if version 6 is available and makes use of new LHAPDFv6 features. * ThePEG-1.9.1 release: 2014-04-30 ** Build fix for SLC6 Fixed problems with a missing header in ACDCGen.h that affected some builds on SLC6 ** Build fix for Rivet 2.1.1 Adapted to Rivet 2.1.1 changed header file layout ** OS X Mavericks build fix for readline The problem of infinite hangs when linking against libreadline in Mavericks has been resolved. * ThePEG-1.9.0 release: 2013-10-28 ** Rapidity edge cases Changed behavior for vanishing pt in eta() and vanishing mt in rapidity(): no error is thrown, but a ridculously large rapidity is returned instead. ** Command line interface Adding a tag of the form "#first-last" when running a MultiEventGenerator now allows to run a subset of the runs ** Pre- and Posthandlers A warning is now issued if the same handler is inserted twice into a pre- or posthandler list. ** Statistics fixes Various issues for the handling of statistics in the presence of negative weights have been fixed. ** Rivet search paths A new interface RivetAnalysis:Paths allows more search paths to be added to the analysis finding routine. This supplements the RIVET_ANALYSIS_PATH environment variable. ** Vertex classes A chain of sign and prefactor fixes has been implemented in the Vertex classes to correct various vertex structures in Herwig++ conversions of Feynrules models. ** Custom XComb objects Matrix element classes can built with customized XComb objects. ** Reweighting of SubProcessGroups and projections Matrix element groups can reweight contributions in a SubProcessGroup and select one of the dependent subprocesses to be used as the hard one instead of the group in total. ** Fuzzy cuts Jet cuts in the jet cut framework can be assigned a fuzzy shape to improve the stability of NLO calculations. ** NLORivetAnalysis, NLOHepMCFile The NLOHepMCFile and NLORivetAnalysis classes have been added to allow Rivet to analyse NLO calculations which perform output for the subtracted real emission matrix elements as ThePEG::SubProcessGroups; individual subprocesses in these groups are flagged as correlated by being assigned the same event number. ** C++-11 testing To help with the coming transition to C++-11, we provide the new --enable-stdcxx11 configure flag. Please try to test builds with this flag enabled and let us know any problems, but do not use this in production code yet. In future releases, this flag will be on by default. * ThePEG-1.8.3 release: 2013-02-22 ** Fixed HepMC status code assignment The incoming line to a technical vertex that only changes a particle's momentum is now labelled 11 (MC-internal) instead of 2 (unstable). * ThePEG-1.8.2 release: 2013-01-30 ** Changes to scheduled event dumps Set the EventGenerator option "KeepAllDumps" to keep all dump files of a run, labelled by event number. These scheduled dumps now produce a cleaned generator state between events. ** SLHA block bug fix In some circumstances, the end of an SLHA block was not parsed correctly. * ThePEG-1.8.1 release: 2012-10-15 ** Repository changes *** Stable flag The behaviour of the 'Particle:Stable' flag has changed slightly. When all decaymodes are removed from a particle, the flag will be automatically set to stable. However, it still needs to be set unstable by hand when new decaymodes are added to a formerly stable particle. *** Search paths The search paths for reading input files are now saved in the repository. ** Rivet analysis YODA capable The configure time check for Rivet will now detect the version to check if it is YODA capable. ** NLOHepMCFile An AnalysisHandler, similar to the standard HepMCFile has been added to allow analysing plain NLO calculations by communicating each member of a subprocess group (typically real emission and subtraction contributions) to a HepMC file; until Rivet supports the correct treatment of errors in this case, the subprocess group members are written out as events independent of each other. ** Jet cuts A more flexible framework for cuts on jets has been added, including jet finders (either builtin or via an optional link to fastjet). All kinds of exclusive and inclusive jet cuts, as well as jet vetoes on the level of the hard process are now supported. ** Tree2toNDiagram A bug has been fixed in Tree2toNDiagram::isSame(tcDiagPtr, map&) method to take into account symmetries when swapping two external legs attached to the same vertex ** Quark thresholds in alphaS Support for setting quark masses for threshold matching in couplings deriving from AlphaSBase independently of masses used in ParticleData objects has been added. The O1AlphaS implementation is fully aware of this enhancement. ** LesHouches reader fixes The LesHouches readers have been improved, and will spot many more consistency errors, such as coloured Standard Model leptons, or helicity values outside of [-1,1] and 9. ** Spinor enhancements The LorentzSpinor class has gained member functions for projection operations and the contraction with the sigma-mu-nu commutator. * ThePEG-1.8.0 release: 2012-05-21 ** NLO support *** ThePEG now includes structures to ease implementing next-to-leading order (NLO) calculations as well as for interfacing external matrix element codes through runtime interfaces. Particularly, the newly introduced MEGroup and accompanying StdXCombGroup, StdDependentXComb and SubProcessGroup classes provide the functionality required by subtraction approaches to higher orders. A general interface for cutting on reconstructed jets as required by higher-order calculations is included, along with an implementation of kt, Cambridge-Aachen and anti-kt jet finding as relevant for NLO calculations. Hard process implementations deriving from MEBase are no longer limited to the evaluation of PDFs by PartonExtractor objects, thus allowing for a more flexible and more stable implementation of finite collinear contributioins appearing in the context of higher order corrections. *** The generation of phasespace points for the hard subprocess has been made more flexible, particularly to allow generation of incoming parton momenta by the hard matrix element as is typically done by phasespace generators provided with fixed-order codes. Along with this change, generation of the phasespace point does not need to take place in the centre-of-mass system of the incoming partons. *** Various helpers have been added to MEBase and dependent code along with the improvements described above, including simple functionality required for caching intermediate results. *** Tree2toNDiagram supports merging of two external legs, yielding another Tree2toNDiagram object to assist in determining subtraction terms required for a particular process ** Support for SU(3)-sextet colour lines ** Named weights support, also in HepMC Named, optional weights on top of the usual event weight are now fully supported; this includes their communication to HepMC events as well as their parsing from the extented Les Houches file format drafted at the Les Houches workshop 2009. ** Complex masses supported in Helicity code ** Several minor fixes and enhancements * ThePEG-1.7.3 release: 2012-03-05 The only changes are in LesHouches.so, now at version 14. ** Spin information Spin correlation information will now be set up correctly for tau leptons. To go back to the old behaviour, set LesHouchesReader:IncludeSpin No ** Consistency checks Catch broken input where mother-daughter relations are circular. * ThePEG-1.7.2 release: 2011-11-01 ** HepMC configuration Clarified at configure time that HepMC versions before 2.05 are not officially supported. ** Rivet configuration Rivet builds with external header dependencies are now correctly recognized. ** Helicity vertex consistency To help debugging, the addToList() function for registering particle lines connected to a vertex now checks for electric charge conservation at the vertex. Additionally, the specified QED/QCD order of the interaction is checked. ** Ticket #355: Global library list for resume functionality The list of global libraries is now correctly included in the dump file, to fix the functionality of resuming a run from regular checkpoints. * ThePEG-1.7.1 release: 2011-06-20 ** Ticket #238: Self-consistent electroweak schemes The default behaviour of Herwig++ is to use the best values for all the electroweak parameters, which can be inconsistent. Optionally now, a self-consistent electroweak scheme can be chosen in the parameter Model:EW/Scheme. Note that values of 'EW/Scheme' away from the default have not received the same amount of testing. ** Ticket #338: Fixed reporting of floating point exceptions This was an issue whenever LHAPDF libraries were linked in. ** Fixed cTau() behaviour The new behavior is that if both width and lifetime are zero, cTau() returns zero for unstable particles and MaxLength for stable ones. ** MaxErrors The cutoff can be disabled by setting MaxErrors to -1. ** StdOut redirect CurrentGenerator::Redirect now does not redirect to to the internal stream in EventGenerator if the useStdout flag has been set. ** Run name tags Aded possibility to add a tag to the run name when running with the '-t' option. One run file can thus be run with different seeds and result in different output files. ** Exception names EventGenerator tries to convert exception type names into human-readable form. Currently this only works for gcc-compatible compilers. ** Repository API changes Instead of printing an error message to cerr, the Repository::load() and Repository::read(filename,os) commands now behave like the other repo commands and return an error string. This allows --exitonerror to work correctly for load() and read(). Users of these functions need to send the string to cerr themselves if the old output behaviour is required. Repository::read(is, os, prompt) is unchanged. ** HepMC precision The precision() option for HepMC GenEvent is now available as an interface in the HepMCFile analysis handler. ** gcc-4.6 The build has now also been tested with gcc 4.6.0. * ThePEG-1.7.0 release: 2011-02-08 ** Behaviour *** Cross-section information The .out file contains a better estimate of the cross-section directly from the phase space sampler. It should be reliable if not too many events were vetoed during the later phases of the production. *** Simpler decay mode selection Instead of having to turn off every mode individually, the new 'SelectDecayModes' interface allows commands such as tbar:SelectDecayModes none tbar:SelectDecayModes tbar->nu_ebar,e-,bbar; tbar->nu_mubar,mu-,bbar; Use 'PrintDecayModes' to list the available choices. *** Rivet interface The interface will check before the run if all chosen analyses are actually available in Rivet, and will only call finalize() if any events have been generated. Event weights are now passed correctly into Rivet. *** Les Houches QNUMBER support QNUMBER particle creation support has been added to the Les Houches reader. *** Debug level If a debug level is set on the command line, it will always be used. *** Abort preserves events A hard abort exception during event generation will try to finalize as best as it can, thus preserving information about the run until this point. *** Progress log There is a new ThePEG::ProgressLog analysis handler, which prints timing information about the run to screen. *** Graphviz The event graph can show missing momentum information. *** CRLF line endings (Windows-style) File readers can now cope with files that have CRLF (Windows) and CR (Mac) line endings. ** Structure *** Diffraction support To provide support for the simulation of diffractive events, the LeptonLeptonRemnant class was renamed to UnresolvedRemnant, the WeizsackerWilliams PDF extended, BudnevPDF added, and PartonExtractor modified to allow separate override PDFs for each beam. *** Polarized beams The PolarizedBeamParticleData class permits a spin polarization choice on the incoming particles. *** Mixing particles The MixedParticleData class supports mixed particle states. *** SpinBase The SpinBase class has been removed, SpinInfo is now the base class. *** Vertex classes Several new vertices were added for BSM physics, and some minor bugs fixed with existing classes. *** PID type Particle IDs now have their own type, 'PID'. It can only be converted to 'long' to avoid unsigned int overflow errors on 64bit machines. *** ClassDescription There is a simpler way to register ClassDescription information with the Repository: the DescribeClass<> template. No information is needed in the class headers anymore, reducing build dependencies. New code will use this method now, older classes will be migrated in future. *** LWH histogramming The built-in implementation of AIDA histogramming has been restructured slightly to decouple the implementation from the interface. ** Build system *** Silent build rules 'make' now builds silently, to improve readability. To get the old behaviour, run 'make V=1' *** zlib Integrated zlib to read compressed files, such as Les Houches events. *** Libtool 2.4 Will fix some issues on OS X. *** gsl check This check now also works with Rivet ** Bug fixes *** Ticket #286: Implementation of Cuts in LesHouchesReader Les Houches events are given in the lab frame, but QCDCuts expects to be given momenta in the parton-parton cmf. Boost added. *** Ticket #303: AlphaS thresholds AlphaS thresholds were fixed for exactly massless quarks. *** Ticket #304: Length units in HepMC *** Ticket #309: Particle initialization order *** Ticket #310: LeptonLeptonPDF fix * ThePEG-1.6.1 release: 2009-12-11 ** Ticket #292: Spin correlation fix to stabilize tau decay numerics We have restructured the spin correlation code to stabilize the numerical problems seen in tau decays. ** Speed increase Improved decay chain handling speeds up a typical run by a few percent. ** Exception logging The log file lists different exception types individually again instead of grouping them all by severity only. This was broken in the last few releases. * ThePEG-1.6.0 release: 2009-11-19 ** Helicity amplitudes The main change in this release is a streamlining of the helicity amplitude code. If you have self-written vertex classes, you will need to adapt them slightly: *** Spinor representation All spinors are now in HELAS representation, the optional representation switching has been removed. *** Adding particles to the vertex Instead of calling setList(v1, v2, v3) with three vectors of particles that need to be filled in sync, call addToList(p1, p2, p3) repeatedly. *** Name changes To make them consistent with the rest of ThePEG, the names of functions starting with get...() have changed: getFoo() becomes foo(); setFoo(...) becomes foo(...). ** Vector code changes *** Vector3 has been renamed ThreeVector This makes it consistent with the other vector classes. *** LorentzVector::mag()/mag2() removed, to reduce confusion Use the equivalent ::m()/m2() instead to get E^2-p^2. LorentzVector::rho2() == ThreeVector::mag2() == p^2 *** Calculating with a zero-length vector Previously, mathematically undefined values were arbitrarily set to 0 in this situation. Now an assertion failure is triggered in debug mode. Only the azimuthal angle phi() still returns 0. ** Environment variable interpretation removed The programs setupThePEG and runThePEG are not wrapped in shell scripts anymore. All usage of environment variables at runtime has been removed. To influence the behaviour of ThePEG, you will need to use explicit command line flags, or calls to Repository:: functions. ** StandardModelBase now provides G_Fermi InvEnergy2 StandardModelBase::fermiConstant() const; provides the PDG 2006 value of G_Fermi. ** Allow particle width cuts to be unset Setting a negative value for the lower or upper width cut removes that bound on the width. ** Ticket #271: Decay mode names are normalized Previously, the ordering of decay products in a decay mode specifier needed to match ThePEG's internal ordering exactly. This is now done automatically. ** Ticket #273: NoPDF and LesHouches reader The LesHouches reader has been fixed for the case where no PDFs are used in the LHE file. ** Ticket #275: doinitrun() ordering The ACDC sampler now ensures that initrun() of all ME objects is run first. ** Ticket #277: Repository command help texts ThePEG's repository command language now includes a 'help' functionality. ** Redirection of various files The log file stream now goes to stdout instead of stderr when EventGenerator:UseStdout is set. ** Readline support can be disabled Using the configure switch '--disable-readline', the linking of libreadline can be suppressed. This can be useful for batch code that will never be used interactively, if the number of linked-in libraries is a problem. ** --with-LHAPDF configure flag Previously, the full LHAPDF path including lib/ needed to be specified. This now also works with the more common usage of just LHAPDF's prefix path. ** Rivet analysis plugin The Rivet analysis output files are now named consistently like the other output from a run, with the run name as prefix. ** Graphviz event visualization This is now independent of HepMC. The call to void ThePEG::printGraphviz(ostream & os, tcEventPtr event); on any event will output a Graphviz file to the stream, suitable for interpretation with the 'dot' tool. It shows a visualization of the generator's internal event structure, useful for debugging. This is an initial version, feedback is welcome! ** Fixed compatibility with older HepMC versions A problem with rejecting a missing HepMC unit implementation was fixed. * ThePEG-1.5.0 release: 2009-09-01 ** New ZERO object The ZERO object can be used to set any dimensionful quantity to zero. This avoids explicit constructs like 0.0*GeV. ** Readline interface The interactive repository access now uses the readline library, providing a command history and easier command line editing. ** Syntax highlighting We now have a syntax highlighting mode for emacs. To enable it, use 'M-x ThePEG-repository-mode' on any .in file. ** Configure information Important configuration information is listed at the end of the 'configure' run and in the file 'config.thepeg'. Please provide this file in any bug reports. ** Rivet interface ThePEG now supports Rivet internally as an AnalysisHandler if it's available. ** HepMC tools; CLHEP support removed The HepMC file output and graphviz event view have migrated from Herwig++ to ThePEG. The deprecated CLHEP support has been removed. ** Exception specifiers removed Client code changes are needed in doinit() etc. Simply remove the exception specifier after the function name. ** Support for HepMC 2.05 *** New features ThePEG now supports cross-section output, PDF information and unit specifications if they are available in HepMC. *** IO_ASCII Support for the deprecated IO_ASCII format has been removed. *** Status codes ThePEG uses codes 1, 2 and 11 according to the HepMC agreement. ** Redirection of .out, .log and .tex to stdout Set 'EventGenerator:UseStdout' to 'Yes' and (almost) all output will be streamed to stdout instead of files. ** Ticket #248: Les Houches reader The cross-section information is now reported correctly when reading several files. ** Cuts output If the debug level is set > 0, the current set of cuts is prepended to the logfile. ** Preweighting of matrix elements A segfault when using preweights was fixed. Preweights are now correctly included in handler statistics. ** Other technical changes *** Colour line improvements *** PDFsets.index search improved *** Ticket #232: Java check on OS X now works headless *** Running couplings restructured *** LeptonLeptonRemnant iprovements to support GammaGamma *** WaveFunction constructors streamlined *** VertexBase now provides sin2ThetaW etc. * ThePEG-1.4.2 release: 2009-05-08 ** Ticket #242 Fixed a compiler problem that showed up on openSUSE 10.2, g++ 4.1.2. A source line was omitted if the optimization level was higher than -O1. ** User interaction Dump file generation can now be disabled completely by setting EventGenerator:DumpPeriod to -1. * ThePEG-1.4.1 release: 2009-03-31 ** User interaction Error messages have been clarified in BaseRepository and StandardEventHandler ** Les Houches files File readers are more robust, with clearer messages when things go wrong. ** Floating point issues fixed in ThreeVector and VertexBase. ** HepMC converter Fixed PDF choice for asymmetric beams. ** Libtool Updated to version 2.2.6 * ThePEG-1.4.0 release: 2008-12-02 ** Efficiency improvements The LorentzVector class, the helicity amplitude code and PDF lookups have been profiled and restructured to eliminate speed bottlenecks. ** Deep inelastic scattering Support for DIS is now implemented in ThePEG. ** New rapidity cut Added alternative pT cut that cuts on rapidity rather than pseudorapidty as the existing one fails for zero-pt massive particles. ** HepMC units support Users of HepMC versions > 2.04 get full units support. The HepMC GenEvent object has the correct units set. ** Support for HepMC PdfInfo data Users of the HepMC converter can now fill the PdfInfo data, which has been available since HepMC 1.28.00. Older versions are no longer supported. ** Ticket #199: Particle lifetime cutoff Users can set a maximum lifetime. Particles that live longer than this are not decayed. ** Ticket #215: Madgraph Fixed a problem in reading certain Madgraph event files. ** Les Houches files Optional rescaling of energy or mass of particles which were read in. Check the file to trap 'nan' and 'inf' values early during the read-in. ** File cleanup Most inline functions are now defined in the headers rather than a separate .icc file. * ThePEG-1.3.0 release: 2008-06-20 ** Statistical errors Error estimates on the cross-sections are now reported in the .out files. ** Decaymode setup The decaymode setup has been reworked, keeping backwards compatibility. The 'defaultparticle' command has been removed. ** Madgraph reader Updated to latest Madevent version. ** LHAPDF improvements lhapdf-config is not used anymore to determine the location of the PDF sets. Instead, they are fixed at configure-time. ** HepMC The beam particles are now set correctly. ** Arbitrary search paths for .in files Input files don't have to be in '.', use '-I' to specify additional directories. ** Ticket #172 Fix for cuts in mirrored processes. ** Simpler emacs macros The emacs macros have been significantly cleaned up. ** Helicity vertex classes Potential prolems with uninitialized variables were fixed. No actual bugs had occurred from here. ** Memory leak fixes and performance Several loops of shared pointers were fixed involving DecayModes and ParticleData. FixedSizeAllocator was removed, the regular 'new' and 'delete' is now used for all allocations, giving a 5% speedup. * ThePEG-1.2.0 release: 2008-04-18 ** ThePEG uses GSL The GNU Scientific Library and its headers are now required for building ThePEG. RandomGenerator partially uses GSL now. ** Ticket #160: HepMC converter Optionally, the HepMC converter can fill an external GenEvent object, instead of newing one internally. ** 'globallibrary' command The 'globallibrary' command can be used to register libraries which are useful for the whole run. They do not need to be listed in each class's library() function. ** Resume from dump files (also solves #149) The --resume command line flag instructs runThePEG to resume the run from a previous dump file. 'set Generator:DumpPeriod 1000' writes such a checkpoint every 1000 events. ** New Repository interface (also solves #141) The repository now provides a Repository::cleanup() method, to be called at the end of a run. Alternatively, a Repository object can be created and its member functions called. ** Les Houches interface improvements. LesHouchesReader had had a major overhaul. ** XSecCheck analysis Issues a warning if a target cross section is not met in the run. ** Weighted events Handling of weighted events was improved. ** Ticket #124: 'Deleted' interface option Interfaces can be declared obsolete, a warning will be issued when they're used. ** LHAPDF interface The interface now allows photons as partons inside a hadron. ** gcc 4.3.0 ThePEG compiles cleanly with the new gcc 4.3 series. ** Bug #138 Lepton NoPDF now works. * ThePEG-1.1.2 release: 2008-02-25 ** Bug #136: dSigHatDR Efficiency improvement for zero PDF. ** Bug #137: HepMC conversion The HepMC converter now takes a unit argument to specify which energy and length units should be used in the HepMC event. ** Bug #140 / #141: Crash on shutdown This fixes a bug introduced in 1.1.1. External code interfaces should now work again. ** Bug #151: Loop in Remnant record The loop between remnants in the event record has been removed. ** PDF improvements Fix to handling of maximum flavour from LHAPDF. Fix for xmin calculation. * ThePEG-1.1.1 release: 2007-12-07 ** Bug #46: Reproducibility Fixed a problem where runs were not identical for a given random number seed. You now _must_ reset the seed if you need independent event generator runs. ** Detection of gcc abs bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34130 configure now checks for and works around the gcc abs() bug. ** Separate LWHFactory library Fixed problem in Rivet interaction by factoring out LWHFactory into its own dynamic library. * ThePEG-1.1.0 release: 2007-11-20 ** New vector classes ThePEG now uses its own internal Vector classes, making it independent of CLHEP. ** New dimension checking mechanism Optionally, any physical expression is checked for dimensional correctness at compile time. ** Extended Helicity classes A full set of helicity amplitude classes has been transferred from Herwig++. ** unlisted Many other improvements and small bug fixes, see ChangeLog. * ThePEG-1.0.1 release: 2006-11-22 ** unlisted: Fixed memory leak in LesHouchesReader. ** Bug #58 maximumCMEnergy() member of the EventGenerator returns zero. See ChangeLog entry 2006-10-06 ** Bug #62 fixed 'const' behaviour in Lorentz spinor classes ** Bug #68 Improved error message for switch options ** unlisted Improved compile-time LHAPDF library and include file handling. ** unlisted Bug in IteratorRange::rrange(const Container &). ** unlisted fixed Selector::swap() ** unlisted Bug in ClusterCollapser where no colour-singlet particles were considered for momentum compensation if no coloured particles were present. ** unlisted Bug in LeptonLeptonRemnant: minX variable not persistent ** unlisted scale of the produced coloured particles was not set in Onium3GDecayer and ColourPairDecayer ** unlisted unused default path removed from DynamicLoader * ThePEG-1.0 release: 2006-09-27 diff --git a/Utilities/ColourOutput.cc b/Utilities/ColourOutput.cc new file mode 100644 --- /dev/null +++ b/Utilities/ColourOutput.cc @@ -0,0 +1,47 @@ +// -*- C++ -*- +// +// ColourOutput.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 ColourOutput class. +// + +#include "ColourOutput.h" +#include +#include + + +namespace { + +bool useColours(const std::ostream & os) { + + // are we cout? + if ( os.rdbuf() == std::cout.rdbuf() ) { + return isatty(fileno(stdout)); + } + // are we cerr? + else if ( os.rdbuf() == std::cerr.rdbuf() ) { + return isatty(fileno(stderr)); + } + + // otherwise play safe + return false; + +} + +} + +namespace ThePEG { + +std::ostream& operator<<(std::ostream & os, ANSI c) { + if ( useColours(os) ) + os << "\x1B[" << static_cast(c) << 'm'; + return os; +} + +} diff --git a/Utilities/ColourOutput.h b/Utilities/ColourOutput.h new file mode 100644 --- /dev/null +++ b/Utilities/ColourOutput.h @@ -0,0 +1,47 @@ +// -*- C++ -*- +// +// ColourOutput.h is a part of ThePEG - Toolkit for HEP Event Generation +// Copyright (C) 1999-2016 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_ColourOutput_H +#define ThePEG_ColourOutput_H + +#include + +namespace ThePEG { + +enum class ANSI { + reset = 0, + + black = 30, + red = 31, + green = 32, + yellow = 33, + blue = 34, + magenta = 35, + cyan = 36, + white = 37, + + fg_reset = 39, + + bg_black = 40, + bg_red = 41, + bg_green = 42, + bg_yellow = 43, + bg_blue = 44, + bg_magenta = 45, + bg_cyan = 46, + bg_white = 47, + + bg_reset = 49 + +}; + +std::ostream& operator<<(std::ostream & os, ANSI c); + +} + +#endif /* ThePEG_ColourOutput_H */ diff --git a/Utilities/DIterator.h b/Utilities/DIterator.h deleted file mode 100644 --- a/Utilities/DIterator.h +++ /dev/null @@ -1,162 +0,0 @@ -// -*- C++ -*- -// -// DIterator.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_DIterator_H -#define ThePEG_DIterator_H -// This is the declaration of the DIterator class. - -#include -#include "ThePEG/Pointer/PtrTraits.h" - -namespace ThePEG { - -template -/** - * DIterator is an iterator adaptor class. It can be used whenever one - * has a container with pointers to facilitate member selection. The - * only requirement is that the underlying pointer is pointing to a - * valid object. Given e.g. a vector of pointers, vector - * pv where the class A has a member function - * dosomething(), it can be used as follows:
- * typedef DIterator::iterator> It;
- * for ( It i = dv.begin(), i != dv.end(), ++i ) - * i->dosomething();
- */ -class DIterator { - -public: - - /** Forward typedef from underlying iterator */ - typedef std::iterator_traits Traits; - /** Forward typedef from underlying iterator */ - typedef typename Traits::iterator_category iterator_category; - /** Forward typedef from underlying iterator */ - typedef typename Traits::difference_type difference_type; - /** Forward typedef from underlying iterator */ - typedef typename Traits::value_type PtrType; - /** Forward typedef from underlying iterator */ - typedef Pointer::PtrTraits PtrTraits; - /** Forward typedef from underlying iterator */ - typedef typename PtrTraits::value_type value_type; - /** Forward typedef from underlying iterator */ - typedef typename PtrTraits::pointer pointer; - /** Forward typedef from underlying iterator */ - typedef typename PtrTraits::reference reference; - -public: - - /** - * Constructor from a normal iterator. - */ - DIterator(const BaseIterator & in): i(in) {} - - /** - * Copy constructor. - */ - DIterator(const DIterator & pi): i(pi.i) {} - -public: - - /** - * Dereference the pointer referred to by the underlying iterator. - */ - reference operator*() const { return **i; } - - /** - * Select member from the pointer referred to by the underlying iterator. - */ - pointer operator->() const { return *i; } - - /** - * Standard assignment operator. - */ - DIterator & operator=(const DIterator & pi) { i = pi.i; return *this; } - - /** - * Assignment from a a normal iterator. - */ - DIterator & operator=(const BaseIterator & pi) { i = pi; return *this; } - - /** @name Increment and decrement operators. */ - //@{ - /** Pre increment the underlying iterator. */ - DIterator & operator++() { ++i; return *this; } - /** Post increment the underlying iterator. */ - DIterator operator++(int) { DIterator tmp(*this); ++i; return tmp; } - /** Pre decrement the underlying iterator. */ - DIterator & operator--() { --i; return *this; } - /** Post decrement the underlying iterator. */ - DIterator operator--(int) { DIterator tmp(*this); --i; return tmp; } - /** Jump forward n steps */ - DIterator & operator+=(int n) { i += n; return *this; } - /** Get an iterator n steps forward. */ - DIterator operator+(int n) { return DIterator(i + n); } - /** Jump backward n steps */ - DIterator & operator-=(int n) { i -= n; return *this; } - /** Get an iterator n steps backward. */ - DIterator operator-(int n) { return DIterator(i - n); } - //@} - - /** - * Select a pointer with the given index and return a reference to - * the object pointed to. - */ - reference operator[](difference_type n) { return *(i[n]); } - - /** - * Return the distance to the given iterator. - */ - difference_type operator-(const DIterator & pi) { return i - pi.i; } - - /** @name Comparison operators. */ - //@{ - /** Test for equality. */ - bool operator==(const DIterator & pi) { return i == pi.i; } - /** Test for inequality. */ - bool operator!=(const DIterator & pi) { return i != pi.i; } - /** Test for less. */ - bool operator<(const DIterator & pi) { return i < pi.i; } - /** Test for greater. */ - bool operator>(const DIterator & pi) { return i > pi.i; } - /** Test for less or equal. */ - bool operator<=(const DIterator & pi) { return i <= pi.i; } - /** Test for greater or equal. */ - bool operator>=(const DIterator & pi) { return i >= pi.i; } - /** Test for equality. */ - bool operator==(const BaseIterator & bi) { return i == bi; } - /** Test for inequality. */ - bool operator!=(const BaseIterator & bi) { return i != bi; } - /** Test for less. */ - bool operator<(const BaseIterator & bi) { return i < bi; } - /** Test for greater. */ - bool operator>(const BaseIterator & bi) { return i > bi; } - /** Test for less or equal. */ - bool operator<=(const BaseIterator & bi) { return i <= bi; } - /** Test for greater or equal. */ - bool operator>=(const BaseIterator & bi) { return i >= bi; } - //@} - -private: - - /** - * The underlying standard iterator. - */ - BaseIterator i; - -private: - - /** - * The default constructor should never be used. - */ - DIterator() {} - -}; - -} - -#endif /* ThePEG_DIterator_H */ diff --git a/Utilities/Makefile.am b/Utilities/Makefile.am --- a/Utilities/Makefile.am +++ b/Utilities/Makefile.am @@ -1,30 +1,30 @@ mySOURCES = SimplePhaseSpace.cc Debug.cc DescriptionList.cc Maths.cc \ Direction.cc DynamicLoader.cc StringUtils.cc \ Exception.cc ClassDescription.cc CFileLineReader.cc \ - XSecStat.cc CFile.cc DebugItem.cc + XSecStat.cc CFile.cc DebugItem.cc ColourOutput.cc DOCFILES = ClassDescription.h ClassTraits.h Debug.h DescriptionList.h \ HoldFlag.h Interval.h Maths.h Rebinder.h Selector.h \ SimplePhaseSpace.h Triplet.h Direction.h UtilityBase.h \ TypeInfo.h DynamicLoader.h UnitIO.h EnumIO.h \ - DIterator.h StringUtils.h Exception.h Named.h \ + StringUtils.h Exception.h Named.h \ VSelector.h LoopGuard.h ObjectIndexer.h \ CFileLineReader.h CompSelector.h XSecStat.h Throw.h MaxCmp.h \ - Level.h Current.h CFile.h DescribeClass.h DebugItem.h AnyReference.h + Level.h Current.h CFile.h DescribeClass.h DebugItem.h AnyReference.h ColourOutput.h INCLUDEFILES = $(DOCFILES) ClassDescription.fh \ Interval.fh Interval.tcc Rebinder.fh \ Selector.tcc SimplePhaseSpace.tcc SimplePhaseSpace.xh \ Direction.xh UtilityBase.tcc \ Exception.fh VSelector.tcc CFileLineReader.fh noinst_LTLIBRARIES = libThePEGUtilities.la libThePEGUtilities_la_SOURCES = $(mySOURCES) $(INCLUDEFILES) libThePEGUtilities_la_CPPFLAGS = $(AM_CPPFLAGS) \ -DTHEPEG_PKGLIBDIR="\"$(pkglibdir)\"" include $(top_srcdir)/Config/Makefile.aminclude diff --git a/Vectors/HepMCTraits.h b/Vectors/HepMCTraits.h --- a/Vectors/HepMCTraits.h +++ b/Vectors/HepMCTraits.h @@ -1,285 +1,293 @@ // -*- C++ -*- // // HepMCTraits.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_HepMCTraits_H #define ThePEG_HepMCTraits_H #include "HepMC/GenEvent.h" namespace HepMC { class GenEvent; class GenParticle; class GenVertex; class Polarization; class PdfInfo; } namespace ThePEG { /** * HepMCTraitsBase is a convenient base class for specializing the * HepMCTraits class to deal with different flavours of HepMC in the * HepMCConverter class. The default version will work for the CLHEP * implementation of HepMC. To use the HepMCConverter class for any * flavour of HepMC you have to specialize the HepMCTraits class * accordingly, possibly inheriting the functionality from the * HepMCTraitsBase class and only overriding the functions and * typedefs which are different. For the CLHEP flavour of HepMC you * only need to do template<> struct * HepMCTraits<HepMC::GenEvent>: public * HepMCTraitsBase<HepMC::GenEvent,HepMC::GenParticle,HepMC::GenVertex, * HepMC::Polarization> {}; somewhere inside the ThePEG * namespace. The boolean template argument determines whether the * HepMC implementation is specifying units or not. */ template struct HepMCTraitsBase { /** Typedef of the particle class. */ typedef HepMCParticleT ParticleT; /** Typedef of the event class. */ typedef HepMCEventT EventT; /** Typedef of the vertex class. */ typedef HepMCVertexT VertexT; /** Typedef of the polarization class. */ typedef HepMCPolarizationT PolarizationT; /** Typedef of the PdfInfo class. */ typedef HepMCPdfInfoT PdfInfoT; /** Create an event object with number \a evno and \a weight. */ static EventT * newEvent(long evno, double weight, const map& optionalWeights) { EventT * e = new EventT(); e->set_event_number(evno); - e->weights().push_back(weight); +#ifdef HEPMC_HAS_NAMED_WEIGHTS + e->weights()["Default"] = weight; +#else + e->weights().push_back(weight); +#endif for ( map::const_iterator w = optionalWeights.begin(); w != optionalWeights.end(); ++w ) { #ifdef HEPMC_HAS_NAMED_WEIGHTS e->weights()[w->first] = w->second; #else e->weights().push_back(w->second); #endif } return e; } /** Reset event weight and number of a re-used GenEvent. */ static void resetEvent(EventT * e, long evno, double weight, const map& optionalWeights) { e->set_event_number(evno); e->weights().clear(); - e->weights().push_back(weight); +#ifdef HEPMC_HAS_NAMED_WEIGHTS + e->weights()["Default"] = weight; +#else + e->weights().push_back(weight); +#endif for ( map::const_iterator w = optionalWeights.begin(); w != optionalWeights.end(); ++w ) { #ifdef HEPMC_HAS_NAMED_WEIGHTS e->weights()[w->first] = w->second; #else e->weights().push_back(w->second); #endif } } /** * Return true if this version of HepMC accept user-defined units. */ static bool hasUnits() { #ifdef HEPMC_HAS_UNITS return true; #else return false; #endif } /** * Return the energy unit used in the installed version of HepMC. */ static Energy defaultEnergyUnit() { #ifndef HEPMC_HAS_UNITS return GeV; #else return HepMC::Units::default_momentum_unit() == HepMC::Units::GEV? GeV: MeV; #endif } /** * Return the length unit used in the installed version of HepMC. */ static Length defaultLengthUnit() { #ifndef HEPMC_HAS_UNITS return millimeter; #else return HepMC::Units::default_length_unit() == HepMC::Units::MM? millimeter: 10.0*millimeter; #endif } /** * Return the momentum unit used by a given GenEvent object. If * HepMC does not support units this must return GeV. */ static Energy momentumUnit(const EventT & e) { #ifdef HEPMC_HAS_UNITS return e.momentum_unit() == HepMC::Units::MEV? MeV: GeV; #else return GeV; #endif } /** * Return the length unit used by a given GenEvent object. If * HepMC does not support units this must return millimeter. */ static Length lengthUnit(const EventT & e) { #ifdef HEPMC_HAS_UNITS return e.length_unit() == HepMC::Units::CM? centimeter: millimeter; #else return millimeter; #endif } /** * Set the units to be used by the given GenEvent object. If * HepMC does not support units this should be a no-op. */ #ifdef HEPMC_HAS_UNITS static void setUnits(EventT & e, Energy momu, Length lenu) { e.use_units(momu == MeV? HepMC::Units::MEV: HepMC::Units::GEV, lenu == centimeter? HepMC::Units::CM: HepMC::Units::MM); } #else static void setUnits(EventT &, Energy, Length) {} #endif /** Set the \a scale, \f$\alpha_S\f$ (\a aS) and \f$\alpha_{EM}\f$ (\a aEM) for the event \a e. The scale will be scaled with \a unit before given to the GenEvent. */ static void setScaleAndAlphas(EventT & e, Energy2 scale, double aS, double aEM, Energy unit) { e.set_event_scale(sqrt(scale)/unit); e.set_alphaQCD(aS); e.set_alphaQED(aEM); } /** Set the primary vertex, \a v, for the event \a e. */ static void setSignalProcessVertex(EventT & e, VertexT * v) { e.set_signal_process_vertex(v); } /** Set a vertex, \a v, for the event \a e. */ static void addVertex(EventT & e, VertexT * v) { e.add_vertex(v); } /** Create a new particle object with momentum \a p, PDG number \a id and status code \a status. The momentum will be scaled with \a unit which according to the HepMC documentation should be GeV. */ static ParticleT * newParticle(const Lorentz5Momentum & p, long id, int status, Energy unit) { // Note that according to the documentation the momentum is stored in a // HepLorentzVector in GeV (event though the CLHEP standard is MeV). LorentzVector p_scalar = p/unit; ParticleT * genp = new ParticleT(p_scalar, id, status); genp->setGeneratedMass(p.mass()/unit); return genp; } /** Set the polarization directions, \a the and \a phi, for particle \a p. */ static void setPolarization(ParticleT & genp, double the, double phi) { genp.set_polarization(PolarizationT(the, phi)); } /** Set the colour line (with index \a indx) to \a coline for particle \a p. */ static void setColourLine(ParticleT & p, int indx, int coline) { p.set_flow(indx, coline); } /** Create a new vertex. */ static VertexT * newVertex() { return new VertexT(); } /** Add an incoming particle, \a p, to the vertex, \a v. */ static void addIncoming(VertexT & v, ParticleT * p) { v.add_particle_in(p); } /** Add an outgoing particle, \a p, to the vertex, \a v. */ static void addOutgoing(VertexT & v, ParticleT * p) { v.add_particle_out(p); } /** Set the position \a p for the vertex, \a v. The length will be scaled with \a unit which normally should be millimeters. */ static void setPosition(VertexT & v, const LorentzPoint & p, Length unit) { LorentzVector p_scaled = p/unit; v.set_position(p_scaled); } /** Set the beam particles for the event.*/ static void setBeamParticles(EventT & e, ParticleT * p1, ParticleT * p2) { e.set_beam_particles(p1,p2); p1->set_status(4); p2->set_status(4); } /** Set the PDF info for the event. */ #ifdef HEPMC_HAS_PDF_INFO static void setPdfInfo(EventT & e, int id1, int id2, double x1, double x2, double scale, double xf1, double xf2) { e.set_pdf_info(PdfInfoT(id1, id2, x1, x2, scale, xf1, xf2)); } #else static void setPdfInfo(EventT &, int, int, double, double, double, double, double) {} #endif /** Set the cross section info for the event. */ #ifdef HEPMC_HAS_CROSS_SECTION static void setCrossSection(EventT & ev, double xs, double xserr) { HepMC::GenCrossSection x; x.set_cross_section(xs, xserr); ev.set_cross_section(x); } #else static void setCrossSection(EventT &, double, double) {} #endif }; /** * The HepMCTraits class is used to deal with different flavours of * HepMC in the HepMCConverter class. To use the HepMCConverter class * for any flavour of HepMC you have to specialize the * HepMCTraits class accordingly, possibly inheriting the * functionality from the HepMCTraitsBase class and only overriding * the functions and typedefs which are different. For the CLHEP * flavour of HepMC you only need to do template<> struct * HepMCTraits<HepMC::GenEvent>: public * HepMCTraitsBase<HepMC::GenEvent,HepMC::GenParticle,HepMC::GenVertex, * HepMC::Polarization,HepMC::PdfInfo> {}; somewhere inside the ThePEG * namespace. */ template struct HepMCTraits {}; } #endif diff --git a/include/Makefile.am b/include/Makefile.am --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,64 +1,62 @@ BUILT_SOURCES = .done-all-links AUTOMAKE_OPTIONS = -Wno-portability DIRLINKS = $(top_srcdir)/Repository \ $(top_srcdir)/EventRecord \ $(top_srcdir)/Pointer \ $(top_srcdir)/StandardModel \ $(top_srcdir)/Vectors \ $(top_srcdir)/PDT \ $(top_srcdir)/ACDC \ $(top_srcdir)/Interface \ $(top_srcdir)/Handlers \ $(top_srcdir)/LesHouches \ $(top_srcdir)/Persistency \ $(top_srcdir)/PDF \ $(top_srcdir)/Helicity \ $(top_srcdir)/Utilities \ $(top_srcdir)/MatrixElement \ $(top_srcdir)/Cuts \ $(top_srcdir)/Analysis CONFIGHEADERS = $(top_srcdir)/Config/Complex.h \ $(top_srcdir)/Config/Constants.h \ $(top_srcdir)/Config/Containers.h \ $(top_srcdir)/Config/Pointers.h \ $(top_srcdir)/Config/ThePEG.h \ $(top_srcdir)/Config/algorithm.h \ $(top_srcdir)/Config/PhysicalQty.h \ $(top_srcdir)/Config/PhysicalQtyComplex.h \ $(top_srcdir)/Config/PhysicalQtyOps.h \ $(top_srcdir)/Config/TemplateTools.h \ $(top_srcdir)/Config/Unitsystem.h \ $(top_srcdir)/Config/HepMCHelper.h \ $(top_srcdir)/Config/std.h CLEANFILES = .done-all-links .done-all-links: $(DIRLINKS) $(CONFIGHEADERS) @EMPTY@ifdef SHOWCOMMAND mkdir -p ThePEG/Config $(LN_S) -f $(addprefix ../, $(DIRLINKS)) ThePEG $(LN_S) -f $(addprefix ../../, $(CONFIGHEADERS)) ThePEG/Config - $(LN_S) -f ../../../Config/ThePEG_Qty.h ThePEG/Config touch .done-all-links @EMPTY@else @echo "sym-linking header files..." @mkdir -p ThePEG/Config @$(LN_S) -f $(addprefix ../, $(DIRLINKS)) ThePEG @$(LN_S) -f $(addprefix ../../, $(CONFIGHEADERS)) ThePEG/Config - @$(LN_S) -f ../../../Config/ThePEG_Qty.h ThePEG/Config @touch .done-all-links @EMPTY@endif install-data-local: find ThePEG -follow \( -name '*.h' -or -name '*.icc' \ -or -name '*.tcc' -or -name '*.fh' -or -name '*.xh' \) \ -exec $(install_sh_DATA) \{\} $(DESTDIR)$(includedir)/\{\} \; uninstall-local: rm -rf $(DESTDIR)$(includedir)/ThePEG clean-local: rm -rf ThePEG diff --git a/lib/Makefile.am b/lib/Makefile.am --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,72 +1,72 @@ ## workaround for OS X, automake doesn't realize it's meant to use c++ LINK = $(LIBTOOL) --tag=CXX --mode=link $(CXX) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ LINKDIRS = Config Utilities Helicity Interface LesHouches Vectors \ PDT PDF Persistency Handlers MatrixElement Pointer ACDC \ StandardModel Repository EventRecord Cuts Analysis EXTRA_DIST = Makefile.dist.install dist_pkgdata_DATA = ThePEG.el pkglib_LTLIBRARIES = libThePEG.la CLEANFILES = Makefile.dist Makefile.common # Version info should be updated if any interface or persistent I/O # function is changed -libThePEG_la_LDFLAGS = $(AM_LDFLAGS) -version-info 23:0:0 -export-dynamic +libThePEG_la_LDFLAGS = $(AM_LDFLAGS) -version-info 24:0:0 -export-dynamic libThePEG_la_SOURCES = libThePEG_la_LIBADD = \ $(top_builddir)/Utilities/libThePEGUtilities.la \ $(top_builddir)/Vectors/libThePEGVectors.la \ $(top_builddir)/Persistency/libThePEGPersistency.la \ $(top_builddir)/Pointer/libThePEGReferenceCounted.la \ $(top_builddir)/Config/libThePEGConfig.la \ $(top_builddir)/PDF/libThePEGPDF.la \ $(top_builddir)/MatrixElement/libThePEGME.la \ $(top_builddir)/Repository/libThePEGRepo.la \ $(top_builddir)/Handlers/libThePEGHandlers.la \ $(top_builddir)/EventRecord/libThePEGEvent.la \ $(top_builddir)/PDT/libThePEGPDT.la \ $(top_builddir)/StandardModel/libThePEGSM.la \ $(top_builddir)/Interface/libThePEGInter.la \ $(top_builddir)/Helicity/libThePEGHelicity.la \ $(top_builddir)/Cuts/libThePEGCuts.la \ $(top_builddir)/Analysis/libThePEGHist.la \ -ldl $(LIBS) \ $(GSLLIBS) all-local: .done-all-links .done-all-links: libThePEG.la @EMPTY@ifdef SHOWCOMMAND for dir in $(LINKDIRS); do \ for sofile in ../$$dir/.libs/*.so* ../$$dir/.libs/*.la; \ do if test -f $$sofile; then $(LN_S) -f $$sofile .; fi; done; done for sofile in .libs/*.so*; \ do if test -f $$sofile; then $(LN_S) -f $$sofile .; fi; done echo "stamp" > .done-all-links @EMPTY@else @echo "Sym-linking all shared libraries ..." @for dir in $(LINKDIRS); do \ for sofile in ../$$dir/.libs/*.so* ../$$dir/.libs/*.la; \ do if test -f $$sofile; then $(LN_S) -f $$sofile .; fi; done; done @for sofile in .libs/*.so*; \ do if test -f $$sofile; then $(LN_S) -f $$sofile .; fi; done @echo "stamp" > .done-all-links @EMPTY@endif install-data-local: Makefile.common.install sed -e s:@THEPEGLIB@:$(pkglibdir):g -e s:@THEPEGINCLUDE@:-I$(includedir):g Makefile.common.install > Makefile.common sed -e s:@THEPEGLIB@:$(pkglibdir):g $(srcdir)/Makefile.dist.install > Makefile.dist test -z "$(pkglibdir)" || $(mkdir_p) "$(DESTDIR)$(pkglibdir)" $(INSTALL_DATA) Makefile.common $(DESTDIR)$(pkglibdir)/Makefile.common $(INSTALL_DATA) Makefile.dist $(DESTDIR)$(pkglibdir)/Makefile uninstall-local: rm -f $(DESTDIR)$(pkglibdir)/Makefile.common $(DESTDIR)$(pkglibdir)/Makefile clean-local: rm -f *.so* *.la *.rpo .done-all-links